diff -r 000000000000 -r e35f40988205 xmlsecurityengine/xmlseccrypto/src/xmlsecc_digests.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xmlsecurityengine/xmlseccrypto/src/xmlsecc_digests.cpp Thu Dec 17 09:29:21 2009 +0200 @@ -0,0 +1,337 @@ +/** + * 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 +#include "xmlsecc_config.h" +#include "xmlsec_xmlsec.h" +#include "xmlsec_keys.h" +#include "xmlsec_transforms.h" +#include "xmlsec_errors.h" +#include "xmlsec_error_flag.h" + +#include "xmlsecc_app.h" +#include "xmlsecc_crypto.h" +#include "xmlsecc_cryptowrapper.h" // replace gnutils/gnutls.h + +//#define XMLSEC_SYMBIAN_MAX_DIGEST_SIZE 32 + +/************************************************************************** + * + * Internal SymbianCrypto Digest CTX + * + *****************************************************************************/ +typedef struct _xmlSecSymbianCryptoDigestCtx + xmlSecSymbianCryptoDigestCtx, *xmlSecSymbianCryptoDigestCtxPtr; +struct _xmlSecSymbianCryptoDigestCtx { + int digest; + ScMDHd digestCtx; + xmlSecByte dgst[XMLSEC_SYMBIAN_MAX_DIGEST_SIZE]; + xmlSecSize dgstSize; /* dgst size in bytes */ +}; + +xmlSecTransformGetDataTypeMethod const xmlSecCrpytoGetDataTypeMethod = xmlSecTransformDefaultGetDataType; +xmlSecTransformPushBinMethod const xmlSecCryptoPushBinMethod = xmlSecTransformDefaultPushBin; +xmlSecTransformPopBinMethod const xmlSecCryptoPopBinMethod = xmlSecTransformDefaultPopBin; + +/****************************************************************************** + * + * Digest transforms + * + * xmlSecSymbianCryptoDigestCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecSymbianCryptoDigestSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecSymbianCryptoDigestCtx)) +#define xmlSecSymbianCryptoDigestGetCtx(transform) \ + ((xmlSecSymbianCryptoDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecSymbianCryptoDigestInitialize (xmlSecTransformPtr transform); +static void xmlSecSymbianCryptoDigestFinalize (xmlSecTransformPtr transform); +static int xmlSecSymbianCryptoDigestVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecSymbianCryptoDigestExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecSymbianCryptoDigestCheckId (xmlSecTransformPtr transform); + +static int +xmlSecSymbianCryptoDigestCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) { + return(1); + } +#endif /* XMLSEC_NO_SHA1 */ + + return(0); +} + +static int +xmlSecSymbianCryptoDigestInitialize(xmlSecTransformPtr transform) { + xmlSecSymbianCryptoDigestCtxPtr ctx; +#ifndef XMLSEC_GNUTLS_OLD + TInt ret; +#endif /* XMLSEC_GNUTLS_OLD */ + + xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); + + ctx = xmlSecSymbianCryptoDigestGetCtx(transform); + xmlSecAssert2(ctx, -1); + + /* initialize context */ + memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx)); + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) { + ctx->digest = SC_MD_SHA1; + } else +#endif /* XMLSEC_NO_SHA1 */ + + 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_md_open(&ctx->digestCtx, ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */ + if(ret != KErrNone) { +#else /* XMLSEC_GNUTLS_OLD */ + ctx->digestCtx = sc_md_open(ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */ + if(!ctx->digestCtx) { +#endif /* XMLSEC_GNUTLS_OLD */ + if ( ret != KErrNone ) + { + xmlSecSetErrorFlag( ret ); + } + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "sc_md_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); +} + +static void +xmlSecSymbianCryptoDigestFinalize(xmlSecTransformPtr transform) { + xmlSecSymbianCryptoDigestCtxPtr ctx; + + xmlSecAssert(xmlSecSymbianCryptoDigestCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize)); + + ctx = xmlSecSymbianCryptoDigestGetCtx(transform); + xmlSecAssert(ctx); + + if(ctx->digestCtx) { + sc_md_close(ctx->digestCtx); + } + memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx)); +} + +static int +xmlSecSymbianCryptoDigestVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSymbianCryptoDigestCtxPtr ctx; + + xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data, -1); + xmlSecAssert2(transformCtx, -1); + + ctx = xmlSecSymbianCryptoDigestGetCtx(transform); + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->dgstSize > 0, -1); + + if(dataSize != ctx->dgstSize) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data and digest sizes are different (data=%d, dgst=%d)", + dataSize, ctx->dgstSize); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + if(memcmp(ctx->dgst, data, dataSize) != 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + NULL, + XMLSEC_ERRORS_R_INVALID_DATA, + "data and digest do not match"); + transform->status = xmlSecTransformStatusFail; + return(0); + } + + transform->status = xmlSecTransformStatusOk; + return(0); +} + +static int +xmlSecSymbianCryptoDigestExecute(xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx) { + xmlSecSymbianCryptoDigestCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) + || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(transformCtx, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); + + ctx = xmlSecSymbianCryptoDigestGetCtx(transform); + xmlSecAssert2(ctx, -1); + xmlSecAssert2(ctx->digest != SC_MD_NONE, -1); + xmlSecAssert2(ctx->digestCtx, -1); + + in = &(transform->inBuf); + out = &(transform->outBuf); + + if(transform->status == xmlSecTransformStatusNone) { + transform->status = xmlSecTransformStatusWorking; + } + + if(transform->status == xmlSecTransformStatusWorking) { + xmlSecSize inSize; + + inSize = xmlSecBufferGetSize(in); + if(inSize > 0) { + sc_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize); + + ret = xmlSecBufferRemoveHead(in, inSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferRemoveHead", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", inSize); + return(-1); + } + } + if(last) { + const xmlSecByte* buf; + + /* get the final digest */ + sc_md_final(ctx->digestCtx); + + /* get length before sc_md_read */ + ctx->dgstSize = sc_md_get_algo_dlen(ctx->digestCtx); + xmlSecAssert2(ctx->dgstSize > 0, -1); + xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1); + + buf = sc_md_read(ctx->digestCtx, ctx->digest); + if(!buf) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "sc_md_read", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy it to our internal buffer */ + memcpy(ctx->dgst, buf, ctx->dgstSize); + + /* and to the output if needed */ + if(transform->operation == xmlSecTransformOperationSign) { + ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize); + if(ret < 0) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "xmlSecBufferAppend", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", ctx->dgstSize); + 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(&(transform->inBuf)) == 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_SHA1 +/****************************************************************************** + * + * SHA1 Digest transforms + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecSymbianCryptoSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecSymbianCryptoDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha1, /* const xmlChar* name; */ + xmlSecHrefSha1, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecSymbianCryptoDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecSymbianCryptoDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecSymbianCryptoDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecSymbianCryptoDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecSymbianCryptoTransformSha1GetKlass: + * + * SHA-1 digest transform klass. + * + * Returns pointer to SHA-1 digest transform klass. + */ +EXPORT_C +xmlSecTransformId +xmlSecSymbianCryptoTransformSha1GetKlass(void) { + return(&xmlSecSymbianCryptoSha1Klass); +} +#endif /* XMLSEC_NO_SHA1 */ + + + +