diff -r 000000000000 -r e35f40988205 xmlsecurityengine/xmlseccrypto/src/xmlsecc_ciphers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xmlsecurityengine/xmlseccrypto/src/xmlsecc_ciphers.cpp Thu Dec 17 09:29:21 2009 +0200 @@ -0,0 +1,865 @@ +/** + * XMLSec library + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2003 Aleksey Sanin + * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. + */ +#include "xmlsecc_globals.h" + +#include +#include "xmlsecc_config.h" +#include "xmlsec_xmlsec.h" +#include "xmlsec_keys.h" +#include "xmlsec_transforms.h" +#include "xmlsec_errors.h" + +#include "xmlsecc_crypto.h" +#include "xmlsecc_cryptowrapper.h" // replace gnutils/gnutls.h + +/************************************************************************** + * + * Internal SymbianCrypto Block cipher CTX + * + *****************************************************************************/ +xmlSecTransformGetDataTypeMethod const xmlSecCrpytoGetDataTypeMethod = xmlSecTransformDefaultGetDataType; +xmlSecTransformPushBinMethod const xmlSecCryptoPushBinMethod = xmlSecTransformDefaultPushBin; +xmlSecTransformPopBinMethod const xmlSecCryptoPopBinMethod = xmlSecTransformDefaultPopBin; + +typedef struct _xmlSecSymbianCryptoBlockCipherCtx xmlSecSymbianCryptoBlockCipherCtx, + *xmlSecSymbianCryptoBlockCipherCtxPtr; +struct _xmlSecSymbianCryptoBlockCipherCtx { + int cipher; + int mode; + ScCipherHd cipherCtx; + //sc_cipher_hd_t cipherCtx; + xmlSecKeyDataId keyId; + int keyInitialized; + int ctxInitialized; +}; + +static int xmlSecSymbianCryptoBlockCipherCtxInit (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecSymbianCryptoBlockCipherCtxUpdate (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecSymbianCryptoBlockCipherCtxFinal (xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx); +static int +xmlSecSymbianCryptoBlockCipherCtxInit(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + int blockLen; + int ret; + + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx, -1); + xmlSecAssert2(ctx->keyInitialized != 0, -1); + xmlSecAssert2(ctx->ctxInitialized == 0, -1); + xmlSecAssert2(in, -1); + xmlSecAssert2(out, -1); + xmlSecAssert2(transformCtx, -1); + + /* iv len == block len */ + blockLen = sc_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + set_ctx_blocksize(ctx->cipherCtx, blockLen); //set blocksize + + if(encrypt) { + xmlSecByte* iv; + xmlSecSize outSize; + + /* allocate space for IV */ + outSize = xmlSecBufferGetSize(out); + ret = xmlSecBufferSetSize(out, outSize + blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + blockLen); + return(-1); + } + iv = xmlSecBufferGetData(out) + outSize; + + /* generate and use random iv */ + ret = sc_randomize(iv, blockLen, SC_STRONG_RANDOM); + if( ret != 0 ) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_randomize", + XMLSEC_ERRORS_R_MALLOC_FAILED, + "ret=%d", ret); + return( -1 ); + } + ret = sc_cipher_setiv(ctx->cipherCtx, iv, blockLen); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + } else { + /* if we don't have enough data, exit and hope that + * we'll have iv next time */ + if(xmlSecBufferGetSize(in) < (xmlSecSize)blockLen) { + return(0); + } + xmlSecAssert2(xmlSecBufferGetData(in), -1); + + /* set iv */ + ret = sc_cipher_setiv(ctx->cipherCtx, xmlSecBufferGetData(in), blockLen); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_setiv", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + + /* and remove from input */ + ret = xmlSecBufferRemoveHead(in, blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", blockLen); + return(-1); + } + } + + ctx->ctxInitialized = 1; + return(0); +} + +static int +xmlSecSymbianCryptoBlockCipherCtxUpdate(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSize inSize, inBlocks, outSize; + int blockLen; + xmlSecByte* outBuf; + int ret; + + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(in, -1); + xmlSecAssert2(out, -1); + xmlSecAssert2(transformCtx, -1); + + blockLen = sc_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + if(inSize < (xmlSecSize)blockLen) { + 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + inSize + blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + if(encrypt) { + ret = sc_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize, NOTLAST); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + } else { + ret = sc_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize, NULL, NOTLAST); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + } + + /* set correct output buffer size */ + ret = xmlSecBufferSetSize(out, outSize + inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + inSize); + return(-1); + } + + /* remove the processed block from input */ + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + return(0); +} + +static int +xmlSecSymbianCryptoBlockCipherCtxFinal(xmlSecSymbianCryptoBlockCipherCtxPtr ctx, + xmlSecBufferPtr in, + xmlSecBufferPtr out, + int encrypt, + const xmlChar* cipherName, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSize inSize, outSize; + int blockLen, outLen = 0; + xmlSecByte* inBuf; + xmlSecByte* outBuf; + int ret; + + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->cipherCtx, -1); + xmlSecAssert2(ctx->ctxInitialized != 0, -1); + xmlSecAssert2(in, -1); + xmlSecAssert2(out, -1); + xmlSecAssert2(transformCtx, -1); + + blockLen = sc_cipher_get_algo_blklen(ctx->cipher); + xmlSecAssert2(blockLen > 0, -1); + + inSize = xmlSecBufferGetSize(in); + outSize = xmlSecBufferGetSize(out); + + if(encrypt != 0) { + xmlSecAssert2(inSize < (xmlSecSize)blockLen, -1); + + /* create padding */ + ret = xmlSecBufferSetMaxSize(in, blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", blockLen); + return(-1); + } + inBuf = xmlSecBufferGetData(in); + + } else { + if(inSize != (xmlSecSize)blockLen) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data=%d;block=%d", inSize, blockLen); + return(-1); + } + } + + /* process last block */ + ret = xmlSecBufferSetMaxSize(out, outSize + 2 * blockLen); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferSetMaxSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", outSize + 2 * blockLen); + return(-1); + } + outBuf = xmlSecBufferGetData(out) + outSize; + + if(encrypt) { + ret = sc_cipher_encrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize, ISLAST); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_encrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + + if((xmlSecSize)blockLen >= (inSize + 1)) + { + // Symbian should have done the padding, + //we should re-align inSize so that higher layer won't break + inSize = blockLen; + } + + } else { + ret = sc_cipher_decrypt(ctx->cipherCtx, outBuf, inSize + blockLen, + xmlSecBufferGetData(in), inSize, &outLen, ISLAST); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "sc_cipher_decrypt", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + } + + if(encrypt == 0) { + /* check padding */ + if(inSize < outBuf[blockLen - 1]) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "padding=%d;buffer=%d", + outBuf[blockLen - 1], inSize); + return(-1); + } + // outLen is explicitely written and returned from sc_cipher_decrypt() + // outLen = inSize - outBuf[blockLen - 1]; + } else { + outLen = inSize; + } + + /* 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) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(cipherName), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + + + return(0); +} + + +/****************************************************************************** + * + * Block Cipher transforms + * + * xmlSecSymbianCryptoBlockCipherCtx block is located after xmlSecTransform structure + * + *****************************************************************************/ +#define xmlSecSymbianCryptoBlockCipherSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecSymbianCryptoBlockCipherCtx)) +#define xmlSecSymbianCryptoBlockCipherGetCtx(transform) \ + ((xmlSecSymbianCryptoBlockCipherCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecSymbianCryptoBlockCipherInitialize (xmlSecTransformPtr transform); +static void xmlSecSymbianCryptoBlockCipherFinalize (xmlSecTransformPtr transform); +static int xmlSecSymbianCryptoBlockCipherSetKeyReq (xmlSecTransformPtr transform, + xmlSecKeyReqPtr keyReq); +static int xmlSecSymbianCryptoBlockCipherSetKey (xmlSecTransformPtr transform, + xmlSecKeyPtr key); +static int xmlSecSymbianCryptoBlockCipherExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecSymbianCryptoBlockCipherCheckId (xmlSecTransformPtr transform); + + + +static int +xmlSecSymbianCryptoBlockCipherCheckId(xmlSecTransformPtr transform) { +#ifndef XMLSEC_NO_DES + if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformDes3CbcId)) { + return(1); + } +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes128CbcId) || + xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes192CbcId) || + xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformAes256CbcId)) { + + return(1); + } +#endif /* XMLSEC_NO_AES */ + + return(0); +} + +static int +xmlSecSymbianCryptoBlockCipherInitialize(xmlSecTransformPtr transform) { + xmlSecSymbianCryptoBlockCipherCtxPtr ctx; +#ifndef XMLSEC_GNUTLS_OLD + //gpg_err_code_t ret; + //sc_error_t ret; + int ret; +#endif /* XMLSEC_GNUTLS_OLD */ + + xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); + + ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); + xmlSecAssert2(ctx, -1); + + memset(ctx, 0, sizeof(xmlSecSymbianCryptoBlockCipherCtx)); + +#ifndef XMLSEC_NO_DES + if(transform->id == xmlSecSymbianCryptoTransformDes3CbcId) { + ctx->cipher = SC_CIPHER_3DES; + ctx->mode = SC_CIPHER_MODE_CBC; + ctx->keyId = xmlSecSymbianCryptoKeyDataDesId; + } else +#endif /* XMLSEC_NO_DES */ + +#ifndef XMLSEC_NO_AES + if(transform->id == xmlSecSymbianCryptoTransformAes128CbcId) { + ctx->cipher = SC_CIPHER_AES128; + ctx->mode = SC_CIPHER_MODE_CBC; + ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; + } else if(transform->id == xmlSecSymbianCryptoTransformAes192CbcId) { + ctx->cipher = SC_CIPHER_AES192; + ctx->mode = SC_CIPHER_MODE_CBC; + ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; + } else if(transform->id == xmlSecSymbianCryptoTransformAes256CbcId) { + ctx->cipher = SC_CIPHER_AES256; + ctx->mode = SC_CIPHER_MODE_CBC; + ctx->keyId = xmlSecSymbianCryptoKeyDataAesId; + } else +#endif /* XMLSEC_NO_AES */ + + if(1) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_TRANSFORM, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + +#ifndef XMLSEC_GNUTLS_OLD + ret = sc_cipher_open(&ctx->cipherCtx, ctx->cipher, ctx->mode, SC_CIPHER_SECURE); /* we are paranoid */ + if(ret != 0/*GPG_ERR_NO_ERROR*/) { +#else /* XMLSEC_GNUTLS_OLD */ + ctx->cipherCtx = sc_cipher_open(ctx->cipher, ctx->mode, SC_CIPHER_SECURE); /* we are paranoid */ + if(!ctx->cipherCtx) { +#endif /* XMLSEC_GNUTLS_OLD */ + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "sc_cipher_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +static void +xmlSecSymbianCryptoBlockCipherFinalize(xmlSecTransformPtr transform) { + xmlSecSymbianCryptoBlockCipherCtxPtr ctx; + + xmlSecAssert(xmlSecSymbianCryptoBlockCipherCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize)); + + ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); + xmlSecAssert(ctx); + + if(ctx->cipherCtx) { + sc_cipher_close(ctx->cipherCtx); + } + + memset(ctx, 0, sizeof(xmlSecSymbianCryptoBlockCipherCtx)); +} + +static int +xmlSecSymbianCryptoBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) { + xmlSecSymbianCryptoBlockCipherCtxPtr ctx; + + xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) + || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); + xmlSecAssert2(keyReq, -1); + + ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->keyId, -1); + + keyReq->keyId = ctx->keyId; + keyReq->keyType = xmlSecKeyDataTypeSymmetric; + if(transform->operation == xmlSecTransformOperationEncrypt) { + keyReq->keyUsage = xmlSecKeyUsageEncrypt; + } else { + keyReq->keyUsage = xmlSecKeyUsageDecrypt; + } + + keyReq->keyBitsSize = 8 * sc_cipher_get_algo_keylen(ctx->cipher); + return(0); +} + +static int +xmlSecSymbianCryptoBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) { + xmlSecSymbianCryptoBlockCipherCtxPtr ctx; + xmlSecBufferPtr buffer; + xmlSecSize keySize; + int ret; + + xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) + || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); + xmlSecAssert2(key, -1); + + ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->cipherCtx, -1); + xmlSecAssert2(ctx->cipher != 0, -1); + xmlSecAssert2(ctx->keyInitialized == 0, -1); + xmlSecAssert2(ctx->keyId, -1); + xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1); + + keySize = sc_cipher_get_algo_keylen(ctx->cipher); + xmlSecAssert2(keySize > 0, -1); + + buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key)); + xmlSecAssert2(buffer, -1); + + if(xmlSecBufferGetSize(buffer) < keySize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, + "keySize=%d;expected=%d", + xmlSecBufferGetSize(buffer), keySize); + return(-1); + } + + xmlSecAssert2(xmlSecBufferGetData(buffer), -1); + ret = sc_cipher_setkey(ctx->cipherCtx, xmlSecBufferGetData(buffer), keySize); + if(ret != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "sc_cipher_setkey", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + "ret=%d", ret); + return(-1); + } + + ctx->keyInitialized = 1; + return(0); +} + +static int +xmlSecSymbianCryptoBlockCipherExecute(xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSymbianCryptoBlockCipherCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecSymbianCryptoBlockCipherCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) + || (transform->operation == xmlSecTransformOperationDecrypt), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoBlockCipherSize), -1); + xmlSecAssert2(transformCtx, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + ctx = xmlSecSymbianCryptoBlockCipherGetCtx(transform); + xmlSecAssert2(ctx, -1); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + if(ctx->ctxInitialized == 0) { + ret = xmlSecSymbianCryptoBlockCipherCtxInit(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecSymbianCryptoBlockCipherCtxInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + if((ctx->ctxInitialized == 0) && (last != 0)) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "not enough data to initialize transform"); + return(-1); + } + if(ctx->ctxInitialized != 0) { + ret = xmlSecSymbianCryptoBlockCipherCtxUpdate(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecSymbianCryptoBlockCipherCtxUpdate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } + + if(last) { + ret = xmlSecSymbianCryptoBlockCipherCtxFinal(ctx, in, out, + (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0, + xmlSecTransformGetName(transform), transformCtx); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecSymbianCryptoBlockCipherCtxFinal", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + 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); + } else { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_STATUS, + "status=%d", transform->status); + return(-1); + } + + return(0); +} + + +#ifndef XMLSEC_NO_AES +/********************************************************************* + * + * AES CBC cipher transforms + * + ********************************************************************/ +static xmlSecTransformKlass xmlSecSymbianCryptoAes128CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes128Cbc, /* const xmlChar* name; */ + xmlSecHrefAes128Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecSymbianCryptoTransformAes128CbcGetKlass: + * + * AES 128 CBC encryption transform klass. + * + * Returns pointer to AES 128 CBC encryption transform. + */ +EXPORT_C +xmlSecTransformId +xmlSecSymbianCryptoTransformAes128CbcGetKlass(void) { + return(&xmlSecSymbianCryptoAes128CbcKlass); +} + +static xmlSecTransformKlass xmlSecSymbianCryptoAes192CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes192Cbc, /* const xmlChar* name; */ + xmlSecHrefAes192Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecSymbianCryptoTransformAes192CbcGetKlass: + * + * AES 192 CBC encryption transform klass. + * + * Returns pointer to AES 192 CBC encryption transform. + */ +EXPORT_C +xmlSecTransformId +xmlSecSymbianCryptoTransformAes192CbcGetKlass(void) { + return(&xmlSecSymbianCryptoAes192CbcKlass); +} + +static xmlSecTransformKlass xmlSecSymbianCryptoAes256CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameAes256Cbc, /* const xmlChar* name; */ + xmlSecHrefAes256Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecSymbianCryptoTransformAes256CbcGetKlass: + * + * AES 256 CBC encryption transform klass. + * + * Returns pointer to AES 256 CBC encryption transform. + */ +EXPORT_C +xmlSecTransformId +xmlSecSymbianCryptoTransformAes256CbcGetKlass(void) { + return(&xmlSecSymbianCryptoAes256CbcKlass); +} + +#endif /* XMLSEC_NO_AES */ + +#ifndef XMLSEC_NO_DES +static xmlSecTransformKlass xmlSecSymbianCryptoDes3CbcKlass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecSymbianCryptoBlockCipherSize, /* xmlSecSize objSize */ + + xmlSecNameDes3Cbc, /* const xmlChar* name; */ + xmlSecHrefDes3Cbc, /* const xmlChar* href; */ + xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */ + + xmlSecSymbianCryptoBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecSymbianCryptoBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecSymbianCryptoBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */ + xmlSecSymbianCryptoBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + NULL, /* xmlSecTransformValidateMethod validate; */ + xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecSymbianCryptoBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecSymbianCryptoTransformDes3CbcGetKlass: + * + * Triple DES CBC encryption transform klass. + * + * Returns pointer to Triple DES encryption transform. + */ +EXPORT_C +xmlSecTransformId +xmlSecSymbianCryptoTransformDes3CbcGetKlass(void) { + return(&xmlSecSymbianCryptoDes3CbcKlass); +} +#endif /* XMLSEC_NO_DES */ + +