Git init
[external/xmlsec1.git] / src / mscrypto / certkeys.c
1 /** 
2  * XMLSec library
3  *
4  * This is free software; see Copyright file in the source
5  * distribution for preciese wording.
6  * 
7  * Copyrigth (C) 2003 Cordys R&D BV, All rights reserved.
8  * Copyright (C) 2003 Aleksey Sanin <aleksey@aleksey.com>
9  */
10 #include "globals.h"
11
12 #include <string.h>
13
14 #include <windows.h>
15 #include <wincrypt.h>
16
17 #ifndef XMLSEC_NO_GOST
18 #include "csp_oid.h"
19 #include "csp_calg.h"
20 #endif
21
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>
29
30 #include <xmlsec/mscrypto/certkeys.h>
31 #include <xmlsec/mscrypto/crypto.h>
32 #include <xmlsec/mscrypto/x509.h>
33
34 #if defined(__MINGW32__)
35 #  include "xmlsec-mingw.h"
36 #endif
37
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
42 #endif
43 #endif
44
45 #define XMLSEC_CONTAINER_NAME "xmlsec-key-container"
46
47 /**************************************************************************
48  *
49  * Internal MSCrypto PCCERT_CONTEXT key CTX
50  *
51  *************************************************************************/
52 typedef struct _xmlSecMSCryptoKeyDataCtx xmlSecMSCryptoKeyDataCtx, 
53                                                 *xmlSecMSCryptoKeyDataCtxPtr;
54
55 #ifdef XMLSEC_MSCRYPTO_NT4
56 /*-
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
60  */
61 struct _mscrypt_key {
62         HCRYPTKEY hKey ;
63         volatile LONG refcnt ;
64 } ;
65
66 /*-
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
70  */
71 struct _mscrypt_prov {
72         HCRYPTPROV hProv ;
73     BOOL fCallerFreeProv ;
74         volatile LONG refcnt ;
75 } ;
76 #endif /* XMLSEC_MSCRYPTO_NT4 */
77
78 /*
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
84  */
85 struct _xmlSecMSCryptoKeyDataCtx {
86 #ifndef XMLSEC_MSCRYPTO_NT4
87     HCRYPTPROV          hProv;
88     BOOL                    fCallerFreeProv;
89     HCRYPTKEY           hKey;
90 #else /* XMLSEC_MSCRYPTO_NT4 */
91         struct _mscrypt_prov* p_prov ;
92     struct _mscrypt_key*  p_key ;   
93 #endif /* XMLSEC_MSCRYPTO_NT4 */
94     PCCERT_CONTEXT      pCert;
95     LPCTSTR                 providerName;
96     DWORD                   providerType;
97     DWORD                   dwKeySpec;
98     xmlSecKeyDataType   type;
99 };          
100
101 #ifndef XMLSEC_MSCRYPTO_NT4
102
103 /******************************** Provider *****************************************/
104 #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx)            (ctx)->hProv
105
106 static void
107 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
108     xmlSecAssert(ctx != NULL);
109
110         ctx->hProv = 0;
111         ctx->fCallerFreeProv = FALSE;
112 }
113
114 static void
115 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
116     xmlSecAssert(ctx != NULL);
117  
118     if ((ctx->hProv != 0) && (ctx->fCallerFreeProv)) {
119             CryptReleaseContext(ctx->hProv, 0);
120     }
121         ctx->hProv = 0;
122         ctx->fCallerFreeProv = FALSE;
123 }
124
125 static void
126 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
127 {
128     xmlSecAssert(ctx != NULL);
129  
130     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
131     ctx->hProv               = hProv;
132     ctx->fCallerFreeProv = fCallerFreeProv;
133 }
134
135 static int
136 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
137     xmlSecAssert2(ctxDst != NULL, -1);
138     xmlSecAssert2(ctxSrc != NULL, -1);
139
140     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
141
142     if(ctxSrc->hProv != 0) {
143         if(!CryptContextAddRef(ctxSrc->hProv, NULL, 0)) {
144                 xmlSecError(XMLSEC_ERRORS_HERE,
145                             NULL,
146                             "CryptContextAddRef",
147                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
148                             XMLSEC_ERRORS_NO_MESSAGE);
149             return(-1);
150         }
151
152             ctxDst->hProv                   = ctxSrc->hProv;
153             ctxDst->fCallerFreeProv = TRUE;
154     }
155     return(0);
156 }
157
158 /******************************** Key *****************************************/
159 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx)            ((ctx)->hKey)
160
161 static void
162 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
163     xmlSecAssert(ctx != NULL);
164
165     ctx->hKey = 0;
166 }
167
168 static void
169 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
170     xmlSecAssert(ctx != NULL);
171     
172     if (ctx->hKey != 0) {
173             CryptDestroyKey(ctx->hKey);
174     }
175     ctx->hKey = 0;
176 }
177
178 static void
179 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
180     xmlSecAssert(ctx != NULL);
181
182     xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
183     ctx->hKey = hKey;
184 }
185
186 static int
187 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
188     xmlSecAssert2(ctxDst != NULL, -1);
189     xmlSecAssert2(ctxSrc != NULL, -1);
190
191     xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
192     if (ctxSrc->hKey != 0) {
193             if (!CryptDuplicateKey(ctxSrc->hKey, NULL, 0, &(ctxDst->hKey))) {
194                 xmlSecError(XMLSEC_ERRORS_HERE,
195                             NULL,
196                             "CryptDuplicateKey",
197                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
198                             XMLSEC_ERRORS_NO_MESSAGE);
199                 return(-1);
200             }
201     }
202
203     return(0);
204 }
205
206 #else /* XMLSEC_MSCRYPTO_NT4 */
207
208 /******************************** Provider *****************************************/
209 #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx)            (((ctx)->p_prov) ? ((ctx)->p_prov->hProv) : 0)
210
211 static void
212 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
213     xmlSecAssert(ctx != NULL);
214
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" ,
219                         NULL,
220                         XMLSEC_ERRORS_R_MALLOC_FAILED ,
221                         XMLSEC_ERRORS_NO_MESSAGE
222                 );
223         }
224     memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
225 }
226
227 static void
228 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
229     xmlSecAssert(ctx != NULL);
230  
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) ;
235                         }
236             memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
237                         xmlFree(ctx->p_prov) ;
238                 }
239         ctx->p_prov = NULL;
240         }
241 }
242
243 static void
244 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
245 {
246     xmlSecAssert(ctx != NULL);
247  
248     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
249
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) ;
253                 }
254         memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
255     } else {
256         xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
257         xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
258     }
259
260     ctx->p_prov->hProv = hProv;
261     ctx->p_prov->fCallerFreeProv = fCallerFreeProv;
262     ctx->p_prov->refcnt = 1;
263 }
264
265 static int
266 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
267     xmlSecAssert2(ctxDst != NULL, -1);
268     xmlSecAssert2(ctxSrc != NULL, -1);
269
270     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
271
272     if (ctxSrc->p_prov != NULL) {
273         ctxDst->p_prov = ctxSrc->p_prov;
274         InterlockedIncrement(&(ctxDst->p_prov->refcnt));
275     }
276
277     return(0);
278 }
279
280 /********************************  Key  *****************************************/
281 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx)            (((ctx)->p_key) ? ((ctx)->p_key->hKey) : 0)
282
283 static void
284 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
285     xmlSecAssert(ctx != NULL);
286
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" ,
291                         NULL,
292                         XMLSEC_ERRORS_R_MALLOC_FAILED ,
293                         XMLSEC_ERRORS_NO_MESSAGE
294                 );
295         }
296     memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
297 }
298
299 static void
300 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
301     xmlSecAssert(ctx != NULL);
302     
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) ;
307                         }
308             memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
309                         xmlFree(ctx->p_key) ;
310                 }
311         ctx->p_key = NULL;
312         }
313 }
314
315 static void
316 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
317     xmlSecAssert(ctx != NULL);
318
319     if((ctx->p_key != NULL) && (ctx->p_key->refcnt == 1)) {
320                 if(ctx->p_key->hKey != 0) {
321                         CryptDestroyKey(ctx->p_key->hKey) ;
322                 }
323         memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
324     } else {
325         xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
326         xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
327     }
328     ctx->p_key->hKey = hKey;
329     ctx->p_key->refcnt = 1;
330 }
331
332 static int
333 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
334     xmlSecAssert2(ctxDst != NULL, -1);
335     xmlSecAssert2(ctxSrc != NULL, -1);
336
337     xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
338     if (ctxSrc->p_key != NULL) {
339         ctxDst->p_key = ctxSrc->p_key;
340         InterlockedIncrement(&(ctxDst->p_key->refcnt));
341     }
342
343     return(0);
344 }
345
346 #endif /* XMLSEC_MSCRYPTO_NT4 */
347
348 /******************************** Cert *****************************************/
349 #define xmlSecMSCryptoKeyDataCtxGetCert(ctx)            ((ctx)->pCert)
350
351 static void
352 xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
353     xmlSecAssert(ctx != NULL);
354
355     ctx->pCert = NULL;
356 }
357
358 static void
359 xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
360     xmlSecAssert(ctx != NULL);
361     
362     if(ctx->pCert != NULL) {
363             CertFreeCertificateContext(ctx->pCert);
364     }
365     ctx->pCert = NULL;
366 }
367
368 static void
369 xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx, PCCERT_CONTEXT pCert) {
370     xmlSecAssert(ctx != NULL);
371
372     xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
373     ctx->pCert = pCert;
374 }
375
376 static int
377 xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
378     xmlSecAssert2(ctxDst != NULL, -1);
379     xmlSecAssert2(ctxSrc != NULL, -1);
380
381     xmlSecMSCryptoKeyDataCtxDestroyCert(ctxDst);  
382     if(ctxSrc->pCert != NULL) {
383             ctxDst->pCert = xmlSecMSCryptoCertDup(ctxSrc->pCert);
384             if(ctxDst->pCert == NULL) {
385                 xmlSecError(XMLSEC_ERRORS_HERE,
386                             NULL,
387                             "xmlSecMSCryptoPCCDup",
388                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
389                             XMLSEC_ERRORS_NO_MESSAGE);
390                 return(-1);
391             }
392     } 
393     return(0);
394 }
395
396 /******************************************************************************
397  *
398  * xmlSecMSCryptoKeyDataCtx is located after xmlSecTransform
399  *
400  *****************************************************************************/
401 #define xmlSecMSCryptoKeyDataSize       \
402     (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoKeyDataCtx))  
403 #define xmlSecMSCryptoKeyDataGetCtx(data) \
404     ((xmlSecMSCryptoKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
405
406 static int      xmlSecMSCryptoKeyDataDuplicate  (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
407 static void             xmlSecMSCryptoKeyDataFinalize   (xmlSecKeyDataPtr data);
408 static int              xmlSecMSCryptoKeyDataGetSize    (xmlSecKeyDataPtr data);
409
410 /**
411  * xmlSecMSCryptoKeyDataAdoptCert:
412  * @data:               the pointer to MSCrypto pccert data.
413  * @pCert:              the pointer to PCCERT key.
414  *
415  * Sets the value of key data.
416  *
417  * Returns: 0 on success or a negative value otherwise.
418  */
419 static int 
420 xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
421     xmlSecMSCryptoKeyDataCtxPtr ctx;
422     HCRYPTKEY hKey = 0;
423
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);
429
430     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
431     xmlSecAssert2(ctx != NULL, -1);
432
433     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
434     xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
435     xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
436
437     ctx->type = type;
438
439     /* Now we acquire a context for this key(pair). The context is needed
440      * for the real crypto stuff in MS Crypto.
441      */
442     if((type & xmlSecKeyDataTypePrivate) != 0){
443         HCRYPTPROV hProv = 0;
444         BOOL fCallerFreeProv = FALSE;
445
446         if (!CryptAcquireCertificatePrivateKey(pCert, 
447                                                CRYPT_ACQUIRE_COMPARE_KEY_FLAG, 
448                                                NULL, 
449                                                &hProv, 
450                                                &(ctx->dwKeySpec), 
451                                                &fCallerFreeProv)) {
452                 xmlSecError(XMLSEC_ERRORS_HERE,
453                             NULL,
454                             "CryptAcquireCertificatePrivateKey",
455                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
456                             XMLSEC_ERRORS_NO_MESSAGE);
457                 return(-1);
458             }
459         xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
460     } else if((type & xmlSecKeyDataTypePublic) != 0){
461         HCRYPTPROV hProv = 0;
462         if (!CryptAcquireContext(&hProv, 
463                                     NULL, 
464                                     NULL, /* ctx->providerName, */
465                                     ctx->providerType, 
466                                     CRYPT_VERIFYCONTEXT)) {
467                 xmlSecError(XMLSEC_ERRORS_HERE,
468                             NULL,
469                             "CryptAcquireContext",
470                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
471                             XMLSEC_ERRORS_NO_MESSAGE);
472                 return(-1);
473             }
474         xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
475             ctx->dwKeySpec = 0;
476     } else {
477             xmlSecError(XMLSEC_ERRORS_HERE,
478                         NULL,
479                         NULL,
480                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
481                         "Unsupported keytype");
482             return(-1);
483     }
484
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
490      * made. WK
491      */
492     if(!CryptImportPublicKeyInfo(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), 
493                 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
494                 &(pCert->pCertInfo->SubjectPublicKeyInfo), 
495                 &hKey)) {
496             xmlSecError(XMLSEC_ERRORS_HERE,
497                         NULL,
498                         "CryptImportPublicKeyInfo",
499                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
500                         XMLSEC_ERRORS_NO_MESSAGE);
501             return(-1);
502     }
503     
504     xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
505     xmlSecMSCryptoKeyDataCtxSetCert(ctx, pCert);
506     return(0);
507 }
508
509 static int 
510 xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data, 
511                               HCRYPTPROV hProv,
512                               BOOL fCallerFreeProv,
513                               HCRYPTKEY hKey, 
514                               DWORD dwKeySpec,
515                               xmlSecKeyDataType type) {
516     xmlSecMSCryptoKeyDataCtxPtr ctx;
517
518     xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
519     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
520     xmlSecAssert2(hKey != 0, -1);
521     xmlSecAssert2(type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate), -1);
522     
523     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
524     xmlSecAssert2(ctx != NULL, -1);
525
526     xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
527     xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
528     xmlSecMSCryptoKeyDataCtxSetCert(ctx, NULL);
529
530     ctx->dwKeySpec       = dwKeySpec;
531     ctx->type            = type;
532
533     return(0);
534 }
535
536 /**
537  * xmlSecMSCryptoKeyDataGetKey:
538  * @data:               the key data to retrieve certificate from.
539  * @type:              type of key requested (public/private)
540  *
541  * Native MSCrypto key retrieval from xmlsec keydata. The 
542  * returned HKEY must not be destroyed by the caller.
543  * 
544  * Returns: HKEY on success or NULL otherwise.
545  */
546 HCRYPTKEY
547 xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data, xmlSecKeyDataType type) {
548     xmlSecMSCryptoKeyDataCtxPtr ctx;
549
550     xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
551     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
552
553     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
554     xmlSecAssert2(ctx != NULL, 0);
555  
556     return(xmlSecMSCryptoKeyDataCtxGetKey(ctx));
557 }
558
559 /**
560  * xmlSecMSCryptoKeyDataGetDecryptKey:
561  * @data:       the key data pointer
562  * 
563  * Native MSCrypto decrypt key retrieval from xmlsec keydata. The
564  * returned HKEY must not be destroyed by the caller.
565  *
566  * Returns: HKEY on success or NULL otherwise.
567  */
568 HCRYPTKEY
569 xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data) {
570         xmlSecMSCryptoKeyDataCtxPtr ctx;
571         HCRYPTKEY hKey;
572
573         xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
574         xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
575
576         ctx = xmlSecMSCryptoKeyDataGetCtx(data);
577         xmlSecAssert2(ctx != NULL, 0);
578
579         if( !CryptGetUserKey(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), AT_KEYEXCHANGE, &(hKey))) {
580                 xmlSecError(XMLSEC_ERRORS_HERE,
581                         NULL,
582                         "CryptGetUserKey",
583                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
584                         XMLSEC_ERRORS_NO_MESSAGE);
585                 return(0);
586         }
587         return (hKey);
588 }
589
590 /**
591  * xmlSecMSCryptoKeyDataGetCert:
592  * @data:               the key data to retrieve certificate from.
593  * 
594  * Native MSCrypto certificate retrieval from xmlsec keydata. The 
595  * returned PCCERT_CONTEXT must not be released by the caller.
596  * 
597  * Returns: PCCERT_CONTEXT on success or NULL otherwise.
598  */
599 PCCERT_CONTEXT
600 xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data) {
601     xmlSecMSCryptoKeyDataCtxPtr ctx;
602
603     xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
604     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
605
606     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
607     xmlSecAssert2(ctx != NULL, 0);
608  
609     return(xmlSecMSCryptoKeyDataCtxGetCert(ctx));
610 }
611
612 HCRYPTPROV
613 xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
614     xmlSecMSCryptoKeyDataCtxPtr ctx;
615
616     xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
617     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
618
619     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
620     xmlSecAssert2(ctx != NULL, 0);
621
622     return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx));
623 }
624
625 DWORD
626 xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) {
627     xmlSecMSCryptoKeyDataCtxPtr ctx;
628
629     xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
630     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
631
632     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
633     xmlSecAssert2(ctx != NULL, 0);
634
635     return(ctx->dwKeySpec);
636 }
637
638 static int 
639 xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
640     xmlSecMSCryptoKeyDataCtxPtr ctxDst;
641     xmlSecMSCryptoKeyDataCtxPtr ctxSrc;
642
643     xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
644     xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecMSCryptoKeyDataSize), -1);
645     xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
646     xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecMSCryptoKeyDataSize), -1);
647
648     ctxDst = xmlSecMSCryptoKeyDataGetCtx(dst);
649     xmlSecAssert2(ctxDst != NULL, -1);
650
651     ctxSrc = xmlSecMSCryptoKeyDataGetCtx(src);
652     xmlSecAssert2(ctxSrc != NULL, -1);
653
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);
660             return(-1);
661     }
662
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);
669             return(-1);
670     }
671
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);
678             return(-1);
679     }
680     
681     ctxDst->dwKeySpec       = ctxSrc->dwKeySpec;
682     ctxDst->providerName    = ctxSrc->providerName;
683     ctxDst->providerType    = ctxSrc->providerType;
684     ctxDst->type            = ctxSrc->type;
685
686     return(0);
687 }
688
689 static void 
690 xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data) {
691     xmlSecMSCryptoKeyDataCtxPtr ctx;    
692
693     xmlSecAssert(xmlSecKeyDataIsValid(data));
694     xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
695
696     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
697     xmlSecAssert(ctx != NULL);
698
699     memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
700
701     xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
702     xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
703     xmlSecMSCryptoKeyDataCtxCreateCert(ctx);
704 }
705
706 static void 
707 xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data) {
708     xmlSecMSCryptoKeyDataCtxPtr ctx;
709     
710     xmlSecAssert(xmlSecKeyDataIsValid(data));
711     xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
712
713     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
714     xmlSecAssert(ctx != NULL);
715     
716     xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
717     xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
718     xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
719
720     memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
721 }
722
723 static int 
724 xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data) {
725     xmlSecMSCryptoKeyDataCtxPtr ctx;
726
727     xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
728     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
729
730     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
731     xmlSecAssert2(ctx != NULL, 0);
732
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) {
738         DWORD length = 0;
739             DWORD lenlen = sizeof(DWORD);
740         
741         if (!CryptGetKeyParam(xmlSecMSCryptoKeyDataCtxGetKey(ctx), KP_KEYLEN, (BYTE *)&length, &lenlen, 0)) {
742             xmlSecError(XMLSEC_ERRORS_HERE,
743                         NULL,
744                         "CertDuplicateCertificateContext",
745                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
746                         XMLSEC_ERRORS_NO_MESSAGE);
747             return(0);
748         }
749         return(length);
750     }
751     
752     return (0);
753 }
754
755 static xmlSecKeyDataType 
756 xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data) {
757     xmlSecMSCryptoKeyDataCtxPtr ctx;
758     
759     xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
760     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
761
762     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
763     xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
764
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.
769      */
770     return(ctx->type);
771 }
772
773 /**
774  * xmlSecMSCryptoCertDup:
775  * @pCert:              the pointer to cert.
776  * 
777  * Duplicates the @pCert.
778  *
779  * Returns: pointer to newly created PCCERT_CONTEXT object or 
780  * NULL if an error occurs.
781  */
782 PCCERT_CONTEXT xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert) {
783     PCCERT_CONTEXT ret;
784
785     xmlSecAssert2(pCert != NULL, NULL);
786
787     ret = CertDuplicateCertificateContext(pCert);
788     if(ret == NULL) {
789         xmlSecError(XMLSEC_ERRORS_HERE,
790                     NULL,
791                     "CertDuplicateCertificateContext",
792                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
793                     XMLSEC_ERRORS_NO_MESSAGE);
794         return(NULL);                   
795     }
796     
797     return(ret);
798 }
799
800
801 /**
802  * xmlSecMSCryptoCertAdopt:
803  * @pCert:              the pointer to cert.
804  * @type:               the expected key type.
805  *
806  * Creates key data value from the cert.
807  *
808  * Returns: pointer to newly created xmlsec key or NULL if an error occurs.
809  */
810 xmlSecKeyDataPtr 
811 xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
812     xmlSecKeyDataPtr data = NULL;
813     int ret;
814     
815     xmlSecAssert2(pCert != NULL, NULL);
816     xmlSecAssert2(pCert->pCertInfo != NULL, NULL);
817     xmlSecAssert2(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL, NULL);
818
819 #ifndef XMLSEC_NO_RSA
820     if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA)) {
821         data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataRsaId);
822         if(data == NULL) {
823             xmlSecError(XMLSEC_ERRORS_HERE,
824                         NULL,
825                         "xmlSecKeyDataCreate",
826                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
827                         "xmlSecMSCryptoDataRsaId");
828             return(NULL);           
829         }
830     }
831 #endif /* XMLSEC_NO_RSA */      
832
833 #ifndef XMLSEC_NO_DSA
834     if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_X957_DSA /*szOID_DSALG_SIGN*/)) {
835         data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataDsaId);
836         if(data == NULL) {
837                 xmlSecError(XMLSEC_ERRORS_HERE,
838                             NULL,
839                             "xmlSecKeyDataCreate",
840                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
841                             "xmlSecMSCryptoKeyDataDsaId");
842                 return(NULL);       
843         }
844     }
845 #endif /* XMLSEC_NO_DSA */      
846
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);
852         if(data == NULL) {
853                 xmlSecError(XMLSEC_ERRORS_HERE,
854                             NULL,
855                             "xmlSecKeyDataCreate",
856                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
857                             "xmlSecMSCryptoKeyDataGost2001Id");
858                 return(NULL);       
859         }
860     }
861 #endif /* XMLSEC_NO_GOST*/      
862
863     if (NULL == data) {
864         xmlSecError(XMLSEC_ERRORS_HERE,
865                     NULL,
866                     NULL,
867                     XMLSEC_ERRORS_R_INVALID_TYPE,
868                     "PCCERT_CONTEXT key type %s not supported", pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
869         return(NULL);
870     }
871
872     xmlSecAssert2(data != NULL, NULL);    
873
874     ret = xmlSecMSCryptoKeyDataAdoptCert(data, pCert, type);
875     if(ret < 0) {
876         xmlSecError(XMLSEC_ERRORS_HERE,
877                         NULL,
878                         "xmlSecMSCryptoPCCDataAdoptPCC",
879                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
880                         XMLSEC_ERRORS_NO_MESSAGE);
881         xmlSecKeyDataDestroy(data);
882         return(NULL);       
883     }
884     return(data);
885 }
886
887
888 #ifndef XMLSEC_NO_RSA
889 /**************************************************************************
890  *
891  * <dsig:RSAKeyValue> processing
892  *
893  * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
894  * The RSAKeyValue Element
895  *
896  * RSA key values have two fields: Modulus and Exponent.
897  *
898  * <RSAKeyValue>
899  *   <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
900  *     jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
901  *        5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
902  *   </Modulus>
903  *   <Exponent>AQAB</Exponent>
904  * </RSAKeyValue>
905  *
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.
908  *
909  * Schema Definition:
910  * 
911  * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
912  * <complexType name="RSAKeyValueType">
913  *   <sequence>
914  *     <element name="Modulus" type="ds:CryptoBinary"/> 
915  *     <element name="Exponent" type="ds:CryptoBinary"/>
916  *   </sequence>
917  * </complexType>
918  *
919  * DTD Definition:
920  * 
921  * <!ELEMENT RSAKeyValue (Modulus, Exponent) > 
922  * <!ELEMENT Modulus (#PCDATA) >
923  * <!ELEMENT Exponent (#PCDATA) >
924  *
925  * ============================================================================
926  * 
927  *
928  *************************************************************************/
929
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,
934                                                 xmlSecKeyPtr key,
935                                                 xmlNodePtr node,
936                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
937 static int      xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id,
938                                                  xmlSecKeyPtr key,
939                                                  xmlNodePtr node,
940                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
941 static int      xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data,
942                                                  xmlSecSize sizeBits,
943                                                  xmlSecKeyDataType type);
944
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);
949
950 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = {
951     sizeof(xmlSecKeyDataKlass),
952     xmlSecMSCryptoKeyDataSize,
953
954     /* data */
955     xmlSecNameRSAKeyValue,
956     xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, 
957                                                 /* xmlSecKeyDataUsage usage; */
958     xmlSecHrefRSAKeyValue,                      /* const xmlChar* href; */
959     xmlSecNodeRSAKeyValue,                      /* const xmlChar* dataNodeName; */
960     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
961     
962     /* constructors/destructor */
963     xmlSecMSCryptoKeyDataRsaInitialize,         /* xmlSecKeyDataInitializeMethod initialize; */
964     xmlSecMSCryptoKeyDataRsaDuplicate,          /* xmlSecKeyDataDuplicateMethod duplicate; */
965     xmlSecMSCryptoKeyDataRsaFinalize,           /* xmlSecKeyDataFinalizeMethod finalize; */
966     xmlSecMSCryptoKeyDataRsaGenerate,           /* xmlSecKeyDataGenerateMethod generate; */
967     
968     /* get info */
969     xmlSecMSCryptoKeyDataRsaGetType,            /* xmlSecKeyDataGetTypeMethod getType; */
970     xmlSecMSCryptoKeyDataRsaGetSize,            /* xmlSecKeyDataGetSizeMethod getSize; */
971     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */    
972
973     /* read/write */
974     xmlSecMSCryptoKeyDataRsaXmlRead,            /* xmlSecKeyDataXmlReadMethod xmlRead; */
975     xmlSecMSCryptoKeyDataRsaXmlWrite,           /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
976     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
977     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
978
979     /* debug */
980     xmlSecMSCryptoKeyDataRsaDebugDump,          /* xmlSecKeyDataDebugDumpMethod debugDump; */
981     xmlSecMSCryptoKeyDataRsaDebugXmlDump,       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
982
983     /* reserved for the future */
984     NULL,                                       /* void* reserved0; */
985     NULL,                                       /* void* reserved1; */
986 };
987
988 /** 
989  * xmlSecMSCryptoKeyDataRsaGetKlass:
990  *
991  * The MSCrypto RSA CertKey data klass.
992  *
993  * Returns: pointer to MSCrypto RSA key data klass.
994  */
995 xmlSecKeyDataId 
996 xmlSecMSCryptoKeyDataRsaGetKlass(void) {
997     return(&xmlSecMSCryptoKeyDataRsaKlass);
998 }
999
1000 static int 
1001 xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
1002     xmlSecMSCryptoKeyDataCtxPtr ctx;
1003     
1004     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), xmlSecKeyDataTypeUnknown);
1005
1006     xmlSecMSCryptoKeyDataInitialize(data);
1007
1008     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1009     xmlSecAssert2(ctx != NULL, -1);
1010
1011     ctx->providerName = MS_ENHANCED_PROV;
1012     ctx->providerType = PROV_RSA_FULL;
1013     
1014     return(0);
1015 }
1016
1017 static int 
1018 xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1019     xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataRsaId), -1);
1020     xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataRsaId), -1);
1021
1022     return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1023 }
1024
1025 static void 
1026 xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
1027     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1028
1029     xmlSecMSCryptoKeyDataFinalize(data);
1030 }
1031
1032 static int 
1033 xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1034                                 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {                                  
1035     xmlSecBn modulus, exponent;
1036     xmlSecBuffer blob;
1037     unsigned int blobBufferLen;
1038     PUBLICKEYSTRUC* pubKeyStruc = NULL;
1039     RSAPUBKEY* pubKey = NULL;
1040     xmlSecByte* modulusBlob = NULL;
1041     xmlSecKeyDataPtr data = NULL;
1042     HCRYPTPROV hProv = 0;
1043     HCRYPTKEY hKey = 0;
1044     xmlNodePtr cur;
1045     int res = -1;
1046     int ret;
1047
1048     xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
1049     xmlSecAssert2(key != NULL, -1);
1050     xmlSecAssert2(node != NULL, -1);
1051     xmlSecAssert2(keyInfoCtx != NULL, -1);
1052     
1053     if(xmlSecKeyGetValue(key) != NULL) {
1054         xmlSecError(XMLSEC_ERRORS_HERE,
1055                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1056                     NULL,                   
1057                     XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1058                     "key already has a value");
1059         return(-1);
1060     }
1061
1062     /* initialize buffers */
1063     ret = xmlSecBnInitialize(&modulus, 0);
1064     if(ret < 0) {
1065         xmlSecError(XMLSEC_ERRORS_HERE,
1066                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1067                     "xmlSecBnInitialize",
1068                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1069                     "modulus");
1070         return(-1);
1071     }
1072
1073     ret = xmlSecBnInitialize(&exponent, 0);
1074     if(ret < 0) {
1075         xmlSecError(XMLSEC_ERRORS_HERE,
1076                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1077                     "xmlSecBnInitialize",
1078                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1079                     "exponent");
1080         xmlSecBnFinalize(&modulus);
1081         return(-1);
1082     }
1083
1084     ret = xmlSecBufferInitialize(&blob, 0);
1085     if(ret < 0) {
1086         xmlSecError(XMLSEC_ERRORS_HERE,
1087                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1088                     "xmlSecBufferInitialize",
1089                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1090                     "blob");
1091         xmlSecBnFinalize(&modulus);
1092         xmlSecBnFinalize(&exponent);
1093         return(-1);
1094     }
1095
1096     /* read xml */
1097     cur = xmlSecGetNextElementNode(node->children);
1098
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,
1105                     "node=%s", 
1106                     xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1107         goto done;
1108     }
1109
1110     ret = xmlSecBnGetNodeValue(&modulus, cur, xmlSecBnBase64, 1);
1111     if((ret < 0) || (xmlSecBnGetSize(&modulus) == 0)){
1112         xmlSecError(XMLSEC_ERRORS_HERE,
1113                     NULL,
1114                     "xmlSecBnGetNodeValue",
1115                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1116                     "node=%s", 
1117                     xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1118         goto done;
1119     }
1120     cur = xmlSecGetNextElementNode(cur->next);
1121     
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,
1128                     "node=%s", 
1129                     xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1130         goto done;
1131     }
1132     ret = xmlSecBnGetNodeValue(&exponent, cur, xmlSecBnBase64, 1);
1133     if((ret < 0) || (xmlSecBnGetSize(&exponent) == 0)) {
1134         xmlSecError(XMLSEC_ERRORS_HERE,
1135                     NULL,
1136                     "xmlSecBnGetNodeValue",
1137                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1138                     "node=%s", 
1139                     xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1140         goto done;
1141     }
1142     cur = xmlSecGetNextElementNode(cur->next);
1143     
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);
1148     }
1149
1150     if(cur != NULL) {
1151         xmlSecError(XMLSEC_ERRORS_HERE,
1152                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1153                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1154                     XMLSEC_ERRORS_R_INVALID_NODE,
1155                     "no nodes expected");
1156         goto done;
1157     }
1158
1159     /* Now try to create the key */
1160     blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + xmlSecBnGetSize(&modulus);
1161     ret = xmlSecBufferSetSize(&blob, blobBufferLen);
1162     if(ret < 0) {
1163         xmlSecError(XMLSEC_ERRORS_HERE,
1164                     NULL,
1165                     "xmlSecBufferSetSize",
1166                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1167                     "size=%d", blobBufferLen);
1168         goto done;
1169     }
1170
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;
1177
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 */
1182     pubKey->pubexp          = 0;
1183     if(sizeof(pubKey->pubexp) < xmlSecBnGetSize(&exponent)) {
1184         xmlSecError(XMLSEC_ERRORS_HERE,
1185                     NULL,
1186                     NULL,
1187                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1188                     "exponent size=%d", 
1189                     xmlSecBnGetSize(&exponent));
1190         goto done;
1191     }
1192     xmlSecAssert2(xmlSecBnGetData(&exponent) != NULL, -1);
1193     memcpy(&(pubKey->pubexp), xmlSecBnGetData(&exponent), xmlSecBnGetSize(&exponent));
1194
1195     modulusBlob = (xmlSecByte*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
1196     xmlSecAssert2(xmlSecBnGetData(&modulus) != NULL, -1);
1197     memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus));
1198
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);
1208                 goto done;
1209             }
1210         } else {
1211             xmlSecError(XMLSEC_ERRORS_HERE,
1212                         xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1213                         "CryptAcquireContext",
1214                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
1215                         XMLSEC_ERRORS_NO_MESSAGE);
1216             goto done;
1217         }
1218     }
1219
1220     if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
1221         xmlSecError(XMLSEC_ERRORS_HERE,
1222                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1223                     "CryptImportKey",
1224                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1225                     XMLSEC_ERRORS_NO_MESSAGE);
1226         goto done;
1227     }
1228
1229     data = xmlSecKeyDataCreate(id);
1230     if(data == NULL ) {
1231         xmlSecError(XMLSEC_ERRORS_HERE,
1232                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1233                     "xmlSecKeyDataCreate",
1234                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1235                     XMLSEC_ERRORS_NO_MESSAGE);
1236         goto done;
1237     }
1238
1239     ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
1240     if(ret < 0) {
1241         xmlSecError(XMLSEC_ERRORS_HERE,
1242                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1243                     "xmlSecMSCryptoKeyDataAdoptKey",
1244                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1245                     XMLSEC_ERRORS_NO_MESSAGE);
1246         goto done;
1247     }
1248     hProv = 0;
1249     hKey = 0;
1250
1251     ret = xmlSecKeySetValue(key, data);
1252     if(ret < 0) {
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);
1259         goto done;
1260     }
1261     data = NULL;
1262
1263     /* success */
1264     res = 0;
1265
1266 done:
1267     if (hProv == 0) {
1268         CryptReleaseContext(hProv, 0);
1269     }
1270     if (hKey != 0) {
1271         CryptDestroyKey(hKey);
1272     }
1273     if (data != 0) {
1274         xmlSecKeyDataDestroy(data);
1275     }
1276
1277     xmlSecBnFinalize(&modulus);
1278     xmlSecBnFinalize(&exponent);
1279     xmlSecBufferFinalize(&blob);
1280     return(res);
1281 }
1282
1283 static int 
1284 xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
1285                                 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1286     xmlSecMSCryptoKeyDataCtxPtr ctx;
1287     xmlSecBuffer buf;
1288     DWORD dwBlobLen;
1289     xmlSecByte* blob;
1290     PUBLICKEYSTRUC* pubKeyStruc;
1291     RSAPUBKEY *pubKey;
1292     xmlSecSize modulusLen, exponentLen;
1293     xmlNodePtr cur;
1294     int ret;
1295     
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);
1301
1302     ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
1303     xmlSecAssert2(ctx != NULL, -1);
1304     xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
1305
1306     if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
1307         xmlSecError(XMLSEC_ERRORS_HERE,
1308                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1309                     "CryptExportKey",
1310                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1311                     XMLSEC_ERRORS_NO_MESSAGE);
1312         return(-1);
1313     }
1314     
1315     ret = xmlSecBufferInitialize(&buf, dwBlobLen);
1316     if(ret < 0) {
1317         xmlSecError(XMLSEC_ERRORS_HERE,
1318                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1319                     "xmlSecBufferInitialize",
1320                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1321                     "size=%ld", dwBlobLen);
1322         return(-1);
1323     }
1324
1325     blob = xmlSecBufferGetData(&buf);
1326     if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
1327         xmlSecError(XMLSEC_ERRORS_HERE,
1328                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1329                     "CryptExportKey",
1330                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1331                     XMLSEC_ERRORS_NO_MESSAGE);
1332         xmlSecBufferFinalize(&buf);
1333         return(-1);
1334     }
1335     if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
1336         xmlSecError(XMLSEC_ERRORS_HERE,
1337                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1338                     NULL,
1339                     XMLSEC_ERRORS_R_INVALID_DATA,
1340                     "blobLen=%ld", dwBlobLen);
1341         xmlSecBufferFinalize(&buf);
1342         return(-1);
1343     }
1344
1345     /* check PUBLICKEYSTRUC */
1346     pubKeyStruc = (PUBLICKEYSTRUC*)blob;
1347     if(pubKeyStruc->bVersion != 0x02) {
1348         xmlSecError(XMLSEC_ERRORS_HERE, 
1349                     NULL,
1350                     "CryptExportKey",
1351                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1352                     "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
1353         xmlSecBufferFinalize(&buf);
1354         return(-1);
1355     }
1356     if(pubKeyStruc->bType != PUBLICKEYBLOB) {
1357         xmlSecError(XMLSEC_ERRORS_HERE, 
1358                     NULL,
1359                     "CryptExportKey",
1360                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1361                     "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
1362         xmlSecBufferFinalize(&buf);
1363         return(-1);
1364     }
1365
1366     /* check RSAPUBKEY */
1367     pubKey          = (RSAPUBKEY *)(blob + sizeof(PUBLICKEYSTRUC));
1368     if(pubKey->magic != 0x31415352) { /* RSA public key magic */
1369         xmlSecError(XMLSEC_ERRORS_HERE, 
1370                     NULL,
1371                     "CryptExportKey",
1372                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1373                     "pubKey->magic=0x%08lx", pubKey->magic);
1374         xmlSecBufferFinalize(&buf);
1375         return(-1);
1376     }
1377     modulusLen      = pubKey->bitlen / 8;
1378
1379     if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen) {
1380         xmlSecError(XMLSEC_ERRORS_HERE,
1381                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1382                     NULL,
1383                     XMLSEC_ERRORS_R_INVALID_DATA,
1384                     "blobLen=%ld; modulusLen=%d", dwBlobLen, modulusLen);
1385         xmlSecBufferFinalize(&buf);
1386         return(-1);
1387     }
1388     blob            += sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
1389
1390     /* first is Modulus node */
1391     cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
1392     if(cur == NULL) {
1393         xmlSecError(XMLSEC_ERRORS_HERE,
1394                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1395                     "xmlSecAddChild",
1396                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1397                     "node=%s", 
1398                     xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1399         xmlSecBufferFinalize(&buf);
1400         return(-1);     
1401     }
1402
1403     ret = xmlSecBnBlobSetNodeValue(blob, modulusLen, cur, xmlSecBnBase64, 1, 1);
1404     if(ret < 0) {
1405         xmlSecError(XMLSEC_ERRORS_HERE,
1406                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1407                     "xmlSecBnBlobSetNodeValue",
1408                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1409                     "node=%s", 
1410                     xmlSecErrorsSafeString(xmlSecNodeRSAModulus));
1411         xmlSecBufferFinalize(&buf);
1412         return(-1);
1413     }    
1414
1415     /* next is Exponent node. */
1416     cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
1417     if(cur == NULL) {
1418         xmlSecError(XMLSEC_ERRORS_HERE,
1419                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1420                     "xmlSecAddChild",
1421                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1422                     "node=%s", 
1423                     xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1424         xmlSecBufferFinalize(&buf);
1425         return(-1);     
1426     }
1427
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) {
1432         exponentLen--;
1433     }
1434
1435     ret = xmlSecBnBlobSetNodeValue(blob, exponentLen, cur, xmlSecBnBase64, 1, 1);
1436     if(ret < 0) {
1437         xmlSecError(XMLSEC_ERRORS_HERE,
1438                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1439                     "xmlSecBnBlobSetNodeValue",
1440                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1441                     "node=%s", 
1442                     xmlSecErrorsSafeString(xmlSecNodeRSAExponent));
1443         xmlSecBufferFinalize(&buf);
1444         return(-1);     
1445     }
1446
1447     /* next is PrivateExponent node: not supported in MSCrypto */
1448
1449     xmlSecBufferFinalize(&buf);
1450     return(0);
1451 }
1452
1453 static int 
1454 xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, 
1455                                 xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
1456     xmlSecMSCryptoKeyDataCtxPtr ctx;
1457     HCRYPTPROV hProv = 0;
1458     HCRYPTKEY hKey = 0;
1459     DWORD dwKeySpec;
1460     DWORD dwSize;
1461     int res = -1;
1462     int ret;
1463
1464     xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
1465     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
1466     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), -1);
1467     xmlSecAssert2(sizeBits > 0, -1);
1468
1469     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1470     xmlSecAssert2(ctx != NULL, -1);
1471
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);
1480         
1481                 return(-1);
1482             }
1483         } else {
1484             xmlSecError(XMLSEC_ERRORS_HERE,
1485                             xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1486                             "CryptAcquireContext",
1487                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
1488                             XMLSEC_ERRORS_NO_MESSAGE);
1489                 
1490             return(-1);
1491         }
1492     }
1493
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)),
1499                     "CryptGenKey",
1500                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
1501                     XMLSEC_ERRORS_NO_MESSAGE);
1502         goto done;
1503     }
1504
1505     ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec, 
1506                                         xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
1507     if(ret < 0) {
1508         xmlSecError(XMLSEC_ERRORS_HERE,
1509                     xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
1510                     "xmlSecMSCryptoKeyDataAdoptKey",
1511                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1512                     XMLSEC_ERRORS_NO_MESSAGE);
1513         goto done;
1514     }
1515     hProv = 0;
1516     hKey = 0;
1517
1518     /* success */
1519     res = 0;
1520
1521 done:
1522     if (hProv != 0) {
1523         CryptReleaseContext(hProv, 0);
1524     }
1525
1526     if (hKey != 0) {
1527         CryptDestroyKey(hKey);
1528     }
1529
1530     return(res);
1531 }
1532
1533 static xmlSecKeyDataType 
1534 xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data) {
1535     return(xmlSecMSCryptoKeyDataGetType(data));
1536 }
1537
1538 static xmlSecSize 
1539 xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
1540     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), 0);
1541
1542     return (xmlSecMSCryptoKeyDataGetSize(data));
1543 }
1544
1545 static void 
1546 xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
1547     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1548     xmlSecAssert(output != NULL);
1549     
1550     fprintf(output, "=== rsa key: size = %d\n", 
1551             xmlSecMSCryptoKeyDataRsaGetSize(data));
1552 }
1553
1554 static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
1555     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1556     xmlSecAssert(output != NULL);
1557         
1558     fprintf(output, "<RSAKeyValue size=\"%d\" />\n", 
1559             xmlSecMSCryptoKeyDataRsaGetSize(data));
1560 }
1561     
1562 #endif /* XMLSEC_NO_RSA */
1563
1564 #ifndef XMLSEC_NO_DSA    
1565 /**************************************************************************
1566  *
1567  * <dsig:DSAKeyValue> processing
1568  *
1569  *
1570  * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
1571  *
1572  * DSA keys and the DSA signature algorithm are specified in [DSS]. 
1573  * DSA public key values can have the following fields:
1574  *      
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 
1577  *         divisor of P-1 
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 
1580  *         public) 
1581  *   * J - (P - 1) / Q 
1582  *   * seed - a DSA prime generation seed 
1583  *   * pgenCounter - a DSA prime generation counter
1584  *
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.
1597  *     
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.
1600  *     
1601  * Schema Definition:
1602  *     
1603  * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/> 
1604  * <complexType name="DSAKeyValueType"> 
1605  *   <sequence>
1606  *     <sequence minOccurs="0">
1607  *        <element name="P" type="ds:CryptoBinary"/> 
1608  *        <element name="Q" type="ds:CryptoBinary"/>
1609  *     </sequence>
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"/> 
1616  *     </sequence>
1617  *   </sequence>
1618  * </complexType>
1619  *     
1620  * DTD Definition:
1621  *     
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) >
1630  *
1631  * ============================================================================
1632  * 
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*!
1636  *
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,
1643                                                          xmlSecKeyPtr key,
1644                                                          xmlNodePtr node,
1645                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
1646 static int              xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id,
1647                                                          xmlSecKeyPtr key,
1648                                                          xmlNodePtr node,
1649                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
1650 static int              xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data,
1651                                                          xmlSecSize sizeBits,
1652                                                          xmlSecKeyDataType type);
1653
1654 static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data);
1655 static xmlSecSize        xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data);
1656 static void              xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data,
1657                                                          FILE* output);
1658 static void             xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,
1659                                                          FILE* output);
1660
1661 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = {
1662     sizeof(xmlSecKeyDataKlass),
1663     xmlSecMSCryptoKeyDataSize,
1664
1665     /* data */
1666     xmlSecNameDSAKeyValue,
1667     xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, 
1668                                         /* xmlSecKeyDataUsage usage; */
1669     xmlSecHrefDSAKeyValue,              /* const xmlChar* href; */
1670     xmlSecNodeDSAKeyValue,              /* const xmlChar* dataNodeName; */
1671     xmlSecDSigNs,                       /* const xmlChar* dataNodeNs; */
1672     
1673     /* constructors/destructor */
1674     xmlSecMSCryptoKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
1675     xmlSecMSCryptoKeyDataDsaDuplicate,  /* xmlSecKeyDataDuplicateMethod duplicate; */
1676     xmlSecMSCryptoKeyDataDsaFinalize,   /* xmlSecKeyDataFinalizeMethod finalize; */
1677     xmlSecMSCryptoKeyDataDsaGenerate,   /* xmlSecKeyDataGenerateMethod generate; */
1678     
1679     /* get info */
1680     xmlSecMSCryptoKeyDataDsaGetType,    /* xmlSecKeyDataGetTypeMethod getType; */
1681     xmlSecMSCryptoKeyDataDsaGetSize,    /* xmlSecKeyDataGetSizeMethod getSize; */
1682     NULL,                               /* xmlSecKeyDataGetIdentifier getIdentifier; */    
1683
1684     /* read/write */
1685     xmlSecMSCryptoKeyDataDsaXmlRead,    /* xmlSecKeyDataXmlReadMethod xmlRead; */
1686     xmlSecMSCryptoKeyDataDsaXmlWrite,   /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1687     NULL,                               /* xmlSecKeyDataBinReadMethod binRead; */
1688     NULL,                               /* xmlSecKeyDataBinWriteMethod binWrite; */
1689
1690     /* debug */
1691     xmlSecMSCryptoKeyDataDsaDebugDump,  /* xmlSecKeyDataDebugDumpMethod debugDump; */
1692     xmlSecMSCryptoKeyDataDsaDebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1693
1694     /* reserved for the future */
1695     NULL,                               /* void* reserved0; */
1696     NULL,                               /* void* reserved1; */
1697 };
1698
1699 /**
1700  * xmlSecMSCryptoKeyDataDsaGetKlass:
1701  * 
1702  * The DSA key data klass.
1703  *
1704  * Returns: pointer to DSA key data klass.
1705  */
1706 xmlSecKeyDataId 
1707 xmlSecMSCryptoKeyDataDsaGetKlass(void) {
1708     return(&xmlSecMSCryptoKeyDataDsaKlass);
1709 }
1710
1711
1712 static int
1713 xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
1714     xmlSecMSCryptoKeyDataCtxPtr ctx;
1715
1716     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), xmlSecKeyDataTypeUnknown);
1717
1718     xmlSecMSCryptoKeyDataInitialize(data);
1719
1720     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1721     xmlSecAssert2(ctx != NULL, -1);
1722
1723     ctx->providerName = MS_DEF_DSS_PROV;
1724     ctx->providerType = PROV_DSS;
1725     
1726     return(0);
1727 }
1728
1729 static int
1730 xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1731     xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataDsaId), -1);
1732     xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataDsaId), -1);
1733
1734     return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1735 }
1736
1737 static void
1738 xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
1739     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
1740     
1741     xmlSecMSCryptoKeyDataFinalize(data);
1742 }
1743
1744 static int
1745 xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1746                            xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1747     xmlSecKeyDataPtr data = NULL;
1748     xmlNodePtr cur;
1749     xmlSecBn p, q, g, y;
1750     xmlSecBuffer blob;
1751     unsigned int blobBufferLen;
1752     PUBLICKEYSTRUC *pubKeyStruc = NULL;
1753     DSSPUBKEY *pubKey = NULL;
1754     DSSSEED* seed = NULL;
1755     BYTE *buf = NULL;
1756     HCRYPTPROV hProv = 0;
1757     HCRYPTKEY hKey = 0;
1758     xmlSecSize i;
1759     int res = -1;
1760     int ret;
1761
1762     xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
1763     xmlSecAssert2(key != NULL, -1);
1764     xmlSecAssert2(node != NULL, -1);
1765     xmlSecAssert2(keyInfoCtx != NULL, -1);
1766
1767     if(xmlSecKeyGetValue(key) != NULL) {
1768         xmlSecError(XMLSEC_ERRORS_HERE,
1769                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1770                     NULL,
1771                     XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1772                     "key already has a value");
1773         return(-1);
1774     }
1775
1776     /* initialize buffers */
1777     ret = xmlSecBnInitialize(&p, 0);
1778     if(ret < 0) {
1779         xmlSecError(XMLSEC_ERRORS_HERE,
1780                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1781                     "xmlSecBnInitialize",
1782                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1783                     "p");
1784         return(-1);
1785     }
1786
1787     ret = xmlSecBnInitialize(&q, 0);
1788     if(ret < 0) {
1789         xmlSecError(XMLSEC_ERRORS_HERE,
1790                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1791                     "xmlSecBnInitialize",
1792                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1793                     "q");
1794         xmlSecBnFinalize(&p);
1795         return(-1);
1796     }
1797
1798     ret = xmlSecBnInitialize(&g, 0);
1799     if(ret < 0) {
1800         xmlSecError(XMLSEC_ERRORS_HERE,
1801                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1802                     "xmlSecBnInitialize",
1803                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1804                     "g");
1805         xmlSecBnFinalize(&p);
1806         xmlSecBnFinalize(&q);
1807         return(-1);
1808     }
1809
1810     ret = xmlSecBnInitialize(&y, 0);
1811     if(ret < 0) {
1812         xmlSecError(XMLSEC_ERRORS_HERE,
1813                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1814                     "xmlSecBnInitialize",
1815                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1816                     "y");
1817         xmlSecBnFinalize(&p);
1818         xmlSecBnFinalize(&q);
1819         xmlSecBnFinalize(&g);
1820         return(-1);
1821     }
1822
1823     ret = xmlSecBufferInitialize(&blob, 0);
1824     if(ret < 0) {
1825         xmlSecError(XMLSEC_ERRORS_HERE,
1826                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1827                     "xmlSecBufferInitialize",
1828                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1829                     "blob");
1830         xmlSecBnFinalize(&p);
1831         xmlSecBnFinalize(&q);
1832         xmlSecBnFinalize(&g);
1833         xmlSecBnFinalize(&y);
1834         return(-1);
1835     }
1836
1837     /* read xml */
1838     cur = xmlSecGetNextElementNode(node->children);
1839
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,
1846                     "node=%s", 
1847                     xmlSecErrorsSafeString(xmlSecNodeDSAP));
1848         goto done;
1849     }
1850
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,
1857                     "node=%s", 
1858                     xmlSecErrorsSafeString(xmlSecNodeDSAP));
1859         goto done;
1860     }
1861     cur = xmlSecGetNextElementNode(cur->next);
1862
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,
1869                     "node=%s", 
1870                     xmlSecErrorsSafeString(xmlSecNodeDSAQ));
1871         goto done;
1872     }
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,
1879                     "node=%s", 
1880                     xmlSecErrorsSafeString(xmlSecNodeDSAQ));
1881         goto done;
1882     }
1883     cur = xmlSecGetNextElementNode(cur->next);
1884
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,
1891                     "node=%s", 
1892                     xmlSecErrorsSafeString(xmlSecNodeDSAG));
1893         goto done;
1894     }
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,
1901                     "node=%s", 
1902                     xmlSecErrorsSafeString(xmlSecNodeDSAG));
1903         goto done;
1904     }
1905     cur = xmlSecGetNextElementNode(cur->next);
1906
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 */
1910
1911         cur = xmlSecGetNextElementNode(cur->next);  
1912     }
1913
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,
1920                     "node=%s", 
1921                     xmlSecErrorsSafeString(xmlSecNodeDSAY));
1922         goto done;
1923     }
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));
1931         goto done;
1932     }
1933     cur = xmlSecGetNextElementNode(cur->next);
1934
1935     /* todo: add support for J */
1936     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
1937         cur = xmlSecGetNextElementNode(cur->next);  
1938     }
1939     
1940     /* todo: add support for seed */
1941     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
1942         cur = xmlSecGetNextElementNode(cur->next);  
1943     }
1944
1945     /* todo: add support for pgencounter */
1946     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
1947         cur = xmlSecGetNextElementNode(cur->next);  
1948     }
1949
1950     if(cur != NULL) {
1951         xmlSecError(XMLSEC_ERRORS_HERE,
1952                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
1953                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1954                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1955                     XMLSEC_ERRORS_NO_MESSAGE);
1956         goto done;
1957     }
1958
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);
1962     if(ret < 0) {
1963         xmlSecError(XMLSEC_ERRORS_HERE,
1964                     NULL,
1965                     "xmlSecBufferSetSize",
1966                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1967                     "size=%d", blobBufferLen);
1968         goto done;
1969     }
1970
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;
1977
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 */
1982
1983     /* copy the key data */
1984     buf                     = (BYTE*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY));
1985     
1986     /* set p */
1987     xmlSecAssert2(xmlSecBnGetData(&p) != NULL, -1);
1988     memcpy(buf, xmlSecBnGetData(&p), xmlSecBnGetSize(&p));
1989     buf += xmlSecBnGetSize(&p);
1990
1991     /* set q */
1992     if(xmlSecBnGetSize(&q) > 0x14) {
1993         xmlSecError(XMLSEC_ERRORS_HERE,
1994                     NULL,
1995                     "q",
1996                     XMLSEC_ERRORS_R_INVALID_SIZE,
1997                     "size=%d > 0x14", xmlSecBnGetSize(&q));
1998         goto done;
1999     }
2000     xmlSecAssert2(xmlSecBnGetData(&q) != NULL, -1);
2001     memcpy(buf, xmlSecBnGetData(&q), xmlSecBnGetSize(&q));
2002     buf += xmlSecBnGetSize(&q);
2003
2004     /* Pad with zeros */
2005     for(i = xmlSecBnGetSize(&q); i < 0x14; ++i) {
2006         *(buf++) = 0;    
2007     }
2008
2009     /* set generator */
2010     if(xmlSecBnGetSize(&g) > xmlSecBnGetSize(&p)) {
2011         xmlSecError(XMLSEC_ERRORS_HERE,
2012                     NULL,
2013                     "g",
2014                     XMLSEC_ERRORS_R_INVALID_SIZE,
2015                     "size=%d > %d", 
2016                     xmlSecBnGetSize(&g), 
2017                     xmlSecBnGetSize(&p));
2018         goto done;
2019     }
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) {
2025         *(buf++) = 0;    
2026     }
2027
2028     /* Public key */
2029     if(xmlSecBnGetSize(&y) > xmlSecBnGetSize(&p)) {
2030         xmlSecError(XMLSEC_ERRORS_HERE,
2031                     NULL,
2032                     "y",
2033                     XMLSEC_ERRORS_R_INVALID_SIZE,
2034                     "size=%d > %d", 
2035                     xmlSecBnGetSize(&y), 
2036                     xmlSecBnGetSize(&p));
2037         goto done;
2038     }
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) {
2044         *(buf++) = 0;    
2045     }
2046
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 */
2051
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);
2060                 goto done;
2061             }
2062         } else {
2063             xmlSecError(XMLSEC_ERRORS_HERE,
2064                         xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2065                         "CryptAcquireContext",
2066                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
2067                         XMLSEC_ERRORS_NO_MESSAGE);
2068             goto done;
2069         }
2070     }
2071
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)),
2076                     "CryptImportKey",
2077                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
2078                     XMLSEC_ERRORS_NO_MESSAGE);
2079         goto done;
2080     }
2081
2082     data = xmlSecKeyDataCreate(id);
2083     if(data == NULL ) {
2084         xmlSecError(XMLSEC_ERRORS_HERE,
2085                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2086                     "xmlSecKeyDataCreate",
2087                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2088                     XMLSEC_ERRORS_NO_MESSAGE);
2089         goto done;
2090     }
2091
2092     ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
2093     if(ret < 0) {
2094         xmlSecError(XMLSEC_ERRORS_HERE,
2095                     xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2096                     "xmlSecMSCryptoKeyDataAdoptKey",
2097                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2098                     XMLSEC_ERRORS_NO_MESSAGE);
2099         goto done;
2100     }
2101     hProv = 0;
2102     hKey = 0;
2103
2104     ret = xmlSecKeySetValue(key, data);
2105     if(ret < 0) {
2106         xmlSecError(XMLSEC_ERRORS_HERE,
2107                     xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2108                     "xmlSecKeySetValue",
2109                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2110                     XMLSEC_ERRORS_NO_MESSAGE);
2111         goto done;
2112     }
2113     data = NULL;
2114
2115     /* success */
2116     res = 0;
2117
2118 done:
2119     if (hKey != 0) {
2120         CryptDestroyKey(hKey);
2121     }
2122     if (hProv != 0) {
2123         CryptReleaseContext(hProv, 0);
2124     }
2125     if (data != NULL) {
2126         xmlSecKeyDataDestroy(data);
2127     }
2128
2129     xmlSecBufferFinalize(&blob);
2130     xmlSecBnFinalize(&p);
2131     xmlSecBnFinalize(&q);
2132     xmlSecBnFinalize(&g);
2133     xmlSecBnFinalize(&y);
2134
2135     return(res);
2136 }
2137
2138 static int 
2139 xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
2140                                 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
2141     xmlSecMSCryptoKeyDataCtxPtr ctx;
2142     xmlSecBuffer buf;
2143     DWORD dwBlobLen;
2144     xmlSecByte* blob;
2145     PUBLICKEYSTRUC* pubKeyStruc;
2146     DSSPUBKEY *pubKey;
2147     xmlSecSize keyLen, len;
2148     xmlNodePtr cur;
2149     int ret;
2150
2151     
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);
2157
2158     ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
2159     xmlSecAssert2(ctx != NULL, -1);
2160     xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
2161     
2162     if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
2163         xmlSecError(XMLSEC_ERRORS_HERE,
2164                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2165                     "CryptExportKey",
2166                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2167                     XMLSEC_ERRORS_NO_MESSAGE);
2168         return(-1);
2169     }
2170
2171     ret = xmlSecBufferInitialize(&buf, dwBlobLen);
2172     if(ret < 0) {
2173         xmlSecError(XMLSEC_ERRORS_HERE,
2174                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2175                     "xmlSecBufferInitialize",
2176                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2177                     "size=%ld", dwBlobLen);
2178         return(-1);
2179     }
2180
2181     blob = xmlSecBufferGetData(&buf);
2182     if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
2183         xmlSecError(XMLSEC_ERRORS_HERE,
2184                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2185                     "CryptExportKey",
2186                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
2187                     XMLSEC_ERRORS_NO_MESSAGE);
2188         xmlSecBufferFinalize(&buf);
2189         return(-1);
2190     }
2191     if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
2192         xmlSecError(XMLSEC_ERRORS_HERE,
2193                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2194                     NULL,
2195                     XMLSEC_ERRORS_R_INVALID_DATA,
2196                     "blobLen=%ld", dwBlobLen);
2197         xmlSecBufferFinalize(&buf);
2198         return(-1);
2199     }
2200
2201     /* check PUBLICKEYSTRUC */
2202     pubKeyStruc     = (PUBLICKEYSTRUC*)blob;
2203     if(pubKeyStruc->bVersion != 0x02) {
2204         xmlSecError(XMLSEC_ERRORS_HERE, 
2205                     NULL,
2206                     "CryptExportKey",
2207                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
2208                     "pubKeyStruc->bVersion=%d", pubKeyStruc->bVersion);
2209         xmlSecBufferFinalize(&buf);
2210         return(-1);
2211     }
2212     if(pubKeyStruc->bType != PUBLICKEYBLOB) {
2213         xmlSecError(XMLSEC_ERRORS_HERE, 
2214                     NULL,
2215                     "CryptExportKey",
2216                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
2217                     "pubKeyStruc->bType=%d", (int)pubKeyStruc->bType);
2218         xmlSecBufferFinalize(&buf);
2219         return(-1);
2220     }
2221
2222     /* check DSSPUBKEY */
2223     pubKey          = (DSSPUBKEY*)(blob + sizeof(PUBLICKEYSTRUC));
2224     if(pubKey->magic != 0x31535344) { /* DSS key magic */
2225         xmlSecError(XMLSEC_ERRORS_HERE, 
2226                     NULL,
2227                     "CryptExportKey",
2228                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
2229                     "pubKey->magic=0x%08lx", pubKey->magic);
2230         xmlSecBufferFinalize(&buf);
2231         return(-1);
2232     }
2233     keyLen          = pubKey->bitlen / 8;
2234
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)),
2239                     NULL,
2240                     XMLSEC_ERRORS_R_INVALID_DATA,
2241                     "blobLen=%ld; keyLen=%d", dwBlobLen, keyLen);
2242         xmlSecBufferFinalize(&buf);
2243         return(-1);
2244     }
2245     blob            += sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY);
2246
2247     /* first is P node */
2248     cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
2249     if(cur == NULL) {
2250         xmlSecError(XMLSEC_ERRORS_HERE,
2251                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2252                     "xmlSecAddChild",
2253                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2254                     "node=%s", 
2255                     xmlSecErrorsSafeString(xmlSecNodeDSAP));
2256         xmlSecBufferFinalize(&buf);
2257         return(-1);     
2258     }
2259
2260     ret = xmlSecBnBlobSetNodeValue(blob, keyLen, cur, xmlSecBnBase64, 1, 1);
2261     if(ret < 0) {
2262         xmlSecError(XMLSEC_ERRORS_HERE,
2263                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2264                     "xmlSecBnBlobSetNodeValue",
2265                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2266                     "node=%s", 
2267                     xmlSecErrorsSafeString(xmlSecNodeDSAP));
2268         xmlSecBufferFinalize(&buf);
2269         return(-1);
2270     }    
2271     blob += keyLen;
2272
2273     /* next is Q node. */
2274     cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
2275     if(cur == NULL) {
2276         xmlSecError(XMLSEC_ERRORS_HERE,
2277                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2278                     "xmlSecAddChild",
2279                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2280                     "node=%s", 
2281                     xmlSecErrorsSafeString(xmlSecNodeDSAQ));
2282         xmlSecBufferFinalize(&buf);
2283         return(-1);     
2284     }
2285
2286     /* we think that the size of q is 0x14, skip trailing zeros */
2287     for(len = 0x14; len > 0 && blob[len - 1] == 0; --len);
2288
2289     ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2290     if(ret < 0) {
2291         xmlSecError(XMLSEC_ERRORS_HERE,
2292                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2293                     "xmlSecBnBlobSetNodeValue",
2294                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2295                     "node=%s", 
2296                     xmlSecErrorsSafeString(xmlSecNodeDSAQ));
2297         xmlSecBufferFinalize(&buf);
2298         return(-1);
2299     }
2300     blob += 0x14;
2301
2302     /* next is G node. */
2303     cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
2304     if(cur == NULL) {
2305         xmlSecError(XMLSEC_ERRORS_HERE,
2306                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2307                     "xmlSecAddChild",
2308                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2309                     "node=%s", 
2310                     xmlSecErrorsSafeString(xmlSecNodeDSAG));
2311         xmlSecBufferFinalize(&buf);
2312         return(-1);     
2313     }
2314
2315     /* skip trailing zeros */
2316     for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2317
2318     ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2319     if(ret < 0) {
2320         xmlSecError(XMLSEC_ERRORS_HERE,
2321                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2322                     "xmlSecBnBlobSetNodeValue",
2323                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2324                     "node=%s", 
2325                     xmlSecErrorsSafeString(xmlSecNodeDSAG));
2326         xmlSecBufferFinalize(&buf);
2327         return(-1);
2328     }
2329     blob += keyLen;
2330
2331     /* next is X node: not supported in MSCrypto */
2332
2333     /* next is Y node. */
2334     cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
2335     if(cur == NULL) {
2336         xmlSecError(XMLSEC_ERRORS_HERE,
2337                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2338                     "xmlSecAddChild",
2339                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2340                     "node=%s", 
2341                     xmlSecErrorsSafeString(xmlSecNodeDSAY));
2342         xmlSecBufferFinalize(&buf);
2343         return(-1);     
2344     }
2345
2346     /* skip trailing zeros */
2347     for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2348
2349     ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2350     if(ret < 0) {
2351         xmlSecError(XMLSEC_ERRORS_HERE,
2352                     xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
2353                     "xmlSecBnBlobSetNodeValue",
2354                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
2355                     "node=%s", 
2356                     xmlSecErrorsSafeString(xmlSecNodeDSAY));
2357         xmlSecBufferFinalize(&buf);
2358         return(-1);
2359     }
2360     blob += keyLen;
2361
2362     xmlSecBufferFinalize(&buf);
2363     return(0);
2364 }
2365
2366 static int
2367 xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
2368     xmlSecMSCryptoKeyDataCtxPtr ctx;
2369     HCRYPTPROV hProv = 0; 
2370     HCRYPTKEY hKey = 0;
2371     DWORD dwKeySpec;
2372     DWORD dwSize;
2373     int res = -1;
2374     int ret;
2375
2376     xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
2377     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
2378     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), -1);
2379     xmlSecAssert2(sizeBits > 0, -1);
2380
2381     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2382
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);
2391                         return(-1);
2392                 }
2393             } else {
2394                 xmlSecError(XMLSEC_ERRORS_HERE,
2395                             xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2396                             "CryptAcquireContext",
2397                             XMLSEC_ERRORS_R_CRYPTO_FAILED,
2398                             XMLSEC_ERRORS_NO_MESSAGE);
2399                 return(-1);
2400             }
2401     }
2402
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)),
2408                         "CryptGenKey",
2409                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
2410                         XMLSEC_ERRORS_NO_MESSAGE);
2411             goto done;
2412     }
2413
2414     ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec, 
2415         xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
2416     if(ret < 0) {
2417             xmlSecError(XMLSEC_ERRORS_HERE,
2418                         xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2419                         "xmlSecMSCryptoKeyDataAdoptKey",
2420                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2421                         XMLSEC_ERRORS_NO_MESSAGE);
2422             goto done;
2423     }
2424     hProv = 0;
2425     hKey = 0;
2426
2427     /* success */
2428     res = 0;
2429
2430 done:
2431     if (hProv != 0) {
2432         CryptReleaseContext(hProv, 0);
2433     }
2434
2435     if (hKey != 0) {
2436             CryptDestroyKey(hKey);
2437     }
2438
2439     return(res);
2440 }
2441
2442 static xmlSecKeyDataType
2443 xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data) {
2444     return(xmlSecMSCryptoKeyDataGetType(data));
2445 }
2446
2447 static xmlSecSize 
2448 xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
2449     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), 0);
2450
2451     return xmlSecMSCryptoKeyDataGetSize(data);
2452 }
2453
2454 static void 
2455 xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
2456     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2457     xmlSecAssert(output != NULL);
2458     
2459     fprintf(output, "=== dsa key: size = %d\n", 
2460             xmlSecMSCryptoKeyDataDsaGetSize(data));
2461 }
2462
2463 static void
2464 xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2465     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2466     xmlSecAssert(output != NULL);
2467         
2468     fprintf(output, "<DSAKeyValue size=\"%d\" />\n", 
2469             xmlSecMSCryptoKeyDataDsaGetSize(data));
2470 }
2471
2472 #endif /* XMLSEC_NO_DSA */
2473
2474
2475 #ifndef XMLSEC_NO_GOST
2476 /**************************************************************************
2477  *
2478  * GOST2001 xml key representation processing. Contain errors.
2479  *
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,
2486                                                          xmlSecKeyPtr key,
2487                                                          xmlNodePtr node,
2488                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
2489 static int              xmlSecMSCryptoKeyDataGost2001XmlWrite(xmlSecKeyDataId id,
2490                                                          xmlSecKeyPtr key,
2491                                                          xmlNodePtr node,
2492                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
2493 static int              xmlSecMSCryptoKeyDataGost2001Generate(xmlSecKeyDataPtr data,
2494                                                          xmlSecSize sizeBits,
2495                                                          xmlSecKeyDataType type);
2496
2497 static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data);
2498 static xmlSecSize        xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data);
2499 static void              xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data,
2500                                                          FILE* output);
2501 static void             xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data,
2502                                                          FILE* output);
2503
2504 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = {
2505     sizeof(xmlSecKeyDataKlass),
2506     xmlSecMSCryptoKeyDataSize,
2507
2508     /* data */
2509     xmlSecNameGOST2001KeyValue,
2510     xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml, 
2511                                         /* xmlSecKeyDataUsage usage; */
2512     xmlSecHrefGOST2001KeyValue,         /* const xmlChar* href; */
2513     xmlSecNodeGOST2001KeyValue,         /* const xmlChar* dataNodeName; */
2514     xmlSecDSigNs,                       /* const xmlChar* dataNodeNs; */
2515     
2516     /* constructors/destructor */
2517     xmlSecMSCryptoKeyDataGost2001Initialize,    /* xmlSecKeyDataInitializeMethod initialize; */
2518     xmlSecMSCryptoKeyDataGost2001Duplicate,     /* xmlSecKeyDataDuplicateMethod duplicate; */
2519     xmlSecMSCryptoKeyDataGost2001Finalize,      /* xmlSecKeyDataFinalizeMethod finalize; */
2520     NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/   /* xmlSecKeyDataGenerateMethod generate; */
2521     
2522     /* get info */
2523     xmlSecMSCryptoKeyDataGost2001GetType,       /* xmlSecKeyDataGetTypeMethod getType; */
2524     xmlSecMSCryptoKeyDataGost2001GetSize,       /* xmlSecKeyDataGetSizeMethod getSize; */
2525     NULL,                               /* xmlSecKeyDataGetIdentifier getIdentifier; */    
2526
2527     /* read/write */
2528     NULL,       /* xmlSecKeyDataXmlReadMethod xmlRead; */
2529     NULL,       /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
2530     NULL,                               /* xmlSecKeyDataBinReadMethod binRead; */
2531     NULL,                               /* xmlSecKeyDataBinWriteMethod binWrite; */
2532
2533     /* debug */
2534     xmlSecMSCryptoKeyDataGost2001DebugDump,     /* xmlSecKeyDataDebugDumpMethod debugDump; */
2535     xmlSecMSCryptoKeyDataGost2001DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
2536
2537     /* reserved for the future */
2538     NULL,                               /* void* reserved0; */
2539     NULL,                               /* void* reserved1; */
2540 };
2541
2542 /**
2543  * xmlSecMSCryptoKeyDataGost2001GetKlass:
2544  * 
2545  * The GOST2001 key data klass.
2546  *
2547  * Returns: pointer to GOST2001 key data klass.
2548  */
2549 xmlSecKeyDataId 
2550 xmlSecMSCryptoKeyDataGost2001GetKlass(void) {
2551     return(&xmlSecMSCryptoKeyDataGost2001Klass);
2552 }
2553
2554
2555 static int
2556 xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
2557     xmlSecMSCryptoKeyDataCtxPtr ctx;
2558     HCRYPTPROV tmp_ctx = 0;
2559
2560     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
2561
2562     xmlSecMSCryptoKeyDataInitialize(data);
2563
2564     ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2565     xmlSecAssert2(ctx != NULL, -1);
2566
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;
2571     } else {
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;
2575       } else {
2576           xmlSecError(XMLSEC_ERRORS_HERE,
2577                       xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
2578                       "xmlSecMSCryptoKeyDataGost2001Initialize",
2579                       XMLSEC_ERRORS_R_XMLSEC_FAILED,
2580                       XMLSEC_ERRORS_NO_MESSAGE);
2581                     return -1;
2582      }
2583     }
2584     CryptReleaseContext(tmp_ctx, 0);
2585     return(0);
2586 }
2587
2588 static int
2589 xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
2590     xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2001Id), -1);
2591     xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2001Id), -1);
2592
2593     return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
2594 }
2595
2596 static void
2597 xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data) {
2598     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2599     
2600     xmlSecMSCryptoKeyDataFinalize(data);
2601 }
2602
2603 static xmlSecKeyDataType
2604 xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data) {
2605     return(xmlSecMSCryptoKeyDataGetType(data));
2606 }
2607
2608 static xmlSecSize 
2609 xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data) {
2610     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), 0);
2611
2612     return xmlSecMSCryptoKeyDataGetSize(data);
2613 }
2614
2615 static void 
2616 xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output) {
2617     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2618     xmlSecAssert(output != NULL);
2619     
2620     fprintf(output, "=== dsa key: size = %d\n", 
2621             xmlSecMSCryptoKeyDataGost2001GetSize(data));
2622 }
2623
2624 static void
2625 xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2626     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2627     xmlSecAssert(output != NULL);
2628         
2629     fprintf(output, "<GOST2001KeyValue size=\"%d\" />\n", 
2630             xmlSecMSCryptoKeyDataGost2001GetSize(data));
2631 }
2632
2633 #endif /* XMLSEC_NO_GOST*/