From 6240557e4429a4bb6be19a0e27479a5a0df9fa34 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 2 Feb 2016 15:49:10 +0100 Subject: [PATCH] mscrypto glue layer: add SHA-256 support --- include/xmlsec/mscrypto/crypto.h | 27 ++++++++ src/mscrypto/certkeys.c | 2 +- src/mscrypto/crypto.c | 4 ++ src/mscrypto/digests.c | 70 +++++++++++++++++++++ src/mscrypto/signatures.c | 130 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+), 1 deletion(-) diff --git a/include/xmlsec/mscrypto/crypto.h b/include/xmlsec/mscrypto/crypto.h index 28d792a..96aaa78 100644 --- a/include/xmlsec/mscrypto/crypto.h +++ b/include/xmlsec/mscrypto/crypto.h @@ -133,6 +133,16 @@ XMLSEC_CRYPTO_EXPORT xmlSecKeyDataId xmlSecMSCryptoKeyDataRsaGetKlass(void); XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha1GetKlass(void); /** + * xmlSecMSCryptoTransformRsaSha256Id: + * + * The RSA-SHA256 signature transform klass. + */ + +#define xmlSecMSCryptoTransformRsaSha256Id \ + xmlSecMSCryptoTransformRsaSha256GetKlass() +XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformRsaSha256GetKlass(void); + +/** * xmlSecMSCryptoTransformRsaPkcs1Id: * * The RSA PKCS1 key transport transform klass. @@ -172,6 +182,23 @@ XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha1GetKlass(void) /******************************************************************** * + * SHA256 transform + * + *******************************************************************/ +#ifndef XMLSEC_NO_SHA256 + +/** + * xmlSecMSCryptoTransformSha256Id: + * + * The SHA256 digest transform klass. + */ +#define xmlSecMSCryptoTransformSha256Id \ + xmlSecMSCryptoTransformSha256GetKlass() +XMLSEC_CRYPTO_EXPORT xmlSecTransformId xmlSecMSCryptoTransformSha256GetKlass(void); +#endif /* XMLSEC_NO_SHA256 */ + +/******************************************************************** + * * GOSTR3411_94 transform * *******************************************************************/ diff --git a/src/mscrypto/certkeys.c b/src/mscrypto/certkeys.c index 73a6c26..e0b4f47 100644 --- a/src/mscrypto/certkeys.c +++ b/src/mscrypto/certkeys.c @@ -1009,7 +1009,7 @@ xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) { xmlSecAssert2(ctx != NULL, -1); ctx->providerName = MS_ENHANCED_PROV; - ctx->providerType = PROV_RSA_FULL; + ctx->providerType = PROV_RSA_AES; return(0); } diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c index d60d3c6..b2fde85 100644 --- a/src/mscrypto/crypto.c +++ b/src/mscrypto/crypto.c @@ -105,6 +105,7 @@ xmlSecCryptoGetFunctions_mscrypto(void) { #ifndef XMLSEC_NO_RSA gXmlSecMSCryptoFunctions->transformRsaSha1GetKlass = xmlSecMSCryptoTransformRsaSha1GetKlass; + gXmlSecMSCryptoFunctions->transformRsaSha256GetKlass = xmlSecMSCryptoTransformRsaSha256GetKlass; gXmlSecMSCryptoFunctions->transformRsaPkcs1GetKlass = xmlSecMSCryptoTransformRsaPkcs1GetKlass; #endif /* XMLSEC_NO_RSA */ @@ -119,6 +120,9 @@ xmlSecCryptoGetFunctions_mscrypto(void) { #ifndef XMLSEC_NO_SHA1 gXmlSecMSCryptoFunctions->transformSha1GetKlass = xmlSecMSCryptoTransformSha1GetKlass; #endif /* XMLSEC_NO_SHA1 */ +#ifndef XMLSEC_NO_SHA256 + gXmlSecMSCryptoFunctions->transformSha256GetKlass = xmlSecMSCryptoTransformSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_GOST gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass = xmlSecMSCryptoTransformGostR3411_94GetKlass; diff --git a/src/mscrypto/digests.c b/src/mscrypto/digests.c index 19acc65..2b466b7 100644 --- a/src/mscrypto/digests.c +++ b/src/mscrypto/digests.c @@ -66,6 +66,11 @@ xmlSecMSCryptoDigestCheckId(xmlSecTransformPtr transform) { return(1); } #endif /* XMLSEC_NO_SHA1 */ +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) { + return(1); + } +#endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_GOST if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) { @@ -94,6 +99,11 @@ xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) { ctx->alg_id = CALG_SHA; } else #endif /* XMLSEC_NO_SHA1 */ +#ifndef XMLSEC_NO_SHA256 + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformSha256Id)) { + ctx->alg_id = CALG_SHA_256; + } else +#endif /* XMLSEC_NO_SHA256 */ #ifndef XMLSEC_NO_GOST if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformGostR3411_94Id)) { @@ -124,6 +134,8 @@ xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) { } /* TODO: Check what provider is best suited here.... */ + if (ctx->alg_id != CALG_SHA_256) + { if (!CryptAcquireContext(&ctx->provider, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if (!CryptAcquireContext(&ctx->provider, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { xmlSecError(XMLSEC_ERRORS_HERE, @@ -134,6 +146,20 @@ xmlSecMSCryptoDigestInitialize(xmlSecTransformPtr transform) { return(-1); } } + } + else + { + // SHA-256 + if (!CryptAcquireContext(&ctx->provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "CryptAcquireContext", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); + } + } return(0); } @@ -367,6 +393,50 @@ xmlSecMSCryptoTransformSha1GetKlass(void) { } #endif /* XMLSEC_NO_SHA1 */ +#ifndef XMLSEC_NO_SHA256 +/****************************************************************************** + * + * SHA256 + * + *****************************************************************************/ +static xmlSecTransformKlass xmlSecMSCryptoSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* size_t klassSize */ + xmlSecMSCryptoDigestSize, /* size_t objSize */ + + xmlSecNameSha256, /* const xmlChar* name; */ + xmlSecHrefSha256, /* const xmlChar* href; */ + xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ + xmlSecMSCryptoDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ + xmlSecMSCryptoDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ + NULL, /* xmlSecTransformNodeReadMethod readNode; */ + NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ + NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ + NULL, /* xmlSecTransformSetKeyMethod setKey; */ + xmlSecMSCryptoDigestVerify, /* xmlSecTransformVerifyMethod verify; */ + xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */ + xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */ + xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */ + NULL, /* xmlSecTransformPushXmlMethod pushXml; */ + NULL, /* xmlSecTransformPopXmlMethod popXml; */ + xmlSecMSCryptoDigestExecute, /* xmlSecTransformExecuteMethod execute; */ + NULL, /* void* reserved0; */ + NULL, /* void* reserved1; */ +}; + +/** + * xmlSecMSCryptoTransformSha256GetKlass: + * + * SHA-256 digest transform klass. + * + * Returns: pointer to SHA-256 digest transform klass. + */ +xmlSecTransformId +xmlSecMSCryptoTransformSha256GetKlass(void) { + return(&xmlSecMSCryptoSha256Klass); +} +#endif /* XMLSEC_NO_SHA256 */ + #ifndef XMLSEC_NO_GOST /****************************************************************************** * diff --git a/src/mscrypto/signatures.c b/src/mscrypto/signatures.c index a567db7..34c17bb 100644 --- a/src/mscrypto/signatures.c +++ b/src/mscrypto/signatures.c @@ -97,6 +97,9 @@ static int xmlSecMSCryptoSignatureCheckId(xmlSecTransformPtr transform) { if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha1Id)) { return(1); } + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) { + return(1); + } #endif /* XMLSEC_NO_RSA */ return(0); @@ -118,6 +121,10 @@ static int xmlSecMSCryptoSignatureInitialize(xmlSecTransformPtr transform) { ctx->digestAlgId = CALG_SHA1; ctx->keyId = xmlSecMSCryptoKeyDataRsaId; } else + if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) { + ctx->digestAlgId = CALG_SHA_256; + ctx->keyId = xmlSecMSCryptoKeyDataRsaId; + } else #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_GOST @@ -282,6 +289,12 @@ static int xmlSecMSCryptoSignatureVerify(xmlSecTransformPtr transform, while (l >= tmpBuf) { *l-- = *j++; } + } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) { + j = (BYTE *)data; + l = tmpBuf + dataSize - 1; + while (l >= tmpBuf) { + *l-- = *j++; + } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), @@ -372,6 +385,68 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra XMLSEC_ERRORS_NO_MESSAGE); return (-1); } + + if (transform->operation == xmlSecTransformOperationSign && ctx->digestAlgId == CALG_SHA_256) + { + /* CryptCreateHash() would fail with NTE_BAD_ALGID, as hProv is of + * type PROV_RSA_FULL, not PROV_RSA_AES. */ + + DWORD dwDataLen; + xmlSecSize nameSize; + xmlSecBuffer nameBuffer; + BYTE* nameData; + + if (!CryptGetProvParam(hProv, PP_CONTAINER, NULL, &dwDataLen, 0)) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "CryptGetProvParam", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + nameSize = (xmlSecSize)dwDataLen; + ret = xmlSecBufferInitialize(&nameBuffer, nameSize); + if (ret < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "mlSecBufferInitialize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", nameSize); + return -1; + } + + nameData = xmlSecBufferGetData(&nameBuffer); + if (!CryptGetProvParam(hProv, PP_CONTAINER, nameData, &dwDataLen, 0)) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "CryptGetProvParam", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&nameBuffer); + return -1; + } + + HCRYPTPROV hCryptProv; + if (!CryptAcquireContext(&hCryptProv, nameData, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_SILENT)) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), + "CryptAcquireContext", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + xmlSecBufferFinalize(&nameBuffer); + return -1; + } + xmlSecBufferFinalize(&nameBuffer); + + hProv = hCryptProv; + } + + if (!CryptCreateHash(hProv, ctx->digestAlgId, 0, 0, &(ctx->mscHash))) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, @@ -445,6 +520,10 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra xmlSecBufferFinalize(&tmp); return(-1); } + + if (ctx->digestAlgId == CALG_SHA_256) + CryptReleaseContext(hProv, 0); + outSize = (xmlSecSize)dwSigLen; ret = xmlSecBufferSetSize(out, outSize); @@ -487,6 +566,13 @@ xmlSecMSCryptoSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTra while (j >= outBuf) { *j-- = *i++; } + } else if (xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformRsaSha256Id)) { + i = tmpBuf; + j = outBuf + dwSigLen - 1; + + while (j >= outBuf) { + *j-- = *i++; + } } else { /* We shouldn't get at this place */ xmlSecError(XMLSEC_ERRORS_HERE, @@ -563,6 +649,50 @@ xmlSecMSCryptoTransformRsaSha1GetKlass(void) { return(&xmlSecMSCryptoRsaSha1Klass); } +/**************************************************************************** + * + * RSA-SHA256 signature transform + * + ***************************************************************************/ +static xmlSecTransformKlass xmlSecMSCryptoRsaSha256Klass = { + /* klass/object sizes */ + sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ + xmlSecMSCryptoSignatureSize, /* xmlSecSize objSize */ + + xmlSecNameRsaSha256, /* const xmlChar* name; */ + xmlSecHrefRsaSha256, /* 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; */ +}; + +/** + * xmlSecMSCryptoTransformRsaSha256GetKlass: + * + * The RSA-SHA1 signature transform klass. + * + * Returns: RSA-SHA1 signature transform klass. + */ +xmlSecTransformId +xmlSecMSCryptoTransformRsaSha256GetKlass(void) { + return(&xmlSecMSCryptoRsaSha256Klass); +} + #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_DSA -- 2.4.5