--- misc/xmlsec1-1.2.14/src/nss/ciphers.c 2009-09-10 05:16:27.000000000 -0400 +++ misc/build/xmlsec1-1.2.14/src/nss/ciphers.c 2009-09-10 06:59:39.000000000 -0400 @@ -11,180 +11,421 @@ #include -#include #include -#include #include #include +#include +#include #include #include #include #include - -#define XMLSEC_NSS_MAX_KEY_SIZE 32 -#define XMLSEC_NSS_MAX_IV_SIZE 32 -#define XMLSEC_NSS_MAX_BLOCK_SIZE 32 +#include /************************************************************************** * - * Internal Nss Block cipher CTX + * Internal Nss Block Cipher Context + * This context is designed for repositing a block cipher for transform * *****************************************************************************/ -typedef struct _xmlSecNssBlockCipherCtx xmlSecNssBlockCipherCtx, - *xmlSecNssBlockCipherCtxPtr; +typedef struct _xmlSecNssBlockCipherCtx xmlSecNssBlockCipherCtx ; +typedef struct _xmlSecNssBlockCipherCtx* xmlSecNssBlockCipherCtxPtr ; + struct _xmlSecNssBlockCipherCtx { CK_MECHANISM_TYPE cipher; + PK11SymKey* symkey ; PK11Context* cipherCtx; xmlSecKeyDataId keyId; - int keyInitialized; - int ctxInitialized; - xmlSecByte key[XMLSEC_NSS_MAX_KEY_SIZE]; - xmlSecSize keySize; - xmlSecByte iv[XMLSEC_NSS_MAX_IV_SIZE]; - xmlSecSize ivSize; }; -static int xmlSecNssBlockCipherCtxInit (xmlSecNssBlockCipherCtxPtr ctx, - xmlSecBufferPtr in, - xmlSecBufferPtr out, - int encrypt, - const xmlChar* cipherName, - xmlSecTransformCtxPtr transformCtx); -static int xmlSecNssBlockCipherCtxUpdate (xmlSecNssBlockCipherCtxPtr ctx, - xmlSecBufferPtr in, - xmlSecBufferPtr out, - int encrypt, - const xmlChar* cipherName, - xmlSecTransformCtxPtr transformCtx); -static int xmlSecNssBlockCipherCtxFinal (xmlSecNssBlockCipherCtxPtr ctx, - xmlSecBufferPtr in, - xmlSecBufferPtr out, - int encrypt, - const xmlChar* cipherName, - xmlSecTransformCtxPtr transformCtx); + +#define xmlSecNssBlockCipherSize \ + ( sizeof( xmlSecTransform ) + sizeof( xmlSecNssBlockCipherCtx ) ) + +#define xmlSecNssBlockCipherGetCtx( transform ) \ + ( ( xmlSecNssBlockCipherCtxPtr )( ( ( xmlSecByte* )( transform ) ) + sizeof( xmlSecTransform ) ) ) + +static int +xmlSecNssBlockCipherCheckId( + xmlSecTransformPtr transform +) { + #ifndef XMLSEC_NO_DES + if( xmlSecTransformCheckId( transform, xmlSecNssTransformDes3CbcId ) ) { + return 1 ; + } + #endif /* XMLSEC_NO_DES */ + + #ifndef XMLSEC_NO_AES + if( xmlSecTransformCheckId( transform, xmlSecNssTransformAes128CbcId ) || + xmlSecTransformCheckId( transform, xmlSecNssTransformAes192CbcId ) || + xmlSecTransformCheckId( transform, xmlSecNssTransformAes256CbcId ) ) { + + return 1 ; + } + #endif /* XMLSEC_NO_AES */ + + return 0 ; +} + +static int +xmlSecNssBlockCipherFetchCtx( + xmlSecNssBlockCipherCtxPtr context , + xmlSecTransformId id +) { + xmlSecAssert2( context != NULL, -1 ) ; + + #ifndef XMLSEC_NO_DES + if( id == xmlSecNssTransformDes3CbcId ) { + context->cipher = CKM_DES3_CBC ; + context->keyId = xmlSecNssKeyDataDesId ; + } else + #endif /* XMLSEC_NO_DES */ + + #ifndef XMLSEC_NO_AES + if( id == xmlSecNssTransformAes128CbcId ) { + context->cipher = CKM_AES_CBC ; + context->keyId = xmlSecNssKeyDataAesId ; + } else + if( id == xmlSecNssTransformAes192CbcId ) { + context->cipher = CKM_AES_CBC ; + context->keyId = xmlSecNssKeyDataAesId ; + } else + if( id == xmlSecNssTransformAes256CbcId ) { + context->cipher = CKM_AES_CBC ; + context->keyId = xmlSecNssKeyDataAesId ; + } else + #endif /* XMLSEC_NO_AES */ + + if( 1 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + NULL , + NULL , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + return 0 ; +} + +/** + * xmlSecTransformInitializeMethod: + * @transform: the pointer to transform object. + * + * The transform specific initialization method. + * + * Returns 0 on success or a negative value otherwise. + */ +static int +xmlSecNssBlockCipherInitialize( + xmlSecTransformPtr transform +) { + xmlSecNssBlockCipherCtxPtr context = NULL ; + + xmlSecAssert2( xmlSecNssBlockCipherCheckId( transform ), -1 ) ; + xmlSecAssert2( xmlSecTransformCheckSize( transform, xmlSecNssBlockCipherSize ), -1 ) ; + + context = xmlSecNssBlockCipherGetCtx( transform ) ; + if( context == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + "xmlSecNssBlockCipherGetCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + if( xmlSecNssBlockCipherFetchCtx( context , transform->id ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + "xmlSecNssBlockCipherFetchCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + context->symkey = NULL ; + context->cipherCtx = NULL ; + + return 0 ; +} + +/** + * xmlSecTransformFinalizeMethod: + * @transform: the pointer to transform object. + * + * The transform specific destroy method. + */ +static void +xmlSecNssBlockCipherFinalize( + xmlSecTransformPtr transform +) { + xmlSecNssBlockCipherCtxPtr context = NULL ; + + xmlSecAssert( xmlSecNssBlockCipherCheckId( transform ) ) ; + xmlSecAssert( xmlSecTransformCheckSize( transform, xmlSecNssBlockCipherSize ) ) ; + + context = xmlSecNssBlockCipherGetCtx( transform ) ; + if( context == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + "xmlSecNssBlockCipherGetCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return ; + } + + if( context->cipherCtx != NULL ) { + PK11_DestroyContext( context->cipherCtx, PR_TRUE ) ; + context->cipherCtx = NULL ; + } + + if( context->symkey != NULL ) { + PK11_FreeSymKey( context->symkey ) ; + context->symkey = NULL ; + } + + context->cipher = CKM_INVALID_MECHANISM ; + context->keyId = NULL ; +} + +/** + * xmlSecTransformSetKeyRequirementsMethod: + * @transform: the pointer to transform object. + * @keyReq: the pointer to key requirements structure. + * + * Transform specific method to set transform's key requirements. + * + * Returns 0 on success or a negative value otherwise. + */ +static int +xmlSecNssBlockCipherSetKeyReq( + xmlSecTransformPtr transform , + xmlSecKeyReqPtr keyReq +) { + xmlSecNssBlockCipherCtxPtr context = NULL ; + xmlSecSize cipherSize = 0 ; + + xmlSecAssert2( xmlSecNssBlockCipherCheckId( transform ), -1 ) ; + xmlSecAssert2( xmlSecTransformCheckSize( transform, xmlSecNssBlockCipherSize ), -1 ) ; + xmlSecAssert2( keyReq != NULL , -1 ) ; + xmlSecAssert2( ( transform->operation == xmlSecTransformOperationEncrypt ) || ( transform->operation == xmlSecTransformOperationDecrypt ), -1 ) ; + + context = xmlSecNssBlockCipherGetCtx( transform ) ; + if( context == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + "xmlSecNssBlockCipherGetCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + keyReq->keyId = context->keyId ; + keyReq->keyType = xmlSecKeyDataTypeSymmetric ; + + if( transform->operation == xmlSecTransformOperationEncrypt ) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt ; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt ; + } + + /* + if( context->symkey != NULL ) + cipherSize = PK11_GetKeyLength( context->symkey ) ; + + keyReq->keyBitsSize = cipherSize * 8 ; + */ + + return 0 ; +} + +/** + * xmlSecTransformSetKeyMethod: + * @transform: the pointer to transform object. + * @key: the pointer to key. + * + * The transform specific method to set the key for use. + * + * Returns 0 on success or a negative value otherwise. + */ +static int +xmlSecNssBlockCipherSetKey( + xmlSecTransformPtr transform , + xmlSecKeyPtr key +) { + xmlSecNssBlockCipherCtxPtr context = NULL ; + xmlSecKeyDataPtr keyData = NULL ; + PK11SymKey* symkey = NULL ; + CK_ATTRIBUTE_TYPE operation ; + int ivLen ; + + xmlSecAssert2( xmlSecNssBlockCipherCheckId( transform ), -1 ) ; + xmlSecAssert2( xmlSecTransformCheckSize( transform, xmlSecNssBlockCipherSize ), -1 ) ; + xmlSecAssert2( key != NULL , -1 ) ; + xmlSecAssert2( ( transform->operation == xmlSecTransformOperationEncrypt ) || ( transform->operation == xmlSecTransformOperationDecrypt ), -1 ) ; + + context = xmlSecNssBlockCipherGetCtx( transform ) ; + if( context == NULL || context->keyId == NULL || context->symkey != NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + "xmlSecNssBlockCipherGetCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + xmlSecAssert2( xmlSecKeyCheckId( key, context->keyId ), -1 ) ; + + keyData = xmlSecKeyGetValue( key ) ; + if( keyData == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecKeyGetName( key ) ) , + "xmlSecKeyGetValue" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + if( ( symkey = xmlSecNssSymKeyDataGetKey( keyData ) ) == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecKeyDataGetName( keyData ) ) , + "xmlSecNssSymKeyDataGetKey" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + context->symkey = symkey ; + + return 0 ; +} + static int xmlSecNssBlockCipherCtxInit(xmlSecNssBlockCipherCtxPtr ctx, xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt, const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) { - SECItem keyItem; SECItem ivItem; - PK11SlotInfo* slot; - PK11SymKey* symKey; + SECItem* secParam = NULL ; + xmlSecBufferPtr ivBuf = NULL ; int ivLen; - SECStatus rv; - int ret; xmlSecAssert2(ctx != NULL, -1); - xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ; + xmlSecAssert2( ctx->symkey != NULL , -1 ) ; xmlSecAssert2(ctx->cipherCtx == NULL, -1); - xmlSecAssert2(ctx->keyInitialized != 0, -1); - xmlSecAssert2(ctx->ctxInitialized == 0, -1); + xmlSecAssert2( ctx->keyId != NULL , -1 ) ; xmlSecAssert2(in != NULL, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(transformCtx != NULL, -1); ivLen = PK11_GetIVLength(ctx->cipher); - xmlSecAssert2(ivLen > 0, -1); - xmlSecAssert2((xmlSecSize)ivLen <= sizeof(ctx->iv), -1); + if( ivLen < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + NULL , + "PK11_GetIVLength" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + if( ( ivBuf = xmlSecBufferCreate( ivLen ) ) == NULL ) { + xmlSecError( XMLSEC_ERRORS_HERE , + NULL , + "xmlSecBufferCreate" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } if(encrypt) { - /* generate random iv */ - rv = PK11_GenerateRandom(ctx->iv, ivLen); - if(rv != SECSuccess) { + if( PK11_GenerateRandom( ivBuf->data , ivLen ) != SECSuccess ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "PK11_GenerateRandom", XMLSEC_ERRORS_R_CRYPTO_FAILED, - "size=%d", ivLen); + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferDestroy( ivBuf ) ; return(-1); } + if( xmlSecBufferSetSize( ivBuf , ivLen ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + NULL , + "xmlSecBufferSetSize" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + xmlSecBufferDestroy( ivBuf ) ; + return -1 ; + } - /* write iv to the output */ - ret = xmlSecBufferAppend(out, ctx->iv, ivLen); - if(ret < 0) { + if( xmlSecBufferAppend( out , ivBuf->data , ivLen ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferAppend", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", ivLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferDestroy( ivBuf ) ; return(-1); } } else { - /* if we don't have enough data, exit and hope that - * we'll have iv next time */ - if(xmlSecBufferGetSize(in) < (xmlSecSize)ivLen) { - return(0); - } - - /* copy iv to our buffer*/ - xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1); - memcpy(ctx->iv, xmlSecBufferGetData(in), ivLen); - - /* and remove from input */ - ret = xmlSecBufferRemoveHead(in, ivLen); - if(ret < 0) { + if( xmlSecBufferSetData( ivBuf , in->data , ivLen ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), - "xmlSecBufferRemoveHead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", ivLen); + "xmlSecBufferSetData", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferDestroy( ivBuf ) ; return(-1); } } - memset(&keyItem, 0, sizeof(keyItem)); - keyItem.data = ctx->key; - keyItem.len = ctx->keySize; - memset(&ivItem, 0, sizeof(ivItem)); - ivItem.data = ctx->iv; - ivItem.len = ctx->ivSize; - - slot = PK11_GetBestSlot(ctx->cipher, NULL); - if(slot == NULL) { + if( xmlSecBufferRemoveHead( in , ivLen ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), - "PK11_GetBestSlot", + "xmlSecBufferRemoveHead", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferDestroy( ivBuf ) ; return(-1); } - symKey = PK11_ImportSymKey(slot, ctx->cipher, PK11_OriginDerive, - CKA_SIGN, &keyItem, NULL); - if(symKey == NULL) { + ivItem.data = xmlSecBufferGetData( ivBuf ) ; + ivItem.len = xmlSecBufferGetSize( ivBuf ) ; + if( ( secParam = PK11_ParamFromIV( ctx->cipher , &ivItem ) ) == NULL ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), - "PK11_ImportSymKey", + "PK11_ParamFromIV", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); - PK11_FreeSlot(slot); + xmlSecBufferDestroy( ivBuf ) ; return(-1); } ctx->cipherCtx = PK11_CreateContextBySymKey(ctx->cipher, (encrypt) ? CKA_ENCRYPT : CKA_DECRYPT, - symKey, &ivItem); + ctx->symkey, secParam); if(ctx->cipherCtx == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), - "PK11_CreateContextBySymKey", + "xmlSecBufferRemoveHead", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); - PK11_FreeSymKey(symKey); - PK11_FreeSlot(slot); + SECITEM_FreeItem( secParam , PR_TRUE ) ; + xmlSecBufferDestroy( ivBuf ) ; return(-1); } - ctx->ctxInitialized = 1; - PK11_FreeSymKey(symKey); - PK11_FreeSlot(slot); + SECITEM_FreeItem( secParam , PR_TRUE ) ; + xmlSecBufferDestroy( ivBuf ) ; return(0); } +/** + * Block cipher transform update + */ static int xmlSecNssBlockCipherCtxUpdate(xmlSecNssBlockCipherCtxPtr ctx, xmlSecBufferPtr in, xmlSecBufferPtr out, @@ -192,54 +433,49 @@ const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) { xmlSecSize inSize, inBlocks, outSize; - int blockLen; + int blockSize; int outLen = 0; xmlSecByte* outBuf; - SECStatus rv; - int ret; xmlSecAssert2(ctx != NULL, -1); - xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ; + xmlSecAssert2( ctx->symkey != NULL , -1 ) ; xmlSecAssert2(ctx->cipherCtx != NULL, -1); - xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2( ctx->keyId != NULL , -1 ) ; xmlSecAssert2(in != NULL, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(transformCtx != NULL, -1); - blockLen = PK11_GetBlockSize(ctx->cipher, NULL); - xmlSecAssert2(blockLen > 0, -1); + if( ( blockSize = PK11_GetBlockSize( ctx->cipher , NULL ) ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( cipherName ) , + "PK11_GetBlockSize" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } inSize = xmlSecBufferGetSize(in); outSize = xmlSecBufferGetSize(out); - - if(inSize < (xmlSecSize)blockLen) { - return(0); + + inBlocks = ( encrypt != 0 ? inSize : ( inSize - 1 ) ) / blockSize ; + inSize = inBlocks * blockSize ; + + if( inSize < blockSize ) { + return 0 ; } - if(encrypt) { - inBlocks = inSize / ((xmlSecSize)blockLen); - } else { - /* we want to have the last block in the input buffer - * for padding check */ - inBlocks = (inSize - 1) / ((xmlSecSize)blockLen); - } - inSize = inBlocks * ((xmlSecSize)blockLen); - - /* we write out the input size plus may be one block */ - ret = xmlSecBufferSetMaxSize(out, outSize + inSize + blockLen); - if(ret < 0) { + if( xmlSecBufferSetMaxSize( out , outSize + inSize + blockSize ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferSetMaxSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize + inSize + blockLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outBuf = xmlSecBufferGetData(out) + outSize; - rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, inSize + blockLen, - xmlSecBufferGetData(in), inSize); - if(rv != SECSuccess) { + if(PK11_CipherOp( ctx->cipherCtx , outBuf , &outLen , inSize + blockSize , xmlSecBufferGetData( in ) , inSize ) != SECSuccess ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "PK11_CipherOp", @@ -247,27 +483,22 @@ XMLSEC_ERRORS_NO_MESSAGE); return(-1); } - xmlSecAssert2((xmlSecSize)outLen == inSize, -1); - /* set correct output buffer size */ - ret = xmlSecBufferSetSize(out, outSize + outLen); - if(ret < 0) { + if( xmlSecBufferSetSize( out , outSize + outLen ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferSetSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize + outLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } - /* remove the processed block from input */ - ret = xmlSecBufferRemoveHead(in, inSize); - if(ret < 0) { + if( xmlSecBufferRemoveHead( in , inSize ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferRemoveHead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", inSize); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } return(0); @@ -281,81 +512,82 @@ const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) { xmlSecSize inSize, outSize; - int blockLen, outLen = 0; + int blockSize, outLen = 0; xmlSecByte* inBuf; xmlSecByte* outBuf; - SECStatus rv; - int ret; xmlSecAssert2(ctx != NULL, -1); - xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2( ctx->cipher != CKM_INVALID_MECHANISM , -1 ) ; + xmlSecAssert2( ctx->symkey != NULL , -1 ) ; xmlSecAssert2(ctx->cipherCtx != NULL, -1); - xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2( ctx->keyId != NULL , -1 ) ; xmlSecAssert2(in != NULL, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(transformCtx != NULL, -1); - blockLen = PK11_GetBlockSize(ctx->cipher, NULL); - xmlSecAssert2(blockLen > 0, -1); + if( ( blockSize = PK11_GetBlockSize( ctx->cipher , NULL ) ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( cipherName ) , + "PK11_GetBlockSize" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } inSize = xmlSecBufferGetSize(in); outSize = xmlSecBufferGetSize(out); + /******************************************************************/ if(encrypt != 0) { - xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1); + xmlSecAssert2( inSize < blockSize, -1 ) ; /* create padding */ - ret = xmlSecBufferSetMaxSize(in, blockLen); - if(ret < 0) { + if( xmlSecBufferSetMaxSize( in , blockSize ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferSetMaxSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", blockLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } inBuf = xmlSecBufferGetData(in); - /* generate random padding */ - if((xmlSecSize)blockLen > (inSize + 1)) { - rv = PK11_GenerateRandom(inBuf + inSize, blockLen - inSize - 1); - if(rv != SECSuccess) { + /* generate random */ + if( blockSize > ( inSize + 1 ) ) { + if( PK11_GenerateRandom( inBuf + inSize, blockSize - inSize - 1 ) != SECSuccess ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "PK11_GenerateRandom", XMLSEC_ERRORS_R_CRYPTO_FAILED, - "size=%d", blockLen - inSize - 1); + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } - inBuf[blockLen - 1] = blockLen - inSize; - inSize = blockLen; + inBuf[blockSize-1] = blockSize - inSize ; + inSize = blockSize ; } else { - if(inSize != (xmlSecSize)blockLen) { + if( inSize != blockSize ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "data=%d;block=%d", inSize, blockLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } - /* process last block */ - ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen); - if(ret < 0) { + /* process the last block */ + if( xmlSecBufferSetMaxSize( out , outSize + inSize + blockSize ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "xmlSecBufferSetMaxSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize + 2 * blockLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } outBuf = xmlSecBufferGetData(out) + outSize; - rv = PK11_CipherOp(ctx->cipherCtx, outBuf, &outLen, 2 * blockLen, - xmlSecBufferGetData(in), inSize); - if(rv != SECSuccess) { + if( PK11_CipherOp( ctx->cipherCtx , outBuf , &outLen , inSize + blockSize , xmlSecBufferGetData( in ) , inSize ) != SECSuccess ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), "PK11_CipherOp", @@ -363,300 +595,169 @@ XMLSEC_ERRORS_NO_MESSAGE); return(-1); } - xmlSecAssert2((xmlSecSize)outLen == inSize, -1); if(encrypt == 0) { /* check padding */ - if(outLen < outBuf[blockLen - 1]) { + if( outLen < outBuf[blockSize-1] ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), NULL, - XMLSEC_ERRORS_R_INVALID_DATA, - "padding=%d;buffer=%d", - outBuf[blockLen - 1], outLen); + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); return(-1); } - outLen -= outBuf[blockLen - 1]; + outLen -= outBuf[blockSize-1] ; } - /* set correct output buffer size */ - ret = xmlSecBufferSetSize(out, outSize + outLen); - if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(cipherName), - "xmlSecBufferSetSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize + outLen); - return(-1); - } + /******************************************************************/ - /* remove the processed block from input */ - ret = xmlSecBufferRemoveHead(in, inSize); - if(ret < 0) { + /****************************************************************** + if( xmlSecBufferSetMaxSize( out , outSize + blockSize ) < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(cipherName), - "xmlSecBufferRemoveHead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", inSize); - return(-1); - } - - return(0); -} - - -/****************************************************************************** - * - * EVP Block Cipher transforms - * - * xmlSecNssBlockCipherCtx block is located after xmlSecTransform structure - * - *****************************************************************************/ -#define xmlSecNssBlockCipherSize \ - (sizeof(xmlSecTransform) + sizeof(xmlSecNssBlockCipherCtx)) -#define xmlSecNssBlockCipherGetCtx(transform) \ - ((xmlSecNssBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) - -static int xmlSecNssBlockCipherInitialize (xmlSecTransformPtr transform); -static void xmlSecNssBlockCipherFinalize (xmlSecTransformPtr transform); -static int xmlSecNssBlockCipherSetKeyReq (xmlSecTransformPtr transform, - xmlSecKeyReqPtr keyReq); -static int xmlSecNssBlockCipherSetKey (xmlSecTransformPtr transform, - xmlSecKeyPtr key); -static int xmlSecNssBlockCipherExecute (xmlSecTransformPtr transform, - int last, - xmlSecTransformCtxPtr transformCtx); -static int xmlSecNssBlockCipherCheckId (xmlSecTransformPtr transform); - - - -static int -xmlSecNssBlockCipherCheckId(xmlSecTransformPtr transform) { -#ifndef XMLSEC_NO_DES - if(xmlSecTransformCheckId(transform, xmlSecNssTransformDes3CbcId)) { - return(1); - } -#endif /* XMLSEC_NO_DES */ - -#ifndef XMLSEC_NO_AES - if(xmlSecTransformCheckId(transform, xmlSecNssTransformAes128CbcId) || - xmlSecTransformCheckId(transform, xmlSecNssTransformAes192CbcId) || - xmlSecTransformCheckId(transform, xmlSecNssTransformAes256CbcId)) { - - return(1); - } -#endif /* XMLSEC_NO_AES */ - - return(0); -} - -static int -xmlSecNssBlockCipherInitialize(xmlSecTransformPtr transform) { - xmlSecNssBlockCipherCtxPtr ctx; - - xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1); - xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1); - - ctx = xmlSecNssBlockCipherGetCtx(transform); - xmlSecAssert2(ctx != NULL, -1); - - memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx)); - -#ifndef XMLSEC_NO_DES - if(transform->id == xmlSecNssTransformDes3CbcId) { - ctx->cipher = CKM_DES3_CBC; - ctx->keyId = xmlSecNssKeyDataDesId; - ctx->keySize = 24; - } else -#endif /* XMLSEC_NO_DES */ - -#ifndef XMLSEC_NO_AES - if(transform->id == xmlSecNssTransformAes128CbcId) { - ctx->cipher = CKM_AES_CBC; - ctx->keyId = xmlSecNssKeyDataAesId; - ctx->keySize = 16; - } else if(transform->id == xmlSecNssTransformAes192CbcId) { - ctx->cipher = CKM_AES_CBC; - ctx->keyId = xmlSecNssKeyDataAesId; - ctx->keySize = 24; - } else if(transform->id == xmlSecNssTransformAes256CbcId) { - ctx->cipher = CKM_AES_CBC; - ctx->keyId = xmlSecNssKeyDataAesId; - ctx->keySize = 32; - } else -#endif /* XMLSEC_NO_AES */ - - if(1) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - NULL, - XMLSEC_ERRORS_R_INVALID_TRANSFORM, + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); - } - - return(0); -} - -static void -xmlSecNssBlockCipherFinalize(xmlSecTransformPtr transform) { - xmlSecNssBlockCipherCtxPtr ctx; - - xmlSecAssert(xmlSecNssBlockCipherCheckId(transform)); - xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize)); - - ctx = xmlSecNssBlockCipherGetCtx(transform); - xmlSecAssert(ctx != NULL); - - if(ctx->cipherCtx != NULL) { - PK11_DestroyContext(ctx->cipherCtx, PR_TRUE); } - - memset(ctx, 0, sizeof(xmlSecNssBlockCipherCtx)); -} -static int -xmlSecNssBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { - xmlSecNssBlockCipherCtxPtr ctx; - - xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1); - xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); - xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1); - xmlSecAssert2(keyReq != NULL, -1); - - ctx = xmlSecNssBlockCipherGetCtx(transform); - xmlSecAssert2(ctx != NULL, -1); - xmlSecAssert2(ctx->keyId != NULL, -1); + outBuf = xmlSecBufferGetData( out ) + outSize ; + if( PK11_DigestFinal( ctx->cipherCtx , outBuf , &outLen , blockSize ) != SECSuccess ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( cipherName ) , + "PK11_DigestFinal" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + ******************************************************************/ + + if( xmlSecBufferSetSize( out , outSize + outLen ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( cipherName ) , + "xmlSecBufferSetSize" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + + if( xmlSecBufferRemoveHead( in , inSize ) < 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( cipherName ) , + "xmlSecBufferRemoveHead" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; + return -1 ; + } + +/* PK11_Finalize( ctx->cipherCtx ) ;*/ + PK11_DestroyContext(ctx->cipherCtx, PR_TRUE); + ctx->cipherCtx = NULL ; - keyReq->keyId = ctx->keyId; - keyReq->keyType = xmlSecKeyDataTypeSymmetric; - if(transform->operation == xmlSecTransformOperationEncrypt) { - keyReq->keyUsage = xmlSecKeyUsageEncrypt; - } else { - keyReq->keyUsage = xmlSecKeyUsageDecrypt; - } - keyReq->keyBitsSize = 8 * ctx->keySize; return(0); } -static int -xmlSecNssBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { - xmlSecNssBlockCipherCtxPtr ctx; - xmlSecBufferPtr buffer; +/** + * xmlSecTransformExecuteMethod: + * @transform: the pointer to transform object. + * @last: the flag: if set to 1 then it's the last data chunk. + * @transformCtx: the pointer to transform context object. + * + * Transform specific method to process a chunk of data. + * + * Returns 0 on success or a negative value otherwise. + */ +xmlSecNssBlockCipherExecute( + xmlSecTransformPtr transform , + int last , + xmlSecTransformCtxPtr transformCtx +) { + xmlSecNssBlockCipherCtxPtr context = NULL ; + xmlSecBufferPtr inBuf = NULL ; + xmlSecBufferPtr outBuf = NULL ; + const xmlChar* cipherName ; + int operation ; + int rtv ; xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1); - xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1); - xmlSecAssert2(key != NULL, -1); - - ctx = xmlSecNssBlockCipherGetCtx(transform); - xmlSecAssert2(ctx != NULL, -1); - xmlSecAssert2(ctx->cipher != 0, -1); - xmlSecAssert2(ctx->keyInitialized == 0, -1); - xmlSecAssert2(ctx->keyId != NULL, -1); - xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); - - xmlSecAssert2(ctx->keySize > 0, -1); - xmlSecAssert2(ctx->keySize <= sizeof(ctx->key), -1); - buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); - xmlSecAssert2(buffer != NULL, -1); + xmlSecAssert2( ( transform->operation == xmlSecTransformOperationEncrypt ) || ( transform->operation == xmlSecTransformOperationDecrypt ), -1 ) ; + xmlSecAssert2( transformCtx != NULL , -1 ) ; - if(xmlSecBufferGetSize(buffer) < ctx->keySize) { + context = xmlSecNssBlockCipherGetCtx( transform ) ; + if( context == NULL ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - NULL, - XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, - "keySize=%d;expected=%d", - xmlSecBufferGetSize(buffer), ctx->keySize); - return(-1); + "xmlSecNssBlockCipherGetCtx" , + XMLSEC_ERRORS_R_CRYPTO_FAILED , + XMLSEC_ERRORS_NO_MESSAGE ) ; } - - xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1); - memcpy(ctx->key, xmlSecBufferGetData(buffer), ctx->keySize); - - ctx->keyInitialized = 1; - return(0); -} - -static int -xmlSecNssBlockCipherExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { - xmlSecNssBlockCipherCtxPtr ctx; - xmlSecBufferPtr in, out; - int ret; - - xmlSecAssert2(xmlSecNssBlockCipherCheckId(transform), -1); - xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1); - xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssBlockCipherSize), -1); - xmlSecAssert2(transformCtx != NULL, -1); - in = &(transform->inBuf); - out = &(transform->outBuf); - - ctx = xmlSecNssBlockCipherGetCtx(transform); - xmlSecAssert2(ctx != NULL, -1); + inBuf = &( transform->inBuf ) ; + outBuf = &( transform->outBuf ) ; if(transform->status == xmlSecTransformStatusNone) { transform->status = xmlSecTransformStatusWorking; } + operation = ( transform->operation == xmlSecTransformOperationEncrypt ) ? 1 : 0 ; + cipherName = xmlSecTransformGetName( transform ) ; + if(transform->status == xmlSecTransformStatusWorking) { - if(ctx->ctxInitialized == 0) { - ret = xmlSecNssBlockCipherCtxInit(ctx, in, out, - (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, - xmlSecTransformGetName(transform), transformCtx); - if(ret < 0) { + if( context->cipherCtx == NULL ) { + rtv = xmlSecNssBlockCipherCtxInit( context, inBuf , outBuf , operation , cipherName , transformCtx ) ; + if( rtv < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecNssBlockCipherCtxInit", - XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_R_INVALID_STATUS, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } - if((ctx->ctxInitialized == 0) && (last != 0)) { + if( context->cipherCtx == NULL && last != 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), NULL, - XMLSEC_ERRORS_R_INVALID_DATA, + XMLSEC_ERRORS_R_INVALID_STATUS, "not enough data to initialize transform"); return(-1); } - if(ctx->ctxInitialized != 0) { - ret = xmlSecNssBlockCipherCtxUpdate(ctx, in, out, - (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, - xmlSecTransformGetName(transform), transformCtx); - if(ret < 0) { + if( context->cipherCtx != NULL ) { + rtv = xmlSecNssBlockCipherCtxUpdate( context, inBuf , outBuf , operation , cipherName , transformCtx ) ; + if( rtv < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecNssBlockCipherCtxUpdate", - XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_R_INVALID_STATUS, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } if(last) { - ret = xmlSecNssBlockCipherCtxFinal(ctx, in, out, - (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, - xmlSecTransformGetName(transform), transformCtx); - if(ret < 0) { + rtv = xmlSecNssBlockCipherCtxFinal( context, inBuf , outBuf , operation , cipherName , transformCtx ) ; + if( rtv < 0 ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecNssBlockCipherCtxFinal", - XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_R_INVALID_STATUS, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } transform->status = xmlSecTransformStatusFinished; } } else if(transform->status == xmlSecTransformStatusFinished) { - /* the only way we can get here is if there is no input */ - xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1); - } else if(transform->status == xmlSecTransformStatusNone) { - /* the only way we can get here is if there is no enough data in the input */ - xmlSecAssert2(last == 0, -1); + if( xmlSecBufferGetSize( inBuf ) != 0 ) { + xmlSecError( XMLSEC_ERRORS_HERE , + xmlSecErrorsSafeString( xmlSecTransformGetName( transform ) ) , + NULL , + XMLSEC_ERRORS_R_INVALID_STATUS , + "status=%d", transform->status ) ; + return -1 ; + } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),