4 * This is free software; see Copyright file in the source
5 * distribution for preciese wording.
7 * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
8 * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
17 #ifndef XMLSEC_NO_GOST
22 #include <xmlsec/xmlsec.h>
23 #include <xmlsec/xmltree.h>
24 #include <xmlsec/keys.h>
25 #include <xmlsec/keyinfo.h>
26 #include <xmlsec/transforms.h>
27 #include <xmlsec/errors.h>
28 #include <xmlsec/bn.h>
30 #include <xmlsec/mscrypto/certkeys.h>
31 #include <xmlsec/mscrypto/crypto.h>
32 #include <xmlsec/mscrypto/x509.h>
34 #if defined(__MINGW32__)
35 # include "xmlsec-mingw.h"
38 // GOST CSP don't support keys duplicating, so we use NT4 analogs for these...
39 #ifndef XMLSEC_NO_GOST
40 #ifndef XMLSEC_MSCRYPTO_NT4
41 #define XMLSEC_MSCRYPTO_NT4
45 #define XMLSEC_CONTAINER_NAME "xmlsec-key-container"
47 /**************************************************************************
49 * Internal MSCrypto PCCERT_CONTEXT key CTX
51 *************************************************************************/
52 typedef struct _xmlSecMSCryptoKeyDataCtx xmlSecMSCryptoKeyDataCtx,
53 *xmlSecMSCryptoKeyDataCtxPtr;
55 #ifdef XMLSEC_MSCRYPTO_NT4
57 * A wrapper of HCRYPTKEY, a reference countor is introduced, the function is
58 * the same as CryptDuplicateKey. Because the CryptDuplicateKey is not support
59 * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
63 volatile LONG refcnt ;
67 * A wrapper of HCRYPTPROV, a reference countor is introduced, the function is
68 * the same as CryptContextAddRef. Because the CryptContextAddRef is not support
69 * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
71 struct _mscrypt_prov {
73 BOOL fCallerFreeProv ;
74 volatile LONG refcnt ;
76 #endif /* XMLSEC_MSCRYPTO_NT4 */
79 * Since MSCrypto does not provide direct handles to private keys, we support
80 * only private keys linked to a certificate context. The certificate context
81 * also provides the public key. Only when no certificate context is used, and
82 * a public key from xml document is provided, we need HCRYPTKEY.... The focus
83 * now is however directed to certificates. Wouter
85 struct _xmlSecMSCryptoKeyDataCtx {
86 #ifndef XMLSEC_MSCRYPTO_NT4
90 #else /* XMLSEC_MSCRYPTO_NT4 */
91 struct _mscrypt_prov* p_prov ;
92 struct _mscrypt_key* p_key ;
93 #endif /* XMLSEC_MSCRYPTO_NT4 */
98 xmlSecKeyDataType type;
101 #ifndef XMLSEC_MSCRYPTO_NT4
103 /******************************** Provider *****************************************/
104 #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (ctx)->hProv
107 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
108 xmlSecAssert(ctx != NULL);
111 ctx->fCallerFreeProv = FALSE;
115 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
116 xmlSecAssert(ctx != NULL);
118 if ((ctx->hProv != 0) && (ctx->fCallerFreeProv)) {
119 CryptReleaseContext(ctx->hProv, 0);
122 ctx->fCallerFreeProv = FALSE;
126 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
128 xmlSecAssert(ctx != NULL);
130 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
132 ctx->fCallerFreeProv = fCallerFreeProv;
136 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
137 xmlSecAssert2(ctxDst != NULL, -1);
138 xmlSecAssert2(ctxSrc != NULL, -1);
140 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
142 if(ctxSrc->hProv != 0) {
143 if(!CryptContextAddRef(ctxSrc->hProv, NULL, 0)) {
144 xmlSecError(XMLSEC_ERRORS_HERE,
146 "CryptContextAddRef",
147 XMLSEC_ERRORS_R_CRYPTO_FAILED,
148 XMLSEC_ERRORS_NO_MESSAGE);
152 ctxDst->hProv = ctxSrc->hProv;
153 ctxDst->fCallerFreeProv = TRUE;
158 /******************************** Key *****************************************/
159 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) ((ctx)->hKey)
162 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
163 xmlSecAssert(ctx != NULL);
169 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
170 xmlSecAssert(ctx != NULL);
172 if (ctx->hKey != 0) {
173 CryptDestroyKey(ctx->hKey);
179 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
180 xmlSecAssert(ctx != NULL);
182 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
187 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
188 xmlSecAssert2(ctxDst != NULL, -1);
189 xmlSecAssert2(ctxSrc != NULL, -1);
191 xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
192 if (ctxSrc->hKey != 0) {
193 if (!CryptDuplicateKey(ctxSrc->hKey, NULL, 0, &(ctxDst->hKey))) {
194 xmlSecError(XMLSEC_ERRORS_HERE,
197 XMLSEC_ERRORS_R_CRYPTO_FAILED,
198 XMLSEC_ERRORS_NO_MESSAGE);
206 #else /* XMLSEC_MSCRYPTO_NT4 */
208 /******************************** Provider *****************************************/
209 #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (((ctx)->p_prov) ? ((ctx)->p_prov->hProv) : 0)
212 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
213 xmlSecAssert(ctx != NULL);
215 ctx->p_prov = (struct _mscrypt_prov*)xmlMalloc(sizeof(struct _mscrypt_prov));
216 if(ctx->p_prov == NULL ) {
217 xmlSecError( XMLSEC_ERRORS_HERE,
218 "mscrypt_create_prov" ,
220 XMLSEC_ERRORS_R_MALLOC_FAILED ,
221 XMLSEC_ERRORS_NO_MESSAGE
224 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
228 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
229 xmlSecAssert(ctx != NULL);
231 if(ctx->p_prov != NULL) {
232 if(InterlockedDecrement(&(ctx->p_prov->refcnt)) <= 0) {
233 if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
234 CryptReleaseContext(ctx->p_prov->hProv, 0) ;
236 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
237 xmlFree(ctx->p_prov) ;
244 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
246 xmlSecAssert(ctx != NULL);
248 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
250 if((ctx->p_prov != NULL) && (ctx->p_prov->refcnt == 1)) {
251 if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
252 CryptReleaseContext(ctx->p_prov->hProv, 0) ;
254 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
256 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
257 xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
260 ctx->p_prov->hProv = hProv;
261 ctx->p_prov->fCallerFreeProv = fCallerFreeProv;
262 ctx->p_prov->refcnt = 1;
266 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
267 xmlSecAssert2(ctxDst != NULL, -1);
268 xmlSecAssert2(ctxSrc != NULL, -1);
270 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
272 if (ctxSrc->p_prov != NULL) {
273 ctxDst->p_prov = ctxSrc->p_prov;
274 InterlockedIncrement(&(ctxDst->p_prov->refcnt));
280 /******************************** Key *****************************************/
281 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) (((ctx)->p_key) ? ((ctx)->p_key->hKey) : 0)
284 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
285 xmlSecAssert(ctx != NULL);
287 ctx->p_key = (struct _mscrypt_key*)xmlMalloc(sizeof(struct _mscrypt_key));
288 if(ctx->p_key == NULL ) {
289 xmlSecError( XMLSEC_ERRORS_HERE,
290 "mscrypt_create_key" ,
292 XMLSEC_ERRORS_R_MALLOC_FAILED ,
293 XMLSEC_ERRORS_NO_MESSAGE
296 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
300 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
301 xmlSecAssert(ctx != NULL);
303 if(ctx->p_key != NULL) {
304 if(InterlockedDecrement(&(ctx->p_key->refcnt)) <= 0) {
305 if(ctx->p_key->hKey != 0) {
306 CryptDestroyKey(ctx->p_key->hKey) ;
308 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
309 xmlFree(ctx->p_key) ;
316 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
317 xmlSecAssert(ctx != NULL);
319 if((ctx->p_key != NULL) && (ctx->p_key->refcnt == 1)) {
320 if(ctx->p_key->hKey != 0) {
321 CryptDestroyKey(ctx->p_key->hKey) ;
323 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
325 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
326 xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
328 ctx->p_key->hKey = hKey;
329 ctx->p_key->refcnt = 1;
333 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
334 xmlSecAssert2(ctxDst != NULL, -1);
335 xmlSecAssert2(ctxSrc != NULL, -1);
337 xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
338 if (ctxSrc->p_key != NULL) {
339 ctxDst->p_key = ctxSrc->p_key;
340 InterlockedIncrement(&(ctxDst->p_key->refcnt));
346 #endif /* XMLSEC_MSCRYPTO_NT4 */
348 /******************************** Cert *****************************************/
349 #define xmlSecMSCryptoKeyDataCtxGetCert(ctx) ((ctx)->pCert)
352 xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
353 xmlSecAssert(ctx != NULL);
359 xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
360 xmlSecAssert(ctx != NULL);
362 if(ctx->pCert != NULL) {
363 CertFreeCertificateContext(ctx->pCert);
369 xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx, PCCERT_CONTEXT pCert) {
370 xmlSecAssert(ctx != NULL);
372 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
377 xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
378 xmlSecAssert2(ctxDst != NULL, -1);
379 xmlSecAssert2(ctxSrc != NULL, -1);
381 xmlSecMSCryptoKeyDataCtxDestroyCert(ctxDst);
382 if(ctxSrc->pCert != NULL) {
383 ctxDst->pCert = xmlSecMSCryptoCertDup(ctxSrc->pCert);
384 if(ctxDst->pCert == NULL) {
385 xmlSecError(XMLSEC_ERRORS_HERE,
387 "xmlSecMSCryptoPCCDup",
388 XMLSEC_ERRORS_R_XMLSEC_FAILED,
389 XMLSEC_ERRORS_NO_MESSAGE);
396 /******************************************************************************
398 * xmlSecMSCryptoKeyDataCtx is located after xmlSecTransform
400 *****************************************************************************/
401 #define xmlSecMSCryptoKeyDataSize \
402 (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoKeyDataCtx))
403 #define xmlSecMSCryptoKeyDataGetCtx(data) \
404 ((xmlSecMSCryptoKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
406 static int xmlSecMSCryptoKeyDataDuplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
407 static void xmlSecMSCryptoKeyDataFinalize (xmlSecKeyDataPtr data);
408 static int xmlSecMSCryptoKeyDataGetSize (xmlSecKeyDataPtr data);
411 * xmlSecMSCryptoKeyDataAdoptCert:
412 * @data: the pointer to MSCrypto pccert data.
413 * @pCert: the pointer to PCCERT key.
415 * Sets the value of key data.
417 * Returns: 0 on success or a negative value otherwise.
420 xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
421 xmlSecMSCryptoKeyDataCtxPtr ctx;
424 xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
425 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
426 xmlSecAssert2(pCert != NULL, -1);
427 xmlSecAssert2(pCert->pCertInfo != NULL, -1);
428 xmlSecAssert2((type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) != 0, -1);
430 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
431 xmlSecAssert2(ctx != NULL, -1);
433 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
434 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
435 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
439 /* Now we acquire a context for this key(pair). The context is needed
440 * for the real crypto stuff in MS Crypto.
442 if((type & xmlSecKeyDataTypePrivate) != 0){
443 HCRYPTPROV hProv = 0;
444 BOOL fCallerFreeProv = FALSE;
446 if (!CryptAcquireCertificatePrivateKey(pCert,
447 CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
452 xmlSecError(XMLSEC_ERRORS_HERE,
454 "CryptAcquireCertificatePrivateKey",
455 XMLSEC_ERRORS_R_CRYPTO_FAILED,
456 XMLSEC_ERRORS_NO_MESSAGE);
459 xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
460 } else if((type & xmlSecKeyDataTypePublic) != 0){
461 HCRYPTPROV hProv = 0;
462 if (!CryptAcquireContext(&hProv,
464 NULL, /* ctx->providerName, */
466 CRYPT_VERIFYCONTEXT)) {
467 xmlSecError(XMLSEC_ERRORS_HERE,
469 "CryptAcquireContext",
470 XMLSEC_ERRORS_R_CRYPTO_FAILED,
471 XMLSEC_ERRORS_NO_MESSAGE);
474 xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
477 xmlSecError(XMLSEC_ERRORS_HERE,
480 XMLSEC_ERRORS_R_XMLSEC_FAILED,
481 "Unsupported keytype");
485 /* CryptImportPublicKeyInfo is only needed when a real key handle
486 * is needed. The key handle is needed for de/encrypting and for
487 * verifying of a signature, *not* for signing. We could call
488 * CryptImportPublicKeyInfo in xmlSecMSCryptoKeyDataGetKey instead
489 * so no unnessecary calls to CryptImportPublicKeyInfo are being
492 if(!CryptImportPublicKeyInfo(xmlSecMSCryptoKeyDataCtxGetProvider(ctx),
493 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
494 &(pCert->pCertInfo->SubjectPublicKeyInfo),
496 xmlSecError(XMLSEC_ERRORS_HERE,
498 "CryptImportPublicKeyInfo",
499 XMLSEC_ERRORS_R_CRYPTO_FAILED,
500 XMLSEC_ERRORS_NO_MESSAGE);
504 xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
505 xmlSecMSCryptoKeyDataCtxSetCert(ctx, pCert);
510 xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data,
512 BOOL fCallerFreeProv,
515 xmlSecKeyDataType type) {
516 xmlSecMSCryptoKeyDataCtxPtr ctx;
518 xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
519 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
520 xmlSecAssert2(hKey != 0, -1);
521 xmlSecAssert2(type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate), -1);
523 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
524 xmlSecAssert2(ctx != NULL, -1);
526 xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
527 xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
528 xmlSecMSCryptoKeyDataCtxSetCert(ctx, NULL);
530 ctx->dwKeySpec = dwKeySpec;
537 * xmlSecMSCryptoKeyDataGetKey:
538 * @data: the key data to retrieve certificate from.
539 * @type: type of key requested (public/private)
541 * Native MSCrypto key retrieval from xmlsec keydata. The
542 * returned HKEY must not be destroyed by the caller.
544 * Returns: HKEY on success or NULL otherwise.
547 xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data, xmlSecKeyDataType type) {
548 xmlSecMSCryptoKeyDataCtxPtr ctx;
550 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
551 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
553 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
554 xmlSecAssert2(ctx != NULL, 0);
556 return(xmlSecMSCryptoKeyDataCtxGetKey(ctx));
560 * xmlSecMSCryptoKeyDataGetDecryptKey:
561 * @data: the key data pointer
563 * Native MSCrypto decrypt key retrieval from xmlsec keydata. The
564 * returned HKEY must not be destroyed by the caller.
566 * Returns: HKEY on success or NULL otherwise.
569 xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data) {
570 xmlSecMSCryptoKeyDataCtxPtr ctx;
573 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
574 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
576 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
577 xmlSecAssert2(ctx != NULL, 0);
579 if( !CryptGetUserKey(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), AT_KEYEXCHANGE, &(hKey))) {
580 xmlSecError(XMLSEC_ERRORS_HERE,
583 XMLSEC_ERRORS_R_CRYPTO_FAILED,
584 XMLSEC_ERRORS_NO_MESSAGE);
591 * xmlSecMSCryptoKeyDataGetCert:
592 * @data: the key data to retrieve certificate from.
594 * Native MSCrypto certificate retrieval from xmlsec keydata. The
595 * returned PCCERT_CONTEXT must not be released by the caller.
597 * Returns: PCCERT_CONTEXT on success or NULL otherwise.
600 xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data) {
601 xmlSecMSCryptoKeyDataCtxPtr ctx;
603 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
604 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
606 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
607 xmlSecAssert2(ctx != NULL, 0);
609 return(xmlSecMSCryptoKeyDataCtxGetCert(ctx));
613 xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
614 xmlSecMSCryptoKeyDataCtxPtr ctx;
616 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
617 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
619 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
620 xmlSecAssert2(ctx != NULL, 0);
622 return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx));
626 xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) {
627 xmlSecMSCryptoKeyDataCtxPtr ctx;
629 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
630 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
632 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
633 xmlSecAssert2(ctx != NULL, 0);
635 return(ctx->dwKeySpec);
639 xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
640 xmlSecMSCryptoKeyDataCtxPtr ctxDst;
641 xmlSecMSCryptoKeyDataCtxPtr ctxSrc;
643 xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
644 xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecMSCryptoKeyDataSize), -1);
645 xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
646 xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecMSCryptoKeyDataSize), -1);
648 ctxDst = xmlSecMSCryptoKeyDataGetCtx(dst);
649 xmlSecAssert2(ctxDst != NULL, -1);
651 ctxSrc = xmlSecMSCryptoKeyDataGetCtx(src);
652 xmlSecAssert2(ctxSrc != NULL, -1);
654 if(xmlSecMSCryptoKeyDataCtxDuplicateProvider(ctxDst, ctxSrc) < 0) {
655 xmlSecError(XMLSEC_ERRORS_HERE,
656 xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
657 "xmlSecMSCryptoKeyDataCtxDuplicateProvider",
658 XMLSEC_ERRORS_R_XMLSEC_FAILED,
659 XMLSEC_ERRORS_NO_MESSAGE);
663 if(xmlSecMSCryptoKeyDataCtxDuplicateKey(ctxDst, ctxSrc) < 0) {
664 xmlSecError(XMLSEC_ERRORS_HERE,
665 xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
666 "xmlSecMSCryptoKeyDataCtxDuplicateKey",
667 XMLSEC_ERRORS_R_XMLSEC_FAILED,
668 XMLSEC_ERRORS_NO_MESSAGE);
672 if(xmlSecMSCryptoKeyDataCtxDuplicateCert(ctxDst, ctxSrc) < 0) {
673 xmlSecError(XMLSEC_ERRORS_HERE,
674 xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
675 "xmlSecMSCryptoKeyDataCtxDuplicateCert",
676 XMLSEC_ERRORS_R_XMLSEC_FAILED,
677 XMLSEC_ERRORS_NO_MESSAGE);
681 ctxDst->dwKeySpec = ctxSrc->dwKeySpec;
682 ctxDst->providerName = ctxSrc->providerName;
683 ctxDst->providerType = ctxSrc->providerType;
684 ctxDst->type = ctxSrc->type;
690 xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data) {
691 xmlSecMSCryptoKeyDataCtxPtr ctx;
693 xmlSecAssert(xmlSecKeyDataIsValid(data));
694 xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
696 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
697 xmlSecAssert(ctx != NULL);
699 memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
701 xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
702 xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
703 xmlSecMSCryptoKeyDataCtxCreateCert(ctx);
707 xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data) {
708 xmlSecMSCryptoKeyDataCtxPtr ctx;
710 xmlSecAssert(xmlSecKeyDataIsValid(data));
711 xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
713 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
714 xmlSecAssert(ctx != NULL);
716 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
717 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
718 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
720 memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
724 xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data) {
725 xmlSecMSCryptoKeyDataCtxPtr ctx;
727 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
728 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
730 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
731 xmlSecAssert2(ctx != NULL, 0);
733 if(xmlSecMSCryptoKeyDataCtxGetCert(ctx) != NULL) {
734 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo != NULL, 0);
735 return (CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
736 &(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo->SubjectPublicKeyInfo)));
737 } else if (xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0) {
739 DWORD lenlen = sizeof(DWORD);
741 if (!CryptGetKeyParam(xmlSecMSCryptoKeyDataCtxGetKey(ctx), KP_KEYLEN, (BYTE *)&length, &lenlen, 0)) {
742 xmlSecError(XMLSEC_ERRORS_HERE,
744 "CertDuplicateCertificateContext",
745 XMLSEC_ERRORS_R_CRYPTO_FAILED,
746 XMLSEC_ERRORS_NO_MESSAGE);
755 static xmlSecKeyDataType
756 xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data) {
757 xmlSecMSCryptoKeyDataCtxPtr ctx;
759 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
760 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
762 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
763 xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
765 /* We could make a call to CryptFindCertificateKeyProvInfo here, to find out if
766 * we *really* have a private key or not. However if the certificate is not
767 * linked to a private key, the call takes an ridiculous amount of time.
768 * the way it is now is better I think. WK.
774 * xmlSecMSCryptoCertDup:
775 * @pCert: the pointer to cert.
777 * Duplicates the @pCert.
779 * Returns: pointer to newly created PCCERT_CONTEXT object or
780 * NULL if an error occurs.
782 PCCERT_CONTEXT xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert) {
785 xmlSecAssert2(pCert != NULL, NULL);
787 ret = CertDuplicateCertificateContext(pCert);
789 xmlSecError(XMLSEC_ERRORS_HERE,
791 "CertDuplicateCertificateContext",
792 XMLSEC_ERRORS_R_CRYPTO_FAILED,
793 XMLSEC_ERRORS_NO_MESSAGE);
802 * xmlSecMSCryptoCertAdopt:
803 * @pCert: the pointer to cert.
804 * @type: the expected key type.
806 * Creates key data value from the cert.
808 * Returns: pointer to newly created xmlsec key or NULL if an error occurs.
811 xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
812 xmlSecKeyDataPtr data = NULL;
815 xmlSecAssert2(pCert != NULL, NULL);
816 xmlSecAssert2(pCert->pCertInfo != NULL, NULL);
817 xmlSecAssert2(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL, NULL);
819 #ifndef XMLSEC_NO_RSA
820 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA)) {
821 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataRsaId);
823 xmlSecError(XMLSEC_ERRORS_HERE,
825 "xmlSecKeyDataCreate",
826 XMLSEC_ERRORS_R_XMLSEC_FAILED,
827 "xmlSecMSCryptoDataRsaId");
831 #endif /* XMLSEC_NO_RSA */
833 #ifndef XMLSEC_NO_DSA
834 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_X957_DSA /*szOID_DSALG_SIGN*/)) {
835 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataDsaId);
837 xmlSecError(XMLSEC_ERRORS_HERE,
839 "xmlSecKeyDataCreate",
840 XMLSEC_ERRORS_R_XMLSEC_FAILED,
841 "xmlSecMSCryptoKeyDataDsaId");
845 #endif /* XMLSEC_NO_DSA */
847 #ifndef XMLSEC_NO_GOST
848 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001_CP) ||
849 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001) ||
850 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_94_CP)) {
851 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2001Id);
853 xmlSecError(XMLSEC_ERRORS_HERE,
855 "xmlSecKeyDataCreate",
856 XMLSEC_ERRORS_R_XMLSEC_FAILED,
857 "xmlSecMSCryptoKeyDataGost2001Id");
861 #endif /* XMLSEC_NO_GOST*/
864 xmlSecError(XMLSEC_ERRORS_HERE,
867 XMLSEC_ERRORS_R_INVALID_TYPE,
868 "PCCERT_CONTEXT key type %s not supported", pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
872 xmlSecAssert2(data != NULL, NULL);
874 ret = xmlSecMSCryptoKeyDataAdoptCert(data, pCert, type);
876 xmlSecError(XMLSEC_ERRORS_HERE,
878 "xmlSecMSCryptoPCCDataAdoptPCC",
879 XMLSEC_ERRORS_R_XMLSEC_FAILED,
880 XMLSEC_ERRORS_NO_MESSAGE);
881 xmlSecKeyDataDestroy(data);
888 #ifndef XMLSEC_NO_RSA
889 /**************************************************************************
891 * <dsig:RSAKeyValue> processing
893 * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
894 * The RSAKeyValue Element
896 * RSA key values have two fields: Modulus and Exponent.
899 * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
900 * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
901 * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
903 * <Exponent>AQAB</Exponent>
906 * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
907 * represented in XML as octet strings as defined by the ds:CryptoBinary type.
911 * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
912 * <complexType name="RSAKeyValueType">
914 * <element name="Modulus" type="ds:CryptoBinary"/>
915 * <element name="Exponent" type="ds:CryptoBinary"/>
921 * <!ELEMENT RSAKeyValue (Modulus, Exponent) >
922 * <!ELEMENT Modulus (#PCDATA) >
923 * <!ELEMENT Exponent (#PCDATA) >
925 * ============================================================================
928 *************************************************************************/
930 static int xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data);
931 static int xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
932 static void xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data);
933 static int xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id,
936 xmlSecKeyInfoCtxPtr keyInfoCtx);
937 static int xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id,
940 xmlSecKeyInfoCtxPtr keyInfoCtx);
941 static int xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data,
943 xmlSecKeyDataType type);
945 static xmlSecKeyDataType xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data);
946 static xmlSecSize xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data);
947 static void xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output);
948 static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output);
950 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = {
951 sizeof(xmlSecKeyDataKlass),
952 xmlSecMSCryptoKeyDataSize,
955 xmlSecNameRSAKeyValue,
956 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
957 /* xmlSecKeyDataUsage usage; */
958 xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
959 xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
960 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
962 /* constructors/destructor */
963 xmlSecMSCryptoKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
964 xmlSecMSCryptoKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
965 xmlSecMSCryptoKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
966 xmlSecMSCryptoKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
969 xmlSecMSCryptoKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
970 xmlSecMSCryptoKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
971 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
974 xmlSecMSCryptoKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
975 xmlSecMSCryptoKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
976 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
977 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
980 xmlSecMSCryptoKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
981 xmlSecMSCryptoKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
983 /* reserved for the future */
984 NULL, /* void* reserved0; */
985 NULL, /* void* reserved1; */
989 * xmlSecMSCryptoKeyDataRsaGetKlass:
991 * The MSCrypto RSA CertKey data klass.
993 * Returns: pointer to MSCrypto RSA key data klass.
996 xmlSecMSCryptoKeyDataRsaGetKlass(void) {
997 return(&xmlSecMSCryptoKeyDataRsaKlass);
1001 xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
1002 xmlSecMSCryptoKeyDataCtxPtr ctx;
1004 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), xmlSecKeyDataTypeUnknown);
1006 xmlSecMSCryptoKeyDataInitialize(data);
1008 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1009 xmlSecAssert2(ctx != NULL, -1);
1011 ctx->providerName = MS_ENHANCED_PROV;
1012 ctx->providerType = PROV_RSA_FULL;
1018 xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1019 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataRsaId), -1);
1020 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataRsaId), -1);
1022 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1026 xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
1027 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1029 xmlSecMSCryptoKeyDataFinalize(data);
1033 xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1034 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1035 xmlSecBn modulus, exponent;
1037 unsigned int blobBufferLen;
1038 PUBLICKEYSTRUC* pubKeyStruc = NULL;
1039 RSAPUBKEY* pubKey = NULL;
1040 xmlSecByte* modulusBlob = NULL;
1041 xmlSecKeyDataPtr data = NULL;
1042 HCRYPTPROV hProv = 0;
1048 xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
1049 xmlSecAssert2(key != NULL, -1);
1050 xmlSecAssert2(node != NULL, -1);
1051 xmlSecAssert2(keyInfoCtx != NULL, -1);
1053 if(xmlSecKeyGetValue(key) != NULL) {
1054 xmlSecError(XMLSEC_ERRORS_HERE,
1055 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1057 XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1058 "key already has a value");
1062 /* initialize buffers */
1063 ret = xmlSecBnInitialize(&modulus, 0);
1065 xmlSecError(XMLSEC_ERRORS_HERE,
1066 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1067 "xmlSecBnInitialize",
1068 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1073 ret = xmlSecBnInitialize(&exponent, 0);
1075 xmlSecError(XMLSEC_ERRORS_HERE,
1076 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1077 "xmlSecBnInitialize",
1078 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1080 xmlSecBnFinalize(&modulus);
1084 ret = xmlSecBufferInitialize(&blob, 0);
1086 xmlSecError(XMLSEC_ERRORS_HERE,
1087 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1088 "xmlSecBufferInitialize",
1089 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1091 xmlSecBnFinalize(&modulus);
1092 xmlSecBnFinalize(&exponent);
1097 cur = xmlSecGetNextElementNode(node->children);
1099 /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/
1100 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) {
1101 xmlSecError(XMLSEC_ERRORS_HERE,
1102 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1103 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1104 XMLSEC_ERRORS_R_INVALID_NODE,
1106 xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1110 ret = xmlSecBnGetNodeValue(&modulus, cur, xmlSecBnBase64, 1);
1111 if((ret < 0) || (xmlSecBnGetSize(&modulus) == 0)){
1112 xmlSecError(XMLSEC_ERRORS_HERE,
1114 "xmlSecBnGetNodeValue",
1115 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1117 xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1120 cur = xmlSecGetNextElementNode(cur->next);
1122 /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/
1123 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) {
1124 xmlSecError(XMLSEC_ERRORS_HERE,
1125 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1126 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1127 XMLSEC_ERRORS_R_INVALID_NODE,
1129 xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1132 ret = xmlSecBnGetNodeValue(&exponent, cur, xmlSecBnBase64, 1);
1133 if((ret < 0) || (xmlSecBnGetSize(&exponent) == 0)) {
1134 xmlSecError(XMLSEC_ERRORS_HERE,
1136 "xmlSecBnGetNodeValue",
1137 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1139 xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1142 cur = xmlSecGetNextElementNode(cur->next);
1144 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
1145 /* next is X node. It is REQUIRED for private key but
1146 * MSCrypto does not support it. We just ignore it */
1147 cur = xmlSecGetNextElementNode(cur->next);
1151 xmlSecError(XMLSEC_ERRORS_HERE,
1152 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1153 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1154 XMLSEC_ERRORS_R_INVALID_NODE,
1155 "no nodes expected");
1159 /* Now try to create the key */
1160 blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + xmlSecBnGetSize(&modulus);
1161 ret = xmlSecBufferSetSize(&blob, blobBufferLen);
1163 xmlSecError(XMLSEC_ERRORS_HERE,
1165 "xmlSecBufferSetSize",
1166 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1167 "size=%d", blobBufferLen);
1171 /* Set the PUBLICKEYSTRUC */
1172 pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
1173 pubKeyStruc->bType = PUBLICKEYBLOB;
1174 pubKeyStruc->bVersion = 0x02;
1175 pubKeyStruc->reserved = 0;
1176 pubKeyStruc->aiKeyAlg = CALG_RSA_KEYX | CALG_RSA_SIGN;
1178 /* Set the public key header */
1179 pubKey = (RSAPUBKEY*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
1180 pubKey->magic = 0x31415352; /* == RSA1 public */
1181 pubKey->bitlen = xmlSecBnGetSize(&modulus) * 8; /* Number of bits in prime modulus */
1183 if(sizeof(pubKey->pubexp) < xmlSecBnGetSize(&exponent)) {
1184 xmlSecError(XMLSEC_ERRORS_HERE,
1187 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1189 xmlSecBnGetSize(&exponent));
1192 xmlSecAssert2(xmlSecBnGetData(&exponent) != NULL, -1);
1193 memcpy(&(pubKey->pubexp), xmlSecBnGetData(&exponent), xmlSecBnGetSize(&exponent));
1195 modulusBlob = (xmlSecByte*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
1196 xmlSecAssert2(xmlSecBnGetData(&modulus) != NULL, -1);
1197 memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus));
1199 /* Now that we have the blob, import */
1200 if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) {
1201 if(NTE_BAD_KEYSET == GetLastError()) {
1202 if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
1203 xmlSecError(XMLSEC_ERRORS_HERE,
1204 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1205 "CryptAcquireContext",
1206 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1207 XMLSEC_ERRORS_NO_MESSAGE);
1211 xmlSecError(XMLSEC_ERRORS_HERE,
1212 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1213 "CryptAcquireContext",
1214 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1215 XMLSEC_ERRORS_NO_MESSAGE);
1220 if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
1221 xmlSecError(XMLSEC_ERRORS_HERE,
1222 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1224 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1225 XMLSEC_ERRORS_NO_MESSAGE);
1229 data = xmlSecKeyDataCreate(id);
1231 xmlSecError(XMLSEC_ERRORS_HERE,
1232 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1233 "xmlSecKeyDataCreate",
1234 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1235 XMLSEC_ERRORS_NO_MESSAGE);
1239 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
1241 xmlSecError(XMLSEC_ERRORS_HERE,
1242 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1243 "xmlSecMSCryptoKeyDataAdoptKey",
1244 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1245 XMLSEC_ERRORS_NO_MESSAGE);
1251 ret = xmlSecKeySetValue(key, data);
1253 xmlSecError(XMLSEC_ERRORS_HERE,
1254 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1255 "xmlSecKeySetValue",
1256 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1257 XMLSEC_ERRORS_NO_MESSAGE);
1258 xmlSecKeyDataDestroy(data);
1268 CryptReleaseContext(hProv, 0);
1271 CryptDestroyKey(hKey);
1274 xmlSecKeyDataDestroy(data);
1277 xmlSecBnFinalize(&modulus);
1278 xmlSecBnFinalize(&exponent);
1279 xmlSecBufferFinalize(&blob);
1284 xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
1285 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1286 xmlSecMSCryptoKeyDataCtxPtr ctx;
1290 PUBLICKEYSTRUC* pubKeyStruc;
1292 xmlSecSize modulusLen, exponentLen;
1296 xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
1297 xmlSecAssert2(key != NULL, -1);
1298 xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1);
1299 xmlSecAssert2(node != NULL, -1);
1300 xmlSecAssert2(keyInfoCtx != NULL, -1);
1302 ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
1303 xmlSecAssert2(ctx != NULL, -1);
1304 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
1306 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
1307 xmlSecError(XMLSEC_ERRORS_HERE,
1308 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1310 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1311 XMLSEC_ERRORS_NO_MESSAGE);
1315 ret = xmlSecBufferInitialize(&buf, dwBlobLen);
1317 xmlSecError(XMLSEC_ERRORS_HERE,
1318 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1319 "xmlSecBufferInitialize",
1320 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1321 "size=%ld", dwBlobLen);
1325 blob = xmlSecBufferGetData(&buf);
1326 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
1327 xmlSecError(XMLSEC_ERRORS_HERE,
1328 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1330 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1331 XMLSEC_ERRORS_NO_MESSAGE);
1332 xmlSecBufferFinalize(&buf);
1335 if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
1336 xmlSecError(XMLSEC_ERRORS_HERE,
1337 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1339 XMLSEC_ERRORS_R_INVALID_DATA,
1340 "blobLen=%ld", dwBlobLen);
1341 xmlSecBufferFinalize(&buf);
1345 /* check PUBLICKEYSTRUC */
1346 pubKeyStruc = (PUBLICKEYSTRUC*)blob;
1347 if(pubKeyStruc->bVersion != 0x02) {
1348 xmlSecError(XMLSEC_ERRORS_HERE,
1351 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1352 "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
1353 xmlSecBufferFinalize(&buf);
1356 if(pubKeyStruc->bType != PUBLICKEYBLOB) {
1357 xmlSecError(XMLSEC_ERRORS_HERE,
1360 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1361 "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
1362 xmlSecBufferFinalize(&buf);
1366 /* check RSAPUBKEY */
1367 pubKey = (RSAPUBKEY *)(blob + sizeof(PUBLICKEYSTRUC));
1368 if(pubKey->magic != 0x31415352) { /* RSA public key magic */
1369 xmlSecError(XMLSEC_ERRORS_HERE,
1372 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1373 "pubKey->magic=0x%08lx", pubKey->magic);
1374 xmlSecBufferFinalize(&buf);
1377 modulusLen = pubKey->bitlen / 8;
1379 if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen) {
1380 xmlSecError(XMLSEC_ERRORS_HERE,
1381 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1383 XMLSEC_ERRORS_R_INVALID_DATA,
1384 "blobLen=%ld; modulusLen=%d", dwBlobLen, modulusLen);
1385 xmlSecBufferFinalize(&buf);
1388 blob += sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
1390 /* first is Modulus node */
1391 cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
1393 xmlSecError(XMLSEC_ERRORS_HERE,
1394 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1396 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1398 xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1399 xmlSecBufferFinalize(&buf);
1403 ret = xmlSecBnBlobSetNodeValue(blob, modulusLen, cur, xmlSecBnBase64, 1, 1);
1405 xmlSecError(XMLSEC_ERRORS_HERE,
1406 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1407 "xmlSecBnBlobSetNodeValue",
1408 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1410 xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1411 xmlSecBufferFinalize(&buf);
1415 /* next is Exponent node. */
1416 cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
1418 xmlSecError(XMLSEC_ERRORS_HERE,
1419 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1421 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1423 xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1424 xmlSecBufferFinalize(&buf);
1428 /* Remove leading zero's (from least significant end) */
1429 blob = (xmlSecByte*)(&(pubKey->pubexp));
1430 exponentLen = sizeof(pubKey->pubexp);
1431 while (exponentLen > 0 && blob[exponentLen - 1] == 0) {
1435 ret = xmlSecBnBlobSetNodeValue(blob, exponentLen, cur, xmlSecBnBase64, 1, 1);
1437 xmlSecError(XMLSEC_ERRORS_HERE,
1438 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1439 "xmlSecBnBlobSetNodeValue",
1440 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1442 xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1443 xmlSecBufferFinalize(&buf);
1447 /* next is PrivateExponent node: not supported in MSCrypto */
1449 xmlSecBufferFinalize(&buf);
1454 xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits,
1455 xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
1456 xmlSecMSCryptoKeyDataCtxPtr ctx;
1457 HCRYPTPROV hProv = 0;
1464 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
1465 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
1466 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), -1);
1467 xmlSecAssert2(sizeBits > 0, -1);
1469 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1470 xmlSecAssert2(ctx != NULL, -1);
1472 if (!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, 0)) {
1473 if (NTE_BAD_KEYSET == GetLastError()) {
1474 if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
1475 xmlSecError(XMLSEC_ERRORS_HERE,
1476 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1477 "CryptAcquireContext",
1478 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1479 XMLSEC_ERRORS_NO_MESSAGE);
1484 xmlSecError(XMLSEC_ERRORS_HERE,
1485 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1486 "CryptAcquireContext",
1487 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1488 XMLSEC_ERRORS_NO_MESSAGE);
1494 dwKeySpec = AT_KEYEXCHANGE | AT_SIGNATURE;
1495 dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
1496 if (!CryptGenKey(hProv, CALG_RSA_SIGN, dwSize, &hKey)) {
1497 xmlSecError(XMLSEC_ERRORS_HERE,
1498 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1500 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1501 XMLSEC_ERRORS_NO_MESSAGE);
1505 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
1506 xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
1508 xmlSecError(XMLSEC_ERRORS_HERE,
1509 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1510 "xmlSecMSCryptoKeyDataAdoptKey",
1511 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1512 XMLSEC_ERRORS_NO_MESSAGE);
1523 CryptReleaseContext(hProv, 0);
1527 CryptDestroyKey(hKey);
1533 static xmlSecKeyDataType
1534 xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data) {
1535 return(xmlSecMSCryptoKeyDataGetType(data));
1539 xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
1540 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), 0);
1542 return (xmlSecMSCryptoKeyDataGetSize(data));
1546 xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
1547 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1548 xmlSecAssert(output != NULL);
1550 fprintf(output, "=== rsa key: size = %d\n",
1551 xmlSecMSCryptoKeyDataRsaGetSize(data));
1554 static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
1555 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1556 xmlSecAssert(output != NULL);
1558 fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
1559 xmlSecMSCryptoKeyDataRsaGetSize(data));
1562 #endif /* XMLSEC_NO_RSA */
1564 #ifndef XMLSEC_NO_DSA
1565 /**************************************************************************
1567 * <dsig:DSAKeyValue> processing
1570 * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
1572 * DSA keys and the DSA signature algorithm are specified in [DSS].
1573 * DSA public key values can have the following fields:
1575 * * P - a prime modulus meeting the [DSS] requirements
1576 * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime
1578 * * G - an integer with certain properties with respect to P and Q
1579 * * Y - G**X mod P (where X is part of the private key and not made
1582 * * seed - a DSA prime generation seed
1583 * * pgenCounter - a DSA prime generation counter
1585 * Parameter J is available for inclusion solely for efficiency as it is
1586 * calculatable from P and Q. Parameters seed and pgenCounter are used in the
1587 * DSA prime number generation algorithm specified in [DSS]. As such, they are
1588 * optional but must either both be present or both be absent. This prime
1589 * generation algorithm is designed to provide assurance that a weak prime is
1590 * not being used and it yields a P and Q value. Parameters P, Q, and G can be
1591 * public and common to a group of users. They might be known from application
1592 * context. As such, they are optional but P and Q must either both appear or
1593 * both be absent. If all of P, Q, seed, and pgenCounter are present,
1594 * implementations are not required to check if they are consistent and are
1595 * free to use either P and Q or seed and pgenCounter. All parameters are
1596 * encoded as base64 [MIME] values.
1598 * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
1599 * represented in XML as octet strings as defined by the ds:CryptoBinary type.
1601 * Schema Definition:
1603 * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
1604 * <complexType name="DSAKeyValueType">
1606 * <sequence minOccurs="0">
1607 * <element name="P" type="ds:CryptoBinary"/>
1608 * <element name="Q" type="ds:CryptoBinary"/>
1610 * <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
1611 * <element name="Y" type="ds:CryptoBinary"/>
1612 * <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
1613 * <sequence minOccurs="0">
1614 * <element name="Seed" type="ds:CryptoBinary"/>
1615 * <element name="PgenCounter" type="ds:CryptoBinary"/>
1622 * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) >
1623 * <!ELEMENT P (#PCDATA) >
1624 * <!ELEMENT Q (#PCDATA) >
1625 * <!ELEMENT G (#PCDATA) >
1626 * <!ELEMENT Y (#PCDATA) >
1627 * <!ELEMENT J (#PCDATA) >
1628 * <!ELEMENT Seed (#PCDATA) >
1629 * <!ELEMENT PgenCounter (#PCDATA) >
1631 * ============================================================================
1633 * To support reading/writing private keys an X element added (before Y).
1634 * todo: The current implementation does not support Seed and PgenCounter!
1635 * by this the P, Q and G are *required*!
1637 *************************************************************************/
1638 static int xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data);
1639 static int xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst,
1640 xmlSecKeyDataPtr src);
1641 static void xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data);
1642 static int xmlSecMSCryptoKeyDataDsaXmlRead (xmlSecKeyDataId id,
1645 xmlSecKeyInfoCtxPtr keyInfoCtx);
1646 static int xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id,
1649 xmlSecKeyInfoCtxPtr keyInfoCtx);
1650 static int xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data,
1651 xmlSecSize sizeBits,
1652 xmlSecKeyDataType type);
1654 static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data);
1655 static xmlSecSize xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data);
1656 static void xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data,
1658 static void xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,
1661 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = {
1662 sizeof(xmlSecKeyDataKlass),
1663 xmlSecMSCryptoKeyDataSize,
1666 xmlSecNameDSAKeyValue,
1667 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1668 /* xmlSecKeyDataUsage usage; */
1669 xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
1670 xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
1671 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
1673 /* constructors/destructor */
1674 xmlSecMSCryptoKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
1675 xmlSecMSCryptoKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
1676 xmlSecMSCryptoKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
1677 xmlSecMSCryptoKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
1680 xmlSecMSCryptoKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
1681 xmlSecMSCryptoKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
1682 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
1685 xmlSecMSCryptoKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
1686 xmlSecMSCryptoKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1687 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
1688 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
1691 xmlSecMSCryptoKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
1692 xmlSecMSCryptoKeyDataDsaDebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1694 /* reserved for the future */
1695 NULL, /* void* reserved0; */
1696 NULL, /* void* reserved1; */
1700 * xmlSecMSCryptoKeyDataDsaGetKlass:
1702 * The DSA key data klass.
1704 * Returns: pointer to DSA key data klass.
1707 xmlSecMSCryptoKeyDataDsaGetKlass(void) {
1708 return(&xmlSecMSCryptoKeyDataDsaKlass);
1713 xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
1714 xmlSecMSCryptoKeyDataCtxPtr ctx;
1716 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), xmlSecKeyDataTypeUnknown);
1718 xmlSecMSCryptoKeyDataInitialize(data);
1720 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1721 xmlSecAssert2(ctx != NULL, -1);
1723 ctx->providerName = MS_DEF_DSS_PROV;
1724 ctx->providerType = PROV_DSS;
1730 xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1731 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataDsaId), -1);
1732 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataDsaId), -1);
1734 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1738 xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
1739 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
1741 xmlSecMSCryptoKeyDataFinalize(data);
1745 xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1746 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1747 xmlSecKeyDataPtr data = NULL;
1749 xmlSecBn p, q, g, y;
1751 unsigned int blobBufferLen;
1752 PUBLICKEYSTRUC *pubKeyStruc = NULL;
1753 DSSPUBKEY *pubKey = NULL;
1754 DSSSEED* seed = NULL;
1756 HCRYPTPROV hProv = 0;
1762 xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
1763 xmlSecAssert2(key != NULL, -1);
1764 xmlSecAssert2(node != NULL, -1);
1765 xmlSecAssert2(keyInfoCtx != NULL, -1);
1767 if(xmlSecKeyGetValue(key) != NULL) {
1768 xmlSecError(XMLSEC_ERRORS_HERE,
1769 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1771 XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1772 "key already has a value");
1776 /* initialize buffers */
1777 ret = xmlSecBnInitialize(&p, 0);
1779 xmlSecError(XMLSEC_ERRORS_HERE,
1780 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1781 "xmlSecBnInitialize",
1782 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1787 ret = xmlSecBnInitialize(&q, 0);
1789 xmlSecError(XMLSEC_ERRORS_HERE,
1790 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1791 "xmlSecBnInitialize",
1792 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1794 xmlSecBnFinalize(&p);
1798 ret = xmlSecBnInitialize(&g, 0);
1800 xmlSecError(XMLSEC_ERRORS_HERE,
1801 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1802 "xmlSecBnInitialize",
1803 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1805 xmlSecBnFinalize(&p);
1806 xmlSecBnFinalize(&q);
1810 ret = xmlSecBnInitialize(&y, 0);
1812 xmlSecError(XMLSEC_ERRORS_HERE,
1813 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1814 "xmlSecBnInitialize",
1815 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1817 xmlSecBnFinalize(&p);
1818 xmlSecBnFinalize(&q);
1819 xmlSecBnFinalize(&g);
1823 ret = xmlSecBufferInitialize(&blob, 0);
1825 xmlSecError(XMLSEC_ERRORS_HERE,
1826 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1827 "xmlSecBufferInitialize",
1828 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1830 xmlSecBnFinalize(&p);
1831 xmlSecBnFinalize(&q);
1832 xmlSecBnFinalize(&g);
1833 xmlSecBnFinalize(&y);
1838 cur = xmlSecGetNextElementNode(node->children);
1840 /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/
1841 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) {
1842 xmlSecError(XMLSEC_ERRORS_HERE,
1843 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1844 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1845 XMLSEC_ERRORS_R_INVALID_NODE,
1847 xmlSecErrorsSafeString(xmlSecNodeDSAP));
1851 ret = xmlSecBnGetNodeValue(&p, cur, xmlSecBnBase64, 1);
1852 if((ret < 0) || (xmlSecBnGetSize(&p) == 0)){
1853 xmlSecError(XMLSEC_ERRORS_HERE,
1854 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1855 "xmlSecBnGetNodeValue",
1856 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1858 xmlSecErrorsSafeString(xmlSecNodeDSAP));
1861 cur = xmlSecGetNextElementNode(cur->next);
1863 /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/
1864 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) {
1865 xmlSecError(XMLSEC_ERRORS_HERE,
1866 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1867 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1868 XMLSEC_ERRORS_R_INVALID_NODE,
1870 xmlSecErrorsSafeString(xmlSecNodeDSAQ));
1873 ret = xmlSecBnGetNodeValue(&q, cur, xmlSecBnBase64, 1);
1874 if((ret < 0) || (xmlSecBnGetSize(&q) == 0)){
1875 xmlSecError(XMLSEC_ERRORS_HERE,
1876 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1877 "xmlSecBnGetNodeValue",
1878 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1880 xmlSecErrorsSafeString(xmlSecNodeDSAQ));
1883 cur = xmlSecGetNextElementNode(cur->next);
1885 /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/
1886 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) {
1887 xmlSecError(XMLSEC_ERRORS_HERE,
1888 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1889 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1890 XMLSEC_ERRORS_R_INVALID_NODE,
1892 xmlSecErrorsSafeString(xmlSecNodeDSAG));
1895 ret = xmlSecBnGetNodeValue(&g, cur, xmlSecBnBase64, 1);
1896 if((ret < 0) || (xmlSecBnGetSize(&q) == 0)) {
1897 xmlSecError(XMLSEC_ERRORS_HERE,
1898 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1899 "xmlSecBnGetNodeValue",
1900 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1902 xmlSecErrorsSafeString(xmlSecNodeDSAG));
1905 cur = xmlSecGetNextElementNode(cur->next);
1907 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
1908 /* next is X node. It is REQUIRED for private key but
1909 * MSCrypto does not support it, we just ignore it */
1911 cur = xmlSecGetNextElementNode(cur->next);
1914 /* next is Y node. */
1915 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) {
1916 xmlSecError(XMLSEC_ERRORS_HERE,
1917 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1918 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1919 XMLSEC_ERRORS_R_INVALID_NODE,
1921 xmlSecErrorsSafeString(xmlSecNodeDSAY));
1924 ret = xmlSecBnGetNodeValue(&y, cur, xmlSecBnBase64, 1);
1925 if((ret < 0) || (xmlSecBnGetSize(&y) == 0)) {
1926 xmlSecError(XMLSEC_ERRORS_HERE,
1927 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1928 "xmlSecBnGetNodeValue",
1929 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1930 "node=%s", xmlSecErrorsSafeString(xmlSecNodeDSAY));
1933 cur = xmlSecGetNextElementNode(cur->next);
1935 /* todo: add support for J */
1936 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
1937 cur = xmlSecGetNextElementNode(cur->next);
1940 /* todo: add support for seed */
1941 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
1942 cur = xmlSecGetNextElementNode(cur->next);
1945 /* todo: add support for pgencounter */
1946 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
1947 cur = xmlSecGetNextElementNode(cur->next);
1951 xmlSecError(XMLSEC_ERRORS_HERE,
1952 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1953 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1954 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1955 XMLSEC_ERRORS_NO_MESSAGE);
1959 /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
1960 blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * xmlSecBnGetSize(&p) + 0x14 + sizeof(DSSSEED);
1961 ret = xmlSecBufferSetSize(&blob, blobBufferLen);
1963 xmlSecError(XMLSEC_ERRORS_HERE,
1965 "xmlSecBufferSetSize",
1966 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1967 "size=%d", blobBufferLen);
1971 /* Set PUBLICKEYSTRUC */
1972 pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
1973 pubKeyStruc->bType = PUBLICKEYBLOB;
1974 pubKeyStruc->bVersion = 0x02;
1975 pubKeyStruc->reserved = 0;
1976 pubKeyStruc->aiKeyAlg = CALG_DSS_SIGN;
1978 /* Set the public key header */
1979 pubKey = (DSSPUBKEY *) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
1980 pubKey->magic = 0x31535344; /* == DSS1 pub key */
1981 pubKey->bitlen = xmlSecBnGetSize(&p) * 8; /* Number of bits in prime modulus */
1983 /* copy the key data */
1984 buf = (BYTE*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY));
1987 xmlSecAssert2(xmlSecBnGetData(&p) != NULL, -1);
1988 memcpy(buf, xmlSecBnGetData(&p), xmlSecBnGetSize(&p));
1989 buf += xmlSecBnGetSize(&p);
1992 if(xmlSecBnGetSize(&q) > 0x14) {
1993 xmlSecError(XMLSEC_ERRORS_HERE,
1996 XMLSEC_ERRORS_R_INVALID_SIZE,
1997 "size=%d > 0x14", xmlSecBnGetSize(&q));
2000 xmlSecAssert2(xmlSecBnGetData(&q) != NULL, -1);
2001 memcpy(buf, xmlSecBnGetData(&q), xmlSecBnGetSize(&q));
2002 buf += xmlSecBnGetSize(&q);
2004 /* Pad with zeros */
2005 for(i = xmlSecBnGetSize(&q); i < 0x14; ++i) {
2010 if(xmlSecBnGetSize(&g) > xmlSecBnGetSize(&p)) {
2011 xmlSecError(XMLSEC_ERRORS_HERE,
2014 XMLSEC_ERRORS_R_INVALID_SIZE,
2016 xmlSecBnGetSize(&g),
2017 xmlSecBnGetSize(&p));
2020 xmlSecAssert2(xmlSecBnGetData(&g) != NULL, -1);
2021 memcpy(buf, xmlSecBnGetData(&g), xmlSecBnGetSize(&g));
2022 buf += xmlSecBnGetSize(&g);
2023 /* Pad with zeros */
2024 for(i = xmlSecBnGetSize(&g); i < xmlSecBnGetSize(&p); ++i) {
2029 if(xmlSecBnGetSize(&y) > xmlSecBnGetSize(&p)) {
2030 xmlSecError(XMLSEC_ERRORS_HERE,
2033 XMLSEC_ERRORS_R_INVALID_SIZE,
2035 xmlSecBnGetSize(&y),
2036 xmlSecBnGetSize(&p));
2039 xmlSecAssert2(xmlSecBnGetData(&y) != NULL, -1);
2040 memcpy(buf, xmlSecBnGetData(&y), xmlSecBnGetSize(&y));
2041 buf += xmlSecBnGetSize(&y);
2042 /* Pad with zeros */
2043 for(i = xmlSecBnGetSize(&y); i < xmlSecBnGetSize(&p); ++i) {
2047 /* Set seed to 0xFFFFFFFFF */
2048 seed = (DSSSEED*)buf;
2049 memset(seed, 0, sizeof(*seed));
2050 seed->counter = 0xFFFFFFFF; /* SEED Counter set to 0xFFFFFFFF will cause seed to be ignored */
2052 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, 0)) {
2053 if (NTE_BAD_KEYSET == GetLastError()) {
2054 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_DSS_PROV, PROV_DSS, CRYPT_NEWKEYSET)) {
2055 xmlSecError(XMLSEC_ERRORS_HERE,
2056 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2057 "CryptAcquireContext",
2058 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2059 XMLSEC_ERRORS_NO_MESSAGE);
2063 xmlSecError(XMLSEC_ERRORS_HERE,
2064 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2065 "CryptAcquireContext",
2066 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2067 XMLSEC_ERRORS_NO_MESSAGE);
2072 /* import the key blob */
2073 if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
2074 xmlSecError(XMLSEC_ERRORS_HERE,
2075 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2077 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2078 XMLSEC_ERRORS_NO_MESSAGE);
2082 data = xmlSecKeyDataCreate(id);
2084 xmlSecError(XMLSEC_ERRORS_HERE,
2085 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2086 "xmlSecKeyDataCreate",
2087 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2088 XMLSEC_ERRORS_NO_MESSAGE);
2092 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
2094 xmlSecError(XMLSEC_ERRORS_HERE,
2095 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2096 "xmlSecMSCryptoKeyDataAdoptKey",
2097 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2098 XMLSEC_ERRORS_NO_MESSAGE);
2104 ret = xmlSecKeySetValue(key, data);
2106 xmlSecError(XMLSEC_ERRORS_HERE,
2107 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2108 "xmlSecKeySetValue",
2109 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2110 XMLSEC_ERRORS_NO_MESSAGE);
2120 CryptDestroyKey(hKey);
2123 CryptReleaseContext(hProv, 0);
2126 xmlSecKeyDataDestroy(data);
2129 xmlSecBufferFinalize(&blob);
2130 xmlSecBnFinalize(&p);
2131 xmlSecBnFinalize(&q);
2132 xmlSecBnFinalize(&g);
2133 xmlSecBnFinalize(&y);
2139 xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
2140 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
2141 xmlSecMSCryptoKeyDataCtxPtr ctx;
2145 PUBLICKEYSTRUC* pubKeyStruc;
2147 xmlSecSize keyLen, len;
2152 xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
2153 xmlSecAssert2(key != NULL, -1);
2154 xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataDsaId), -1);
2155 xmlSecAssert2(node != NULL, -1);
2156 xmlSecAssert2(keyInfoCtx != NULL, -1);
2158 ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
2159 xmlSecAssert2(ctx != NULL, -1);
2160 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
2162 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
2163 xmlSecError(XMLSEC_ERRORS_HERE,
2164 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2166 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2167 XMLSEC_ERRORS_NO_MESSAGE);
2171 ret = xmlSecBufferInitialize(&buf, dwBlobLen);
2173 xmlSecError(XMLSEC_ERRORS_HERE,
2174 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2175 "xmlSecBufferInitialize",
2176 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2177 "size=%ld", dwBlobLen);
2181 blob = xmlSecBufferGetData(&buf);
2182 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
2183 xmlSecError(XMLSEC_ERRORS_HERE,
2184 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2186 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2187 XMLSEC_ERRORS_NO_MESSAGE);
2188 xmlSecBufferFinalize(&buf);
2191 if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
2192 xmlSecError(XMLSEC_ERRORS_HERE,
2193 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2195 XMLSEC_ERRORS_R_INVALID_DATA,
2196 "blobLen=%ld", dwBlobLen);
2197 xmlSecBufferFinalize(&buf);
2201 /* check PUBLICKEYSTRUC */
2202 pubKeyStruc = (PUBLICKEYSTRUC*)blob;
2203 if(pubKeyStruc->bVersion != 0x02) {
2204 xmlSecError(XMLSEC_ERRORS_HERE,
2207 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2208 "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
2209 xmlSecBufferFinalize(&buf);
2212 if(pubKeyStruc->bType != PUBLICKEYBLOB) {
2213 xmlSecError(XMLSEC_ERRORS_HERE,
2216 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2217 "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
2218 xmlSecBufferFinalize(&buf);
2222 /* check DSSPUBKEY */
2223 pubKey = (DSSPUBKEY*)(blob + sizeof(PUBLICKEYSTRUC));
2224 if(pubKey->magic != 0x31535344) { /* DSS key magic */
2225 xmlSecError(XMLSEC_ERRORS_HERE,
2228 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2229 "pubKey->magic=0x%08lx", pubKey->magic);
2230 xmlSecBufferFinalize(&buf);
2233 keyLen = pubKey->bitlen / 8;
2235 /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
2236 if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * keyLen + 0x14 + sizeof(DSSSEED)) {
2237 xmlSecError(XMLSEC_ERRORS_HERE,
2238 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2240 XMLSEC_ERRORS_R_INVALID_DATA,
2241 "blobLen=%ld; keyLen=%d", dwBlobLen, keyLen);
2242 xmlSecBufferFinalize(&buf);
2245 blob += sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY);
2247 /* first is P node */
2248 cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
2250 xmlSecError(XMLSEC_ERRORS_HERE,
2251 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2253 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2255 xmlSecErrorsSafeString(xmlSecNodeDSAP));
2256 xmlSecBufferFinalize(&buf);
2260 ret = xmlSecBnBlobSetNodeValue(blob, keyLen, cur, xmlSecBnBase64, 1, 1);
2262 xmlSecError(XMLSEC_ERRORS_HERE,
2263 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2264 "xmlSecBnBlobSetNodeValue",
2265 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2267 xmlSecErrorsSafeString(xmlSecNodeDSAP));
2268 xmlSecBufferFinalize(&buf);
2273 /* next is Q node. */
2274 cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
2276 xmlSecError(XMLSEC_ERRORS_HERE,
2277 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2279 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2281 xmlSecErrorsSafeString(xmlSecNodeDSAQ));
2282 xmlSecBufferFinalize(&buf);
2286 /* we think that the size of q is 0x14, skip trailing zeros */
2287 for(len = 0x14; len > 0 && blob[len - 1] == 0; --len);
2289 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2291 xmlSecError(XMLSEC_ERRORS_HERE,
2292 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2293 "xmlSecBnBlobSetNodeValue",
2294 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2296 xmlSecErrorsSafeString(xmlSecNodeDSAQ));
2297 xmlSecBufferFinalize(&buf);
2302 /* next is G node. */
2303 cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
2305 xmlSecError(XMLSEC_ERRORS_HERE,
2306 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2308 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2310 xmlSecErrorsSafeString(xmlSecNodeDSAG));
2311 xmlSecBufferFinalize(&buf);
2315 /* skip trailing zeros */
2316 for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2318 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2320 xmlSecError(XMLSEC_ERRORS_HERE,
2321 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2322 "xmlSecBnBlobSetNodeValue",
2323 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2325 xmlSecErrorsSafeString(xmlSecNodeDSAG));
2326 xmlSecBufferFinalize(&buf);
2331 /* next is X node: not supported in MSCrypto */
2333 /* next is Y node. */
2334 cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
2336 xmlSecError(XMLSEC_ERRORS_HERE,
2337 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2339 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2341 xmlSecErrorsSafeString(xmlSecNodeDSAY));
2342 xmlSecBufferFinalize(&buf);
2346 /* skip trailing zeros */
2347 for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2349 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2351 xmlSecError(XMLSEC_ERRORS_HERE,
2352 xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2353 "xmlSecBnBlobSetNodeValue",
2354 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2356 xmlSecErrorsSafeString(xmlSecNodeDSAY));
2357 xmlSecBufferFinalize(&buf);
2362 xmlSecBufferFinalize(&buf);
2367 xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
2368 xmlSecMSCryptoKeyDataCtxPtr ctx;
2369 HCRYPTPROV hProv = 0;
2376 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
2377 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
2378 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), -1);
2379 xmlSecAssert2(sizeBits > 0, -1);
2381 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2383 if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, 0)) {
2384 if (NTE_BAD_KEYSET == GetLastError()) {
2385 if(!CryptAcquireContext(&hProv, XMLSEC_CONTAINER_NAME, ctx->providerName, ctx->providerType, CRYPT_NEWKEYSET)) {
2386 xmlSecError(XMLSEC_ERRORS_HERE,
2387 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2388 "CryptAcquireContext",
2389 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2390 XMLSEC_ERRORS_NO_MESSAGE);
2394 xmlSecError(XMLSEC_ERRORS_HERE,
2395 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2396 "CryptAcquireContext",
2397 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2398 XMLSEC_ERRORS_NO_MESSAGE);
2403 dwKeySpec = AT_SIGNATURE;
2404 dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
2405 if (!CryptGenKey(hProv, CALG_DSS_SIGN, dwSize, &hKey)) {
2406 xmlSecError(XMLSEC_ERRORS_HERE,
2407 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2409 XMLSEC_ERRORS_R_CRYPTO_FAILED,
2410 XMLSEC_ERRORS_NO_MESSAGE);
2414 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
2415 xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
2417 xmlSecError(XMLSEC_ERRORS_HERE,
2418 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2419 "xmlSecMSCryptoKeyDataAdoptKey",
2420 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2421 XMLSEC_ERRORS_NO_MESSAGE);
2432 CryptReleaseContext(hProv, 0);
2436 CryptDestroyKey(hKey);
2442 static xmlSecKeyDataType
2443 xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data) {
2444 return(xmlSecMSCryptoKeyDataGetType(data));
2448 xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
2449 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), 0);
2451 return xmlSecMSCryptoKeyDataGetSize(data);
2455 xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
2456 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2457 xmlSecAssert(output != NULL);
2459 fprintf(output, "=== dsa key: size = %d\n",
2460 xmlSecMSCryptoKeyDataDsaGetSize(data));
2464 xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2465 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2466 xmlSecAssert(output != NULL);
2468 fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
2469 xmlSecMSCryptoKeyDataDsaGetSize(data));
2472 #endif /* XMLSEC_NO_DSA */
2475 #ifndef XMLSEC_NO_GOST
2476 /**************************************************************************
2478 * GOST2001 xml key representation processing. Contain errors.
2480 *************************************************************************/
2481 static int xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data);
2482 static int xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst,
2483 xmlSecKeyDataPtr src);
2484 static void xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data);
2485 static int xmlSecMSCryptoKeyDataGost2001XmlRead (xmlSecKeyDataId id,
2488 xmlSecKeyInfoCtxPtr keyInfoCtx);
2489 static int xmlSecMSCryptoKeyDataGost2001XmlWrite(xmlSecKeyDataId id,
2492 xmlSecKeyInfoCtxPtr keyInfoCtx);
2493 static int xmlSecMSCryptoKeyDataGost2001Generate(xmlSecKeyDataPtr data,
2494 xmlSecSize sizeBits,
2495 xmlSecKeyDataType type);
2497 static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data);
2498 static xmlSecSize xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data);
2499 static void xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data,
2501 static void xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data,
2504 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = {
2505 sizeof(xmlSecKeyDataKlass),
2506 xmlSecMSCryptoKeyDataSize,
2509 xmlSecNameGOST2001KeyValue,
2510 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
2511 /* xmlSecKeyDataUsage usage; */
2512 xmlSecHrefGOST2001KeyValue, /* const xmlChar* href; */
2513 xmlSecNodeGOST2001KeyValue, /* const xmlChar* dataNodeName; */
2514 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
2516 /* constructors/destructor */
2517 xmlSecMSCryptoKeyDataGost2001Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
2518 xmlSecMSCryptoKeyDataGost2001Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
2519 xmlSecMSCryptoKeyDataGost2001Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
2520 NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */
2523 xmlSecMSCryptoKeyDataGost2001GetType, /* xmlSecKeyDataGetTypeMethod getType; */
2524 xmlSecMSCryptoKeyDataGost2001GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
2525 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
2528 NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
2529 NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
2530 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
2531 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
2534 xmlSecMSCryptoKeyDataGost2001DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
2535 xmlSecMSCryptoKeyDataGost2001DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
2537 /* reserved for the future */
2538 NULL, /* void* reserved0; */
2539 NULL, /* void* reserved1; */
2543 * xmlSecMSCryptoKeyDataGost2001GetKlass:
2545 * The GOST2001 key data klass.
2547 * Returns: pointer to GOST2001 key data klass.
2550 xmlSecMSCryptoKeyDataGost2001GetKlass(void) {
2551 return(&xmlSecMSCryptoKeyDataGost2001Klass);
2556 xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
2557 xmlSecMSCryptoKeyDataCtxPtr ctx;
2558 HCRYPTPROV tmp_ctx = 0;
2560 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
2562 xmlSecMSCryptoKeyDataInitialize(data);
2564 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2565 xmlSecAssert2(ctx != NULL, -1);
2567 /* GOST Algorithm is provided by several CSP's, so we try to find any installed */
2568 if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_MAGPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
2569 ctx->providerName = "MagPro CSP";
2570 ctx->providerType = PROV_MAGPRO_GOST;
2572 if (CryptAcquireContext(&tmp_ctx, NULL, NULL, PROV_CRYPTOPRO_GOST, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
2573 ctx->providerName = "CryptoPro CSP";
2574 ctx->providerType = PROV_CRYPTOPRO_GOST;
2576 xmlSecError(XMLSEC_ERRORS_HERE,
2577 xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2578 "xmlSecMSCryptoKeyDataGost2001Initialize",
2579 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2580 XMLSEC_ERRORS_NO_MESSAGE);
2584 CryptReleaseContext(tmp_ctx, 0);
2589 xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
2590 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2001Id), -1);
2591 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2001Id), -1);
2593 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
2597 xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data) {
2598 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2600 xmlSecMSCryptoKeyDataFinalize(data);
2603 static xmlSecKeyDataType
2604 xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data) {
2605 return(xmlSecMSCryptoKeyDataGetType(data));
2609 xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data) {
2610 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), 0);
2612 return xmlSecMSCryptoKeyDataGetSize(data);
2616 xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output) {
2617 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2618 xmlSecAssert(output != NULL);
2620 fprintf(output, "=== dsa key: size = %d\n",
2621 xmlSecMSCryptoKeyDataGost2001GetSize(data));
2625 xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2626 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2627 xmlSecAssert(output != NULL);
2629 fprintf(output, "<GOST2001KeyValue size=\"%d\" />\n",
2630 xmlSecMSCryptoKeyDataGost2001GetSize(data));
2633 #endif /* XMLSEC_NO_GOST*/