diff options
Diffstat (limited to 'src/gnutls/digests.c')
-rw-r--r-- | src/gnutls/digests.c | 346 |
1 files changed, 276 insertions, 70 deletions
diff --git a/src/gnutls/digests.c b/src/gnutls/digests.c index 2df20706..fb8109de 100644 --- a/src/gnutls/digests.c +++ b/src/gnutls/digests.c @@ -1,15 +1,18 @@ -/** +/** * XMLSec library * * This is free software; see Copyright file in the source * distribution for preciese wording. - * + * * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> */ #include "globals.h" #include <string.h> +#include <gnutls/gnutls.h> +#include <gcrypt.h> + #include <xmlsec/xmlsec.h> #include <xmlsec/keys.h> #include <xmlsec/transforms.h> @@ -18,95 +21,298 @@ #include <xmlsec/gnutls/app.h> #include <xmlsec/gnutls/crypto.h> +#define XMLSEC_GNUTLS_MAX_DIGEST_SIZE 32 + /************************************************************************** * - * We use xmlsec-gcrypt for all the basic crypto ops + * Internal GNUTLS Digest CTX * *****************************************************************************/ -#include <xmlsec/gcrypt/crypto.h> +typedef struct _xmlSecGnuTLSDigestCtx xmlSecGnuTLSDigestCtx, *xmlSecGnuTLSDigestCtxPtr; +struct _xmlSecGnuTLSDigestCtx { + int digest; + GcryMDHd digestCtx; + xmlSecByte dgst[XMLSEC_GNUTLS_MAX_DIGEST_SIZE]; + xmlSecSize dgstSize; /* dgst size in bytes */ +}; -#ifndef XMLSEC_NO_SHA1 -/** - * xmlSecGnuTLSTransformSha1GetKlass: +/****************************************************************************** * - * SHA-1 digest transform klass. + * Digest transforms * - * Returns: pointer to SHA-1 digest transform klass. - */ -xmlSecTransformId -xmlSecGnuTLSTransformSha1GetKlass(void) { - return (xmlSecGCryptTransformSha1GetKlass()); + * xmlSecGnuTLSDigestCtx is located after xmlSecTransform + * + *****************************************************************************/ +#define xmlSecGnuTLSDigestSize \ + (sizeof(xmlSecTransform) + sizeof(xmlSecGnuTLSDigestCtx)) +#define xmlSecGnuTLSDigestGetCtx(transform) \ + ((xmlSecGnuTLSDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) + +static int xmlSecGnuTLSDigestInitialize (xmlSecTransformPtr transform); +static void xmlSecGnuTLSDigestFinalize (xmlSecTransformPtr transform); +static int xmlSecGnuTLSDigestVerify (xmlSecTransformPtr transform, + const xmlSecByte* data, + xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGnuTLSDigestExecute (xmlSecTransformPtr transform, + int last, + xmlSecTransformCtxPtr transformCtx); +static int xmlSecGnuTLSDigestCheckId (xmlSecTransformPtr transform); + +static int +xmlSecGnuTLSDigestCheckId(xmlSecTransformPtr transform) { + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformSha1Id)) { + return(1); + } +#endif /* XMLSEC_NO_SHA1 */ + + return(0); } -#endif /* XMLSEC_NO_SHA1 */ +static int +xmlSecGnuTLSDigestInitialize(xmlSecTransformPtr transform) { + xmlSecGnuTLSDigestCtxPtr ctx; +#ifndef XMLSEC_GNUTLS_OLD + gpg_err_code_t ret; +#endif /* XMLSEC_GNUTLS_OLD */ -#ifndef XMLSEC_NO_SHA256 -/** - * xmlSecGnuTLSTransformSha256GetKlass: - * - * SHA256 digest transform klass. - * - * Returns: pointer to SHA256 digest transform klass. - */ -xmlSecTransformId -xmlSecGnuTLSTransformSha256GetKlass(void) { - return (xmlSecGCryptTransformSha256GetKlass()); + xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1); + + ctx = xmlSecGnuTLSDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + + /* initialize context */ + memset(ctx, 0, sizeof(xmlSecGnuTLSDigestCtx)); + +#ifndef XMLSEC_NO_SHA1 + if(xmlSecTransformCheckId(transform, xmlSecGnuTLSTransformSha1Id)) { + ctx->digest = GCRY_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 = gcry_md_open(&ctx->digestCtx, ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(ret != GPG_ERR_NO_ERROR) { +#else /* XMLSEC_GNUTLS_OLD */ + ctx->digestCtx = gcry_md_open(ctx->digest, GCRY_MD_FLAG_SECURE); /* we are paranoid */ + if(ctx->digestCtx == NULL) { +#endif /* XMLSEC_GNUTLS_OLD */ + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_open", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + return(0); } -#endif /* XMLSEC_NO_SHA256 */ -#ifndef XMLSEC_NO_SHA384 -/** - * xmlSecGnuTLSTransformSha384GetKlass: - * - * SHA384 digest transform klass. - * - * Returns: pointer to SHA384 digest transform klass. - */ -xmlSecTransformId -xmlSecGnuTLSTransformSha384GetKlass(void) { - return (xmlSecGCryptTransformSha384GetKlass()); +static void +xmlSecGnuTLSDigestFinalize(xmlSecTransformPtr transform) { + xmlSecGnuTLSDigestCtxPtr ctx; + + xmlSecAssert(xmlSecGnuTLSDigestCheckId(transform)); + xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize)); + + ctx = xmlSecGnuTLSDigestGetCtx(transform); + xmlSecAssert(ctx != NULL); + + if(ctx->digestCtx != NULL) { + gcry_md_close(ctx->digestCtx); + } + memset(ctx, 0, sizeof(xmlSecGnuTLSDigestCtx)); } -#endif /* XMLSEC_NO_SHA384 */ -#ifndef XMLSEC_NO_SHA512 -/** - * xmlSecGnuTLSTransformSha512GetKlass: - * - * SHA512 digest transform klass. - * - * Returns: pointer to SHA512 digest transform klass. - */ -xmlSecTransformId -xmlSecGnuTLSTransformSha512GetKlass(void) { - return (xmlSecGCryptTransformSha512GetKlass()); +static int +xmlSecGnuTLSDigestVerify(xmlSecTransformPtr transform, + const xmlSecByte* data, xmlSecSize dataSize, + xmlSecTransformCtxPtr transformCtx) { + xmlSecGnuTLSDigestCtxPtr ctx; + + xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1); + xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); + xmlSecAssert2(data != NULL, -1); + xmlSecAssert2(transformCtx != NULL, -1); + + ctx = xmlSecGnuTLSDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -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); } -#endif /* XMLSEC_NO_SHA512 */ -#ifndef XMLSEC_NO_MD5 +static int +xmlSecGnuTLSDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { + xmlSecGnuTLSDigestCtxPtr ctx; + xmlSecBufferPtr in, out; + int ret; + + xmlSecAssert2(xmlSecGnuTLSDigestCheckId(transform), -1); + xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); + xmlSecAssert2(transformCtx != NULL, -1); + xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecGnuTLSDigestSize), -1); + + ctx = xmlSecGnuTLSDigestGetCtx(transform); + xmlSecAssert2(ctx != NULL, -1); + xmlSecAssert2(ctx->digest != GCRY_MD_NONE, -1); + xmlSecAssert2(ctx->digestCtx != NULL, -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) { + gcry_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) { + xmlSecByte* buf; + + /* get the final digest */ + gcry_md_final(ctx->digestCtx); + buf = gcry_md_read(ctx->digestCtx, ctx->digest); + if(buf == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "gcry_md_read", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + + /* copy it to our internal buffer */ + ctx->dgstSize = gcry_md_get_algo_dlen(ctx->digest); + xmlSecAssert2(ctx->dgstSize > 0, -1); + xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1); + 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); +} -/** - * xmlSecGnuTLSTransformMd5GetKlass: +#ifndef XMLSEC_NO_SHA1 +/****************************************************************************** * - * MD5 digest transform klass. + * SHA1 Digest transforms * - * Returns: pointer to MD5 digest transform klass. - */ -xmlSecTransformId -xmlSecGnuTLSTransformMd5GetKlass(void) { - return (xmlSecGCryptTransformMd5GetKlass()); -} -#endif /* XMLSEC_NO_MD5 */ + *****************************************************************************/ +static xmlSecTransformKlass xmlSecGnuTLSSha1Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecGnuTLSDigestSize, /* xmlSecSize objSize */ + + /* data */ + xmlSecNameSha1, /* const xmlChar* name; */ + xmlSecHrefSha1, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + + /* methods */ + xmlSecGnuTLSDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecGnuTLSDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecGnuTLSDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecGnuTLSDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; -#ifndef XMLSEC_NO_RIPEMD160 -/** - * xmlSecGnuTLSTransformRipemd160GetKlass: +/** + * xmlSecGnuTLSTransformSha1GetKlass: * - * RIPEMD160 digest transform klass. + * SHA-1 digest transform klass. * - * Returns: pointer to RIPEMD160 digest transform klass. + * Returns: pointer to SHA-1 digest transform klass. */ -xmlSecTransformId -xmlSecGnuTLSTransformRipemd160GetKlass(void) { - return (xmlSecGCryptTransformRipemd160GetKlass()); +xmlSecTransformId +xmlSecGnuTLSTransformSha1GetKlass(void) { + return(&xmlSecGnuTLSSha1Klass); } -#endif /* XMLSEC_NO_RIPEMD160 */ +#endif /* XMLSEC_NO_SHA1 */ + + |