diff options
Diffstat (limited to 'src/mscrypto/signatures.c')
-rw-r--r-- | src/mscrypto/signatures.c | 317 |
1 files changed, 227 insertions, 90 deletions
diff --git a/src/mscrypto/signatures.c b/src/mscrypto/signatures.c index 1806dd22..424804eb 100644 --- a/src/mscrypto/signatures.c +++ b/src/mscrypto/signatures.c @@ -1,5 +1,6 @@ -/** - * XMLSec library +/* + * XML Security Library (http://www.aleksey.com/xmlsec). + * * * This is free software; see Copyright file in the source * distribution for preciese wording. @@ -8,6 +9,13 @@ * Copyright (C) 2003-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru). */ +/** + * SECTION:signatures + * @Short_description: Signatures implementation for Microsoft Crypto API. + * @Stability: Private + * + */ + #include "globals.h" #include <string.h> @@ -121,13 +129,20 @@ static int xmlSecMSCryptoSignatureCheckId(xmlSecTransformPtr transform) { } else #endif /* XMLSEC_NO_GOST*/ +#ifndef XMLSEC_NO_GOST2012 + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_256Id)) { + return(1); + } else + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_512Id)) { + return(1); + } else +#endif /* XMLSEC_NO_GOST2012*/ + /* not found */ { return(0); } - - return(0); } static int xmlSecMSCryptoSignatureInitialize(xmlSecTransformPtr transform) { @@ -195,13 +210,20 @@ static int xmlSecMSCryptoSignatureInitialize(xmlSecTransformPtr transform) { } else #endif /* XMLSEC_NO_GOST*/ +#ifndef XMLSEC_NO_GOST2012 + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_256Id)) { + ctx->digestAlgId = CALG_GR3411_2012_256; + ctx->keyId = xmlSecMSCryptoKeyDataGost2012_256Id; + } else + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_512Id)) { + ctx->digestAlgId = CALG_GR3411_2012_512; + ctx->keyId = xmlSecMSCryptoKeyDataGost2012_512Id; + } else +#endif /* XMLSEC_NO_GOST2012*/ + /* not found */ { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - NULL, - XMLSEC_ERRORS_R_INVALID_TRANSFORM, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecInvalidTransfromError(transform) return(-1); } @@ -249,11 +271,8 @@ static int xmlSecMSCryptoSignatureSetKey(xmlSecTransformPtr transform, xmlSecKey ctx->data = xmlSecKeyDataDuplicate(value); if(ctx->data == NULL) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecKeyDataDuplicate", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecInternalError("xmlSecKeyDataDuplicate", + xmlSecTransformGetName(transform)); return(-1); } @@ -307,11 +326,9 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform, ret = xmlSecBufferInitialize(&tmp, dataSize); if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecBufferInitialize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "dataSize=%d", dataSize); + xmlSecInternalError2("xmlSecBufferInitialize", + xmlSecTransformGetName(transform), + "dataSize=%d", dataSize); return(-1); } @@ -367,23 +384,23 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform, } else #endif /* XMLSEC_NO_GOST*/ +#ifndef XMLSEC_NO_GOST2012 + if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_256Id) || + xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_512Id)) { + ConvertEndian(data, tmpBuf, dataSize); + } else +#endif /* XMLSEC_NO_GOST2012*/ + { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - NULL, - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "Invalid algo"); + xmlSecInvalidTypeError("Invalid signature algorithm", xmlSecTransformGetName(transform)); xmlSecBufferFinalize(&tmp); return(-1); } hKey = xmlSecMSCryptoKeyDataGetKey(ctx->data, xmlSecKeyDataTypePublic); if (hKey == 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecMSCryptoKeyDataGetKey", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecInternalError("xmlSecMSCryptoKeyDataGetKey", + xmlSecTransformGetName(transform)); xmlSecBufferFinalize(&tmp); return(-1); } @@ -395,20 +412,15 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform, 0)) { dwError = GetLastError(); if (NTE_BAD_SIGNATURE == dwError) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "CryptVerifySignature", - XMLSEC_ERRORS_R_DATA_NOT_MATCH, - "signature do not match"); + xmlSecOtherError(XMLSEC_ERRORS_R_DATA_NOT_MATCH, + xmlSecTransformGetName(transform), + "CryptVerifySignature: signature does not verify"); transform->status = xmlSecTransformStatusFail; xmlSecBufferFinalize(&tmp); return(0); } else { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "CryptVerifySignature", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecMSCryptoError("CryptVerifySignature", + xmlSecTransformGetName(transform)); xmlSecBufferFinalize(&tmp); return (-1); } @@ -430,6 +442,8 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra int ret; DWORD dwSigLen; BYTE *tmpBuf, *outBuf; + int bOk; + PCRYPT_KEY_PROV_INFO pProviderInfo = NULL; xmlSecAssert2(xmlSecMSCryptoSignatureCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); @@ -452,20 +466,68 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra xmlSecAssert2(outSize == 0, -1); if (0 == (hProv = xmlSecMSCryptoKeyDataGetMSCryptoProvider(ctx->data))) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecMSCryptoKeyDataGetMSCryptoProvider", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecMSCryptoError("xmlSecMSCryptoKeyDataGetMSCryptoProvider", + xmlSecTransformGetName(transform)); return (-1); } - if (!CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash))) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptCreateHash", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + //First try create hash with provider acquired in function xmlSecMSCryptoKeyDataAdoptCert. + bOk = CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash)); + + //Then try it with container name, provider name and type acquired from certificate context. + if(!bOk) { + pProviderInfo = xmlSecMSCryptoKeyDataGetMSCryptoProviderInfo(ctx->data); + + if(pProviderInfo == NULL) { + xmlSecInternalError("xmlSecMSCryptoKeyDataGetMSCryptoProviderInfo", NULL); + return(-1); + } + + if(!CryptReleaseContext(hProv, 0)) { + xmlSecMSCryptoError("CryptReleaseContext", NULL); + return(-1); + } + hProv = (HCRYPTPROV)0; + + if(!CryptAcquireContextW(&hProv, + pProviderInfo->pwszContainerName, + pProviderInfo->pwszProvName, + pProviderInfo->dwProvType, + 0)) { + + xmlSecMSCryptoError("CryptAcquireContext", NULL); + return(-1); + } + + bOk = CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash)); + } + + //Last try it with PROV_RSA_AES provider type. + if(!bOk) { + if (!CryptReleaseContext(hProv, 0)) { + xmlSecMSCryptoError("CryptReleaseContext", NULL); + return(-1); + } + hProv = (HCRYPTPROV)0; + + if(!CryptAcquireContextW(&hProv, + pProviderInfo->pwszContainerName, + NULL, + PROV_RSA_AES, + 0)) { + xmlSecMSCryptoError("CryptAcquireContext", NULL); + return(-1); + } + + bOk = CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash)); + } + + if(pProviderInfo != NULL) { + free(pProviderInfo); + } + + if(!bOk) { + xmlSecMSCryptoError("CryptCreateHash", NULL); return(-1); } @@ -476,21 +538,14 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra xmlSecAssert2(outSize == 0, -1); if (!CryptHashData(ctx->mscHash, xmlSecBufferGetData(in), inSize, 0)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptHashData", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecMSCryptoError("CryptHashData", NULL); return(-1); } ret = xmlSecBufferRemoveHead(in, inSize); if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecBufferRemoveHead", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecInternalError("xmlSecBufferRemoveHead", + xmlSecTransformGetName(transform)); return(-1); } } @@ -503,33 +558,23 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra if(transform->operation == xmlSecTransformOperationSign) { dwKeySpec = xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(ctx->data); if (!CryptSignHash(ctx->mscHash, dwKeySpec, NULL, 0, NULL, &dwSigLen)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptSignHash", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecMSCryptoError("CryptSignHash", NULL); return(-1); } outSize = (xmlSecSize)dwSigLen; ret = xmlSecBufferInitialize(&tmp, outSize); if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecBufferSetMaxSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize); + xmlSecInternalError2("xmlSecBufferSetMaxSize", + xmlSecTransformGetName(transform), + "size=%d", outSize); return(-1); } tmpBuf = xmlSecBufferGetData(&tmp); xmlSecAssert2(tmpBuf != NULL, -1); if (!CryptSignHash(ctx->mscHash, dwKeySpec, NULL, 0, tmpBuf, &dwSigLen)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptSignHash", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); + xmlSecMSCryptoError("CryptSignHash", NULL); xmlSecBufferFinalize(&tmp); return(-1); } @@ -537,11 +582,9 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra ret = xmlSecBufferSetSize(out, outSize); if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - "xmlSecBufferSetSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", outSize); + xmlSecInternalError2("xmlSecBufferSetSize", + xmlSecTransformGetName(transform), + "size=%d", outSize); xmlSecBufferFinalize(&tmp); return(-1); } @@ -597,13 +640,16 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra } else #endif /* XMLSEC_NO_GOST*/ +#ifndef XMLSEC_NO_GOST2012 + if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_256Id) || + xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGost2012_512Id)) { + ConvertEndian(tmpBuf, outBuf, outSize); + } else +#endif /* XMLSEC_NO_GOST2012*/ + { /* We shouldn't get at this place */ - xmlSecError(XMLSEC_ERRORS_HERE, - xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), - NULL, - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "Invalid algo"); + xmlSecInvalidTypeError("Invalid signature algorithm", xmlSecTransformGetName(transform)); xmlSecBufferFinalize(&tmp); return(-1); } @@ -616,11 +662,7 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra /* 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); + xmlSecInvalidTransfromStatusError(transform); return(-1); } @@ -958,3 +1000,98 @@ xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass(void) { #endif /* XMLSEC_NO_GOST*/ + +#ifndef XMLSEC_NO_GOST2012 + +/**************************************************************************** + * + * GOST R 34.10-2012 256 signature transform + * + ***************************************************************************/ + +static xmlSecTransformKlass xmlSecMSCryptoGost2012_256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameGostR3410_2012GostR3411_2012_256, /* const xmlChar* name; */ + xmlSecHrefGostR3410_2012GostR3411_2012_256, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecMSCryptoSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecMSCryptoSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecMSCryptoSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecMSCryptoSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecMSCryptoSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecMSCryptoSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecMSCryptoTransformGost2012GostR3411_94GetKlass: + * + * The GOST R 34.10-2012 signature transform klass. + * + * Returns: GOST2001-GOST R 34.10-2012 signature transform klass. + */ +xmlSecTransformId +xmlSecMSCryptoTransformGost2012_256GetKlass(void) { + return(&xmlSecMSCryptoGost2012_256Klass); +} + +/**************************************************************************** + * + * GOST R 34.10-2012 512 signature transform + * + ***************************************************************************/ + +static xmlSecTransformKlass xmlSecMSCryptoGost2012_512Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameGostR3410_2012GostR3411_2012_512, /* const xmlChar* name; */ + xmlSecHrefGostR3410_2012GostR3411_2012_512, /* const xmlChar* href; */ + xmlSecTransformUsageSignatureMethod, /* xmlSecTransformUsage usage; */ + + xmlSecMSCryptoSignatureInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecMSCryptoSignatureFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + xmlSecMSCryptoSignatureSetKeyReq, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + xmlSecMSCryptoSignatureSetKey, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecMSCryptoSignatureVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecMSCryptoSignatureExecute, /* xmlSecTransformExecuteMethod execute; */ + + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecMSCryptoTransformGost2012GostR3411_94GetKlass: + * + * The GOST R 34.10-2012 signature transform klass. + * + * Returns: GOST2001-GOST R 34.10-2012 signature transform klass. + */ +xmlSecTransformId +xmlSecMSCryptoTransformGost2012_512GetKlass(void) { + return(&xmlSecMSCryptoGost2012_512Klass); +} + +#endif /* XMLSEC_NO_GOST2012*/ + |