diff options
Diffstat (limited to 'src/mscrypto/crypto.c')
-rw-r--r-- | src/mscrypto/crypto.c | 868 |
1 files changed, 685 insertions, 183 deletions
diff --git a/src/mscrypto/crypto.c b/src/mscrypto/crypto.c index d60d3c60..82ab101d 100644 --- a/src/mscrypto/crypto.c +++ b/src/mscrypto/crypto.c @@ -1,12 +1,12 @@ -/** +/** * XMLSec library * * This is free software; see Copyright file in the source * distribution for preciese wording. - * - * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved. + * + * Copyright (C) 2003 Cordys R&D BV, All rights reserved. * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com> - * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru). + * Copyright (c) 2005-2006 Cryptocom LTD (http://www.cryptocom.ru). */ #include "globals.h" @@ -23,11 +23,40 @@ #include <xmlsec/mscrypto/app.h> #include <xmlsec/mscrypto/crypto.h> #include <xmlsec/mscrypto/x509.h> +#include "private.h" #if defined(__MINGW32__) -# include "xmlsec-mingw.h" +/* NOTE mingw.org project don't define any xxx_s function and may + * be never will define them. + * + * In this file is save to use non _s function as into destination + * buffer program code copy empty string and the size of source buffer + * (XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE=4096) is enough for any + * encoding. Also program code don't check result of _s functions. + */ + +static int +strcpy_s(char *dest, size_t n, const char *src) { + strcpy(dest, src); + return(0); +} + +static int +wcscpy_s(wchar_t *dest, size_t n, const wchar_t *src) { + wcscpy(dest, src); + return(0); +} +#endif + +#define XMLSEC_CONTAINER_NAME_A "xmlsec-key-container" +#define XMLSEC_CONTAINER_NAME_W L"xmlsec-key-container" +#ifdef UNICODE +#define XMLSEC_CONTAINER_NAME XMLSEC_CONTAINER_NAME_W +#else +#define XMLSEC_CONTAINER_NAME XMLSEC_CONTAINER_NAME_A #endif + static xmlSecCryptoDLFunctionsPtr gXmlSecMSCryptoFunctions = NULL; /** @@ -40,131 +69,216 @@ static xmlSecCryptoDLFunctionsPtr gXmlSecMSCryptoFunctions = NULL; xmlSecCryptoDLFunctionsPtr xmlSecCryptoGetFunctions_mscrypto(void) { static xmlSecCryptoDLFunctions functions; - + if(gXmlSecMSCryptoFunctions != NULL) { - return(gXmlSecMSCryptoFunctions); + return(gXmlSecMSCryptoFunctions); } memset(&functions, 0, sizeof(functions)); gXmlSecMSCryptoFunctions = &functions; - /** + /******************************************************************** + * * Crypto Init/shutdown - */ - gXmlSecMSCryptoFunctions->cryptoInit = xmlSecMSCryptoInit; - gXmlSecMSCryptoFunctions->cryptoShutdown = xmlSecMSCryptoShutdown; - gXmlSecMSCryptoFunctions->cryptoKeysMngrInit = xmlSecMSCryptoKeysMngrInit; - - /** + * + ********************************************************************/ + gXmlSecMSCryptoFunctions->cryptoInit = xmlSecMSCryptoInit; + gXmlSecMSCryptoFunctions->cryptoShutdown = xmlSecMSCryptoShutdown; + gXmlSecMSCryptoFunctions->cryptoKeysMngrInit = xmlSecMSCryptoKeysMngrInit; + + /******************************************************************** + * * Key data ids - */ -#ifndef XMLSEC_NO_DES - gXmlSecMSCryptoFunctions->keyDataDesGetKlass = xmlSecMSCryptoKeyDataDesGetKlass; + * + ********************************************************************/ +#ifndef XMLSEC_NO_DES + gXmlSecMSCryptoFunctions->keyDataDesGetKlass = xmlSecMSCryptoKeyDataDesGetKlass; #endif /* XMLSEC_NO_DES */ -#ifndef XMLSEC_NO_AES - gXmlSecMSCryptoFunctions->keyDataAesGetKlass = xmlSecMSCryptoKeyDataAesGetKlass; +#ifndef XMLSEC_NO_AES + gXmlSecMSCryptoFunctions->keyDataAesGetKlass = xmlSecMSCryptoKeyDataAesGetKlass; #endif /* XMLSEC_NO_AES */ #ifndef XMLSEC_NO_RSA - gXmlSecMSCryptoFunctions->keyDataRsaGetKlass = xmlSecMSCryptoKeyDataRsaGetKlass; + gXmlSecMSCryptoFunctions->keyDataRsaGetKlass = xmlSecMSCryptoKeyDataRsaGetKlass; #endif /* XMLSEC_NO_RSA */ +#ifndef XMLSEC_NO_HMAC + gXmlSecMSCryptoFunctions->keyDataHmacGetKlass = xmlSecMSCryptoKeyDataHmacGetKlass; +#endif /* XMLSEC_NO_HMAC */ + #ifndef XMLSEC_NO_DSA - gXmlSecMSCryptoFunctions->keyDataDsaGetKlass = xmlSecMSCryptoKeyDataDsaGetKlass; + gXmlSecMSCryptoFunctions->keyDataDsaGetKlass = xmlSecMSCryptoKeyDataDsaGetKlass; #endif /* XMLSEC_NO_DSA */ #ifndef XMLSEC_NO_GOST - gXmlSecMSCryptoFunctions->keyDataGost2001GetKlass = xmlSecMSCryptoKeyDataGost2001GetKlass; + gXmlSecMSCryptoFunctions->keyDataGost2001GetKlass = xmlSecMSCryptoKeyDataGost2001GetKlass; #endif /* XMLSEC_NO_GOST*/ #ifndef XMLSEC_NO_X509 - gXmlSecMSCryptoFunctions->keyDataX509GetKlass = xmlSecMSCryptoKeyDataX509GetKlass; - gXmlSecMSCryptoFunctions->keyDataRawX509CertGetKlass = xmlSecMSCryptoKeyDataRawX509CertGetKlass; + gXmlSecMSCryptoFunctions->keyDataX509GetKlass = xmlSecMSCryptoKeyDataX509GetKlass; + gXmlSecMSCryptoFunctions->keyDataRawX509CertGetKlass = xmlSecMSCryptoKeyDataRawX509CertGetKlass; #endif /* XMLSEC_NO_X509 */ - /** + /******************************************************************** + * * Key data store ids - */ + * + ********************************************************************/ #ifndef XMLSEC_NO_X509 - gXmlSecMSCryptoFunctions->x509StoreGetKlass = xmlSecMSCryptoX509StoreGetKlass; + gXmlSecMSCryptoFunctions->x509StoreGetKlass = xmlSecMSCryptoX509StoreGetKlass; #endif /* XMLSEC_NO_X509 */ - /** + /******************************************************************** + * * Crypto transforms ids - */ -#ifndef XMLSEC_NO_AES - gXmlSecMSCryptoFunctions->transformAes128CbcGetKlass = xmlSecMSCryptoTransformAes128CbcGetKlass; - gXmlSecMSCryptoFunctions->transformAes192CbcGetKlass = xmlSecMSCryptoTransformAes192CbcGetKlass; - gXmlSecMSCryptoFunctions->transformAes256CbcGetKlass = xmlSecMSCryptoTransformAes256CbcGetKlass; + * + ********************************************************************/ + + /******************************* AES ********************************/ +#ifndef XMLSEC_NO_AES + gXmlSecMSCryptoFunctions->transformAes128CbcGetKlass = xmlSecMSCryptoTransformAes128CbcGetKlass; + gXmlSecMSCryptoFunctions->transformAes192CbcGetKlass = xmlSecMSCryptoTransformAes192CbcGetKlass; + gXmlSecMSCryptoFunctions->transformAes256CbcGetKlass = xmlSecMSCryptoTransformAes256CbcGetKlass; + gXmlSecMSCryptoFunctions->transformKWAes128GetKlass = xmlSecMSCryptoTransformKWAes128GetKlass; + gXmlSecMSCryptoFunctions->transformKWAes192GetKlass = xmlSecMSCryptoTransformKWAes192GetKlass; + gXmlSecMSCryptoFunctions->transformKWAes256GetKlass = xmlSecMSCryptoTransformKWAes256GetKlass; #endif /* XMLSEC_NO_AES */ -#ifndef XMLSEC_NO_DES - gXmlSecMSCryptoFunctions->transformDes3CbcGetKlass = xmlSecMSCryptoTransformDes3CbcGetKlass; + /******************************* DES ********************************/ +#ifndef XMLSEC_NO_DES + gXmlSecMSCryptoFunctions->transformDes3CbcGetKlass = xmlSecMSCryptoTransformDes3CbcGetKlass; + gXmlSecMSCryptoFunctions->transformKWDes3GetKlass = xmlSecMSCryptoTransformKWDes3GetKlass; #endif /* XMLSEC_NO_DES */ -#ifndef XMLSEC_NO_RSA - gXmlSecMSCryptoFunctions->transformRsaSha1GetKlass = xmlSecMSCryptoTransformRsaSha1GetKlass; - gXmlSecMSCryptoFunctions->transformRsaPkcs1GetKlass = xmlSecMSCryptoTransformRsaPkcs1GetKlass; -#endif /* XMLSEC_NO_RSA */ - + /******************************* DSA ********************************/ #ifndef XMLSEC_NO_DSA - gXmlSecMSCryptoFunctions->transformDsaSha1GetKlass = xmlSecMSCryptoTransformDsaSha1GetKlass; + gXmlSecMSCryptoFunctions->transformDsaSha1GetKlass = xmlSecMSCryptoTransformDsaSha1GetKlass; #endif /* XMLSEC_NO_DSA */ + /******************************* GOST ********************************/ #ifndef XMLSEC_NO_GOST - gXmlSecMSCryptoFunctions->transformGost2001GostR3411_94GetKlass = xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass; + gXmlSecMSCryptoFunctions->transformGost2001GostR3411_94GetKlass = xmlSecMSCryptoTransformGost2001GostR3411_94GetKlass; #endif /* XMLSEC_NO_GOST */ -#ifndef XMLSEC_NO_SHA1 - gXmlSecMSCryptoFunctions->transformSha1GetKlass = xmlSecMSCryptoTransformSha1GetKlass; +#ifndef XMLSEC_NO_GOST + gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass = xmlSecMSCryptoTransformGostR3411_94GetKlass; +#endif /* XMLSEC_NO_GOST */ + + /******************************* HMAC ********************************/ +#ifndef XMLSEC_NO_HMAC + +#ifndef XMLSEC_NO_MD5 + gXmlSecMSCryptoFunctions->transformHmacMd5GetKlass = xmlSecMSCryptoTransformHmacMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + +#ifndef XMLSEC_NO_SHA1 + gXmlSecMSCryptoFunctions->transformHmacSha1GetKlass = xmlSecMSCryptoTransformHmacSha1GetKlass; #endif /* XMLSEC_NO_SHA1 */ -#ifndef XMLSEC_NO_GOST - gXmlSecMSCryptoFunctions->transformGostR3411_94GetKlass = xmlSecMSCryptoTransformGostR3411_94GetKlass; -#endif /* XMLSEC_NO_GOST */ +#ifndef XMLSEC_NO_SHA256 + gXmlSecMSCryptoFunctions->transformHmacSha256GetKlass = xmlSecMSCryptoTransformHmacSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecMSCryptoFunctions->transformHmacSha384GetKlass = xmlSecMSCryptoTransformHmacSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecMSCryptoFunctions->transformHmacSha512GetKlass = xmlSecMSCryptoTransformHmacSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + +#endif /* XMLSEC_NO_HMAC */ + + /******************************* MD5 ********************************/ +#ifndef XMLSEC_NO_MD5 + gXmlSecMSCryptoFunctions->transformMd5GetKlass = xmlSecMSCryptoTransformMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ + + /******************************* RSA ********************************/ +#ifndef XMLSEC_NO_RSA + +#ifndef XMLSEC_NO_MD5 + gXmlSecMSCryptoFunctions->transformRsaMd5GetKlass = xmlSecMSCryptoTransformRsaMd5GetKlass; +#endif /* XMLSEC_NO_MD5 */ - /** +#ifndef XMLSEC_NO_SHA1 + gXmlSecMSCryptoFunctions->transformRsaSha1GetKlass = xmlSecMSCryptoTransformRsaSha1GetKlass; +#endif /* XMLSEC_NO_SHA1 */ + +#ifndef XMLSEC_NO_SHA256 + gXmlSecMSCryptoFunctions->transformRsaSha256GetKlass = xmlSecMSCryptoTransformRsaSha256GetKlass; +#endif /* XMLSEC_NO_SHA256 */ + +#ifndef XMLSEC_NO_SHA384 + gXmlSecMSCryptoFunctions->transformRsaSha384GetKlass = xmlSecMSCryptoTransformRsaSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ + +#ifndef XMLSEC_NO_SHA512 + gXmlSecMSCryptoFunctions->transformRsaSha512GetKlass = xmlSecMSCryptoTransformRsaSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + + gXmlSecMSCryptoFunctions->transformRsaPkcs1GetKlass = xmlSecMSCryptoTransformRsaPkcs1GetKlass; + gXmlSecMSCryptoFunctions->transformRsaOaepGetKlass = xmlSecMSCryptoTransformRsaOaepGetKlass; +#endif /* XMLSEC_NO_RSA */ + + /******************************* SHA ********************************/ +#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_SHA384 + gXmlSecMSCryptoFunctions->transformSha384GetKlass = xmlSecMSCryptoTransformSha384GetKlass; +#endif /* XMLSEC_NO_SHA384 */ +#ifndef XMLSEC_NO_SHA512 + gXmlSecMSCryptoFunctions->transformSha512GetKlass = xmlSecMSCryptoTransformSha512GetKlass; +#endif /* XMLSEC_NO_SHA512 */ + + /******************************************************************** + * * High level routines form xmlsec command line utility - */ - gXmlSecMSCryptoFunctions->cryptoAppInit = xmlSecMSCryptoAppInit; - gXmlSecMSCryptoFunctions->cryptoAppShutdown = xmlSecMSCryptoAppShutdown; - gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrInit = xmlSecMSCryptoAppDefaultKeysMngrInit; - gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecMSCryptoAppDefaultKeysMngrAdoptKey; - gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecMSCryptoAppDefaultKeysMngrLoad; - gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrSave = xmlSecMSCryptoAppDefaultKeysMngrSave; + * + ********************************************************************/ + gXmlSecMSCryptoFunctions->cryptoAppInit = xmlSecMSCryptoAppInit; + gXmlSecMSCryptoFunctions->cryptoAppShutdown = xmlSecMSCryptoAppShutdown; + gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrInit = xmlSecMSCryptoAppDefaultKeysMngrInit; + gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrAdoptKey = xmlSecMSCryptoAppDefaultKeysMngrAdoptKey; + gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrLoad = xmlSecMSCryptoAppDefaultKeysMngrLoad; + gXmlSecMSCryptoFunctions->cryptoAppDefaultKeysMngrSave = xmlSecMSCryptoAppDefaultKeysMngrSave; #ifndef XMLSEC_NO_X509 - gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoad = xmlSecMSCryptoAppKeysMngrCertLoad; - gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecMSCryptoAppKeysMngrCertLoadMemory; - gXmlSecMSCryptoFunctions->cryptoAppPkcs12Load = xmlSecMSCryptoAppPkcs12Load; - gXmlSecMSCryptoFunctions->cryptoAppPkcs12LoadMemory = xmlSecMSCryptoAppPkcs12LoadMemory; - gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoad = xmlSecMSCryptoAppKeyCertLoad; - gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoadMemory = xmlSecMSCryptoAppKeyCertLoadMemory; + gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoad = xmlSecMSCryptoAppKeysMngrCertLoad; + gXmlSecMSCryptoFunctions->cryptoAppKeysMngrCertLoadMemory = xmlSecMSCryptoAppKeysMngrCertLoadMemory; + gXmlSecMSCryptoFunctions->cryptoAppPkcs12Load = xmlSecMSCryptoAppPkcs12Load; + gXmlSecMSCryptoFunctions->cryptoAppPkcs12LoadMemory = xmlSecMSCryptoAppPkcs12LoadMemory; + gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoad = xmlSecMSCryptoAppKeyCertLoad; + gXmlSecMSCryptoFunctions->cryptoAppKeyCertLoadMemory = xmlSecMSCryptoAppKeyCertLoadMemory; #endif /* XMLSEC_NO_X509 */ - gXmlSecMSCryptoFunctions->cryptoAppKeyLoad = xmlSecMSCryptoAppKeyLoad; - gXmlSecMSCryptoFunctions->cryptoAppKeyLoadMemory = xmlSecMSCryptoAppKeyLoadMemory; - gXmlSecMSCryptoFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecMSCryptoAppGetDefaultPwdCallback(); + gXmlSecMSCryptoFunctions->cryptoAppKeyLoad = xmlSecMSCryptoAppKeyLoad; + gXmlSecMSCryptoFunctions->cryptoAppKeyLoadMemory = xmlSecMSCryptoAppKeyLoadMemory; + gXmlSecMSCryptoFunctions->cryptoAppDefaultPwdCallback = (void*)xmlSecMSCryptoAppGetDefaultPwdCallback(); return(gXmlSecMSCryptoFunctions); } /** * xmlSecMSCryptoInit: - * - * XMLSec library specific crypto engine initialization. + * + * XMLSec library specific crypto engine initialization. * * Returns: 0 on success or a negative value otherwise. */ -int +int xmlSecMSCryptoInit (void) { /* Check loaded xmlsec library version */ if(xmlSecCheckVersionExact() != 1) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecCheckVersionExact", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - return(-1); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCheckVersionExact", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); } /* set default errors callback for xmlsec to us */ @@ -172,24 +286,24 @@ xmlSecMSCryptoInit (void) { /* register our klasses */ if(xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms(xmlSecCryptoGetFunctions_mscrypto()) < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - return(-1); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecCryptoDLFunctionsRegisterKeyDataAndTransforms", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); } return(0); } /** * xmlSecMSCryptoShutdown: - * - * XMLSec library specific crypto engine shutdown. + * + * XMLSec library specific crypto engine shutdown. * * Returns: 0 on success or a negative value otherwise. */ -int +int xmlSecMSCryptoShutdown(void) { /* TODO: if necessary, do additional shutdown here */ return(0); @@ -197,16 +311,16 @@ xmlSecMSCryptoShutdown(void) { /** * xmlSecMSCryptoKeysMngrInit: - * @mngr: the pointer to keys manager. + * @mngr: the pointer to keys manager. * * Adds MSCrypto specific key data stores in keys manager. * * Returns: 0 on success or a negative value otherwise. */ -int +int xmlSecMSCryptoKeysMngrInit(xmlSecKeysMngrPtr mngr) { int ret; - + xmlSecAssert2(mngr != NULL, -1); #ifndef XMLSEC_NO_X509 @@ -241,10 +355,16 @@ xmlSecMSCryptoKeysMngrInit(xmlSecKeysMngrPtr mngr) { } +static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Random[] = { + { MS_STRONG_PROV, PROV_RSA_FULL }, + { MS_ENHANCED_PROV, PROV_RSA_FULL }, + { NULL, 0 } +}; + /** * xmlSecMSCryptoGenerateRandom: - * @buffer: the destination buffer. - * @size: the numer of bytes to generate. + * @buffer: the destination buffer. + * @size: the numer of bytes to generate. * * Generates @size random bytes and puts result in @buffer * (not implemented yet). @@ -252,136 +372,518 @@ xmlSecMSCryptoKeysMngrInit(xmlSecKeysMngrPtr mngr) { * Returns: 0 on success or a negative value otherwise. */ int -xmlSecMSCryptoGenerateRandom(xmlSecBufferPtr buffer, size_t size) { +xmlSecMSCryptoGenerateRandom(xmlSecBufferPtr buffer, size_t size) { HCRYPTPROV hProv = 0; int ret; - + xmlSecAssert2(buffer != NULL, -1); xmlSecAssert2(size > 0, -1); ret = xmlSecBufferSetSize(buffer, size); if(ret < 0) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "xmlSecBufferSetSize", - XMLSEC_ERRORS_R_XMLSEC_FAILED, - "size=%d", size); - return(-1); - } - - if (FALSE == CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptAcquireContext", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - return(-1); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecBufferSetSize", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + "size=%d", size); + return(-1); + } + + hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Random, NULL, CRYPT_VERIFYCONTEXT, FALSE); + if (0 == hProv) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "xmlSecMSCryptoFindProvider", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(-1); } if (FALSE == CryptGenRandom(hProv, (DWORD)size, xmlSecBufferGetData(buffer))) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CryptGenRandom", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - CryptReleaseContext(hProv,0); - return(-1); + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + "CryptGenRandom", + XMLSEC_ERRORS_R_CRYPTO_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + CryptReleaseContext(hProv,0); + return(-1); } CryptReleaseContext(hProv, 0); return(0); } +#define XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE 4096 + /** * xmlSecMSCryptoErrorsDefaultCallback: - * @file: the error location file name (__FILE__ macro). - * @line: the error location line number (__LINE__ macro). - * @func: the error location function name (__FUNCTION__ macro). - * @errorObject: the error specific error object - * @errorSubject: the error specific error subject. - * @reason: the error code. - * @msg: the additional error message. + * @file: the error location file name (__FILE__ macro). + * @line: the error location line number (__LINE__ macro). + * @func: the error location function name (__FUNCTION__ macro). + * @errorObject: the error specific error object + * @errorSubject: the error specific error subject. + * @reason: the error code. + * @msg: the additional error message. * * The default errors reporting callback function. */ -void +void xmlSecMSCryptoErrorsDefaultCallback(const char* file, int line, const char* func, - const char* errorObject, const char* errorSubject, - int reason, const char* msg) { + const char* errorObject, const char* errorSubject, + int reason, const char* msg) { DWORD dwError; - LPVOID lpMsgBuf; - xmlChar buf[500]; + TCHAR errorT[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE]; + WCHAR errorW[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE]; + CHAR errorUTF8[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE]; + xmlChar buf[XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE]; + DWORD rc; + int ret; dwError = GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dwError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (LPTSTR) &lpMsgBuf, - 0, - NULL); + rc = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + errorT, + XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, + NULL); + +#ifdef UNICODE + if(rc <= 0) { + wcscpy_s(errorT, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, L""); + } + ret = WideCharToMultiByte(CP_UTF8, 0, errorT, -1, errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, NULL, NULL); + if(ret <= 0) { + strcpy_s(errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, ""); + } +#else /* UNICODE */ + if(rc <= 0) { + strcpy_s(errorT, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, ""); + } + ret = MultiByteToWideChar(CP_ACP, 0, errorT, -1, errorW, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE); + if(ret <= 0) { + wcscpy_s(errorW, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, L""); + } + ret = WideCharToMultiByte(CP_UTF8, 0, errorW, -1, errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, NULL, NULL); + if(ret <= 0) { + strcpy_s(errorUTF8, XMLSEC_MSCRYPTO_ERROR_MSG_BUFFER_SIZE, ""); + } +#endif /* UNICODE */ + if((msg != NULL) && ((*msg) != '\0')) { - xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last error=%d (0x%08x);last error msg=%s", msg, dwError, dwError, (LPTSTR)lpMsgBuf); + xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "%s;last error=%d (0x%08x);last error msg=%s", msg, dwError, dwError, errorUTF8); } else { - xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "last error=%d (0x%08x);last error msg=%s", dwError, dwError, (LPTSTR)lpMsgBuf); + xmlSecStrPrintf(buf, sizeof(buf), BAD_CAST "last error=%d (0x%08x);last error msg=%s", dwError, dwError, errorUTF8); } - xmlSecErrorsDefaultCallback(file, line, func, - errorObject, errorSubject, - reason, (char*)buf); + xmlSecErrorsDefaultCallback(file, line, func, + errorObject, errorSubject, + reason, (char*)buf); +} - LocalFree(lpMsgBuf); +/** + * xmlSecMSCryptoConvertUtf8ToUnicode: + * @str: the string to convert. + * + * Converts input string from UTF8 to Unicode. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPWSTR +xmlSecMSCryptoConvertUtf8ToUnicode(const xmlChar* str) { + LPWSTR res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call MultiByteToWideChar first to get the buffer size */ + ret = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + if(ret <= 0) { + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", sizeof(WCHAR) * len); + return(NULL); + } + + /* convert */ + ret = MultiByteToWideChar(CP_UTF8, 0, str, -1, res, len); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); } /** - * xmlSecMSCryptoCertStrToName: - * @dwCertEncodingType: the encoding used. - * @pszX500: the string to convert. - * @dwStrType: the string type. - * @len: the result len. + * xmlSecMSCryptoConvertUnicodeToUtf8: + * @str: the string to convert. * - * Converts input string to name by calling @CertStrToName function. + * Converts input string from Unicode to UTF8. * - * Returns: a pointer to newly allocated string or NULL if an error occurs. + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. */ -BYTE* -xmlSecMSCryptoCertStrToName(DWORD dwCertEncodingType, LPCTSTR pszX500, DWORD dwStrType, DWORD* len) { - BYTE* str = NULL; - LPCTSTR ppszError = NULL; - - xmlSecAssert2(pszX500 != NULL, NULL); - xmlSecAssert2(len != NULL, NULL); - - if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType, - NULL, NULL, len, &ppszError)) { - /* this might not be an error, string might just not exist */ - DWORD dw = GetLastError(); - return(NULL); - } - - str = (BYTE *)xmlMalloc((*len) + 1); - if(str == NULL) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - NULL, - XMLSEC_ERRORS_R_MALLOC_FAILED, - "len=%ld", (*len)); - return(NULL); - } - memset(str, 0, (*len) + 1); - - if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType, - NULL, str, len, NULL)) { - xmlSecError(XMLSEC_ERRORS_HERE, - NULL, - "CertStrToName", - XMLSEC_ERRORS_R_CRYPTO_FAILED, - XMLSEC_ERRORS_NO_MESSAGE); - xmlFree(str); - return(NULL); - } - - return(str); +xmlChar* +xmlSecMSCryptoConvertUnicodeToUtf8(LPCWSTR str) { + xmlChar * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", sizeof(xmlChar) * len); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_UTF8, 0, str, -1, res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); +} + +/** + * xmlSecMSCryptoConvertLocaleToUnicode: + * @str: the string to convert. + * + * Converts input string from current system locale to Unicode. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPWSTR +xmlSecMSCryptoConvertLocaleToUnicode(const char* str) { + LPWSTR res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + /* call MultiByteToWideChar first to get the buffer size */ + ret = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if(ret <= 0) { + return(NULL); + } + len = ret; + + /* allocate buffer */ + res = (LPWSTR)xmlMalloc(sizeof(WCHAR) * len); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return(NULL); + } + + /* convert */ + ret = MultiByteToWideChar(CP_ACP, 0, str, -1, res, len); + if(ret <= 0) { + xmlFree(res); + return(NULL); + } + + /* done */ + return(res); +} + +/** + * xmlSecMSCryptoConvertLocaleToUtf8: + * @str: the string to convert. + * + * Converts input string from locale to UTF8. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +xmlChar* +xmlSecMSCryptoConvertLocaleToUtf8(const char * str) { + LPWSTR strW = NULL; + xmlChar * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + strW = xmlSecMSCryptoConvertLocaleToUnicode(str); + if(strW == NULL) { + return(NULL); + } + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (xmlChar*)xmlMalloc(sizeof(xmlChar) * len); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", sizeof(xmlChar) * len); + xmlFree(strW); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + xmlFree(res); + return(NULL); + } + + /* done */ + xmlFree(strW); + return(res); +} + +/** + * xmlSecMSCryptoConvertUtf8ToLocale: + * @str: the string to convert. + * + * Converts input string from UTF8 to locale. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +char * +xmlSecMSCryptoConvertUtf8ToLocale(const xmlChar* str) { + LPWSTR strW = NULL; + char * res = NULL; + int len; + int ret; + + xmlSecAssert2(str != NULL, NULL); + + strW = xmlSecMSCryptoConvertUtf8ToUnicode(str); + if(strW == NULL) { + return(NULL); + } + + /* call WideCharToMultiByte first to get the buffer size */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + return(NULL); + } + len = ret + 1; + + /* allocate buffer */ + res = (char*)xmlMalloc(sizeof(char) * len); + if(res == NULL) { + xmlSecError(XMLSEC_ERRORS_HERE, + NULL, + NULL, + XMLSEC_ERRORS_R_MALLOC_FAILED, + "size=%d", sizeof(xmlChar) * len); + xmlFree(strW); + return(NULL); + } + + /* convert */ + ret = WideCharToMultiByte(CP_ACP, 0, strW, -1, res, len, NULL, NULL); + if(ret <= 0) { + xmlFree(strW); + xmlFree(res); + return(NULL); + } + + /* done */ + xmlFree(strW); + return(res); +} + +/** + * xmlSecMSCryptoConvertTstrToUtf8: + * @str: the string to convert. + * + * Converts input string from TSTR (locale or Unicode) to UTF8. + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +xmlChar* +xmlSecMSCryptoConvertTstrToUtf8(LPCTSTR str) { +#ifdef UNICODE + return xmlSecMSCryptoConvertUnicodeToUtf8(str); +#else /* UNICODE */ + return xmlSecMSCryptoConvertLocaleToUtf8(str); +#endif /* UNICODE */ +} + +/** + * xmlSecMSCryptoConvertUtf8ToTstr: + * @str: the string to convert. + * + * Converts input string from UTF8 to TSTR (locale or Unicode). + * + * Returns: a pointer to newly allocated string (must be freed with xmlFree) or NULL if an error occurs. + */ +LPTSTR +xmlSecMSCryptoConvertUtf8ToTstr(const xmlChar* str) { +#ifdef UNICODE + return xmlSecMSCryptoConvertUtf8ToUnicode(str); +#else /* UNICODE */ + return xmlSecMSCryptoConvertUtf8ToLocale(str); +#endif /* UNICODE */ +} + +/******************************************************************** + * + * Crypto Providers + * + ********************************************************************/ +/** + * xmlSecMSCryptoFindProvider: + * @providers: the pointer to list of providers, last provider should have NULL for name. + * @pszContainer: the container name for CryptAcquireContext call + * @dwFlags: the flags for CryptAcquireContext call + * @bUseXmlSecContainer: the flag to indicate whether we should try to use XmlSec container if default fails + * + * Finds the first provider from the list + * + * Returns: provider handle on success or NULL for error. + */ +HCRYPTPROV +xmlSecMSCryptoFindProvider(const xmlSecMSCryptoProviderInfo * providers, + LPCTSTR pszContainer, + DWORD dwFlags, + BOOL bUseXmlSecContainer) +{ + HCRYPTPROV res = 0; + DWORD dwLastError; + BOOL ret; + int ii; + + xmlSecAssert2(providers != NULL, 0); + + for(ii = 0; (res == 0) && (providers[ii].providerName != NULL) && (providers[ii].providerType != 0); ++ii) { + /* first try */ + ret = CryptAcquireContext(&res, + pszContainer, + providers[ii].providerName, + providers[ii].providerType, + dwFlags); + if((ret == TRUE) && (res != 0)) { + return (res); + } + + /* check errors */ + dwLastError = GetLastError(); + switch(dwLastError) { + case NTE_BAD_KEYSET: + /* This error can indicate that a newly installed provider + * does not have a usable key container yet. It needs to be + * created, and then we have to try again CryptAcquireContext. + * This is also referenced in + * http://www.microsoft.com/mind/0697/crypto.asp (inituser) + */ + ret = CryptAcquireContext(&res, + pszContainer, + providers[ii].providerName, + providers[ii].providerType, + CRYPT_NEWKEYSET | dwFlags); + if((ret == TRUE) && (res != 0)) { + return (res); + } + break; + + case NTE_EXISTS: + /* If we can, try our container */ + if(bUseXmlSecContainer == TRUE) { + ret = CryptAcquireContext(&res, + XMLSEC_CONTAINER_NAME, + providers[ii].providerName, + providers[ii].providerType, + CRYPT_NEWKEYSET | dwFlags); + if((ret == TRUE) && (res != 0)) { + /* ALEKSEY TODO - NEED TO DELETE ALL THE TEMP CONTEXTS ON SHUTDOWN + + CryptAcquireContext(&tmp, XMLSEC_CONTAINER_NAME, + providers[ii].providerName, + providers[ii].providerType, + CRYPT_DELETEKEYSET); + + */ + return (res); + } + } + break; + + default: + /* ignore */ + break; + } + } + + return (0); +} + + +/******************************************************************** + * + * Utils + * + ********************************************************************/ +int +ConvertEndian(const xmlSecByte * src, xmlSecByte * dst, xmlSecSize size) { + xmlSecByte * p; + + xmlSecAssert2(src != NULL, -1); + xmlSecAssert2(dst != NULL, -1); + xmlSecAssert2(size > 0, -1); + + for(p = dst + size - 1; p >= dst; ++src, --p) { + (*p) = (*src); + } + + return (0); +} + +int +ConvertEndianInPlace(xmlSecByte * buf, xmlSecSize size) { + xmlSecByte * p; + xmlSecByte ch; + + xmlSecAssert2(buf != NULL, -1); + xmlSecAssert2(size > 0, -1); + + for(p = buf + size - 1; p >= buf; ++buf, --p) { + ch = (*p); + (*p) = (*buf); + (*buf) = ch; + } + return (0); } |