1 /*
2 * XML Security Library (http://www.aleksey.com/xmlsec).
3 *
4 *
5 * This is free software; see Copyright file in the source
6 * distribution for preciese wording.
7 *
8 * Copyright (C) 2003 Cordys R&D BV, All rights reserved.
9 * Copyright (C) 2003-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
10 */
11 /**
12 * SECTION:certkeys
13 * @Short_description: Certificate keys support functions for Microsoft Crypto API.
14 * @Stability: Stable
15 *
16 */
17
18 #include "globals.h"
19
20 #include <string.h>
21
22 #include <windows.h>
23 #include <wincrypt.h>
24
25 #ifndef XMLSEC_NO_GOST
26 #include "csp_oid.h"
27 #include "csp_calg.h"
28 #endif
29
30 #include <xmlsec/xmlsec.h>
31 #include <xmlsec/xmltree.h>
32 #include <xmlsec/keys.h>
33 #include <xmlsec/keyinfo.h>
34 #include <xmlsec/transforms.h>
35 #include <xmlsec/errors.h>
36 #include <xmlsec/bn.h>
37
38 #include <xmlsec/mscrypto/certkeys.h>
39 #include <xmlsec/mscrypto/crypto.h>
40 #include <xmlsec/mscrypto/x509.h>
41 #include "private.h"
42
43 // GOST CSP don't support keys duplicating, so we use NT4 analogs for these...
44 #ifndef XMLSEC_NO_GOST
45 #ifndef XMLSEC_MSCRYPTO_NT4
46 #define XMLSEC_MSCRYPTO_NT4
47 #endif
48 #endif
49
50
51 /**************************************************************************
52 *
53 * Internal MSCrypto PCCERT_CONTEXT key CTX
54 *
55 *************************************************************************/
56 typedef struct _xmlSecMSCryptoKeyDataCtx xmlSecMSCryptoKeyDataCtx,
57 *xmlSecMSCryptoKeyDataCtxPtr;
58
59 #ifdef XMLSEC_MSCRYPTO_NT4
60 /*-
61 * A wrapper of HCRYPTKEY, a reference counter is introduced, the function is
62 * the same as CryptDuplicateKey. Because the CryptDuplicateKey is not support
63 * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
64 */
65 struct _mscrypt_key {
66 HCRYPTKEY hKey ;
67 volatile LONG refcnt ;
68 } ;
69
70 /*-
71 * A wrapper of HCRYPTPROV, a reference counter is introduced, the function is
72 * the same as CryptContextAddRef. Because the CryptContextAddRef is not support
73 * by WINNT 4.0, the wrapper will enable the library work on WINNT 4.0
74 */
75 struct _mscrypt_prov {
76 HCRYPTPROV hProv ;
77 BOOL fCallerFreeProv ;
78 volatile LONG refcnt ;
79 } ;
80 #endif /* XMLSEC_MSCRYPTO_NT4 */
81
82 /*
83 * Since MSCrypto does not provide direct handles to private keys, we support
84 * only private keys linked to a certificate context. The certificate context
85 * also provides the public key. Only when no certificate context is used, and
86 * a public key from xml document is provided, we need HCRYPTKEY.... The focus
87 * now is however directed to certificates. Wouter
88 */
89 struct _xmlSecMSCryptoKeyDataCtx {
90 #ifndef XMLSEC_MSCRYPTO_NT4
91 HCRYPTPROV hProv;
92 BOOL fCallerFreeProv;
93 HCRYPTKEY hKey;
94 #else /* XMLSEC_MSCRYPTO_NT4 */
95 struct _mscrypt_prov* p_prov ;
96 struct _mscrypt_key* p_key ;
97 #endif /* XMLSEC_MSCRYPTO_NT4 */
98 PCCERT_CONTEXT pCert;
99 const xmlSecMSCryptoProviderInfo * providers;
100 DWORD dwKeySpec;
101 xmlSecKeyDataType type;
102 };
103
104 #ifndef XMLSEC_MSCRYPTO_NT4
105
106 /******************************** Provider *****************************************/
107 #define xmlSecMSCryptoKeyDataCtxGetProvider(ctx) (ctx)->hProv
108
109 static int
xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx)110 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
111 xmlSecAssert2(ctx != NULL, -1);
112
113 ctx->hProv = 0;
114 ctx->fCallerFreeProv = FALSE;
115 return(0);
116 }
117
118 static void
xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx)119 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
120 xmlSecAssert(ctx != NULL);
121
122 if ((ctx->hProv != 0) && (ctx->fCallerFreeProv)) {
123 CryptReleaseContext(ctx->hProv, 0);
124 }
125 ctx->hProv = 0;
126 ctx->fCallerFreeProv = FALSE;
127 }
128
129 static int
xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx,HCRYPTPROV hProv,BOOL fCallerFreeProv)130 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
131 {
132 xmlSecAssert2(ctx != NULL, -1);
133
134 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
135 ctx->hProv = hProv;
136 ctx->fCallerFreeProv = fCallerFreeProv;
137 return(0);
138 }
139
140 static int
xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst,xmlSecMSCryptoKeyDataCtxPtr ctxSrc)141 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
142 xmlSecAssert2(ctxDst != NULL, -1);
143 xmlSecAssert2(ctxSrc != NULL, -1);
144
145 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
146
147 if(ctxSrc->hProv != 0) {
148 if(!CryptContextAddRef(ctxSrc->hProv, NULL, 0)) {
149 xmlSecMSCryptoError("CryptContextAddRef", NULL);
150 return(-1);
151 }
152
153 ctxDst->hProv = ctxSrc->hProv;
154 ctxDst->fCallerFreeProv = TRUE;
155 }
156 return(0);
157 }
158
159
160 /******************************** Key *****************************************/
161 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) ((ctx)->hKey)
162
163 static int
xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx)164 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
165 xmlSecAssert2(ctx != NULL, -1);
166
167 ctx->hKey = 0;
168 return(0);
169 }
170
171 static void
xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx)172 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
173 xmlSecAssert(ctx != NULL);
174
175 if (ctx->hKey != 0) {
176 CryptDestroyKey(ctx->hKey);
177 }
178 ctx->hKey = 0;
179 }
180
181 static int
xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx,HCRYPTKEY hKey)182 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
183 xmlSecAssert2(ctx != NULL, -1);
184
185 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
186 ctx->hKey = hKey;
187 return(0);
188 }
189
190 static int
xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst,xmlSecMSCryptoKeyDataCtxPtr ctxSrc)191 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
192 xmlSecAssert2(ctxDst != NULL, -1);
193 xmlSecAssert2(ctxSrc != NULL, -1);
194
195 xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
196 if (ctxSrc->hKey != 0) {
197 if (!CryptDuplicateKey(ctxSrc->hKey, NULL, 0, &(ctxDst->hKey))) {
198 xmlSecMSCryptoError("CryptDuplicateKey", NULL);
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 int
xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx)212 xmlSecMSCryptoKeyDataCtxCreateProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
213 xmlSecAssert2(ctx != NULL, -1);
214
215 ctx->p_prov = (struct _mscrypt_prov*)xmlMalloc(sizeof(struct _mscrypt_prov));
216 if(ctx->p_prov == NULL) {
217 xmlSecMallocError(sizeof(struct _mscrypt_prov), NULL);
218 return(-1);
219 }
220 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
221 return(0);
222 }
223
224 static void
xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx)225 xmlSecMSCryptoKeyDataCtxDestroyProvider(xmlSecMSCryptoKeyDataCtxPtr ctx) {
226 xmlSecAssert(ctx != NULL);
227
228 if(ctx->p_prov != NULL) {
229 if(InterlockedDecrement(&(ctx->p_prov->refcnt)) <= 0) {
230 if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
231 CryptReleaseContext(ctx->p_prov->hProv, 0) ;
232 }
233 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
234 xmlFree(ctx->p_prov) ;
235 }
236 ctx->p_prov = NULL;
237 }
238 }
239
240 static int
xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx,HCRYPTPROV hProv,BOOL fCallerFreeProv)241 xmlSecMSCryptoKeyDataCtxSetProvider(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTPROV hProv, BOOL fCallerFreeProv)
242 {
243 int ret;
244
245 xmlSecAssert2(ctx != NULL, -1);
246
247 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
248
249 if((ctx->p_prov != NULL) && (ctx->p_prov->refcnt == 1)) {
250 if((ctx->p_prov->hProv != 0) && (ctx->p_prov->fCallerFreeProv)) {
251 CryptReleaseContext(ctx->p_prov->hProv, 0) ;
252 }
253 memset(ctx->p_prov, 0, sizeof(struct _mscrypt_prov));
254 } else {
255 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
256 ret = xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
257 if(ret != 0) {
258 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxCreateProvider", NULL);
259 return(-1);
260 }
261 }
262
263 ctx->p_prov->hProv = hProv;
264 ctx->p_prov->fCallerFreeProv = fCallerFreeProv;
265 ctx->p_prov->refcnt = 1;
266 return(0);
267 }
268
269 static int
xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst,xmlSecMSCryptoKeyDataCtxPtr ctxSrc)270 xmlSecMSCryptoKeyDataCtxDuplicateProvider(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
271 xmlSecAssert2(ctxDst != NULL, -1);
272 xmlSecAssert2(ctxSrc != NULL, -1);
273
274 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctxDst);
275
276 if (ctxSrc->p_prov != NULL) {
277 ctxDst->p_prov = ctxSrc->p_prov;
278 InterlockedIncrement(&(ctxDst->p_prov->refcnt));
279 }
280
281 return(0);
282 }
283
284 /******************************** Key *****************************************/
285 #define xmlSecMSCryptoKeyDataCtxGetKey(ctx) (((ctx)->p_key) ? ((ctx)->p_key->hKey) : 0)
286
287 static int
xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx)288 xmlSecMSCryptoKeyDataCtxCreateKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
289 xmlSecAssert2(ctx != NULL, -1);
290
291 ctx->p_key = (struct _mscrypt_key*)xmlMalloc(sizeof(struct _mscrypt_key));
292 if(ctx->p_key == NULL ) {
293 xmlSecMallocError(sizeof(struct _mscrypt_key), NULL);
294 return(-1);
295 }
296 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
297 return(0);
298 }
299
300 static void
xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx)301 xmlSecMSCryptoKeyDataCtxDestroyKey(xmlSecMSCryptoKeyDataCtxPtr ctx) {
302 xmlSecAssert(ctx != NULL);
303
304 if(ctx->p_key != NULL) {
305 if(InterlockedDecrement(&(ctx->p_key->refcnt)) <= 0) {
306 if(ctx->p_key->hKey != 0) {
307 CryptDestroyKey(ctx->p_key->hKey) ;
308 }
309 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
310 xmlFree(ctx->p_key) ;
311 }
312 ctx->p_key = NULL;
313 }
314 }
315
316 static int
xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx,HCRYPTKEY hKey)317 xmlSecMSCryptoKeyDataCtxSetKey(xmlSecMSCryptoKeyDataCtxPtr ctx, HCRYPTKEY hKey) {
318 int ret;
319 xmlSecAssert2(ctx != NULL, -1);
320
321 if((ctx->p_key != NULL) && (ctx->p_key->refcnt == 1)) {
322 if(ctx->p_key->hKey != 0) {
323 CryptDestroyKey(ctx->p_key->hKey) ;
324 }
325 memset(ctx->p_key, 0, sizeof(struct _mscrypt_key));
326 } else {
327 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
328 ret = xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
329 if(ret != 0) {
330 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxCreateKey", NULL);
331 return(-1);
332 }
333 }
334 ctx->p_key->hKey = hKey;
335 ctx->p_key->refcnt = 1;
336 return(0);
337 }
338
339 static int
xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst,xmlSecMSCryptoKeyDataCtxPtr ctxSrc)340 xmlSecMSCryptoKeyDataCtxDuplicateKey(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
341 xmlSecAssert2(ctxDst != NULL, -1);
342 xmlSecAssert2(ctxSrc != NULL, -1);
343
344 xmlSecMSCryptoKeyDataCtxDestroyKey(ctxDst);
345 if (ctxSrc->p_key != NULL) {
346 ctxDst->p_key = ctxSrc->p_key;
347 InterlockedIncrement(&(ctxDst->p_key->refcnt));
348 }
349
350 return(0);
351 }
352
353 #endif /* XMLSEC_MSCRYPTO_NT4 */
354
355 /******************************** Cert *****************************************/
356 #define xmlSecMSCryptoKeyDataCtxGetCert(ctx) ((ctx)->pCert)
357
358 static void
xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx)359 xmlSecMSCryptoKeyDataCtxCreateCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
360 xmlSecAssert(ctx != NULL);
361
362 ctx->pCert = NULL;
363 }
364
365 static void
xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx)366 xmlSecMSCryptoKeyDataCtxDestroyCert(xmlSecMSCryptoKeyDataCtxPtr ctx) {
367 xmlSecAssert(ctx != NULL);
368
369 if(ctx->pCert != NULL) {
370 CertFreeCertificateContext(ctx->pCert);
371 }
372 ctx->pCert = NULL;
373 }
374
375 static int
xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx,PCCERT_CONTEXT pCert)376 xmlSecMSCryptoKeyDataCtxSetCert(xmlSecMSCryptoKeyDataCtxPtr ctx, PCCERT_CONTEXT pCert) {
377 xmlSecAssert2(ctx != NULL, -1);
378
379 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
380 ctx->pCert = pCert;
381 return(0);
382 }
383
384 static int
xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst,xmlSecMSCryptoKeyDataCtxPtr ctxSrc)385 xmlSecMSCryptoKeyDataCtxDuplicateCert(xmlSecMSCryptoKeyDataCtxPtr ctxDst, xmlSecMSCryptoKeyDataCtxPtr ctxSrc) {
386 xmlSecAssert2(ctxDst != NULL, -1);
387 xmlSecAssert2(ctxSrc != NULL, -1);
388
389 xmlSecMSCryptoKeyDataCtxDestroyCert(ctxDst);
390 if(ctxSrc->pCert != NULL) {
391 ctxDst->pCert = xmlSecMSCryptoCertDup(ctxSrc->pCert);
392 if(ctxDst->pCert == NULL) {
393 xmlSecInternalError("xmlSecMSCryptoPCCDup", NULL);
394 return(-1);
395 }
396 }
397 return(0);
398 }
399
400 /******************************************************************************
401 *
402 * xmlSecMSCryptoKeyDataCtx is located after xmlSecTransform
403 *
404 *****************************************************************************/
405 #define xmlSecMSCryptoKeyDataSize \
406 (sizeof(xmlSecKeyData) + sizeof(xmlSecMSCryptoKeyDataCtx))
407 #define xmlSecMSCryptoKeyDataGetCtx(data) \
408 ((xmlSecMSCryptoKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
409
410 static int xmlSecMSCryptoKeyDataDuplicate (xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
411 static void xmlSecMSCryptoKeyDataFinalize (xmlSecKeyDataPtr data);
412 static int xmlSecMSCryptoKeyDataGetSize (xmlSecKeyDataPtr data);
413
414 /**
415 * xmlSecMSCryptoKeyDataAdoptCert:
416 * @data: the pointer to MSCrypto pccert data.
417 * @pCert: the pointer to PCCERT key.
418 *
419 * Sets the value of key data.
420 *
421 * Returns: 0 on success or a negative value otherwise.
422 */
423 static int
xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data,PCCERT_CONTEXT pCert,xmlSecKeyDataType type)424 xmlSecMSCryptoKeyDataAdoptCert(xmlSecKeyDataPtr data, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
425 xmlSecMSCryptoKeyDataCtxPtr ctx;
426 HCRYPTKEY hKey = 0;
427 int ret;
428
429 xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
430 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
431 xmlSecAssert2(pCert != NULL, -1);
432 xmlSecAssert2(pCert->pCertInfo != NULL, -1);
433 xmlSecAssert2((type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) != 0, -1);
434
435 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
436 xmlSecAssert2(ctx != NULL, -1);
437
438 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
439 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
440 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
441
442 ctx->type = type;
443
444 /* Now we acquire a context for this key(pair). The context is needed
445 * for the real crypto stuff in MS Crypto.
446 */
447 if((type & xmlSecKeyDataTypePrivate) != 0){
448 HCRYPTPROV hProv = 0;
449 BOOL fCallerFreeProv = FALSE;
450
451 if (!CryptAcquireCertificatePrivateKey(pCert,
452 CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
453 NULL,
454 &hProv,
455 &(ctx->dwKeySpec),
456 &fCallerFreeProv)) {
457 xmlSecMSCryptoError("CryptAcquireCertificatePrivateKey", NULL);
458 return(-1);
459 }
460 ret = xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
461 if(ret != 0) {
462 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetProvider", NULL);
463 return(-1);
464 }
465 } else if((type & xmlSecKeyDataTypePublic) != 0){
466 HCRYPTPROV hProv;
467
468 hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, FALSE);
469 if (hProv == 0) {
470 xmlSecInternalError("xmlSecMSCryptoFindProvider", NULL);
471 return(-1);
472 }
473 ret = xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, TRUE);
474 if(ret != 0) {
475 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetProvider", NULL);
476 return(-1);
477 }
478 ctx->dwKeySpec = 0;
479 } else {
480 xmlSecInvalidIntegerTypeError("keytype", type, "supported keytype", NULL);
481 return(-1);
482 }
483
484 /* CryptImportPublicKeyInfo is only needed when a real key handle
485 * is needed. The key handle is needed for de/encrypting and for
486 * verifying of a signature, *not* for signing. We could call
487 * CryptImportPublicKeyInfo in xmlSecMSCryptoKeyDataGetKey instead
488 * so no unnecessary calls to CryptImportPublicKeyInfo are being
489 * made. WK
490 */
491 if(!CryptImportPublicKeyInfo(xmlSecMSCryptoKeyDataCtxGetProvider(ctx),
492 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
493 &(pCert->pCertInfo->SubjectPublicKeyInfo),
494 &hKey)) {
495 xmlSecMSCryptoError("CryptImportPublicKeyInfo", NULL);
496 return(-1);
497 }
498
499 ret = xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
500 if(ret != 0) {
501 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetKey", NULL);
502 return(-1);
503 }
504 ret = xmlSecMSCryptoKeyDataCtxSetCert(ctx, pCert);
505 if(ret != 0) {
506 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetCert", NULL);
507 return(-1);
508 }
509 return(0);
510 }
511
512 static int
xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data,HCRYPTPROV hProv,BOOL fCallerFreeProv,HCRYPTKEY hKey,DWORD dwKeySpec,xmlSecKeyDataType type)513 xmlSecMSCryptoKeyDataAdoptKey(xmlSecKeyDataPtr data,
514 HCRYPTPROV hProv,
515 BOOL fCallerFreeProv,
516 HCRYPTKEY hKey,
517 DWORD dwKeySpec,
518 xmlSecKeyDataType type) {
519 xmlSecMSCryptoKeyDataCtxPtr ctx;
520 int ret;
521
522 xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
523 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
524 xmlSecAssert2(hKey != 0, -1);
525 xmlSecAssert2(type & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate), -1);
526
527 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
528 xmlSecAssert2(ctx != NULL, -1);
529
530 ret = xmlSecMSCryptoKeyDataCtxSetProvider(ctx, hProv, fCallerFreeProv);
531 if(ret != 0) {
532 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetProvider", NULL);
533 return(-1);
534 }
535 ret = xmlSecMSCryptoKeyDataCtxSetKey(ctx, hKey);
536 if(ret != 0) {
537 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetKey", NULL);
538 return(-1);
539 }
540 ret = xmlSecMSCryptoKeyDataCtxSetCert(ctx, NULL);
541 if(ret != 0) {
542 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxSetCert", NULL);
543 return(-1);
544 }
545
546 ctx->dwKeySpec = dwKeySpec;
547 ctx->type = type;
548
549 return(0);
550 }
551
552 /**
553 * xmlSecMSCryptoKeyDataGetKey:
554 * @data: the key data to retrieve certificate from.
555 * @type: type of key requested (public/private)
556 *
557 * Native MSCrypto key retrieval from xmlsec keydata. The
558 * returned HKEY must not be destroyed by the caller.
559 *
560 * Returns: HKEY on success or NULL otherwise.
561 */
562 HCRYPTKEY
xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data,xmlSecKeyDataType type)563 xmlSecMSCryptoKeyDataGetKey(xmlSecKeyDataPtr data, xmlSecKeyDataType type) {
564 xmlSecMSCryptoKeyDataCtxPtr ctx;
565
566 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
567 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
568
569 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
570 xmlSecAssert2(ctx != NULL, 0);
571 UNREFERENCED_PARAMETER(type);
572
573 return(xmlSecMSCryptoKeyDataCtxGetKey(ctx));
574 }
575
576 /**
577 * xmlSecMSCryptoKeyDataGetDecryptKey:
578 * @data: the key data pointer
579 *
580 * Native MSCrypto decrypt key retrieval from xmlsec keydata. The
581 * returned HKEY must not be destroyed by the caller.
582 *
583 * Returns: HKEY on success or NULL otherwise.
584 */
585 HCRYPTKEY
xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data)586 xmlSecMSCryptoKeyDataGetDecryptKey(xmlSecKeyDataPtr data) {
587 xmlSecMSCryptoKeyDataCtxPtr ctx;
588 HCRYPTKEY hKey;
589
590 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
591 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
592
593 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
594 xmlSecAssert2(ctx != NULL, 0);
595
596 if( !CryptGetUserKey(xmlSecMSCryptoKeyDataCtxGetProvider(ctx), AT_KEYEXCHANGE, &(hKey))) {
597 xmlSecMSCryptoError("CryptGetUserKey", NULL);
598 return(0);
599 }
600 return (hKey);
601 }
602
603 /**
604 * xmlSecMSCryptoKeyDataGetCert:
605 * @data: the key data to retrieve certificate from.
606 *
607 * Native MSCrypto certificate retrieval from xmlsec keydata. The
608 * returned PCCERT_CONTEXT must not be released by the caller.
609 *
610 * Returns: PCCERT_CONTEXT on success or NULL otherwise.
611 */
612 PCCERT_CONTEXT
xmlSecMSCryptoKeyDataGetCert(xmlSecKeyDataPtr data)613 xmlSecMSCryptoKeyDataGetCert(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(xmlSecMSCryptoKeyDataCtxGetCert(ctx));
623 }
624
625 /**
626 * xmlSecMSCryptoKeyDataGetMSCryptoProvider:
627 * @data: the key data
628 *
629 * Gets crypto provider handle
630 *
631 * Returns: the crypto provider handler or 0 if there is an error.
632 */
633 HCRYPTPROV
xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data)634 xmlSecMSCryptoKeyDataGetMSCryptoProvider(xmlSecKeyDataPtr data) {
635 xmlSecMSCryptoKeyDataCtxPtr ctx;
636
637 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
638 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
639
640 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
641 xmlSecAssert2(ctx != NULL, 0);
642
643 return(xmlSecMSCryptoKeyDataCtxGetProvider(ctx));
644 }
645
646 /**
647 * xmlSecMSCryptoKeyDataGetMSCryptoKeySpec:
648 * @data: the key data
649 *
650 * Gets key spec info.
651 *
652 * Returns: the key spec info from key data
653 */
654 DWORD
xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data)655 xmlSecMSCryptoKeyDataGetMSCryptoKeySpec(xmlSecKeyDataPtr data) {
656 xmlSecMSCryptoKeyDataCtxPtr ctx;
657
658 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
659 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
660
661 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
662 xmlSecAssert2(ctx != NULL, 0);
663
664 return(ctx->dwKeySpec);
665 }
666
667 /**
668 * xmlSecMSCryptoKeyDataGetMSCryptoProviderInfo:
669 * @data: the key data
670 *
671 * Gets key provider info.
672 *
673 * Returns: the key provider info.
674 */
675 PCRYPT_KEY_PROV_INFO
xmlSecMSCryptoKeyDataGetMSCryptoProviderInfo(xmlSecKeyDataPtr data)676 xmlSecMSCryptoKeyDataGetMSCryptoProviderInfo(xmlSecKeyDataPtr data) {
677 xmlSecMSCryptoKeyDataCtxPtr ctx;
678 LPBYTE pInfoData = NULL;
679 DWORD dwInfoDataLength = 0;
680
681 xmlSecAssert2(data != NULL, NULL);
682
683 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
684 xmlSecAssert2(ctx != NULL, NULL);
685 xmlSecAssert2(ctx->pCert != NULL, NULL);
686
687 if(!CertGetCertificateContextProperty(ctx->pCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwInfoDataLength)) {
688 xmlSecMSCryptoError("CertGetCertificateContextProperty", NULL);
689 return NULL;
690 }
691
692 if(dwInfoDataLength > 0) {
693 pInfoData = malloc(dwInfoDataLength * sizeof(BYTE));
694
695 if(!CertGetCertificateContextProperty(ctx->pCert, CERT_KEY_PROV_INFO_PROP_ID, pInfoData, &dwInfoDataLength)) {
696 xmlSecMSCryptoError("CertGetCertificateContextProperty", NULL);
697 free(pInfoData);
698 return NULL;
699 }
700 }
701
702 return (PCRYPT_KEY_PROV_INFO)pInfoData;
703 }
704
705 static int
xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)706 xmlSecMSCryptoKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
707 xmlSecMSCryptoKeyDataCtxPtr ctxDst;
708 xmlSecMSCryptoKeyDataCtxPtr ctxSrc;
709
710 xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
711 xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecMSCryptoKeyDataSize), -1);
712 xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
713 xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecMSCryptoKeyDataSize), -1);
714
715 ctxDst = xmlSecMSCryptoKeyDataGetCtx(dst);
716 xmlSecAssert2(ctxDst != NULL, -1);
717
718 ctxSrc = xmlSecMSCryptoKeyDataGetCtx(src);
719 xmlSecAssert2(ctxSrc != NULL, -1);
720
721 if(xmlSecMSCryptoKeyDataCtxDuplicateProvider(ctxDst, ctxSrc) < 0) {
722 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxDuplicateProvider",
723 xmlSecKeyDataGetName(dst));
724 return(-1);
725 }
726
727 if(xmlSecMSCryptoKeyDataCtxDuplicateKey(ctxDst, ctxSrc) < 0) {
728 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxDuplicateKey",
729 xmlSecKeyDataGetName(dst));
730 return(-1);
731 }
732
733 if(xmlSecMSCryptoKeyDataCtxDuplicateCert(ctxDst, ctxSrc) < 0) {
734 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxDuplicateCert",
735 xmlSecKeyDataGetName(dst));
736 return(-1);
737 }
738
739 ctxDst->dwKeySpec = ctxSrc->dwKeySpec;
740 ctxDst->providers = ctxSrc->providers;
741 ctxDst->type = ctxSrc->type;
742
743 return(0);
744 }
745
746 static int
xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data)747 xmlSecMSCryptoKeyDataInitialize(xmlSecKeyDataPtr data) {
748 xmlSecMSCryptoKeyDataCtxPtr ctx;
749 int ret;
750
751 xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
752 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), -1);
753
754 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
755 xmlSecAssert2(ctx != NULL, -1);
756
757 memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
758
759 ret = xmlSecMSCryptoKeyDataCtxCreateProvider(ctx);
760 if(ret != 0) {
761 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxCreateProvider", NULL);
762 return(-1);
763 }
764 ret = xmlSecMSCryptoKeyDataCtxCreateKey(ctx);
765 if(ret != 0) {
766 xmlSecInternalError("xmlSecMSCryptoKeyDataCtxCreateKey", NULL);
767 return(-1);
768 }
769 xmlSecMSCryptoKeyDataCtxCreateCert(ctx);
770 return(0);
771 }
772
773 static void
xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data)774 xmlSecMSCryptoKeyDataFinalize(xmlSecKeyDataPtr data) {
775 xmlSecMSCryptoKeyDataCtxPtr ctx;
776
777 xmlSecAssert(xmlSecKeyDataIsValid(data));
778 xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize));
779
780 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
781 xmlSecAssert(ctx != NULL);
782
783 xmlSecMSCryptoKeyDataCtxDestroyKey(ctx);
784 xmlSecMSCryptoKeyDataCtxDestroyCert(ctx);
785 xmlSecMSCryptoKeyDataCtxDestroyProvider(ctx);
786
787 memset(ctx, 0, sizeof(xmlSecMSCryptoKeyDataCtx));
788 }
789
790 static int
xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data)791 xmlSecMSCryptoKeyDataGetSize(xmlSecKeyDataPtr data) {
792 xmlSecMSCryptoKeyDataCtxPtr ctx;
793
794 xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
795 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), 0);
796
797 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
798 xmlSecAssert2(ctx != NULL, 0);
799
800 if(xmlSecMSCryptoKeyDataCtxGetCert(ctx) != NULL) {
801 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo != NULL, 0);
802 return (CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
803 &(xmlSecMSCryptoKeyDataCtxGetCert(ctx)->pCertInfo->SubjectPublicKeyInfo)));
804 } else if (xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0) {
805 DWORD length = 0;
806 DWORD lenlen = sizeof(DWORD);
807
808 if (!CryptGetKeyParam(xmlSecMSCryptoKeyDataCtxGetKey(ctx), KP_KEYLEN, (BYTE *)&length, &lenlen, 0)) {
809 xmlSecMSCryptoError("CertDuplicateCertificateContext", NULL);
810 return(0);
811 }
812 return(length);
813 }
814
815 return (0);
816 }
817
818 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data)819 xmlSecMSCryptoKeyDataGetType(xmlSecKeyDataPtr data) {
820 xmlSecMSCryptoKeyDataCtxPtr ctx;
821
822 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
823 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
824
825 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
826 xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
827
828 /* We could make a call to CryptFindCertificateKeyProvInfo here, to find out if
829 * we *really* have a private key or not. However if the certificate is not
830 * linked to a private key, the call takes an ridiculous amount of time.
831 * the way it is now is better I think. WK.
832 */
833 return(ctx->type);
834 }
835
836 /**
837 * xmlSecMSCryptoCertDup:
838 * @pCert: the pointer to cert.
839 *
840 * Duplicates the @pCert.
841 *
842 * Returns: pointer to newly created PCCERT_CONTEXT object or
843 * NULL if an error occurs.
844 */
xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert)845 PCCERT_CONTEXT xmlSecMSCryptoCertDup(PCCERT_CONTEXT pCert) {
846 PCCERT_CONTEXT ret;
847
848 xmlSecAssert2(pCert != NULL, NULL);
849
850 ret = CertDuplicateCertificateContext(pCert);
851 if(ret == NULL) {
852 xmlSecMSCryptoError("CertDuplicateCertificateContext", NULL);
853 return(NULL);
854 }
855
856 return(ret);
857 }
858
859
860 /**
861 * xmlSecMSCryptoCertAdopt:
862 * @pCert: the pointer to cert.
863 * @type: the expected key type.
864 *
865 * Creates key data value from the cert.
866 *
867 * Returns: pointer to newly created xmlsec key or NULL if an error occurs.
868 */
869 xmlSecKeyDataPtr
xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert,xmlSecKeyDataType type)870 xmlSecMSCryptoCertAdopt(PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
871 xmlSecKeyDataPtr data = NULL;
872 int ret;
873
874 xmlSecAssert2(pCert != NULL, NULL);
875 xmlSecAssert2(pCert->pCertInfo != NULL, NULL);
876 xmlSecAssert2(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL, NULL);
877
878 #ifndef XMLSEC_NO_RSA
879 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_RSA_RSA)) {
880 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataRsaId);
881 if(data == NULL) {
882 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataRsaId)", NULL);
883 return(NULL);
884 }
885 }
886 #endif /* XMLSEC_NO_RSA */
887
888 #ifndef XMLSEC_NO_DSA
889 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_X957_DSA /*szOID_DSALG_SIGN*/)) {
890 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataDsaId);
891 if(data == NULL) {
892 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataDsaId)", NULL);
893 return(NULL);
894 }
895 }
896 #endif /* XMLSEC_NO_DSA */
897
898 #ifndef XMLSEC_NO_GOST
899 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001_CP) ||
900 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_2001) ||
901 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_MAGPRO_PUBKEY_SIGN_R3410_94_CP)) {
902 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2001Id);
903 if(data == NULL) {
904 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataGost2001Id)", NULL);
905 return(NULL);
906 }
907 }
908 #endif /* XMLSEC_NO_GOST*/
909 #ifndef XMLSEC_NO_GOST2012
910 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_CP_GOST_R3410_12_256) ||
911 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_CP_GOST_R3411_12_256_R3410)) {
912 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2012_256Id);
913 if(data == NULL) {
914 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataGost2012_256Id)", NULL);
915 return(NULL);
916 }
917 }
918 if (!strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_CP_GOST_R3410_12_512) ||
919 !strcmp(pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, szOID_CP_GOST_R3411_12_512_R3410)) {
920 data = xmlSecKeyDataCreate(xmlSecMSCryptoKeyDataGost2012_512Id);
921 if(data == NULL) {
922 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataGost2012_512Id)", NULL);
923 return(NULL);
924 }
925 }
926 #endif /* XMLSEC_NO_GOST2012 */
927
928 if (NULL == data) {
929 xmlSecInvalidStringTypeError("PCCERT_CONTEXT key type",
930 pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
931 "unsupported keytype", NULL);
932 return(NULL);
933 }
934
935 xmlSecAssert2(data != NULL, NULL);
936
937 ret = xmlSecMSCryptoKeyDataAdoptCert(data, pCert, type);
938 if(ret < 0) {
939 xmlSecInternalError("xmlSecMSCryptoPCCDataAdoptPCC", NULL);
940 xmlSecKeyDataDestroy(data);
941 return(NULL);
942 }
943 return(data);
944 }
945
946
947 #ifndef XMLSEC_NO_RSA
948 /**************************************************************************
949 *
950 * <dsig:RSAKeyValue> processing
951 *
952 * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
953 * The RSAKeyValue Element
954 *
955 * RSA key values have two fields: Modulus and Exponent.
956 *
957 * <RSAKeyValue>
958 * <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
959 * jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
960 * 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
961 * </Modulus>
962 * <Exponent>AQAB</Exponent>
963 * </RSAKeyValue>
964 *
965 * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
966 * represented in XML as octet strings as defined by the ds:CryptoBinary type.
967 *
968 * Schema Definition:
969 *
970 * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
971 * <complexType name="RSAKeyValueType">
972 * <sequence>
973 * <element name="Modulus" type="ds:CryptoBinary"/>
974 * <element name="Exponent" type="ds:CryptoBinary"/>
975 * </sequence>
976 * </complexType>
977 *
978 * DTD Definition:
979 *
980 * <!ELEMENT RSAKeyValue (Modulus, Exponent) >
981 * <!ELEMENT Modulus (#PCDATA) >
982 * <!ELEMENT Exponent (#PCDATA) >
983 *
984 * ============================================================================
985 *
986 *
987 *************************************************************************/
988
989 static int xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data);
990 static int xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src);
991 static void xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data);
992 static int xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id,
993 xmlSecKeyPtr key,
994 xmlNodePtr node,
995 xmlSecKeyInfoCtxPtr keyInfoCtx);
996 static int xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id,
997 xmlSecKeyPtr key,
998 xmlNodePtr node,
999 xmlSecKeyInfoCtxPtr keyInfoCtx);
1000 static int xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data,
1001 xmlSecSize sizeBits,
1002 xmlSecKeyDataType type);
1003
1004 static xmlSecKeyDataType xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data);
1005 static xmlSecSize xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data);
1006 static void xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output);
1007 static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output);
1008
1009 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataRsaKlass = {
1010 sizeof(xmlSecKeyDataKlass),
1011 xmlSecMSCryptoKeyDataSize,
1012
1013 /* data */
1014 xmlSecNameRSAKeyValue,
1015 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1016 /* xmlSecKeyDataUsage usage; */
1017 xmlSecHrefRSAKeyValue, /* const xmlChar* href; */
1018 xmlSecNodeRSAKeyValue, /* const xmlChar* dataNodeName; */
1019 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
1020
1021 /* constructors/destructor */
1022 xmlSecMSCryptoKeyDataRsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
1023 xmlSecMSCryptoKeyDataRsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
1024 xmlSecMSCryptoKeyDataRsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
1025 xmlSecMSCryptoKeyDataRsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
1026
1027 /* get info */
1028 xmlSecMSCryptoKeyDataRsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
1029 xmlSecMSCryptoKeyDataRsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
1030 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
1031
1032 /* read/write */
1033 xmlSecMSCryptoKeyDataRsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
1034 xmlSecMSCryptoKeyDataRsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1035 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
1036 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
1037
1038 /* debug */
1039 xmlSecMSCryptoKeyDataRsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
1040 xmlSecMSCryptoKeyDataRsaDebugXmlDump, /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1041
1042 /* reserved for the future */
1043 NULL, /* void* reserved0; */
1044 NULL, /* void* reserved1; */
1045 };
1046
1047 /* Ordered list of providers to search for algorithm implementation using
1048 * xmlSecMSCryptoFindProvider() function
1049 *
1050 * MUST END with { NULL, 0 } !!!
1051 */
1052 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Rsa[] = {
1053 { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV, PROV_RSA_AES},
1054 { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE, PROV_RSA_AES },
1055 { MS_STRONG_PROV, PROV_RSA_FULL },
1056 { MS_ENHANCED_PROV, PROV_RSA_FULL },
1057 { MS_DEF_PROV, PROV_RSA_FULL },
1058 { NULL, 0 }
1059 };
1060
1061 /**
1062 * xmlSecMSCryptoKeyDataRsaGetKlass:
1063 *
1064 * The MSCrypto RSA CertKey data klass.
1065 *
1066 * Returns: pointer to MSCrypto RSA key data klass.
1067 */
1068 xmlSecKeyDataId
xmlSecMSCryptoKeyDataRsaGetKlass(void)1069 xmlSecMSCryptoKeyDataRsaGetKlass(void) {
1070 return(&xmlSecMSCryptoKeyDataRsaKlass);
1071 }
1072
1073 static int
xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data)1074 xmlSecMSCryptoKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
1075 xmlSecMSCryptoKeyDataCtxPtr ctx;
1076 int ret;
1077
1078 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), xmlSecKeyDataTypeUnknown);
1079
1080 ret = xmlSecMSCryptoKeyDataInitialize(data);
1081 if(ret != 0) {
1082 xmlSecInternalError("xmlSecMSCryptoKeyDataInitialize", NULL);
1083 return(-1);
1084 }
1085
1086 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1087 xmlSecAssert2(ctx != NULL, -1);
1088
1089 ctx->providers = xmlSecMSCryptoProviderInfo_Rsa;
1090 return(0);
1091 }
1092
1093 static int
xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)1094 xmlSecMSCryptoKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1095 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataRsaId), -1);
1096 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataRsaId), -1);
1097
1098 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1099 }
1100
1101 static void
xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data)1102 xmlSecMSCryptoKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
1103 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1104
1105 xmlSecMSCryptoKeyDataFinalize(data);
1106 }
1107
1108 static int
xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1109 xmlSecMSCryptoKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1110 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1111 xmlSecBn modulus, exponent;
1112 xmlSecBuffer blob;
1113 unsigned int blobBufferLen;
1114 PUBLICKEYSTRUC* pubKeyStruc = NULL;
1115 RSAPUBKEY* pubKey = NULL;
1116 xmlSecByte* modulusBlob = NULL;
1117 xmlSecKeyDataPtr data = NULL;
1118 HCRYPTPROV hProv = 0;
1119 HCRYPTKEY hKey = 0;
1120 xmlNodePtr cur;
1121 int res = -1;
1122 int ret;
1123
1124 xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
1125 xmlSecAssert2(key != NULL, -1);
1126 xmlSecAssert2(node != NULL, -1);
1127 xmlSecAssert2(keyInfoCtx != NULL, -1);
1128
1129 if(xmlSecKeyGetValue(key) != NULL) {
1130 xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1131 xmlSecKeyDataKlassGetName(id),
1132 "key already has a value");
1133 return(-1);
1134 }
1135
1136 /* initialize buffers */
1137 ret = xmlSecBnInitialize(&modulus, 0);
1138 if(ret < 0) {
1139 xmlSecInternalError("xmlSecBnInitialize(modulus)",
1140 xmlSecKeyDataKlassGetName(id));;
1141 return(-1);
1142 }
1143
1144 ret = xmlSecBnInitialize(&exponent, 0);
1145 if(ret < 0) {
1146 xmlSecInternalError("xmlSecBnInitialize(exponent)",
1147 xmlSecKeyDataKlassGetName(id));
1148 xmlSecBnFinalize(&modulus);
1149 return(-1);
1150 }
1151
1152 ret = xmlSecBufferInitialize(&blob, 0);
1153 if(ret < 0) {
1154 xmlSecInternalError("xmlSecBufferInitialize(blob)",
1155 xmlSecKeyDataKlassGetName(id));
1156 xmlSecBnFinalize(&modulus);
1157 xmlSecBnFinalize(&exponent);
1158 return(-1);
1159 }
1160
1161 /* read xml */
1162 cur = xmlSecGetNextElementNode(node->children);
1163
1164 /* first is Modulus node. It is REQUIRED because we do not support Seed and PgenCounter*/
1165 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAModulus, xmlSecDSigNs))) {
1166 xmlSecInvalidNodeError(cur, xmlSecNodeRSAModulus,
1167 xmlSecKeyDataKlassGetName(id));
1168 goto done;
1169 }
1170
1171 ret = xmlSecBnGetNodeValue(&modulus, cur, xmlSecBnBase64, 1);
1172 if((ret < 0) || (xmlSecBnGetSize(&modulus) == 0)) {
1173 xmlSecInternalError("xmlSecBnGetNodeValue(modulus)",
1174 xmlSecKeyDataKlassGetName(id));
1175 goto done;
1176 }
1177 cur = xmlSecGetNextElementNode(cur->next);
1178
1179 /* next is Exponent node. It is REQUIRED because we do not support Seed and PgenCounter*/
1180 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) {
1181 xmlSecInvalidNodeError(cur, xmlSecNodeRSAExponent, xmlSecKeyDataKlassGetName(id));
1182 goto done;
1183 }
1184 ret = xmlSecBnGetNodeValue(&exponent, cur, xmlSecBnBase64, 1);
1185 if((ret < 0) || (xmlSecBnGetSize(&exponent) == 0)) {
1186 xmlSecInternalError("xmlSecBnGetNodeValue(exponent)",
1187 xmlSecKeyDataKlassGetName(id));
1188 goto done;
1189 }
1190 cur = xmlSecGetNextElementNode(cur->next);
1191
1192 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
1193 /* next is X node. It is REQUIRED for private key but
1194 * MSCrypto does not support it. We just ignore it */
1195 cur = xmlSecGetNextElementNode(cur->next);
1196 }
1197
1198 if(cur != NULL) {
1199 xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
1200 goto done;
1201 }
1202
1203 /* Now try to create the key */
1204 blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + xmlSecBnGetSize(&modulus);
1205 ret = xmlSecBufferSetSize(&blob, blobBufferLen);
1206 if(ret < 0) {
1207 xmlSecInternalError2("xmlSecBufferSetSize",
1208 xmlSecKeyDataKlassGetName(id),
1209 "size=%d", blobBufferLen);
1210 goto done;
1211 }
1212
1213 /* Set the PUBLICKEYSTRUC */
1214 pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
1215 pubKeyStruc->bType = PUBLICKEYBLOB;
1216 pubKeyStruc->bVersion = 0x02;
1217 pubKeyStruc->reserved = 0;
1218 pubKeyStruc->aiKeyAlg = CALG_RSA_KEYX | CALG_RSA_SIGN;
1219
1220 /* Set the public key header */
1221 pubKey = (RSAPUBKEY*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
1222 pubKey->magic = 0x31415352; /* == RSA1 public */
1223 pubKey->bitlen = xmlSecBnGetSize(&modulus) * 8; /* Number of bits in prime modulus */
1224 pubKey->pubexp = 0;
1225 if(sizeof(pubKey->pubexp) < xmlSecBnGetSize(&exponent)) {
1226 xmlSecInvalidSizeLessThanError("exponent size",
1227 sizeof(pubKey->pubexp), xmlSecBnGetSize(&exponent),
1228 NULL);
1229 goto done;
1230 }
1231 xmlSecAssert2(xmlSecBnGetData(&exponent) != NULL, -1);
1232 memcpy(&(pubKey->pubexp), xmlSecBnGetData(&exponent), xmlSecBnGetSize(&exponent));
1233
1234 modulusBlob = (xmlSecByte*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
1235 xmlSecAssert2(xmlSecBnGetData(&modulus) != NULL, -1);
1236 memcpy(modulusBlob, xmlSecBnGetData(&modulus), xmlSecBnGetSize(&modulus));
1237
1238 /* Now that we have the blob, import */
1239 hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Rsa, NULL, CRYPT_VERIFYCONTEXT, TRUE);
1240 if(hProv == 0) {
1241 xmlSecInternalError("xmlSecMSCryptoFindProvider",
1242 xmlSecKeyDataKlassGetName(id));
1243 goto done;
1244 }
1245
1246 if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
1247 xmlSecMSCryptoError("CryptImportKey",
1248 xmlSecKeyDataKlassGetName(id));
1249 goto done;
1250 }
1251
1252 data = xmlSecKeyDataCreate(id);
1253 if(data == NULL ) {
1254 xmlSecInternalError("xmlSecKeyDataCreate",
1255 xmlSecKeyDataKlassGetName(id));
1256 goto done;
1257 }
1258
1259 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
1260 if(ret < 0) {
1261 xmlSecInternalError("xmlSecMSCryptoKeyDataAdoptKey",
1262 xmlSecKeyDataKlassGetName(id));
1263 goto done;
1264 }
1265 hProv = 0;
1266 hKey = 0;
1267
1268 ret = xmlSecKeySetValue(key, data);
1269 if(ret < 0) {
1270 xmlSecInternalError("xmlSecKeySetValue",
1271 xmlSecKeyDataKlassGetName(id));
1272 xmlSecKeyDataDestroy(data);
1273 goto done;
1274 }
1275 data = NULL;
1276
1277 /* success */
1278 res = 0;
1279
1280 done:
1281 if (hProv == 0) {
1282 CryptReleaseContext(hProv, 0);
1283 }
1284 if (hKey != 0) {
1285 CryptDestroyKey(hKey);
1286 }
1287 if (data != 0) {
1288 xmlSecKeyDataDestroy(data);
1289 }
1290
1291 xmlSecBnFinalize(&modulus);
1292 xmlSecBnFinalize(&exponent);
1293 xmlSecBufferFinalize(&blob);
1294 return(res);
1295 }
1296
1297 static int
xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1298 xmlSecMSCryptoKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
1299 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1300 xmlSecMSCryptoKeyDataCtxPtr ctx;
1301 xmlSecBuffer buf;
1302 DWORD dwBlobLen;
1303 xmlSecByte* blob;
1304 PUBLICKEYSTRUC* pubKeyStruc;
1305 RSAPUBKEY *pubKey;
1306 xmlSecSize modulusLen, exponentLen;
1307 xmlNodePtr cur;
1308 int ret;
1309
1310 xmlSecAssert2(id == xmlSecMSCryptoKeyDataRsaId, -1);
1311 xmlSecAssert2(key != NULL, -1);
1312 xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataRsaId), -1);
1313 xmlSecAssert2(node != NULL, -1);
1314 xmlSecAssert2(keyInfoCtx != NULL, -1);
1315
1316 ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
1317 xmlSecAssert2(ctx != NULL, -1);
1318 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
1319
1320 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
1321 xmlSecMSCryptoError("CryptExportKey",
1322 xmlSecKeyDataKlassGetName(id));
1323 return(-1);
1324 }
1325
1326 ret = xmlSecBufferInitialize(&buf, dwBlobLen);
1327 if(ret < 0) {
1328 xmlSecInternalError2("xmlSecBufferInitialize",
1329 xmlSecKeyDataKlassGetName(id),
1330 "size=%ld", dwBlobLen);
1331 return(-1);
1332 }
1333
1334 blob = xmlSecBufferGetData(&buf);
1335 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
1336 xmlSecMSCryptoError("CryptExportKey",
1337 xmlSecKeyDataKlassGetName(id));
1338 xmlSecBufferFinalize(&buf);
1339 return(-1);
1340 }
1341 if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
1342 xmlSecInvalidSizeLessThanError("Key blob", dwBlobLen, sizeof(PUBLICKEYSTRUC),
1343 xmlSecKeyDataKlassGetName(id));
1344 xmlSecBufferFinalize(&buf);
1345 return(-1);
1346 }
1347
1348 /* check PUBLICKEYSTRUC */
1349 pubKeyStruc = (PUBLICKEYSTRUC*)blob;
1350 if(pubKeyStruc->bVersion != 0x02) {
1351 xmlSecMSCryptoError2("CryptExportKey",
1352 xmlSecKeyDataKlassGetName(id),
1353 "pubKeyStruc->bVersion=%ld",
1354 (long int)pubKeyStruc->bVersion);
1355 xmlSecBufferFinalize(&buf);
1356 return(-1);
1357 }
1358 if(pubKeyStruc->bType != PUBLICKEYBLOB) {
1359 xmlSecMSCryptoError2("CryptExportKey",
1360 xmlSecKeyDataKlassGetName(id),
1361 "pubKeyStruc->bType=%ld",
1362 (long int)pubKeyStruc->bType);
1363 xmlSecBufferFinalize(&buf);
1364 return(-1);
1365 }
1366
1367 /* check RSAPUBKEY */
1368 pubKey = (RSAPUBKEY *)(blob + sizeof(PUBLICKEYSTRUC));
1369 if(pubKey->magic != 0x31415352) { /* RSA public key magic */
1370 xmlSecMSCryptoError2("CryptExportKey",
1371 xmlSecKeyDataKlassGetName(id),
1372 "pubKey->magic=0x%08lx",
1373 (long int)pubKey->magic);
1374 xmlSecBufferFinalize(&buf);
1375 return(-1);
1376 }
1377 modulusLen = pubKey->bitlen / 8;
1378
1379 if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen) {
1380 xmlSecInvalidSizeLessThanError("Key blob",
1381 dwBlobLen, sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulusLen,
1382 xmlSecKeyDataKlassGetName(id));
1383 xmlSecBufferFinalize(&buf);
1384 return(-1);
1385 }
1386 blob += sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
1387
1388 /* first is Modulus node */
1389 cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
1390 if(cur == NULL) {
1391 xmlSecInternalError("xmlSecAddChild(NodeRSAModulus)",
1392 xmlSecKeyDataKlassGetName(id));
1393 xmlSecBufferFinalize(&buf);
1394 return(-1);
1395 }
1396
1397 ret = xmlSecBnBlobSetNodeValue(blob, modulusLen, cur, xmlSecBnBase64, 1, 1);
1398 if(ret < 0) {
1399 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeRSAModulus)",
1400 xmlSecKeyDataKlassGetName(id));
1401 xmlSecBufferFinalize(&buf);
1402 return(-1);
1403 }
1404
1405 /* next is Exponent node. */
1406 cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
1407 if(cur == NULL) {
1408 xmlSecInternalError("xmlSecAddChild(NodeRSAExponent)",
1409 xmlSecKeyDataKlassGetName(id));
1410 xmlSecBufferFinalize(&buf);
1411 return(-1);
1412 }
1413
1414 /* Remove leading zero's (from least significant end) */
1415 blob = (xmlSecByte*)(&(pubKey->pubexp));
1416 exponentLen = sizeof(pubKey->pubexp);
1417 while (exponentLen > 0 && blob[exponentLen - 1] == 0) {
1418 exponentLen--;
1419 }
1420
1421 ret = xmlSecBnBlobSetNodeValue(blob, exponentLen, cur, xmlSecBnBase64, 1, 1);
1422 if(ret < 0) {
1423 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeRSAExponent)",
1424 xmlSecKeyDataKlassGetName(id));
1425 xmlSecBufferFinalize(&buf);
1426 return(-1);
1427 }
1428
1429 /* next is PrivateExponent node: not supported in MSCrypto */
1430
1431 /* done */
1432 xmlSecBufferFinalize(&buf);
1433 return(0);
1434 }
1435
1436 static int
xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data,xmlSecSize sizeBits,xmlSecKeyDataType type ATTRIBUTE_UNUSED)1437 xmlSecMSCryptoKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits,
1438 xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
1439 xmlSecMSCryptoKeyDataCtxPtr ctx;
1440 HCRYPTPROV hProv = 0;
1441 HCRYPTKEY hKey = 0;
1442 DWORD dwKeySpec;
1443 DWORD dwSize;
1444 int res = -1;
1445 int ret;
1446
1447 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
1448 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
1449 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), -1);
1450 xmlSecAssert2(sizeBits > 0, -1);
1451 UNREFERENCED_PARAMETER(type);
1452
1453 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1454 xmlSecAssert2(ctx != NULL, -1);
1455
1456 /* get provider */
1457 hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
1458 if(hProv == 0) {
1459 xmlSecInternalError("xmlSecMSCryptoFindProvider",
1460 xmlSecKeyDataGetName(data));
1461 goto done;
1462 }
1463
1464 dwKeySpec = AT_KEYEXCHANGE | AT_SIGNATURE;
1465 dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
1466 if (!CryptGenKey(hProv, CALG_RSA_SIGN, dwSize, &hKey)) {
1467 xmlSecMSCryptoError("CryptGenKey",
1468 xmlSecKeyDataGetName(data));
1469 goto done;
1470 }
1471
1472 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
1473 xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
1474 if(ret < 0) {
1475 xmlSecInternalError("xmlSecMSCryptoKeyDataAdoptKey",
1476 xmlSecKeyDataGetName(data));
1477 goto done;
1478 }
1479 hProv = 0;
1480 hKey = 0;
1481
1482 /* success */
1483 res = 0;
1484
1485 done:
1486 if (hProv != 0) {
1487 CryptReleaseContext(hProv, 0);
1488 }
1489
1490 if (hKey != 0) {
1491 CryptDestroyKey(hKey);
1492 }
1493
1494 return(res);
1495 }
1496
1497 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data)1498 xmlSecMSCryptoKeyDataRsaGetType(xmlSecKeyDataPtr data) {
1499 return(xmlSecMSCryptoKeyDataGetType(data));
1500 }
1501
1502 static xmlSecSize
xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data)1503 xmlSecMSCryptoKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
1504 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId), 0);
1505
1506 return (xmlSecMSCryptoKeyDataGetSize(data));
1507 }
1508
1509 static void
xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data,FILE * output)1510 xmlSecMSCryptoKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
1511 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1512 xmlSecAssert(output != NULL);
1513
1514 fprintf(output, "=== rsa key: size = %d\n",
1515 xmlSecMSCryptoKeyDataRsaGetSize(data));
1516 }
1517
xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data,FILE * output)1518 static void xmlSecMSCryptoKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
1519 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataRsaId));
1520 xmlSecAssert(output != NULL);
1521
1522 fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
1523 xmlSecMSCryptoKeyDataRsaGetSize(data));
1524 }
1525
1526 #endif /* XMLSEC_NO_RSA */
1527
1528 #ifndef XMLSEC_NO_DSA
1529 /**************************************************************************
1530 *
1531 * <dsig:DSAKeyValue> processing
1532 *
1533 *
1534 * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
1535 *
1536 * DSA keys and the DSA signature algorithm are specified in [DSS].
1537 * DSA public key values can have the following fields:
1538 *
1539 * * P - a prime modulus meeting the [DSS] requirements
1540 * * Q - an integer in the range 2**159 < Q < 2**160 which is a prime
1541 * divisor of P-1
1542 * * G - an integer with certain properties with respect to P and Q
1543 * * Y - G**X mod P (where X is part of the private key and not made
1544 * public)
1545 * * J - (P - 1) / Q
1546 * * seed - a DSA prime generation seed
1547 * * pgenCounter - a DSA prime generation counter
1548 *
1549 * Parameter J is available for inclusion solely for efficiency as it is
1550 * calculatable from P and Q. Parameters seed and pgenCounter are used in the
1551 * DSA prime number generation algorithm specified in [DSS]. As such, they are
1552 * optional but must either both be present or both be absent. This prime
1553 * generation algorithm is designed to provide assurance that a weak prime is
1554 * not being used and it yields a P and Q value. Parameters P, Q, and G can be
1555 * public and common to a group of users. They might be known from application
1556 * context. As such, they are optional but P and Q must either both appear or
1557 * both be absent. If all of P, Q, seed, and pgenCounter are present,
1558 * implementations are not required to check if they are consistent and are
1559 * free to use either P and Q or seed and pgenCounter. All parameters are
1560 * encoded as base64 [MIME] values.
1561 *
1562 * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
1563 * represented in XML as octet strings as defined by the ds:CryptoBinary type.
1564 *
1565 * Schema Definition:
1566 *
1567 * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
1568 * <complexType name="DSAKeyValueType">
1569 * <sequence>
1570 * <sequence minOccurs="0">
1571 * <element name="P" type="ds:CryptoBinary"/>
1572 * <element name="Q" type="ds:CryptoBinary"/>
1573 * </sequence>
1574 * <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
1575 * <element name="Y" type="ds:CryptoBinary"/>
1576 * <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
1577 * <sequence minOccurs="0">
1578 * <element name="Seed" type="ds:CryptoBinary"/>
1579 * <element name="PgenCounter" type="ds:CryptoBinary"/>
1580 * </sequence>
1581 * </sequence>
1582 * </complexType>
1583 *
1584 * DTD Definition:
1585 *
1586 * <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) >
1587 * <!ELEMENT P (#PCDATA) >
1588 * <!ELEMENT Q (#PCDATA) >
1589 * <!ELEMENT G (#PCDATA) >
1590 * <!ELEMENT Y (#PCDATA) >
1591 * <!ELEMENT J (#PCDATA) >
1592 * <!ELEMENT Seed (#PCDATA) >
1593 * <!ELEMENT PgenCounter (#PCDATA) >
1594 *
1595 * ============================================================================
1596 *
1597 * To support reading/writing private keys an X element added (before Y).
1598 * todo: The current implementation does not support Seed and PgenCounter!
1599 * by this the P, Q and G are *required*!
1600 *
1601 *************************************************************************/
1602 static int xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data);
1603 static int xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst,
1604 xmlSecKeyDataPtr src);
1605 static void xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data);
1606 static int xmlSecMSCryptoKeyDataDsaXmlRead (xmlSecKeyDataId id,
1607 xmlSecKeyPtr key,
1608 xmlNodePtr node,
1609 xmlSecKeyInfoCtxPtr keyInfoCtx);
1610 static int xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id,
1611 xmlSecKeyPtr key,
1612 xmlNodePtr node,
1613 xmlSecKeyInfoCtxPtr keyInfoCtx);
1614 static int xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data,
1615 xmlSecSize sizeBits,
1616 xmlSecKeyDataType type);
1617
1618 static xmlSecKeyDataType xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data);
1619 static xmlSecSize xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data);
1620 static void xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data,
1621 FILE* output);
1622 static void xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,
1623 FILE* output);
1624
1625 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataDsaKlass = {
1626 sizeof(xmlSecKeyDataKlass),
1627 xmlSecMSCryptoKeyDataSize,
1628
1629 /* data */
1630 xmlSecNameDSAKeyValue,
1631 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1632 /* xmlSecKeyDataUsage usage; */
1633 xmlSecHrefDSAKeyValue, /* const xmlChar* href; */
1634 xmlSecNodeDSAKeyValue, /* const xmlChar* dataNodeName; */
1635 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
1636
1637 /* constructors/destructor */
1638 xmlSecMSCryptoKeyDataDsaInitialize, /* xmlSecKeyDataInitializeMethod initialize; */
1639 xmlSecMSCryptoKeyDataDsaDuplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
1640 xmlSecMSCryptoKeyDataDsaFinalize, /* xmlSecKeyDataFinalizeMethod finalize; */
1641 xmlSecMSCryptoKeyDataDsaGenerate, /* xmlSecKeyDataGenerateMethod generate; */
1642
1643 /* get info */
1644 xmlSecMSCryptoKeyDataDsaGetType, /* xmlSecKeyDataGetTypeMethod getType; */
1645 xmlSecMSCryptoKeyDataDsaGetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
1646 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
1647
1648 /* read/write */
1649 xmlSecMSCryptoKeyDataDsaXmlRead, /* xmlSecKeyDataXmlReadMethod xmlRead; */
1650 xmlSecMSCryptoKeyDataDsaXmlWrite, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1651 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
1652 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
1653
1654 /* debug */
1655 xmlSecMSCryptoKeyDataDsaDebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
1656 xmlSecMSCryptoKeyDataDsaDebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1657
1658 /* reserved for the future */
1659 NULL, /* void* reserved0; */
1660 NULL, /* void* reserved1; */
1661 };
1662
1663 /* Ordered list of providers to search for algorithm implementation using
1664 * xmlSecMSCryptoFindProvider() function
1665 *
1666 * MUST END with { NULL, 0 } !!!
1667 */
1668 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Dss[] = {
1669 { MS_DEF_DSS_PROV, PROV_DSS },
1670 { NULL, 0 }
1671 };
1672
1673
1674 /**
1675 * xmlSecMSCryptoKeyDataDsaGetKlass:
1676 *
1677 * The DSA key data klass.
1678 *
1679 * Returns: pointer to DSA key data klass.
1680 */
1681 xmlSecKeyDataId
xmlSecMSCryptoKeyDataDsaGetKlass(void)1682 xmlSecMSCryptoKeyDataDsaGetKlass(void) {
1683 return(&xmlSecMSCryptoKeyDataDsaKlass);
1684 }
1685
1686
1687 static int
xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data)1688 xmlSecMSCryptoKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
1689 xmlSecMSCryptoKeyDataCtxPtr ctx;
1690 int ret;
1691
1692 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), xmlSecKeyDataTypeUnknown);
1693
1694 ret = xmlSecMSCryptoKeyDataInitialize(data);
1695 if(ret != 0) {
1696 xmlSecInternalError("xmlSecMSCryptoKeyDataInitialize", NULL);
1697 return(-1);
1698 }
1699
1700 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
1701 xmlSecAssert2(ctx != NULL, -1);
1702
1703 ctx->providers = xmlSecMSCryptoProviderInfo_Dss;
1704 return(0);
1705 }
1706
1707 static int
xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)1708 xmlSecMSCryptoKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1709 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataDsaId), -1);
1710 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataDsaId), -1);
1711
1712 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
1713 }
1714
1715 static void
xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data)1716 xmlSecMSCryptoKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
1717 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
1718
1719 xmlSecMSCryptoKeyDataFinalize(data);
1720 }
1721
1722 static int
xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1723 xmlSecMSCryptoKeyDataDsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1724 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1725 xmlSecKeyDataPtr data = NULL;
1726 xmlNodePtr cur;
1727 xmlSecBn p, q, g, y;
1728 xmlSecBuffer blob;
1729 unsigned int blobBufferLen;
1730 PUBLICKEYSTRUC *pubKeyStruc = NULL;
1731 DSSPUBKEY *pubKey = NULL;
1732 DSSSEED* seed = NULL;
1733 BYTE *buf = NULL;
1734 HCRYPTPROV hProv = 0;
1735 HCRYPTKEY hKey = 0;
1736 xmlSecSize i;
1737 int res = -1;
1738 int ret;
1739
1740 xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
1741 xmlSecAssert2(key != NULL, -1);
1742 xmlSecAssert2(node != NULL, -1);
1743 xmlSecAssert2(keyInfoCtx != NULL, -1);
1744
1745 if(xmlSecKeyGetValue(key) != NULL) {
1746 xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1747 xmlSecKeyDataKlassGetName(id),
1748 "key already has a value");
1749 return(-1);
1750 }
1751
1752 /* initialize buffers */
1753 ret = xmlSecBnInitialize(&p, 0);
1754 if(ret < 0) {
1755 xmlSecInternalError("xmlSecBnInitialize(p)",
1756 xmlSecKeyDataKlassGetName(id));
1757 return(-1);
1758 }
1759
1760 ret = xmlSecBnInitialize(&q, 0);
1761 if(ret < 0) {
1762 xmlSecInternalError("xmlSecBnInitialize(q)",
1763 xmlSecKeyDataKlassGetName(id));
1764 xmlSecBnFinalize(&p);
1765 return(-1);
1766 }
1767
1768 ret = xmlSecBnInitialize(&g, 0);
1769 if(ret < 0) {
1770 xmlSecInternalError("xmlSecBnInitialize(g)",
1771 xmlSecKeyDataKlassGetName(id));
1772 xmlSecBnFinalize(&p);
1773 xmlSecBnFinalize(&q);
1774 return(-1);
1775 }
1776
1777 ret = xmlSecBnInitialize(&y, 0);
1778 if(ret < 0) {
1779 xmlSecInternalError("xmlSecBnInitialize(y)",
1780 xmlSecKeyDataKlassGetName(id));
1781 xmlSecBnFinalize(&p);
1782 xmlSecBnFinalize(&q);
1783 xmlSecBnFinalize(&g);
1784 return(-1);
1785 }
1786
1787 ret = xmlSecBufferInitialize(&blob, 0);
1788 if(ret < 0) {
1789 xmlSecInternalError("xmlSecBufferInitialize(blob)",
1790 xmlSecKeyDataKlassGetName(id));
1791 xmlSecBnFinalize(&p);
1792 xmlSecBnFinalize(&q);
1793 xmlSecBnFinalize(&g);
1794 xmlSecBnFinalize(&y);
1795 return(-1);
1796 }
1797
1798 /* read xml */
1799 cur = xmlSecGetNextElementNode(node->children);
1800
1801 /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/
1802 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAP, xmlSecDSigNs))) {
1803 xmlSecInvalidNodeError(cur, xmlSecNodeDSAP, xmlSecKeyDataKlassGetName(id));
1804 goto done;
1805 }
1806
1807 ret = xmlSecBnGetNodeValue(&p, cur, xmlSecBnBase64, 1);
1808 if((ret < 0) || (xmlSecBnGetSize(&p) == 0)) {
1809 xmlSecInternalError("xmlSecBnGetNodeValue(p)",
1810 xmlSecKeyDataKlassGetName(id));
1811 goto done;
1812 }
1813 cur = xmlSecGetNextElementNode(cur->next);
1814
1815 /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/
1816 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) {
1817 xmlSecInvalidNodeError(cur, xmlSecNodeDSAQ, xmlSecKeyDataKlassGetName(id));
1818 goto done;
1819 }
1820 ret = xmlSecBnGetNodeValue(&q, cur, xmlSecBnBase64, 1);
1821 if((ret < 0) || (xmlSecBnGetSize(&q) == 0)) {
1822 xmlSecInternalError("xmlSecBnGetNodeValue(q)",
1823 xmlSecKeyDataKlassGetName(id));
1824 goto done;
1825 }
1826 cur = xmlSecGetNextElementNode(cur->next);
1827
1828 /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/
1829 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) {
1830 xmlSecInvalidNodeError(cur, xmlSecNodeDSAG, xmlSecKeyDataKlassGetName(id));
1831 goto done;
1832 }
1833 ret = xmlSecBnGetNodeValue(&g, cur, xmlSecBnBase64, 1);
1834 if((ret < 0) || (xmlSecBnGetSize(&q) == 0)) {
1835 xmlSecInternalError("xmlSecBnGetNodeValue(g)",
1836 xmlSecKeyDataKlassGetName(id));
1837 goto done;
1838 }
1839 cur = xmlSecGetNextElementNode(cur->next);
1840
1841 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
1842 /* next is X node. It is REQUIRED for private key but
1843 * MSCrypto does not support it, we just ignore it */
1844
1845 cur = xmlSecGetNextElementNode(cur->next);
1846 }
1847
1848 /* next is Y node. */
1849 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) {
1850 xmlSecInvalidNodeError(cur, xmlSecNodeDSAY, xmlSecKeyDataKlassGetName(id));
1851 goto done;
1852 }
1853 ret = xmlSecBnGetNodeValue(&y, cur, xmlSecBnBase64, 1);
1854 if((ret < 0) || (xmlSecBnGetSize(&y) == 0)) {
1855 xmlSecInternalError("xmlSecBnGetNodeValue(y)",
1856 xmlSecKeyDataKlassGetName(id));
1857 goto done;
1858 }
1859 cur = xmlSecGetNextElementNode(cur->next);
1860
1861 /* todo: add support for J */
1862 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
1863 cur = xmlSecGetNextElementNode(cur->next);
1864 }
1865
1866 /* todo: add support for seed */
1867 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
1868 cur = xmlSecGetNextElementNode(cur->next);
1869 }
1870
1871 /* todo: add support for pgencounter */
1872 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
1873 cur = xmlSecGetNextElementNode(cur->next);
1874 }
1875
1876 if(cur != NULL) {
1877 xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id))
1878 goto done;
1879 }
1880
1881 /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
1882 blobBufferLen = sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * xmlSecBnGetSize(&p) + 0x14 + sizeof(DSSSEED);
1883 ret = xmlSecBufferSetSize(&blob, blobBufferLen);
1884 if(ret < 0) {
1885 xmlSecInternalError2("xmlSecBufferSetSize", NULL, "size=%d", blobBufferLen);
1886 goto done;
1887 }
1888
1889 /* Set PUBLICKEYSTRUC */
1890 pubKeyStruc = (PUBLICKEYSTRUC *)xmlSecBufferGetData(&blob);
1891 pubKeyStruc->bType = PUBLICKEYBLOB;
1892 pubKeyStruc->bVersion = 0x02;
1893 pubKeyStruc->reserved = 0;
1894 pubKeyStruc->aiKeyAlg = CALG_DSS_SIGN;
1895
1896 /* Set the public key header */
1897 pubKey = (DSSPUBKEY *) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC));
1898 pubKey->magic = 0x31535344; /* == DSS1 pub key */
1899 pubKey->bitlen = xmlSecBnGetSize(&p) * 8; /* Number of bits in prime modulus */
1900
1901 /* copy the key data */
1902 buf = (BYTE*) (xmlSecBufferGetData(&blob) + sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY));
1903
1904 /* set p */
1905 xmlSecAssert2(xmlSecBnGetData(&p) != NULL, -1);
1906 memcpy(buf, xmlSecBnGetData(&p), xmlSecBnGetSize(&p));
1907 buf += xmlSecBnGetSize(&p);
1908
1909 /* set q */
1910 if(xmlSecBnGetSize(&q) > 0x14) {
1911 xmlSecInvalidSizeLessThanError("DSA key q",
1912 xmlSecBnGetSize(&q), 0x14, NULL);
1913 goto done;
1914 }
1915 xmlSecAssert2(xmlSecBnGetData(&q) != NULL, -1);
1916 memcpy(buf, xmlSecBnGetData(&q), xmlSecBnGetSize(&q));
1917 buf += xmlSecBnGetSize(&q);
1918
1919 /* Pad with zeros */
1920 for(i = xmlSecBnGetSize(&q); i < 0x14; ++i) {
1921 *(buf++) = 0;
1922 }
1923
1924 /* set generator */
1925 if(xmlSecBnGetSize(&g) > xmlSecBnGetSize(&p)) {
1926 xmlSecInvalidSizeMoreThanError("DSA key g",
1927 xmlSecBnGetSize(&g),
1928 xmlSecBnGetSize(&p),
1929 NULL);
1930 goto done;
1931 }
1932 xmlSecAssert2(xmlSecBnGetData(&g) != NULL, -1);
1933 memcpy(buf, xmlSecBnGetData(&g), xmlSecBnGetSize(&g));
1934 buf += xmlSecBnGetSize(&g);
1935 /* Pad with zeros */
1936 for(i = xmlSecBnGetSize(&g); i < xmlSecBnGetSize(&p); ++i) {
1937 *(buf++) = 0;
1938 }
1939
1940 /* Public key */
1941 if(xmlSecBnGetSize(&y) > xmlSecBnGetSize(&p)) {
1942 xmlSecInvalidSizeMoreThanError("DSA key y",
1943 xmlSecBnGetSize(&y),
1944 xmlSecBnGetSize(&p),
1945 NULL);
1946 goto done;
1947 }
1948 xmlSecAssert2(xmlSecBnGetData(&y) != NULL, -1);
1949 memcpy(buf, xmlSecBnGetData(&y), xmlSecBnGetSize(&y));
1950 buf += xmlSecBnGetSize(&y);
1951 /* Pad with zeros */
1952 for(i = xmlSecBnGetSize(&y); i < xmlSecBnGetSize(&p); ++i) {
1953 *(buf++) = 0;
1954 }
1955
1956 /* Set seed to 0xFFFFFFFFF */
1957 seed = (DSSSEED*)buf;
1958 memset(seed, 0, sizeof(*seed));
1959 seed->counter = 0xFFFFFFFF; /* SEED Counter set to 0xFFFFFFFF will cause seed to be ignored */
1960
1961 hProv = xmlSecMSCryptoFindProvider(xmlSecMSCryptoProviderInfo_Dss, NULL, CRYPT_VERIFYCONTEXT, TRUE);
1962 if(hProv == 0) {
1963 xmlSecInternalError("xmlSecMSCryptoFindProvider",
1964 xmlSecKeyDataKlassGetName(id));
1965 goto done;
1966 }
1967
1968 /* import the key blob */
1969 if (!CryptImportKey(hProv, xmlSecBufferGetData(&blob), xmlSecBufferGetSize(&blob), 0, 0, &hKey)) {
1970 xmlSecMSCryptoError("CryptImportKey",
1971 xmlSecKeyDataKlassGetName(id));
1972 goto done;
1973 }
1974
1975 data = xmlSecKeyDataCreate(id);
1976 if(data == NULL ) {
1977 xmlSecInternalError("xmlSecKeyDataCreate",
1978 xmlSecKeyDataKlassGetName(id));
1979 goto done;
1980 }
1981
1982 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, 0, xmlSecKeyDataTypePublic);
1983 if(ret < 0) {
1984 xmlSecInternalError("xmlSecMSCryptoKeyDataAdoptKey",
1985 xmlSecKeyDataGetName(data));
1986 goto done;
1987 }
1988 hProv = 0;
1989 hKey = 0;
1990
1991 ret = xmlSecKeySetValue(key, data);
1992 if(ret < 0) {
1993 xmlSecInternalError("xmlSecKeySetValue",
1994 xmlSecKeyDataGetName(data));
1995 goto done;
1996 }
1997 data = NULL;
1998
1999 /* success */
2000 res = 0;
2001
2002 done:
2003 if (hKey != 0) {
2004 CryptDestroyKey(hKey);
2005 }
2006 if (hProv != 0) {
2007 CryptReleaseContext(hProv, 0);
2008 }
2009 if (data != NULL) {
2010 xmlSecKeyDataDestroy(data);
2011 }
2012
2013 xmlSecBufferFinalize(&blob);
2014 xmlSecBnFinalize(&p);
2015 xmlSecBnFinalize(&q);
2016 xmlSecBnFinalize(&g);
2017 xmlSecBnFinalize(&y);
2018
2019 return(res);
2020 }
2021
2022 static int
xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)2023 xmlSecMSCryptoKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
2024 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
2025 xmlSecMSCryptoKeyDataCtxPtr ctx;
2026 xmlSecBuffer buf;
2027 DWORD dwBlobLen;
2028 xmlSecByte* blob;
2029 PUBLICKEYSTRUC* pubKeyStruc;
2030 DSSPUBKEY *pubKey;
2031 xmlSecSize keyLen, len;
2032 xmlNodePtr cur;
2033 int ret;
2034
2035
2036 xmlSecAssert2(id == xmlSecMSCryptoKeyDataDsaId, -1);
2037 xmlSecAssert2(key != NULL, -1);
2038 xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecMSCryptoKeyDataDsaId), -1);
2039 xmlSecAssert2(node != NULL, -1);
2040 xmlSecAssert2(keyInfoCtx != NULL, -1);
2041
2042 ctx = xmlSecMSCryptoKeyDataGetCtx(xmlSecKeyGetValue(key));
2043 xmlSecAssert2(ctx != NULL, -1);
2044 xmlSecAssert2(xmlSecMSCryptoKeyDataCtxGetKey(ctx) != 0, -1);
2045
2046 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
2047 xmlSecInternalError("CryptExportKey",
2048 xmlSecKeyDataKlassGetName(id));
2049 return(-1);
2050 }
2051
2052 ret = xmlSecBufferInitialize(&buf, dwBlobLen);
2053 if(ret < 0) {
2054 xmlSecInternalError2("xmlSecBufferInitialize",
2055 xmlSecKeyDataKlassGetName(id),
2056 "size=%ld", dwBlobLen);
2057 return(-1);
2058 }
2059
2060 blob = xmlSecBufferGetData(&buf);
2061 if (!CryptExportKey(xmlSecMSCryptoKeyDataCtxGetKey(ctx), 0, PUBLICKEYBLOB, 0, blob, &dwBlobLen)) {
2062 xmlSecMSCryptoError("CryptExportKey",
2063 xmlSecKeyDataKlassGetName(id));
2064 xmlSecBufferFinalize(&buf);
2065 return(-1);
2066 }
2067 if (dwBlobLen < sizeof(PUBLICKEYSTRUC)) {
2068 xmlSecInvalidSizeLessThanError("Key blob", dwBlobLen, sizeof(PUBLICKEYSTRUC),
2069 xmlSecKeyDataKlassGetName(id));
2070 xmlSecBufferFinalize(&buf);
2071 return(-1);
2072 }
2073
2074 /* check PUBLICKEYSTRUC */
2075 pubKeyStruc = (PUBLICKEYSTRUC*)blob;
2076 if(pubKeyStruc->bVersion != 0x02) {
2077 xmlSecMSCryptoError2("CryptExportKey",
2078 xmlSecKeyDataKlassGetName(id),
2079 "pubKeyStruc->bVersion=%ld",
2080 (long int)pubKeyStruc->bVersion);
2081 xmlSecBufferFinalize(&buf);
2082 return(-1);
2083 }
2084 if(pubKeyStruc->bType != PUBLICKEYBLOB) {
2085 xmlSecMSCryptoError2("CryptExportKey",
2086 xmlSecKeyDataKlassGetName(id),
2087 "pubKeyStruc->bType=%ld",
2088 (long int)pubKeyStruc->bType);
2089 xmlSecBufferFinalize(&buf);
2090 return(-1);
2091 }
2092
2093 /* check DSSPUBKEY */
2094 pubKey = (DSSPUBKEY*)(blob + sizeof(PUBLICKEYSTRUC));
2095 if(pubKey->magic != 0x31535344) { /* DSS key magic */
2096 xmlSecMSCryptoError2("CryptExportKey",
2097 xmlSecKeyDataKlassGetName(id),
2098 "pubKey->magic=0x%08lx",
2099 (long int)pubKey->magic);
2100 xmlSecBufferFinalize(&buf);
2101 return(-1);
2102 }
2103 keyLen = pubKey->bitlen / 8;
2104
2105 /* we assume that sizeof(q) < 0x14, sizeof(g) <= sizeof(p) and sizeof(y) <= sizeof(p) */
2106 if (dwBlobLen < sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * keyLen + 0x14 + sizeof(DSSSEED)) {
2107 xmlSecInvalidSizeLessThanError("Key blob",
2108 dwBlobLen, sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY) + 3 * keyLen + 0x14 + sizeof(DSSSEED),
2109 xmlSecKeyDataKlassGetName(id));
2110 xmlSecBufferFinalize(&buf);
2111 return(-1);
2112 }
2113 blob += sizeof(PUBLICKEYSTRUC) + sizeof(DSSPUBKEY);
2114
2115 /* first is P node */
2116 cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
2117 if(cur == NULL) {
2118 xmlSecInternalError("xmlSecAddChild(NodeDSAP)",
2119 xmlSecKeyDataKlassGetName(id));
2120 xmlSecBufferFinalize(&buf);
2121 return(-1);
2122 }
2123
2124 ret = xmlSecBnBlobSetNodeValue(blob, keyLen, cur, xmlSecBnBase64, 1, 1);
2125 if(ret < 0) {
2126 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeDSAP)",
2127 xmlSecKeyDataKlassGetName(id));
2128 xmlSecBufferFinalize(&buf);
2129 return(-1);
2130 }
2131 blob += keyLen;
2132
2133 /* next is Q node. */
2134 cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
2135 if(cur == NULL) {
2136 xmlSecInternalError("xmlSecAddChild(NodeDSAQ)",
2137 xmlSecKeyDataKlassGetName(id));
2138 xmlSecBufferFinalize(&buf);
2139 return(-1);
2140 }
2141
2142 /* we think that the size of q is 0x14, skip trailing zeros */
2143 for(len = 0x14; len > 0 && blob[len - 1] == 0; --len);
2144
2145 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2146 if(ret < 0) {
2147 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeDSAQ)",
2148 xmlSecKeyDataKlassGetName(id));
2149 xmlSecBufferFinalize(&buf);
2150 return(-1);
2151 }
2152 blob += 0x14;
2153
2154 /* next is G node. */
2155 cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
2156 if(cur == NULL) {
2157 xmlSecInternalError("xmlSecAddChild(NodeDSAG)",
2158 xmlSecKeyDataKlassGetName(id));
2159 xmlSecBufferFinalize(&buf);
2160 return(-1);
2161 }
2162
2163 /* skip trailing zeros */
2164 for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2165
2166 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2167 if(ret < 0) {
2168 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeDSAG)",
2169 xmlSecKeyDataKlassGetName(id));
2170 xmlSecBufferFinalize(&buf);
2171 return(-1);
2172 }
2173 blob += keyLen;
2174
2175 /* next is X node: not supported in MSCrypto */
2176
2177 /* next is Y node. */
2178 cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
2179 if(cur == NULL) {
2180 xmlSecInternalError("xmlSecAddChild(NodeDSAY)",
2181 xmlSecKeyDataKlassGetName(id));
2182 xmlSecBufferFinalize(&buf);
2183 return(-1);
2184 }
2185
2186 /* skip trailing zeros */
2187 for(len = keyLen; len > 0 && blob[len - 1] == 0; --len);
2188
2189 ret = xmlSecBnBlobSetNodeValue(blob, len, cur, xmlSecBnBase64, 1, 1);
2190 if(ret < 0) {
2191 xmlSecInternalError("xmlSecBnBlobSetNodeValue(NodeDSAY)",
2192 xmlSecKeyDataKlassGetName(id));
2193 xmlSecBufferFinalize(&buf);
2194 return(-1);
2195 }
2196 blob += keyLen;
2197
2198 xmlSecBufferFinalize(&buf);
2199 return(0);
2200 }
2201
2202 static int
xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data,xmlSecSize sizeBits,xmlSecKeyDataType type ATTRIBUTE_UNUSED)2203 xmlSecMSCryptoKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
2204 xmlSecMSCryptoKeyDataCtxPtr ctx;
2205 HCRYPTPROV hProv = 0;
2206 HCRYPTKEY hKey = 0;
2207 DWORD dwKeySpec;
2208 DWORD dwSize;
2209 int res = -1;
2210 int ret;
2211
2212 xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
2213 xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecMSCryptoKeyDataSize), xmlSecKeyDataTypeUnknown);
2214 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), -1);
2215 xmlSecAssert2(sizeBits > 0, -1);
2216 UNREFERENCED_PARAMETER(type);
2217
2218 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2219
2220 hProv = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
2221 if(hProv == 0) {
2222 xmlSecInternalError("xmlSecMSCryptoFindProvider",
2223 xmlSecKeyDataGetName(data));
2224 return(-1);
2225 }
2226
2227 dwKeySpec = AT_SIGNATURE;
2228 dwSize = ((sizeBits << 16) | CRYPT_EXPORTABLE);
2229 if (!CryptGenKey(hProv, CALG_DSS_SIGN, dwSize, &hKey)) {
2230 xmlSecMSCryptoError("CryptGenKey",
2231 xmlSecKeyDataGetName(data));
2232 goto done;
2233 }
2234
2235 ret = xmlSecMSCryptoKeyDataAdoptKey(data, hProv, TRUE, hKey, dwKeySpec,
2236 xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
2237 if(ret < 0) {
2238 xmlSecInternalError("xmlSecMSCryptoKeyDataAdoptKey",
2239 xmlSecKeyDataGetName(data));
2240 goto done;
2241 }
2242 hProv = 0;
2243 hKey = 0;
2244
2245 /* success */
2246 res = 0;
2247
2248 done:
2249 if (hProv != 0) {
2250 CryptReleaseContext(hProv, 0);
2251 }
2252
2253 if (hKey != 0) {
2254 CryptDestroyKey(hKey);
2255 }
2256
2257 return(res);
2258 }
2259
2260 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data)2261 xmlSecMSCryptoKeyDataDsaGetType(xmlSecKeyDataPtr data) {
2262 return(xmlSecMSCryptoKeyDataGetType(data));
2263 }
2264
2265 static xmlSecSize
xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data)2266 xmlSecMSCryptoKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
2267 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId), 0);
2268
2269 return xmlSecMSCryptoKeyDataGetSize(data);
2270 }
2271
2272 static void
xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data,FILE * output)2273 xmlSecMSCryptoKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
2274 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2275 xmlSecAssert(output != NULL);
2276
2277 fprintf(output, "=== dsa key: size = %d\n",
2278 xmlSecMSCryptoKeyDataDsaGetSize(data));
2279 }
2280
2281 static void
xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,FILE * output)2282 xmlSecMSCryptoKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2283 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataDsaId));
2284 xmlSecAssert(output != NULL);
2285
2286 fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
2287 xmlSecMSCryptoKeyDataDsaGetSize(data));
2288 }
2289
2290 #endif /* XMLSEC_NO_DSA */
2291
2292
2293 #ifndef XMLSEC_NO_GOST
2294 /**************************************************************************
2295 *
2296 * GOST2001 xml key representation processing. Contain errors.
2297 *
2298 *************************************************************************/
2299 static int xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data);
2300 static int xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst,
2301 xmlSecKeyDataPtr src);
2302 static void xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data);
2303 static int xmlSecMSCryptoKeyDataGost2001XmlRead (xmlSecKeyDataId id,
2304 xmlSecKeyPtr key,
2305 xmlNodePtr node,
2306 xmlSecKeyInfoCtxPtr keyInfoCtx);
2307 static int xmlSecMSCryptoKeyDataGost2001XmlWrite(xmlSecKeyDataId id,
2308 xmlSecKeyPtr key,
2309 xmlNodePtr node,
2310 xmlSecKeyInfoCtxPtr keyInfoCtx);
2311 static int xmlSecMSCryptoKeyDataGost2001Generate(xmlSecKeyDataPtr data,
2312 xmlSecSize sizeBits,
2313 xmlSecKeyDataType type);
2314
2315 static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data);
2316 static xmlSecSize xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data);
2317 static void xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data,
2318 FILE* output);
2319 static void xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data,
2320 FILE* output);
2321
2322 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2001Klass = {
2323 sizeof(xmlSecKeyDataKlass),
2324 xmlSecMSCryptoKeyDataSize,
2325
2326 /* data */
2327 xmlSecNameGOST2001KeyValue,
2328 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
2329 /* xmlSecKeyDataUsage usage; */
2330 xmlSecHrefGOST2001KeyValue, /* const xmlChar* href; */
2331 xmlSecNodeGOST2001KeyValue, /* const xmlChar* dataNodeName; */
2332 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
2333
2334 /* constructors/destructor */
2335 xmlSecMSCryptoKeyDataGost2001Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
2336 xmlSecMSCryptoKeyDataGost2001Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
2337 xmlSecMSCryptoKeyDataGost2001Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
2338 NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */
2339
2340 /* get info */
2341 xmlSecMSCryptoKeyDataGost2001GetType, /* xmlSecKeyDataGetTypeMethod getType; */
2342 xmlSecMSCryptoKeyDataGost2001GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
2343 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
2344
2345 /* read/write */
2346 NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
2347 NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
2348 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
2349 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
2350
2351 /* debug */
2352 xmlSecMSCryptoKeyDataGost2001DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
2353 xmlSecMSCryptoKeyDataGost2001DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
2354
2355 /* reserved for the future */
2356 NULL, /* void* reserved0; */
2357 NULL, /* void* reserved1; */
2358 };
2359
2360 /* Ordered list of providers to search for algorithm implementation using
2361 * xmlSecMSCryptoFindProvider() function
2362 *
2363 * MUST END with { NULL, 0 } !!!
2364 */
2365 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost[] = {
2366 { MAGPRO_CSP, PROV_MAGPRO_GOST },
2367 { CRYPTOPRO_CSP, PROV_CRYPTOPRO_GOST },
2368 { NULL, 0 }
2369 };
2370
2371 /**
2372 * xmlSecMSCryptoKeyDataGost2001GetKlass:
2373 *
2374 * The GOST2001 key data klass.
2375 *
2376 * Returns: pointer to GOST2001 key data klass.
2377 */
2378 xmlSecKeyDataId
xmlSecMSCryptoKeyDataGost2001GetKlass(void)2379 xmlSecMSCryptoKeyDataGost2001GetKlass(void) {
2380 return(&xmlSecMSCryptoKeyDataGost2001Klass);
2381 }
2382
2383
2384 static int
xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data)2385 xmlSecMSCryptoKeyDataGost2001Initialize(xmlSecKeyDataPtr data) {
2386 xmlSecMSCryptoKeyDataCtxPtr ctx;
2387 int ret;
2388
2389 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), xmlSecKeyDataTypeUnknown);
2390
2391 ret = xmlSecMSCryptoKeyDataInitialize(data);
2392 if(ret != 0) {
2393 xmlSecInternalError("xmlSecMSCryptoKeyDataInitialize", NULL);
2394 return(-1);
2395 }
2396
2397 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2398 xmlSecAssert2(ctx != NULL, -1);
2399
2400 ctx->providers = xmlSecMSCryptoProviderInfo_Gost;
2401 return(0);
2402 }
2403
2404 static int
xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)2405 xmlSecMSCryptoKeyDataGost2001Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
2406 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2001Id), -1);
2407 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2001Id), -1);
2408
2409 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
2410 }
2411
2412 static void
xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data)2413 xmlSecMSCryptoKeyDataGost2001Finalize(xmlSecKeyDataPtr data) {
2414 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2415
2416 xmlSecMSCryptoKeyDataFinalize(data);
2417 }
2418
2419 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data)2420 xmlSecMSCryptoKeyDataGost2001GetType(xmlSecKeyDataPtr data) {
2421 return(xmlSecMSCryptoKeyDataGetType(data));
2422 }
2423
2424 static xmlSecSize
xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data)2425 xmlSecMSCryptoKeyDataGost2001GetSize(xmlSecKeyDataPtr data) {
2426 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id), 0);
2427
2428 return xmlSecMSCryptoKeyDataGetSize(data);
2429 }
2430
2431 static void
xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data,FILE * output)2432 xmlSecMSCryptoKeyDataGost2001DebugDump(xmlSecKeyDataPtr data, FILE* output) {
2433 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2434 xmlSecAssert(output != NULL);
2435
2436 fprintf(output, "=== dsa key: size = %d\n",
2437 xmlSecMSCryptoKeyDataGost2001GetSize(data));
2438 }
2439
2440 static void
xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data,FILE * output)2441 xmlSecMSCryptoKeyDataGost2001DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2442 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2001Id));
2443 xmlSecAssert(output != NULL);
2444
2445 fprintf(output, "<GOST2001KeyValue size=\"%d\" />\n",
2446 xmlSecMSCryptoKeyDataGost2001GetSize(data));
2447 }
2448
2449 #endif /* XMLSEC_NO_GOST */
2450
2451
2452 #ifndef XMLSEC_NO_GOST2012
2453
2454 /**************************************************************************
2455 *
2456 * GOST2012 256 xml key representation processing.
2457 *
2458 *************************************************************************/
2459 static int xmlSecMSCryptoKeyDataGost2012_256Initialize(xmlSecKeyDataPtr data);
2460 static int xmlSecMSCryptoKeyDataGost2012_256Duplicate(xmlSecKeyDataPtr dst,
2461 xmlSecKeyDataPtr src);
2462 static void xmlSecMSCryptoKeyDataGost2012_256Finalize(xmlSecKeyDataPtr data);
2463 static int xmlSecMSCryptoKeyDataGost2012_256XmlRead (xmlSecKeyDataId id,
2464 xmlSecKeyPtr key,
2465 xmlNodePtr node,
2466 xmlSecKeyInfoCtxPtr keyInfoCtx);
2467 static int xmlSecMSCryptoKeyDataGost2012_256XmlWrite(xmlSecKeyDataId id,
2468 xmlSecKeyPtr key,
2469 xmlNodePtr node,
2470 xmlSecKeyInfoCtxPtr keyInfoCtx);
2471 static int xmlSecMSCryptoKeyDataGost2012_256Generate(xmlSecKeyDataPtr data,
2472 xmlSecSize sizeBits,
2473 xmlSecKeyDataType type);
2474
2475 static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2012_256GetType(xmlSecKeyDataPtr data);
2476 static xmlSecSize xmlSecMSCryptoKeyDataGost2012_256GetSize(xmlSecKeyDataPtr data);
2477 static void xmlSecMSCryptoKeyDataGost2012_256DebugDump(xmlSecKeyDataPtr data,
2478 FILE* output);
2479 static void xmlSecMSCryptoKeyDataGost2012_256DebugXmlDump(xmlSecKeyDataPtr data,
2480 FILE* output);
2481
2482 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2012_256Klass = {
2483 sizeof(xmlSecKeyDataKlass),
2484 xmlSecMSCryptoKeyDataSize,
2485
2486 /* data */
2487 xmlSecNameGostR3410_2012_256KeyValue,
2488 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
2489 /* xmlSecKeyDataUsage usage; */
2490 xmlSecHrefGostR3410_2012_256KeyValue, /* const xmlChar* href; */
2491 xmlSecNodeGostR3410_2012_256KeyValue, /* const xmlChar* dataNodeName; */
2492 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
2493
2494 /* constructors/destructor */
2495 xmlSecMSCryptoKeyDataGost2012_256Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
2496 xmlSecMSCryptoKeyDataGost2012_256Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
2497 xmlSecMSCryptoKeyDataGost2012_256Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
2498 NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */
2499
2500 /* get info */
2501 xmlSecMSCryptoKeyDataGost2012_256GetType, /* xmlSecKeyDataGetTypeMethod getType; */
2502 xmlSecMSCryptoKeyDataGost2012_256GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
2503 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
2504
2505 /* read/write */
2506 NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
2507 NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
2508 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
2509 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
2510
2511 /* debug */
2512 xmlSecMSCryptoKeyDataGost2012_256DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
2513 xmlSecMSCryptoKeyDataGost2012_256DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
2514
2515 /* reserved for the future */
2516 NULL, /* void* reserved0; */
2517 NULL, /* void* reserved1; */
2518 };
2519
2520 /* Ordered list of providers to search for algorithm implementation using
2521 * xmlSecMSCryptoFindProvider() function
2522 *
2523 * MUST END with { NULL, 0 } !!!
2524 */
2525 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost2012_256[] = {
2526 { CRYPTOPRO_CSP_256, PROV_GOST_2012_256 },
2527 { NULL, 0 }
2528 };
2529
2530 /**
2531 * xmlSecMSCryptoKeyDataGost2001GetKlass:
2532 *
2533 * The GOST2012_256 key data klass.
2534 *
2535 * Returns: pointer to GOST2012_256 key data klass.
2536 */
2537 xmlSecKeyDataId
xmlSecMSCryptoKeyDataGost2012_256GetKlass(void)2538 xmlSecMSCryptoKeyDataGost2012_256GetKlass(void) {
2539 return(&xmlSecMSCryptoKeyDataGost2012_256Klass);
2540 }
2541
2542
2543 static int
xmlSecMSCryptoKeyDataGost2012_256Initialize(xmlSecKeyDataPtr data)2544 xmlSecMSCryptoKeyDataGost2012_256Initialize(xmlSecKeyDataPtr data) {
2545 xmlSecMSCryptoKeyDataCtxPtr ctx;
2546 int ret;
2547
2548 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_256Id), xmlSecKeyDataTypeUnknown);
2549
2550 ret = xmlSecMSCryptoKeyDataInitialize(data);
2551 if(ret != 0) {
2552 xmlSecInternalError("xmlSecMSCryptoKeyDataInitialize", NULL);
2553 return(-1);
2554 }
2555
2556 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2557 xmlSecAssert2(ctx != NULL, -1);
2558
2559 ctx->providers = xmlSecMSCryptoProviderInfo_Gost2012_256;
2560 return(0);
2561 }
2562
2563 static int
xmlSecMSCryptoKeyDataGost2012_256Duplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)2564 xmlSecMSCryptoKeyDataGost2012_256Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
2565 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2012_256Id), -1);
2566 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2012_256Id), -1);
2567
2568 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
2569 }
2570
2571 static void
xmlSecMSCryptoKeyDataGost2012_256Finalize(xmlSecKeyDataPtr data)2572 xmlSecMSCryptoKeyDataGost2012_256Finalize(xmlSecKeyDataPtr data) {
2573 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_256Id));
2574
2575 xmlSecMSCryptoKeyDataFinalize(data);
2576 }
2577
2578 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataGost2012_256GetType(xmlSecKeyDataPtr data)2579 xmlSecMSCryptoKeyDataGost2012_256GetType(xmlSecKeyDataPtr data) {
2580 return(xmlSecMSCryptoKeyDataGetType(data));
2581 }
2582
2583 static xmlSecSize
xmlSecMSCryptoKeyDataGost2012_256GetSize(xmlSecKeyDataPtr data)2584 xmlSecMSCryptoKeyDataGost2012_256GetSize(xmlSecKeyDataPtr data) {
2585 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_256Id), 0);
2586
2587 return xmlSecMSCryptoKeyDataGetSize(data);
2588 }
2589
2590 static void
xmlSecMSCryptoKeyDataGost2012_256DebugDump(xmlSecKeyDataPtr data,FILE * output)2591 xmlSecMSCryptoKeyDataGost2012_256DebugDump(xmlSecKeyDataPtr data, FILE* output) {
2592 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_256Id));
2593 xmlSecAssert(output != NULL);
2594
2595 fprintf(output, "=== dsa key: size = %d\n",
2596 xmlSecMSCryptoKeyDataGost2012_256GetSize(data));
2597 }
2598
2599 static void
xmlSecMSCryptoKeyDataGost2012_256DebugXmlDump(xmlSecKeyDataPtr data,FILE * output)2600 xmlSecMSCryptoKeyDataGost2012_256DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2601 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_256Id));
2602 xmlSecAssert(output != NULL);
2603
2604 fprintf(output, "<GOST2012_256KeyValue size=\"%d\" />\n",
2605 xmlSecMSCryptoKeyDataGost2012_256GetSize(data));
2606 }
2607
2608
2609 /**************************************************************************
2610 *
2611 * GOST2012 512 xml key representation processing.
2612 *
2613 *************************************************************************/
2614 static int xmlSecMSCryptoKeyDataGost2012_512Initialize(xmlSecKeyDataPtr data);
2615 static int xmlSecMSCryptoKeyDataGost2012_512Duplicate(xmlSecKeyDataPtr dst,
2616 xmlSecKeyDataPtr src);
2617 static void xmlSecMSCryptoKeyDataGost2012_512Finalize(xmlSecKeyDataPtr data);
2618 static int xmlSecMSCryptoKeyDataGost2012_512XmlRead (xmlSecKeyDataId id,
2619 xmlSecKeyPtr key,
2620 xmlNodePtr node,
2621 xmlSecKeyInfoCtxPtr keyInfoCtx);
2622 static int xmlSecMSCryptoKeyDataGost2012_512XmlWrite(xmlSecKeyDataId id,
2623 xmlSecKeyPtr key,
2624 xmlNodePtr node,
2625 xmlSecKeyInfoCtxPtr keyInfoCtx);
2626 static int xmlSecMSCryptoKeyDataGost2012_512Generate(xmlSecKeyDataPtr data,
2627 xmlSecSize sizeBits,
2628 xmlSecKeyDataType type);
2629
2630 static xmlSecKeyDataType xmlSecMSCryptoKeyDataGost2012_512GetType(xmlSecKeyDataPtr data);
2631 static xmlSecSize xmlSecMSCryptoKeyDataGost2012_512GetSize(xmlSecKeyDataPtr data);
2632 static void xmlSecMSCryptoKeyDataGost2012_512DebugDump(xmlSecKeyDataPtr data,
2633 FILE* output);
2634 static void xmlSecMSCryptoKeyDataGost2012_512DebugXmlDump(xmlSecKeyDataPtr data,
2635 FILE* output);
2636
2637 static xmlSecKeyDataKlass xmlSecMSCryptoKeyDataGost2012_512Klass = {
2638 sizeof(xmlSecKeyDataKlass),
2639 xmlSecMSCryptoKeyDataSize,
2640
2641 /* data */
2642 xmlSecNameGostR3410_2012_512KeyValue,
2643 xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
2644 /* xmlSecKeyDataUsage usage; */
2645 xmlSecHrefGostR3410_2012_512KeyValue, /* const xmlChar* href; */
2646 xmlSecNodeGostR3410_2012_512KeyValue, /* const xmlChar* dataNodeName; */
2647 xmlSecDSigNs, /* const xmlChar* dataNodeNs; */
2648
2649 /* constructors/destructor */
2650 xmlSecMSCryptoKeyDataGost2012_512Initialize, /* xmlSecKeyDataInitializeMethod initialize; */
2651 xmlSecMSCryptoKeyDataGost2012_512Duplicate, /* xmlSecKeyDataDuplicateMethod duplicate; */
2652 xmlSecMSCryptoKeyDataGost2012_512Finalize, /* xmlSecKeyDataFinalizeMethod finalize; */
2653 NULL, /* xmlSecMSCryptoKeyDataGost2001Generate,*/ /* xmlSecKeyDataGenerateMethod generate; */
2654
2655 /* get info */
2656 xmlSecMSCryptoKeyDataGost2012_512GetType, /* xmlSecKeyDataGetTypeMethod getType; */
2657 xmlSecMSCryptoKeyDataGost2012_512GetSize, /* xmlSecKeyDataGetSizeMethod getSize; */
2658 NULL, /* xmlSecKeyDataGetIdentifier getIdentifier; */
2659
2660 /* read/write */
2661 NULL, /* xmlSecKeyDataXmlReadMethod xmlRead; */
2662 NULL, /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
2663 NULL, /* xmlSecKeyDataBinReadMethod binRead; */
2664 NULL, /* xmlSecKeyDataBinWriteMethod binWrite; */
2665
2666 /* debug */
2667 xmlSecMSCryptoKeyDataGost2012_512DebugDump, /* xmlSecKeyDataDebugDumpMethod debugDump; */
2668 xmlSecMSCryptoKeyDataGost2012_512DebugXmlDump,/* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
2669
2670 /* reserved for the future */
2671 NULL, /* void* reserved0; */
2672 NULL, /* void* reserved1; */
2673 };
2674
2675 /* Ordered list of providers to search for algorithm implementation using
2676 * xmlSecMSCryptoFindProvider() function
2677 *
2678 * MUST END with { NULL, 0 } !!!
2679 */
2680 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Gost2012_512[] = {
2681 { CRYPTOPRO_CSP_512, PROV_GOST_2012_512 },
2682 { NULL, 0 }
2683 };
2684
2685 /**
2686 * xmlSecMSCryptoKeyDataGost2001GetKlass:
2687 *
2688 * The GOST2012_512 key data klass.
2689 *
2690 * Returns: pointer to GOST2012_512 key data klass.
2691 */
2692 xmlSecKeyDataId
xmlSecMSCryptoKeyDataGost2012_512GetKlass(void)2693 xmlSecMSCryptoKeyDataGost2012_512GetKlass(void) {
2694 return(&xmlSecMSCryptoKeyDataGost2012_512Klass);
2695 }
2696
2697
2698 static int
xmlSecMSCryptoKeyDataGost2012_512Initialize(xmlSecKeyDataPtr data)2699 xmlSecMSCryptoKeyDataGost2012_512Initialize(xmlSecKeyDataPtr data) {
2700 xmlSecMSCryptoKeyDataCtxPtr ctx;
2701 int ret;
2702
2703 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_512Id), xmlSecKeyDataTypeUnknown);
2704
2705 ret = xmlSecMSCryptoKeyDataInitialize(data);
2706 if(ret != 0) {
2707 xmlSecInternalError("xmlSecMSCryptoKeyDataInitialize", NULL);
2708 return(-1);
2709 }
2710
2711 ctx = xmlSecMSCryptoKeyDataGetCtx(data);
2712 xmlSecAssert2(ctx != NULL, -1);
2713
2714 ctx->providers = xmlSecMSCryptoProviderInfo_Gost2012_512;
2715 return(0);
2716 }
2717
2718 static int
xmlSecMSCryptoKeyDataGost2012_512Duplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)2719 xmlSecMSCryptoKeyDataGost2012_512Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
2720 xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecMSCryptoKeyDataGost2012_512Id), -1);
2721 xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecMSCryptoKeyDataGost2012_512Id), -1);
2722
2723 return(xmlSecMSCryptoKeyDataDuplicate(dst, src));
2724 }
2725
2726 static void
xmlSecMSCryptoKeyDataGost2012_512Finalize(xmlSecKeyDataPtr data)2727 xmlSecMSCryptoKeyDataGost2012_512Finalize(xmlSecKeyDataPtr data) {
2728 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_512Id));
2729
2730 xmlSecMSCryptoKeyDataFinalize(data);
2731 }
2732
2733 static xmlSecKeyDataType
xmlSecMSCryptoKeyDataGost2012_512GetType(xmlSecKeyDataPtr data)2734 xmlSecMSCryptoKeyDataGost2012_512GetType(xmlSecKeyDataPtr data) {
2735 return(xmlSecMSCryptoKeyDataGetType(data));
2736 }
2737
2738 static xmlSecSize
xmlSecMSCryptoKeyDataGost2012_512GetSize(xmlSecKeyDataPtr data)2739 xmlSecMSCryptoKeyDataGost2012_512GetSize(xmlSecKeyDataPtr data) {
2740 xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_512Id), 0);
2741
2742 return xmlSecMSCryptoKeyDataGetSize(data);
2743 }
2744
2745 static void
xmlSecMSCryptoKeyDataGost2012_512DebugDump(xmlSecKeyDataPtr data,FILE * output)2746 xmlSecMSCryptoKeyDataGost2012_512DebugDump(xmlSecKeyDataPtr data, FILE* output) {
2747 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_512Id));
2748 xmlSecAssert(output != NULL);
2749
2750 fprintf(output, "=== dsa key: size = %d\n",
2751 xmlSecMSCryptoKeyDataGost2012_512GetSize(data));
2752 }
2753
2754 static void
xmlSecMSCryptoKeyDataGost2012_512DebugXmlDump(xmlSecKeyDataPtr data,FILE * output)2755 xmlSecMSCryptoKeyDataGost2012_512DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
2756 xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecMSCryptoKeyDataGost2012_512Id));
2757 xmlSecAssert(output != NULL);
2758
2759 fprintf(output, "<GOST2012_512KeyValue size=\"%d\" />\n",
2760 xmlSecMSCryptoKeyDataGost2012_512GetSize(data));
2761 }
2762
2763 #endif /* XMLSEC_NO_GOST2012 */
2764