/** * 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 Aleksey Sanin */ #include "globals.h" #include #include #include #ifndef XMLSEC_NO_GOST #include "csp_oid.h" #include "csp_calg.h" #endif #include #include #include #include #include #include #include #include #include #include #if defined(__MINGW32__) # include "xmlsec-mingw.h" #endif // GOST CSP don't support keys duplicating, so we use NT4 analogs for these... #ifndef XMLSEC_NO_GOST #ifndef XMLSEC_MSCRYPTO_NT4 #define XMLSEC_MSCRYPTO_NT4 #endif #endif #define XMLSEC_CONTAINER_NAME "xmlsec-key-container" /************************************************************************** * * Internal MSCrypto PCCERT_CONTEXT key CTX * *************************************************************************/ typedef struct _xmlSecMSCryptoKeyDataCtx xmlSecMSCryptoKeyDataCtx, *xmlSecMSCryptoKeyDataCtxPtr; #ifdef XMLSEC_MSCRYPTO_NT4 /*- * A wrapper of HCRYPTKEY, a reference countor is introduced, the function is * the same as CryptDuplicateKey. Because the CryptDuplicateKey is not support * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0 */ struct _mscrypt_key { HCRYPTKEY hKey ; volatile LONG refcnt ; } ; /*- * A wrapper of HCRYPTPROV, a reference countor is introduced, the function is * the same as CryptContextAddRef. Because the CryptContextAddRef is not support * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0 */ struct _mscrypt_prov { HCRYPTPROV hProv ; BOOL fCallerFreeProv ; volatile LONG refcnt ; } ; #endif /* XMLSEC_MSCRYPTO_NT4 */ /* * Since MSCrypto does not provide direct handles to private keys, we support * only private keys linked to a certificate context. The certificate context * also provides the public key. Only when no certificate context is used, and * a public key from xml document is provided, we need HCRYPTKEY.... The focus * now is however directed to certificates. Wouter */ struct _xmlSecMSCryptoKeyDataCtx { #ifndef XMLSEC_MSCRYPTO_NT4 HCRYPTPROV hProv; BOOL fCallerFreeProv; HCRYPTKEY hKey; #else /* XMLSEC_MSCRYPTO_NT4 */ struct _mscrypt_prov* p_prov ; struct _mscrypt_key* p_key ; #endif /* XMLSEC_MSCRYPTO_NT4 */ PCCERT_CONTEXT pCert; LPCTSTR providerName; DWORD providerType; DWORD dwKeySpec; xmlSecKeyDataType type; }; #ifndef XMLSEC_MSCRYPTO_NT4 /******************************** Provider *****************************************/ #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (ctx)->hProv static void xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); ctx->hProv = 0; ctx->fCallerFreeProv = FALSE; } static void xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if ((ctx->hProv != 0) && (ctx->fCallerFreeProv)) { CryptReleaseContext(ctx->hProv, 0); } ctx->hProv = 0; ctx->fCallerFreeProv = FALSE; } static void xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv) { xmlSecAssert(ctx != NULL); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx); ctx->hProv = hProv; ctx->fCallerFreeProv = fCallerFreeProv; } static int xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) { xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxSrc != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst); if(ctxSrc->hProv != 0) { if(!CryptContextAddRef(ctxSrc->hProv, NULL, 0)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptContextAddRef", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ctxDst->hProv = ctxSrc->hProv; ctxDst->fCallerFreeProv = TRUE; } return(0); } /******************************** Key *****************************************/ #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) ((ctx)->hKey) static void xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); ctx->hKey = 0; } static void xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if (ctx->hKey != 0) { CryptDestroyKey(ctx->hKey); } ctx->hKey = 0; } static void xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) { xmlSecAssert(ctx != NULL); xmlSecMSCryptoKeyDataCtxDestroyKey(ctx); ctx->hKey = hKey; } static int xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) { xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxSrc != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst); if (ctxSrc->hKey != 0) { if (!CryptDuplicateKey(ctxSrc->hKey, NULL, 0, &(ctxDst->hKey))) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptDuplicateKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } return(0); } #else /* XMLSEC_MSCRYPTO_NT4 */ /******************************** Provider *****************************************/ #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (((ctx)->p_prov) ? ((ctx)->p_prov->hProv) : 0) static void xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); ctx->p_prov = (struct _mscrypt_prov*)xmlMalloc(sizeof(struct _mscrypt_prov)); if(ctx->p_prov == NULL ) { xmlSecError( XMLSEC_ERRORS_HERE, "mscrypt_create_prov" , NULL, XMLSEC_ERRORS_R_MALLOC_FAILED , XMLSEC_ERRORS_NO_MESSAGE ); } memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov)); } static void xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if(ctx->p_prov != NULL) { if(InterlockedDecrement(&(ctx->p_prov->refcnt)) <= 0) { if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) { CryptReleaseContext(ctx->p_prov->hProv, 0) ; } memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov)); xmlFree(ctx->p_prov) ; } ctx->p_prov = NULL; } } static void xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv) { xmlSecAssert(ctx != NULL); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx); if((ctx->p_prov != NULL) && (ctx->p_prov->refcnt == 1)) { if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) { CryptReleaseContext(ctx->p_prov->hProv, 0) ; } memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov)); } else { xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx); xmlSecMSCryptoKeyDataCtxCreateProvider(ctx); } ctx->p_prov->hProv = hProv; ctx->p_prov->fCallerFreeProv = fCallerFreeProv; ctx->p_prov->refcnt = 1; } static int xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) { xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxSrc != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst); if (ctxSrc->p_prov != NULL) { ctxDst->p_prov = ctxSrc->p_prov; InterlockedIncrement(&(ctxDst->p_prov->refcnt)); } return(0); } /******************************** Key *****************************************/ #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) (((ctx)->p_key) ? ((ctx)->p_key->hKey) : 0) static void xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); ctx->p_key = (struct _mscrypt_key*)xmlMalloc(sizeof(struct _mscrypt_key)); if(ctx->p_key == NULL ) { xmlSecError( XMLSEC_ERRORS_HERE, "mscrypt_create_key" , NULL, XMLSEC_ERRORS_R_MALLOC_FAILED , XMLSEC_ERRORS_NO_MESSAGE ); } memset(ctx->p_key, 0, sizeof(struct _mscrypt_key)); } static void xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if(ctx->p_key != NULL) { if(InterlockedDecrement(&(ctx->p_key->refcnt)) <= 0) { if(ctx->p_key->hKey != 0) { CryptDestroyKey(ctx->p_key->hKey) ; } memset(ctx->p_key, 0, sizeof(struct _mscrypt_key)); xmlFree(ctx->p_key) ; } ctx->p_key = NULL; } } static void xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) { xmlSecAssert(ctx != NULL); if((ctx->p_key != NULL) && (ctx->p_key->refcnt == 1)) { if(ctx->p_key->hKey != 0) { CryptDestroyKey(ctx->p_key->hKey) ; } memset(ctx->p_key, 0, sizeof(struct _mscrypt_key)); } else { xmlSecMSCryptoKeyDataCtxDestroyKey(ctx); xmlSecMSCryptoKeyDataCtxCreateKey(ctx); } ctx->p_key->hKey = hKey; ctx->p_key->refcnt = 1; } static int xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) { xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxSrc != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst); if (ctxSrc->p_key != NULL) { ctxDst->p_key = ctxSrc->p_key; InterlockedIncrement(&(ctxDst->p_key->refcnt)); } return(0); } #endif /* XMLSEC_MSCRYPTO_NT4 */ /******************************** Cert *****************************************/ #define xmlSecMSCryptoKeyDataCtxGetCert(ctx) ((ctx)->pCert) static void xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); ctx->pCert = NULL; } static void xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx) { xmlSecAssert(ctx != NULL); if(ctx->pCert != NULL) { CertFreeCertificateContext(ctx->pCert); } ctx->pCert = NULL; } static void xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx, PCCERT_CONTEXT pCert) { xmlSecAssert(ctx != NULL); xmlSecMSCryptoKeyDataCtxDestroyCert(ctx); ctx->pCert = pCert; } static int xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) { xmlSecAssert2(ctxDst != NULL, -1); xmlSecAssert2(ctxSrc != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyCert(ctxDst); if(ctxSrc->pCert != NULL) { ctxDst->pCert = xmlSecMSCryptoCertDup(ctxSrc->pCert); if(ctxDst->pCert == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoPCCDup", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } return(0); } /****************************************************************************** * * xmlSecMSCryptoKeyDataCtx is located after xmlSecTransform * *****************************************************************************/ #define xmlSecMSCryptoKeyDataSize \ (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoKeyDataCtx)) #define xmlSecMSCryptoKeyDataGetCtx(data) \ ((xmlSecMSCryptoKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData))) static int xmlSecMSCryptoKeyDataDuplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecMSCryptoKeyDataFinalize (xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataGetSize (xmlSecKeyDataPtr data); /** * xmlSecMSCryptoKeyDataAdoptCert: * @data: the pointer to MSCrypto pccert data. * @pCert: the pointer to PCCERT key. * * Sets the value of key data. * * Returns: 0 on success or a negative value otherwise. */ static int xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) { xmlSecMSCryptoKeyDataCtxPtr ctx; HCRYPTKEY hKey = 0; xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1); xmlSecAssert2(pCert != NULL, -1); xmlSecAssert2(pCert->pCertInfo != NULL, -1); xmlSecAssert2((type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) != 0, -1); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx); xmlSecMSCryptoKeyDataCtxDestroyKey(ctx); xmlSecMSCryptoKeyDataCtxDestroyCert(ctx); ctx->type = type; /* Now we acquire a context for this key(pair). The context is needed * for the real crypto stuff in MS Crypto. */ if((type & xmlSecKeyDataTypePrivate) != 0){ HCRYPTPROV hProv = 0; BOOL fCallerFreeProv = FALSE; if (!CryptAcquireCertificatePrivateKey(pCert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &hProv, &(ctx->dwKeySpec), &fCallerFreeProv)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptAcquireCertificatePrivateKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv); } else if((type & xmlSecKeyDataTypePublic) != 0){ HCRYPTPROV hProv = 0; if (!CryptAcquireContext(&hProv, NULL, NULL, /* ctx->providerName, */ ctx->providerType, CRYPT_VERIFYCONTEXT)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE); ctx->dwKeySpec = 0; } else { xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_R_XMLSEC_FAILED, "Unsupported keytype"); return(-1); } /* CryptImportPublicKeyInfo is only needed when a real key handle * is needed. The key handle is needed for de/encrypting and for * verifying of a signature, *not* for signing. We could call * CryptImportPublicKeyInfo in xmlSecMSCryptoKeyDataGetKey instead * so no unnessecary calls to CryptImportPublicKeyInfo are being * made. WK */ if(!CryptImportPublicKeyInfo(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCert->pCertInfo->SubjectPublicKeyInfo), &hKey)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptImportPublicKeyInfo", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey); xmlSecMSCryptoKeyDataCtxSetCert(ctx, pCert); return(0); } static int xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data, HCRYPTPROV hProv, BOOL fCallerFreeProv, HCRYPTKEY hKey, DWORD dwKeySpec, xmlSecKeyDataType type) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1); xmlSecAssert2(hKey != 0, -1); xmlSecAssert2(type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate), -1); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv); xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey); xmlSecMSCryptoKeyDataCtxSetCert(ctx, NULL); ctx->dwKeySpec = dwKeySpec; ctx->type = type; return(0); } /** * xmlSecMSCryptoKeyDataGetKey: * @data: the key data to retrieve certificate from. * @type: type of key requested (public/private) * * Native MSCrypto key retrieval from xmlsec keydata. The * returned HKEY must not be destroyed by the caller. * * Returns: HKEY on success or NULL otherwise. */ HCRYPTKEY xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data, xmlSecKeyDataType type) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(xmlSecMSCryptoKeyDataCtxGetKey(ctx)); } /** * xmlSecMSCryptoKeyDataGetDecryptKey: * @data: the key data pointer * * Native MSCrypto decrypt key retrieval from xmlsec keydata. The * returned HKEY must not be destroyed by the caller. * * Returns: HKEY on success or NULL otherwise. */ HCRYPTKEY xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; HCRYPTKEY hKey; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); if( !CryptGetUserKey(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), AT_KEYEXCHANGE, &(hKey))) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptGetUserKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(0); } return (hKey); } /** * xmlSecMSCryptoKeyDataGetCert: * @data: the key data to retrieve certificate from. * * Native MSCrypto certificate retrieval from xmlsec keydata. The * returned PCCERT_CONTEXT must not be released by the caller. * * Returns: PCCERT_CONTEXT on success or NULL otherwise. */ PCCERT_CONTEXT xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(xmlSecMSCryptoKeyDataCtxGetCert(ctx)); } HCRYPTPROV xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx)); } DWORD xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); return(ctx->dwKeySpec); } static int xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecMSCryptoKeyDataCtxPtr ctxDst; xmlSecMSCryptoKeyDataCtxPtr ctxSrc; xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecMSCryptoKeyDataSize), -1); xmlSecAssert2(xmlSecKeyDataIsValid(src), -1); xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecMSCryptoKeyDataSize), -1); ctxDst = xmlSecMSCryptoKeyDataGetCtx(dst); xmlSecAssert2(ctxDst != NULL, -1); ctxSrc = xmlSecMSCryptoKeyDataGetCtx(src); xmlSecAssert2(ctxSrc != NULL, -1); if(xmlSecMSCryptoKeyDataCtxDuplicateProvider(ctxDst, ctxSrc) < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataCtxDuplicateProvider", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if(xmlSecMSCryptoKeyDataCtxDuplicateKey(ctxDst, ctxSrc) < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataCtxDuplicateKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if(xmlSecMSCryptoKeyDataCtxDuplicateCert(ctxDst, ctxSrc) < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)), "xmlSecMSCryptoKeyDataCtxDuplicateCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ctxDst->dwKeySpec = ctxSrc->dwKeySpec; ctxDst->providerName = ctxSrc->providerName; ctxDst->providerType = ctxSrc->providerType; ctxDst->type = ctxSrc->type; return(0); } static void xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert(xmlSecKeyDataIsValid(data)); xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize)); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert(ctx != NULL); memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx)); xmlSecMSCryptoKeyDataCtxCreateProvider(ctx); xmlSecMSCryptoKeyDataCtxCreateKey(ctx); xmlSecMSCryptoKeyDataCtxCreateCert(ctx); } static void xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert(xmlSecKeyDataIsValid(data)); xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize)); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert(ctx != NULL); xmlSecMSCryptoKeyDataCtxDestroyKey(ctx); xmlSecMSCryptoKeyDataCtxDestroyCert(ctx); xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx); memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx)); } static int xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), 0); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, 0); if(xmlSecMSCryptoKeyDataCtxGetCert(ctx) != NULL) { xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo != NULL, 0); return (CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo->SubjectPublicKeyInfo))); } else if (xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0) { DWORD length = 0; DWORD lenlen = sizeof(DWORD); if (!CryptGetKeyParam(xmlSecMSCryptoKeyDataCtxGetKey(ctx), KP_KEYLEN, (BYTE *)&length, &lenlen, 0)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(0); } return(length); } return (0); } static xmlSecKeyDataType xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown); /* We could make a call to CryptFindCertificateKeyProvInfo here, to find out if * we *really* have a private key or not. However if the certificate is not * linked to a private key, the call takes an ridiculous amount of time. * the way it is now is better I think. WK. */ return(ctx->type); } /** * xmlSecMSCryptoCertDup: * @pCert: the pointer to cert. * * Duplicates the @pCert. * * Returns: pointer to newly created PCCERT_CONTEXT object or * NULL if an error occurs. */ PCCERT_CONTEXT xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert) { PCCERT_CONTEXT ret; xmlSecAssert2(pCert != NULL, NULL); ret = CertDuplicateCertificateContext(pCert); if(ret == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CertDuplicateCertificateContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(ret); } /** * xmlSecMSCryptoCertAdopt: * @pCert: the pointer to cert. * @type: the expected key type. * * Creates key data value from the cert. * * Returns: pointer to newly created xmlsec key or NULL if an error occurs. */ xmlSecKeyDataPtr xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert, xmlSecKeyDataType type) { xmlSecKeyDataPtr data = NULL; int ret; xmlSecAssert2(pCert != NULL, NULL); xmlSecAssert2(pCert->pCertInfo != NULL, NULL); xmlSecAssert2(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL, NULL); #ifndef XMLSEC_NO_RSA if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA)) { data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataRsaId); if(data == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlSecMSCryptoDataRsaId"); return(NULL); } } #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_DSA if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_X957_DSA /*szOID_DSALG_SIGN*/)) { data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataDsaId); if(data == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlSecMSCryptoKeyDataDsaId"); return(NULL); } } #endif /* XMLSEC_NO_DSA */ #ifndef XMLSEC_NO_GOST if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001_CP) || !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001) || !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_94_CP)) { data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2001Id); if(data == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlSecMSCryptoKeyDataGost2001Id"); return(NULL); } } #endif /* XMLSEC_NO_GOST*/ if (NULL == data) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_R_INVALID_TYPE, "PCCERT_CONTEXT key type %s not supported", pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId); return(NULL); } xmlSecAssert2(data != NULL, NULL); ret = xmlSecMSCryptoKeyDataAdoptCert(data, pCert, type); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoPCCDataAdoptPCC", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecKeyDataDestroy(data); return(NULL); } return(data); } #ifndef XMLSEC_NO_RSA /************************************************************************** * * processing * * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue * The RSAKeyValue Element * * RSA key values have two fields: Modulus and Exponent. * * * xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= * * AQAB * * * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are * represented in XML as octet strings as defined by the ds:CryptoBinary type. * * Schema Definition: * * * * * * * * * * DTD Definition: * * * * * * ============================================================================ * * *************************************************************************/ static int xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type); static xmlSecKeyDataType xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data); static xmlSecSize xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data); static void xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output); static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output); static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = { sizeof(xmlSecKeyDataKlass), xmlSecMSCryptoKeyDataSize, /* data */ xmlSecNameRSAKeyValue, xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, /* xmlSecKeyDataUsage usage; */ xmlSecHrefRSAKeyValue, /* const xmlChar* href; */ xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ xmlSecMSCryptoKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ xmlSecMSCryptoKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ xmlSecMSCryptoKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ xmlSecMSCryptoKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ xmlSecMSCryptoKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ xmlSecMSCryptoKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ xmlSecMSCryptoKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ xmlSecMSCryptoKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ xmlSecMSCryptoKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ xmlSecMSCryptoKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * xmlSecMSCryptoKeyDataRsaGetKlass: * * The MSCrypto RSA CertKey data klass. * * Returns: pointer to MSCrypto RSA key data klass. */ xmlSecKeyDataId xmlSecMSCryptoKeyDataRsaGetKlass(void) { return(&xmlSecMSCryptoKeyDataRsaKlass); } static int xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), xmlSecKeyDataTypeUnknown); xmlSecMSCryptoKeyDataInitialize(data); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); ctx->providerName = MS_ENHANCED_PROV; ctx->providerType = PROV_RSA_FULL; return(0); } static int xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataRsaId), -1); xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataRsaId), -1); return(xmlSecMSCryptoKeyDataDuplicate(dst, src)); } static void xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId)); xmlSecMSCryptoKeyDataFinalize(data); } static int xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecBn modulus, exponent; xmlSecBuffer blob; unsigned int blobBufferLen; PUBLICKEYSTRUC* pubKeyStruc = NULL; RSAPUBKEY* pubKey = NULL; xmlSecByte* modulusBlob = NULL; xmlSecKeyDataPtr data = NULL; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; xmlNodePtr cur; int res = -1; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); if(xmlSecKeyGetValue(key) != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_KEY_DATA, "key already has a value"); return(-1); } /* initialize buffers */ ret = xmlSecBnInitialize(&modulus, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "modulus"); return(-1); } ret = xmlSecBnInitialize(&exponent, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "exponent"); xmlSecBnFinalize(&modulus); return(-1); } ret = xmlSecBufferInitialize(&blob, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBufferInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "blob"); xmlSecBnFinalize(&modulus); xmlSecBnFinalize(&exponent); return(-1); } /* read xml */ cur = xmlSecGetNextElementNode(node->children); /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); goto done; } ret = xmlSecBnGetNodeValue(&modulus, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&modulus) == 0)){ xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); goto done; } cur = xmlSecGetNextElementNode(cur->next); /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); goto done; } ret = xmlSecBnGetNodeValue(&exponent, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&exponent) == 0)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); goto done; } cur = xmlSecGetNextElementNode(cur->next); if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) { /* next is X node. It is REQUIRED for private key but * MSCrypto does not support it. We just ignore it */ cur = xmlSecGetNextElementNode(cur->next); } if(cur != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "no nodes expected"); goto done; } /* Now try to create the key */ blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + xmlSecBnGetSize(&modulus); ret = xmlSecBufferSetSize(&blob, blobBufferLen); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBufferSetSize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", blobBufferLen); goto done; } /* Set the PUBLICKEYSTRUC */ pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob); pubKeyStruc->bType = PUBLICKEYBLOB; pubKeyStruc->bVersion = 0x02; pubKeyStruc->reserved = 0; pubKeyStruc->aiKeyAlg = CALG_RSA_KEYX | CALG_RSA_SIGN; /* Set the public key header */ pubKey = (RSAPUBKEY*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC)); pubKey->magic = 0x31415352; /* == RSA1 public */ pubKey->bitlen = xmlSecBnGetSize(&modulus) * 8; /* Number of bits in prime modulus */ pubKey->pubexp = 0; if(sizeof(pubKey->pubexp) < xmlSecBnGetSize(&exponent)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_R_CRYPTO_FAILED, "exponent size=%d", xmlSecBnGetSize(&exponent)); goto done; } xmlSecAssert2(xmlSecBnGetData(&exponent) != NULL, -1); memcpy(&(pubKey->pubexp), xmlSecBnGetData(&exponent), xmlSecBnGetSize(&exponent)); modulusBlob = (xmlSecByte*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY)); xmlSecAssert2(xmlSecBnGetData(&modulus) != NULL, -1); memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus)); /* Now that we have the blob, import */ if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) { if(NTE_BAD_KEYSET == GetLastError()) { if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptImportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } data = xmlSecKeyDataCreate(id); if(data == NULL ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecMSCryptoKeyDataAdoptKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } hProv = 0; hKey = 0; ret = xmlSecKeySetValue(key, data); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecKeySetValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecKeyDataDestroy(data); goto done; } data = NULL; /* success */ res = 0; done: if (hProv == 0) { CryptReleaseContext(hProv, 0); } if (hKey != 0) { CryptDestroyKey(hKey); } if (data != 0) { xmlSecKeyDataDestroy(data); } xmlSecBnFinalize(&modulus); xmlSecBnFinalize(&exponent); xmlSecBufferFinalize(&blob); return(res); } static int xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecBuffer buf; DWORD dwBlobLen; xmlSecByte* blob; PUBLICKEYSTRUC* pubKeyStruc; RSAPUBKEY *pubKey; xmlSecSize modulusLen, exponentLen; xmlNodePtr cur; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key)); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1); if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecBufferInitialize(&buf, dwBlobLen); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBufferInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%ld", dwBlobLen); return(-1); } blob = xmlSecBufferGetData(&buf); if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecBufferFinalize(&buf); return(-1); } if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_DATA, "blobLen=%ld", dwBlobLen); xmlSecBufferFinalize(&buf); return(-1); } /* check PUBLICKEYSTRUC */ pubKeyStruc = (PUBLICKEYSTRUC*)blob; if(pubKeyStruc->bVersion != 0x02) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion); xmlSecBufferFinalize(&buf); return(-1); } if(pubKeyStruc->bType != PUBLICKEYBLOB) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType); xmlSecBufferFinalize(&buf); return(-1); } /* check RSAPUBKEY */ pubKey = (RSAPUBKEY *)(blob + sizeof(PUBLICKEYSTRUC)); if(pubKey->magic != 0x31415352) { /* RSA public key magic */ xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKey->magic=0x%08lx", pubKey->magic); xmlSecBufferFinalize(&buf); return(-1); } modulusLen = pubKey->bitlen / 8; if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_DATA, "blobLen=%ld; modulusLen=%d", dwBlobLen, modulusLen); xmlSecBufferFinalize(&buf); return(-1); } blob += sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY); /* first is Modulus node */ cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); xmlSecBufferFinalize(&buf); return(-1); } ret = xmlSecBnBlobSetNodeValue(blob, modulusLen, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAModulus)); xmlSecBufferFinalize(&buf); return(-1); } /* next is Exponent node. */ cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); xmlSecBufferFinalize(&buf); return(-1); } /* Remove leading zero's (from least significant end) */ blob = (xmlSecByte*)(&(pubKey->pubexp)); exponentLen = sizeof(pubKey->pubexp); while (exponentLen > 0 && blob[exponentLen - 1] == 0) { exponentLen--; } ret = xmlSecBnBlobSetNodeValue(blob, exponentLen, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRSAExponent)); xmlSecBufferFinalize(&buf); return(-1); } /* next is PrivateExponent node: not supported in MSCrypto */ xmlSecBufferFinalize(&buf); return(0); } static int xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { xmlSecMSCryptoKeyDataCtxPtr ctx; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; DWORD dwKeySpec; DWORD dwSize; int res = -1; int ret; xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), -1); xmlSecAssert2(sizeBits > 0, -1); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); if (!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, 0)) { if (NTE_BAD_KEYSET == GetLastError()) { if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } dwKeySpec = AT_KEYEXCHANGE | AT_SIGNATURE; dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE); if (!CryptGenKey(hProv, CALG_RSA_SIGN, dwSize, &hKey)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptGenKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec, xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataAdoptKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } hProv = 0; hKey = 0; /* success */ res = 0; done: if (hProv != 0) { CryptReleaseContext(hProv, 0); } if (hKey != 0) { CryptDestroyKey(hKey); } return(res); } static xmlSecKeyDataType xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data) { return(xmlSecMSCryptoKeyDataGetType(data)); } static xmlSecSize xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data) { xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), 0); return (xmlSecMSCryptoKeyDataGetSize(data)); } static void xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId)); xmlSecAssert(output != NULL); fprintf(output, "=== rsa key: size = %d\n", xmlSecMSCryptoKeyDataRsaGetSize(data)); } static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId)); xmlSecAssert(output != NULL); fprintf(output, "\n", xmlSecMSCryptoKeyDataRsaGetSize(data)); } #endif /* XMLSEC_NO_RSA */ #ifndef XMLSEC_NO_DSA /************************************************************************** * * processing * * * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue) * * DSA keys and the DSA signature algorithm are specified in [DSS]. * DSA public key values can have the following fields: * * * P - a prime modulus meeting the [DSS] requirements * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime * divisor of P-1 * * G - an integer with certain properties with respect to P and Q * * Y - G**X mod P (where X is part of the private key and not made * public) * * J - (P - 1) / Q * * seed - a DSA prime generation seed * * pgenCounter - a DSA prime generation counter * * Parameter J is available for inclusion solely for efficiency as it is * calculatable from P and Q. Parameters seed and pgenCounter are used in the * DSA prime number generation algorithm specified in [DSS]. As such, they are * optional but must either both be present or both be absent. This prime * generation algorithm is designed to provide assurance that a weak prime is * not being used and it yields a P and Q value. Parameters P, Q, and G can be * public and common to a group of users. They might be known from application * context. As such, they are optional but P and Q must either both appear or * both be absent. If all of P, Q, seed, and pgenCounter are present, * implementations are not required to check if they are consistent and are * free to use either P and Q or seed and pgenCounter. All parameters are * encoded as base64 [MIME] values. * * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are * represented in XML as octet strings as defined by the ds:CryptoBinary type. * * Schema Definition: * * * * * * * * * * * * * * * * * * * DTD Definition: * * * * * * * * * * * ============================================================================ * * To support reading/writing private keys an X element added (before Y). * todo: The current implementation does not support Seed and PgenCounter! * by this the P, Q and G are *required*! * *************************************************************************/ static int xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataDsaXmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type); static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data); static xmlSecSize xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data); static void xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output); static void xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output); static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = { sizeof(xmlSecKeyDataKlass), xmlSecMSCryptoKeyDataSize, /* data */ xmlSecNameDSAKeyValue, xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, /* xmlSecKeyDataUsage usage; */ xmlSecHrefDSAKeyValue, /* const xmlChar* href; */ xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ xmlSecMSCryptoKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */ xmlSecMSCryptoKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ xmlSecMSCryptoKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */ xmlSecMSCryptoKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ xmlSecMSCryptoKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */ xmlSecMSCryptoKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ xmlSecMSCryptoKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */ xmlSecMSCryptoKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ xmlSecMSCryptoKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ xmlSecMSCryptoKeyDataDsaDebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * xmlSecMSCryptoKeyDataDsaGetKlass: * * The DSA key data klass. * * Returns: pointer to DSA key data klass. */ xmlSecKeyDataId xmlSecMSCryptoKeyDataDsaGetKlass(void) { return(&xmlSecMSCryptoKeyDataDsaKlass); } static int xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), xmlSecKeyDataTypeUnknown); xmlSecMSCryptoKeyDataInitialize(data); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); ctx->providerName = MS_DEF_DSS_PROV; ctx->providerType = PROV_DSS; return(0); } static int xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataDsaId), -1); xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataDsaId), -1); return(xmlSecMSCryptoKeyDataDuplicate(dst, src)); } static void xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId)); xmlSecMSCryptoKeyDataFinalize(data); } static int xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyDataPtr data = NULL; xmlNodePtr cur; xmlSecBn p, q, g, y; xmlSecBuffer blob; unsigned int blobBufferLen; PUBLICKEYSTRUC *pubKeyStruc = NULL; DSSPUBKEY *pubKey = NULL; DSSSEED* seed = NULL; BYTE *buf = NULL; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; xmlSecSize i; int res = -1; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); if(xmlSecKeyGetValue(key) != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_KEY_DATA, "key already has a value"); return(-1); } /* initialize buffers */ ret = xmlSecBnInitialize(&p, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "p"); return(-1); } ret = xmlSecBnInitialize(&q, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "q"); xmlSecBnFinalize(&p); return(-1); } ret = xmlSecBnInitialize(&g, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "g"); xmlSecBnFinalize(&p); xmlSecBnFinalize(&q); return(-1); } ret = xmlSecBnInitialize(&y, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "y"); xmlSecBnFinalize(&p); xmlSecBnFinalize(&q); xmlSecBnFinalize(&g); return(-1); } ret = xmlSecBufferInitialize(&blob, 0); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBufferInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "blob"); xmlSecBnFinalize(&p); xmlSecBnFinalize(&q); xmlSecBnFinalize(&g); xmlSecBnFinalize(&y); return(-1); } /* read xml */ cur = xmlSecGetNextElementNode(node->children); /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAP)); goto done; } ret = xmlSecBnGetNodeValue(&p, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&p) == 0)){ xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAP)); goto done; } cur = xmlSecGetNextElementNode(cur->next); /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAQ)); goto done; } ret = xmlSecBnGetNodeValue(&q, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&q) == 0)){ xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAQ)); goto done; } cur = xmlSecGetNextElementNode(cur->next); /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAG)); goto done; } ret = xmlSecBnGetNodeValue(&g, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&q) == 0)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAG)); goto done; } cur = xmlSecGetNextElementNode(cur->next); if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) { /* next is X node. It is REQUIRED for private key but * MSCrypto does not support it, we just ignore it */ cur = xmlSecGetNextElementNode(cur->next); } /* next is Y node. */ if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); goto done; } ret = xmlSecBnGetNodeValue(&y, cur, xmlSecBnBase64, 1); if((ret < 0) || (xmlSecBnGetSize(&y) == 0)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnGetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); goto done; } cur = xmlSecGetNextElementNode(cur->next); /* todo: add support for J */ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) { cur = xmlSecGetNextElementNode(cur->next); } /* todo: add support for seed */ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) { cur = xmlSecGetNextElementNode(cur->next); } /* todo: add support for pgencounter */ if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) { cur = xmlSecGetNextElementNode(cur->next); } if(cur != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), xmlSecErrorsSafeString(xmlSecNodeGetName(cur)), XMLSEC_ERRORS_R_UNEXPECTED_NODE, XMLSEC_ERRORS_NO_MESSAGE); goto done; } /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */ blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * xmlSecBnGetSize(&p) + 0x14 + sizeof(DSSSEED); ret = xmlSecBufferSetSize(&blob, blobBufferLen); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecBufferSetSize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", blobBufferLen); goto done; } /* Set PUBLICKEYSTRUC */ pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob); pubKeyStruc->bType = PUBLICKEYBLOB; pubKeyStruc->bVersion = 0x02; pubKeyStruc->reserved = 0; pubKeyStruc->aiKeyAlg = CALG_DSS_SIGN; /* Set the public key header */ pubKey = (DSSPUBKEY *) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC)); pubKey->magic = 0x31535344; /* == DSS1 pub key */ pubKey->bitlen = xmlSecBnGetSize(&p) * 8; /* Number of bits in prime modulus */ /* copy the key data */ buf = (BYTE*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY)); /* set p */ xmlSecAssert2(xmlSecBnGetData(&p) != NULL, -1); memcpy(buf, xmlSecBnGetData(&p), xmlSecBnGetSize(&p)); buf += xmlSecBnGetSize(&p); /* set q */ if(xmlSecBnGetSize(&q) > 0x14) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "q", XMLSEC_ERRORS_R_INVALID_SIZE, "size=%d > 0x14", xmlSecBnGetSize(&q)); goto done; } xmlSecAssert2(xmlSecBnGetData(&q) != NULL, -1); memcpy(buf, xmlSecBnGetData(&q), xmlSecBnGetSize(&q)); buf += xmlSecBnGetSize(&q); /* Pad with zeros */ for(i = xmlSecBnGetSize(&q); i < 0x14; ++i) { *(buf++) = 0; } /* set generator */ if(xmlSecBnGetSize(&g) > xmlSecBnGetSize(&p)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "g", XMLSEC_ERRORS_R_INVALID_SIZE, "size=%d > %d", xmlSecBnGetSize(&g), xmlSecBnGetSize(&p)); goto done; } xmlSecAssert2(xmlSecBnGetData(&g) != NULL, -1); memcpy(buf, xmlSecBnGetData(&g), xmlSecBnGetSize(&g)); buf += xmlSecBnGetSize(&g); /* Pad with zeros */ for(i = xmlSecBnGetSize(&g); i < xmlSecBnGetSize(&p); ++i) { *(buf++) = 0; } /* Public key */ if(xmlSecBnGetSize(&y) > xmlSecBnGetSize(&p)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "y", XMLSEC_ERRORS_R_INVALID_SIZE, "size=%d > %d", xmlSecBnGetSize(&y), xmlSecBnGetSize(&p)); goto done; } xmlSecAssert2(xmlSecBnGetData(&y) != NULL, -1); memcpy(buf, xmlSecBnGetData(&y), xmlSecBnGetSize(&y)); buf += xmlSecBnGetSize(&y); /* Pad with zeros */ for(i = xmlSecBnGetSize(&y); i < xmlSecBnGetSize(&p); ++i) { *(buf++) = 0; } /* Set seed to 0xFFFFFFFFF */ seed = (DSSSEED*)buf; memset(seed, 0, sizeof(*seed)); seed->counter = 0xFFFFFFFF; /* SEED Counter set to 0xFFFFFFFF will cause seed to be ignored */ if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, 0)) { if (NTE_BAD_KEYSET == GetLastError()) { if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, CRYPT_NEWKEYSET)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } /* import the key blob */ if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptImportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } data = xmlSecKeyDataCreate(id); if(data == NULL ) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataAdoptKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } hProv = 0; hKey = 0; ret = xmlSecKeySetValue(key, data); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecKeySetValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } data = NULL; /* success */ res = 0; done: if (hKey != 0) { CryptDestroyKey(hKey); } if (hProv != 0) { CryptReleaseContext(hProv, 0); } if (data != NULL) { xmlSecKeyDataDestroy(data); } xmlSecBufferFinalize(&blob); xmlSecBnFinalize(&p); xmlSecBnFinalize(&q); xmlSecBnFinalize(&g); xmlSecBnFinalize(&y); return(res); } static int xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecMSCryptoKeyDataCtxPtr ctx; xmlSecBuffer buf; DWORD dwBlobLen; xmlSecByte* blob; PUBLICKEYSTRUC* pubKeyStruc; DSSPUBKEY *pubKey; xmlSecSize keyLen, len; xmlNodePtr cur; int ret; xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1); xmlSecAssert2(key != NULL, -1); xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataDsaId), -1); xmlSecAssert2(node != NULL, -1); xmlSecAssert2(keyInfoCtx != NULL, -1); ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key)); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1); if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptExportKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ret = xmlSecBufferInitialize(&buf, dwBlobLen); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBufferInitialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%ld", dwBlobLen); return(-1); } blob = xmlSecBufferGetData(&buf); if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecBufferFinalize(&buf); return(-1); } if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_DATA, "blobLen=%ld", dwBlobLen); xmlSecBufferFinalize(&buf); return(-1); } /* check PUBLICKEYSTRUC */ pubKeyStruc = (PUBLICKEYSTRUC*)blob; if(pubKeyStruc->bVersion != 0x02) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion); xmlSecBufferFinalize(&buf); return(-1); } if(pubKeyStruc->bType != PUBLICKEYBLOB) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType); xmlSecBufferFinalize(&buf); return(-1); } /* check DSSPUBKEY */ pubKey = (DSSPUBKEY*)(blob + sizeof(PUBLICKEYSTRUC)); if(pubKey->magic != 0x31535344) { /* DSS key magic */ xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptExportKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, "pubKey->magic=0x%08lx", pubKey->magic); xmlSecBufferFinalize(&buf); return(-1); } keyLen = pubKey->bitlen / 8; /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */ if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * keyLen + 0x14 + sizeof(DSSSEED)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), NULL, XMLSEC_ERRORS_R_INVALID_DATA, "blobLen=%ld; keyLen=%d", dwBlobLen, keyLen); xmlSecBufferFinalize(&buf); return(-1); } blob += sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY); /* first is P node */ cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAP)); xmlSecBufferFinalize(&buf); return(-1); } ret = xmlSecBnBlobSetNodeValue(blob, keyLen, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAP)); xmlSecBufferFinalize(&buf); return(-1); } blob += keyLen; /* next is Q node. */ cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAQ)); xmlSecBufferFinalize(&buf); return(-1); } /* we think that the size of q is 0x14, skip trailing zeros */ for(len = 0x14; len > 0 && blob[len - 1] == 0; --len); ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAQ)); xmlSecBufferFinalize(&buf); return(-1); } blob += 0x14; /* next is G node. */ cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAG)); xmlSecBufferFinalize(&buf); return(-1); } /* skip trailing zeros */ for(len = keyLen; len > 0 && blob[len - 1] == 0; --len); ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAG)); xmlSecBufferFinalize(&buf); return(-1); } blob += keyLen; /* next is X node: not supported in MSCrypto */ /* next is Y node. */ cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); xmlSecBufferFinalize(&buf); return(-1); } /* skip trailing zeros */ for(len = keyLen; len > 0 && blob[len - 1] == 0; --len); ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)), "xmlSecBnBlobSetNodeValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY)); xmlSecBufferFinalize(&buf); return(-1); } blob += keyLen; xmlSecBufferFinalize(&buf); return(0); } static int xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) { xmlSecMSCryptoKeyDataCtxPtr ctx; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; DWORD dwKeySpec; DWORD dwSize; int res = -1; int ret; xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown); xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), -1); xmlSecAssert2(sizeBits > 0, -1); ctx = xmlSecMSCryptoKeyDataGetCtx(data); if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, 0)) { if (NTE_BAD_KEYSET == GetLastError()) { if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, CRYPT_NEWKEYSET)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptAcquireContext", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } } dwKeySpec = AT_SIGNATURE; dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE); if (!CryptGenKey(hProv, CALG_DSS_SIGN, dwSize, &hKey)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "CryptGenKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec, xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataAdoptKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } hProv = 0; hKey = 0; /* success */ res = 0; done: if (hProv != 0) { CryptReleaseContext(hProv, 0); } if (hKey != 0) { CryptDestroyKey(hKey); } return(res); } static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data) { return(xmlSecMSCryptoKeyDataGetType(data)); } static xmlSecSize xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data) { xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), 0); return xmlSecMSCryptoKeyDataGetSize(data); } static void xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId)); xmlSecAssert(output != NULL); fprintf(output, "=== dsa key: size = %d\n", xmlSecMSCryptoKeyDataDsaGetSize(data)); } static void xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId)); xmlSecAssert(output != NULL); fprintf(output, "\n", xmlSecMSCryptoKeyDataDsaGetSize(data)); } #endif /* XMLSEC_NO_DSA */ #ifndef XMLSEC_NO_GOST /************************************************************************** * * GOST2001 xml key representation processing. Contain errors. * *************************************************************************/ static int xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src); static void xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data); static int xmlSecMSCryptoKeyDataGost2001XmlRead (xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataGost2001XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx); static int xmlSecMSCryptoKeyDataGost2001Generate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type); static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data); static xmlSecSize xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data); static void xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output); static void xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output); static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = { sizeof(xmlSecKeyDataKlass), xmlSecMSCryptoKeyDataSize, /* data */ xmlSecNameGOST2001KeyValue, xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, /* xmlSecKeyDataUsage usage; */ xmlSecHrefGOST2001KeyValue, /* const xmlChar* href; */ xmlSecNodeGOST2001KeyValue, /* const xmlChar* dataNodeName; */ xmlSecDSigNs, /* const xmlChar* dataNodeNs; */ /* constructors/destructor */ xmlSecMSCryptoKeyDataGost2001Initialize, /* xmlSecKeyDataInitializeMethod initialize; */ xmlSecMSCryptoKeyDataGost2001Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */ xmlSecMSCryptoKeyDataGost2001Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */ NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */ /* get info */ xmlSecMSCryptoKeyDataGost2001GetType, /* xmlSecKeyDataGetTypeMethod getType; */ xmlSecMSCryptoKeyDataGost2001GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */ NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */ /* read/write */ NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */ NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */ NULL, /* xmlSecKeyDataBinReadMethod binRead; */ NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */ /* debug */ xmlSecMSCryptoKeyDataGost2001DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */ xmlSecMSCryptoKeyDataGost2001DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */ /* reserved for the future */ NULL, /* void* reserved0; */ NULL, /* void* reserved1; */ }; /** * xmlSecMSCryptoKeyDataGost2001GetKlass: * * The GOST2001 key data klass. * * Returns: pointer to GOST2001 key data klass. */ xmlSecKeyDataId xmlSecMSCryptoKeyDataGost2001GetKlass(void) { return(&xmlSecMSCryptoKeyDataGost2001Klass); } static int xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) { xmlSecMSCryptoKeyDataCtxPtr ctx; HCRYPTPROV tmp_ctx = 0; xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown); xmlSecMSCryptoKeyDataInitialize(data); ctx = xmlSecMSCryptoKeyDataGetCtx(data); xmlSecAssert2(ctx != NULL, -1); /* GOST Algorithm is provided by several CSP's, so we try to find any installed */ if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { ctx->providerName = "MagPro CSP"; ctx->providerType = PROV_MAGPRO_GOST; } else { if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { ctx->providerName = "CryptoPro CSP"; ctx->providerType = PROV_CRYPTOPRO_GOST; } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "xmlSecMSCryptoKeyDataGost2001Initialize", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return -1; } } CryptReleaseContext(tmp_ctx, 0); return(0); } static int xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) { xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2001Id), -1); xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2001Id), -1); return(xmlSecMSCryptoKeyDataDuplicate(dst, src)); } static void xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id)); xmlSecMSCryptoKeyDataFinalize(data); } static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data) { return(xmlSecMSCryptoKeyDataGetType(data)); } static xmlSecSize xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data) { xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), 0); return xmlSecMSCryptoKeyDataGetSize(data); } static void xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id)); xmlSecAssert(output != NULL); fprintf(output, "=== dsa key: size = %d\n", xmlSecMSCryptoKeyDataGost2001GetSize(data)); } static void xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) { xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id)); xmlSecAssert(output != NULL); fprintf(output, "\n", xmlSecMSCryptoKeyDataGost2001GetSize(data)); } #endif /* XMLSEC_NO_GOST*/