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:x509vfy
13 * @Short_description: X509 certificates verification support functions for Microsoft Crypto API.
14 * @Stability: Private
15 *
16 */
17
18 #include "globals.h"
19
20 #ifndef XMLSEC_NO_X509
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <errno.h>
27
28 #include <libxml/tree.h>
29
30 #include <xmlsec/xmlsec.h>
31 #include <xmlsec/xmltree.h>
32 #include <xmlsec/keys.h>
33 #include <xmlsec/keyinfo.h>
34 #include <xmlsec/keysmngr.h>
35 #include <xmlsec/base64.h>
36 #include <xmlsec/bn.h>
37 #include <xmlsec/errors.h>
38
39 #include <xmlsec/mscrypto/crypto.h>
40 #include <xmlsec/mscrypto/x509.h>
41 #include "private.h"
42
43 /**************************************************************************
44 *
45 * Internal MSCRYPTO X509 store CTX
46 *
47 *************************************************************************/
48 typedef struct _xmlSecMSCryptoX509StoreCtx xmlSecMSCryptoX509StoreCtx,
49 *xmlSecMSCryptoX509StoreCtxPtr;
50 struct _xmlSecMSCryptoX509StoreCtx {
51 HCERTSTORE trusted;
52 HCERTSTORE untrusted;
53 int dont_use_system_trusted_certs;
54 };
55
56 /****************************************************************************
57 *
58 * xmlSecMSCryptoKeyDataStoreX509Id:
59 *
60 * xmlSecMSCryptoX509StoreCtx is located after xmlSecTransform
61 *
62 ***************************************************************************/
63 #define xmlSecMSCryptoX509StoreGetCtx(store) \
64 ((xmlSecMSCryptoX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
65 sizeof(xmlSecKeyDataStoreKlass)))
66 #define xmlSecMSCryptoX509StoreSize \
67 (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecMSCryptoX509StoreCtx))
68
69 static int xmlSecMSCryptoX509StoreInitialize (xmlSecKeyDataStorePtr store);
70 static void xmlSecMSCryptoX509StoreFinalize (xmlSecKeyDataStorePtr store);
71
72 static xmlSecKeyDataStoreKlass xmlSecMSCryptoX509StoreKlass = {
73 sizeof(xmlSecKeyDataStoreKlass),
74 xmlSecMSCryptoX509StoreSize,
75
76 /* data */
77 xmlSecNameX509Store, /* const xmlChar* name; */
78
79 /* constructors/destructor */
80 xmlSecMSCryptoX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
81 xmlSecMSCryptoX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
82
83 /* reserved for the future */
84 NULL, /* void* reserved0; */
85 NULL, /* void* reserved1; */
86 };
87
88 static PCCERT_CONTEXT xmlSecMSCryptoX509FindCert(HCERTSTORE store,
89 const xmlChar *subjectName,
90 const xmlChar *issuerName,
91 const xmlChar *issuerSerial,
92 const xmlChar *ski);
93
94
95 /**
96 * xmlSecMSCryptoX509StoreGetKlass:
97 *
98 * The MSCrypto X509 certificates key data store klass.
99 *
100 * Returns: pointer to MSCrypto X509 certificates key data store klass.
101 */
102 xmlSecKeyDataStoreId
xmlSecMSCryptoX509StoreGetKlass(void)103 xmlSecMSCryptoX509StoreGetKlass(void) {
104 return(&xmlSecMSCryptoX509StoreKlass);
105 }
106
107 /**
108 * xmlSecMSCryptoX509StoreFindCert:
109 * @store: the pointer to X509 key data store klass.
110 * @subjectName: the desired certificate name.
111 * @issuerName: the desired certificate issuer name.
112 * @issuerSerial: the desired certificate issuer serial number.
113 * @ski: the desired certificate SKI.
114 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
115 *
116 * Searches @store for a certificate that matches given criteria.
117 *
118 * Returns: pointer to found certificate or NULL if certificate is not found
119 * or an error occurs.
120 */
121 PCCERT_CONTEXT
xmlSecMSCryptoX509StoreFindCert(xmlSecKeyDataStorePtr store,xmlChar * subjectName,xmlChar * issuerName,xmlChar * issuerSerial,xmlChar * ski,xmlSecKeyInfoCtx * keyInfoCtx)122 xmlSecMSCryptoX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
123 xmlChar *issuerName, xmlChar *issuerSerial,
124 xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
125 xmlSecMSCryptoX509StoreCtxPtr ctx;
126 PCCERT_CONTEXT pCert = NULL;
127
128 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), NULL);
129 xmlSecAssert2(keyInfoCtx != NULL, NULL);
130
131 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
132 xmlSecAssert2(ctx != NULL, NULL);
133
134 /* search untrusted certs store */
135 if((ctx->untrusted != NULL) && (pCert == NULL)) {
136 pCert = xmlSecMSCryptoX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
137 }
138
139 /* search untrusted certs store */
140 if((ctx->trusted != NULL) && (pCert == NULL)) {
141 pCert = xmlSecMSCryptoX509FindCert(ctx->trusted, subjectName, issuerName, issuerSerial, ski);
142 }
143
144 return pCert;
145 }
146
147
148 static void
xmlSecMSCryptoUnixTimeToFileTime(time_t t,LPFILETIME pft)149 xmlSecMSCryptoUnixTimeToFileTime(time_t t, LPFILETIME pft) {
150 /* Note that LONGLONG is a 64-bit value */
151 LONGLONG ll;
152
153 xmlSecAssert(pft != NULL);
154
155 #if defined( __MINGW32__)
156 ll = Int32x32To64(t, 10000000) + 116444736000000000ULL;
157 #else
158 ll = Int32x32To64(t, 10000000) + 116444736000000000;
159 #endif
160 pft->dwLowDateTime = (DWORD)ll;
161 pft->dwHighDateTime = ll >> 32;
162 }
163
164 static BOOL
xmlSecMSCryptoVerifyCertTime(PCCERT_CONTEXT pCert,LPFILETIME pft)165 xmlSecMSCryptoVerifyCertTime(PCCERT_CONTEXT pCert, LPFILETIME pft) {
166 xmlSecAssert2(pCert != NULL, FALSE);
167 xmlSecAssert2(pCert->pCertInfo != NULL, FALSE);
168 xmlSecAssert2(pft != NULL, FALSE);
169
170 if(1 == CompareFileTime(&(pCert->pCertInfo->NotBefore), pft)) {
171 return (FALSE);
172 }
173 if(-1 == CompareFileTime(&(pCert->pCertInfo->NotAfter), pft)) {
174 return (FALSE);
175 }
176
177 return (TRUE);
178 }
179
180 static BOOL
xmlSecMSCryptoCheckRevocation(HCERTSTORE hStore,PCCERT_CONTEXT pCert)181 xmlSecMSCryptoCheckRevocation(HCERTSTORE hStore, PCCERT_CONTEXT pCert) {
182 PCCRL_CONTEXT pCrl = NULL;
183 PCRL_ENTRY pCrlEntry = NULL;
184
185 xmlSecAssert2(pCert != NULL, FALSE);
186 xmlSecAssert2(hStore != NULL, FALSE);
187
188 while((pCrl = CertEnumCRLsInStore(hStore, pCrl)) != NULL) {
189 if (CertFindCertificateInCRL(pCert, pCrl, 0, NULL, &pCrlEntry) && (pCrlEntry != NULL)) {
190 xmlSecOtherError(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, NULL,
191 "CertFindCertificateInCRL: cert found in crl list");
192 return(FALSE);
193 }
194 }
195
196 return(TRUE);
197 }
198
199 static void
xmlSecMSCryptoX509StoreCertError(xmlSecKeyDataStorePtr store,PCCERT_CONTEXT cert,DWORD flags)200 xmlSecMSCryptoX509StoreCertError(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, DWORD flags) {
201 xmlChar * subject = NULL;
202
203 xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
204 xmlSecAssert(cert != NULL);
205 xmlSecAssert(flags != 0);
206
207 /* get certs subject */
208 subject = xmlSecMSCryptoX509GetNameString(cert, CERT_NAME_RDN_TYPE, 0, NULL);
209 if(subject == NULL) {
210 xmlSecInternalError("xmlSecMSCryptoX509GetNameString", NULL);
211 return;
212 }
213
214 /* print error */
215 if (flags & CERT_STORE_SIGNATURE_FLAG) {
216 xmlSecOtherError2(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
217 xmlSecKeyDataStoreGetName(store),
218 "signature failed, subject=%s",
219 xmlSecErrorsSafeString(subject));
220 } else if (flags & CERT_STORE_TIME_VALIDITY_FLAG) {
221 xmlSecOtherError2(XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
222 xmlSecKeyDataStoreGetName(store),
223 "subject=%s",
224 xmlSecErrorsSafeString(subject));
225 } else if (flags & CERT_STORE_REVOCATION_FLAG) {
226 if (flags & CERT_STORE_NO_CRL_FLAG) {
227 xmlSecOtherError2(XMLSEC_ERRORS_R_CERT_REVOKED,
228 xmlSecKeyDataStoreGetName(store),
229 "no crl, subject=%s",
230 xmlSecErrorsSafeString(subject));
231 } else {
232 xmlSecOtherError2(XMLSEC_ERRORS_R_CERT_REVOKED,
233 xmlSecKeyDataStoreGetName(store),
234 "subject=%s",
235 xmlSecErrorsSafeString(subject));
236 }
237 } else {
238 xmlSecOtherError2(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
239 xmlSecKeyDataStoreGetName(store),
240 "subject=%s",
241 xmlSecErrorsSafeString(subject));
242 }
243
244 xmlFree(subject);
245 }
246
247 /**
248 * xmlSecBuildChainUsingWinapi:
249 * @cert: the certificate we check
250 * @pfTime: pointer to FILETIME that we are interested in
251 * @store_untrusted: untrusted certificates added via API
252 * @store_doc: untrusted certificates/CRLs extracted from a document
253 *
254 * Builds certificates chain using Windows API.
255 *
256 * Returns: TRUE on success or FALSE otherwise.
257 */
258 static BOOL
xmlSecBuildChainUsingWinapi(PCCERT_CONTEXT cert,LPFILETIME pfTime,HCERTSTORE store_untrusted,HCERTSTORE store_doc)259 xmlSecBuildChainUsingWinapi (PCCERT_CONTEXT cert, LPFILETIME pfTime,
260 HCERTSTORE store_untrusted, HCERTSTORE store_doc)
261 {
262 PCCERT_CHAIN_CONTEXT pChainContext = NULL;
263 CERT_CHAIN_PARA chainPara;
264 BOOL rc = FALSE;
265 HCERTSTORE store_add = NULL;
266
267 /* Initialize data structures. */
268 memset(&chainPara, 0, sizeof(CERT_CHAIN_PARA));
269 chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
270
271 /* Create additional store for CertGetCertificateChain() */
272 store_add = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 0, NULL);
273 if (!store_add) {
274 xmlSecMSCryptoError("CertOpenStore", NULL);
275 goto end;
276 }
277 if (!CertAddStoreToCollection(store_add, store_doc, 0, 0)) {
278 xmlSecMSCryptoError("CertAddStoreToCollection", NULL);
279 goto end;
280 }
281 if (!CertAddStoreToCollection(store_add, store_untrusted, 0, 0)) {
282 xmlSecMSCryptoError("CertAddStoreToCollection", NULL);
283 goto end;
284 }
285
286 /* Build a chain using CertGetCertificateChain
287 and the certificate retrieved. */
288 if(!CertGetCertificateChain(NULL, /* use the default chain engine */
289 cert,
290 pfTime,
291 store_add,
292 &chainPara,
293 CERT_CHAIN_REVOCATION_CHECK_CHAIN,
294 NULL,
295 &pChainContext)) {
296 xmlSecMSCryptoError("CertGetCertificateChain", NULL);
297 goto end;
298 }
299 if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_REVOCATION_STATUS_UNKNOWN) {
300 CertFreeCertificateChain(pChainContext); pChainContext = NULL;
301 if(!CertGetCertificateChain(NULL, /* use the default chain engine */
302 cert,
303 pfTime,
304 store_add,
305 &chainPara,
306 CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
307 NULL,
308 &pChainContext)) {
309 xmlSecMSCryptoError("CertGetCertificateChain", NULL);
310 goto end;
311 }
312 }
313
314 if (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR) {
315 rc = TRUE;
316 }
317
318 end:
319 if (pChainContext) CertFreeCertificateChain(pChainContext);
320 if (store_add) CertCloseStore(store_add, 0);
321 return (rc);
322 }
323
324 /**
325 * xmlSecMSCryptoBuildCertChainManually:
326 * @cert: the certificate we check
327 * @pfTime: pointer to FILETIME that we are interested in
328 * @store_trusted: trusted certificates added via API
329 * @store_untrusted: untrusted certificates added via API
330 * @certs: untrusted certificates/CRLs extracted from a document
331 * @store: pointer to store klass passed to error functions
332 *
333 * Builds certificates chain manually.
334 *
335 * Returns: TRUE on success or FALSE otherwise.
336 */
337 static BOOL
xmlSecMSCryptoBuildCertChainManually(PCCERT_CONTEXT cert,LPFILETIME pfTime,HCERTSTORE store_trusted,HCERTSTORE store_untrusted,HCERTSTORE certs,xmlSecKeyDataStorePtr store)338 xmlSecMSCryptoBuildCertChainManually (PCCERT_CONTEXT cert, LPFILETIME pfTime,
339 HCERTSTORE store_trusted, HCERTSTORE store_untrusted, HCERTSTORE certs,
340 xmlSecKeyDataStorePtr store) {
341 PCCERT_CONTEXT issuerCert = NULL;
342 DWORD flags;
343
344 if (!xmlSecMSCryptoVerifyCertTime(cert, pfTime)) {
345 xmlSecMSCryptoX509StoreCertError(store, cert, CERT_STORE_TIME_VALIDITY_FLAG);
346 return(FALSE);
347 }
348
349 if (!xmlSecMSCryptoCheckRevocation(certs, cert)) {
350 return(FALSE);
351 }
352
353 /*
354 * Try to find the cert in the trusted cert store. We will trust
355 * the certificate in the trusted store.
356 */
357 issuerCert = CertFindCertificateInStore(store_trusted,
358 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
359 0,
360 CERT_FIND_SUBJECT_NAME,
361 &(cert->pCertInfo->Subject),
362 NULL);
363 if( issuerCert != NULL) {
364 /* We have found the trusted cert, so return true */
365 /* todo: do we want to verify the trusted cert's revocation? we must, I think */
366 CertFreeCertificateContext( issuerCert ) ;
367 return( TRUE ) ;
368 }
369
370 /* Check whether the certificate is self signed certificate */
371 if(CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(cert->pCertInfo->Subject), &(cert->pCertInfo->Issuer))) {
372 return(FALSE);
373 }
374
375 /* try to find issuer cert in the trusted cert in the store */
376 issuerCert = CertFindCertificateInStore(store_trusted,
377 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
378 0,
379 CERT_FIND_SUBJECT_NAME,
380 &(cert->pCertInfo->Issuer),
381 NULL);
382 if(issuerCert != NULL) {
383 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
384 if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
385 xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
386 CertFreeCertificateContext(issuerCert);
387 return(FALSE);
388 }
389 /* todo: do we want to verify the trusted cert? we must check
390 * revocation, I think */
391 CertFreeCertificateContext(issuerCert);
392 return(TRUE);
393 }
394
395 /* try the untrusted certs in the chain */
396 issuerCert = CertFindCertificateInStore(certs,
397 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
398 0,
399 CERT_FIND_SUBJECT_NAME,
400 &(cert->pCertInfo->Issuer),
401 NULL);
402 if(issuerCert != NULL) {
403 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
404 if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
405 xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
406 CertFreeCertificateContext(issuerCert);
407 return(FALSE);
408 }
409 if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
410 xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
411 CertFreeCertificateContext(issuerCert);
412 return(FALSE);
413 }
414 CertFreeCertificateContext(issuerCert);
415 return(TRUE);
416 }
417
418 /* try the untrusted certs in the store */
419 issuerCert = CertFindCertificateInStore(store_untrusted,
420 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
421 0,
422 CERT_FIND_SUBJECT_NAME,
423 &(cert->pCertInfo->Issuer),
424 NULL);
425 if(issuerCert != NULL) {
426 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
427 if(!CertVerifySubjectCertificateContext(cert, issuerCert, &flags)) {
428 xmlSecMSCryptoX509StoreCertError(store, issuerCert, flags);
429 CertFreeCertificateContext(issuerCert);
430 return(FALSE);
431 }
432 if(!xmlSecMSCryptoBuildCertChainManually(issuerCert, pfTime, store_trusted, store_untrusted, certs, store)) {
433 CertFreeCertificateContext(issuerCert);
434 return(FALSE);
435 }
436 CertFreeCertificateContext(issuerCert);
437 return(TRUE);
438 }
439
440 return(FALSE);
441 }
442
443 static BOOL
xmlSecMSCryptoX509StoreConstructCertsChain(xmlSecKeyDataStorePtr store,PCCERT_CONTEXT cert,HCERTSTORE certs,xmlSecKeyInfoCtx * keyInfoCtx)444 xmlSecMSCryptoX509StoreConstructCertsChain(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT cert, HCERTSTORE certs,
445 xmlSecKeyInfoCtx* keyInfoCtx) {
446 xmlSecMSCryptoX509StoreCtxPtr ctx;
447 PCCERT_CONTEXT tempCert = NULL;
448 FILETIME fTime;
449 BOOL res = FALSE;
450
451 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), FALSE);
452 xmlSecAssert2(cert != NULL, FALSE);
453 xmlSecAssert2(cert->pCertInfo != NULL, FALSE);
454 xmlSecAssert2(certs != NULL, FALSE);
455 xmlSecAssert2(keyInfoCtx != NULL, FALSE);
456
457 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
458 xmlSecAssert2(ctx != NULL, FALSE);
459 xmlSecAssert2(ctx->trusted != NULL, FALSE);
460 xmlSecAssert2(ctx->untrusted != NULL, FALSE);
461
462 if(keyInfoCtx->certsVerificationTime > 0) {
463 /* convert the time to FILETIME */
464 xmlSecMSCryptoUnixTimeToFileTime(keyInfoCtx->certsVerificationTime, &fTime);
465 } else {
466 /* Defaults to current time */
467 GetSystemTimeAsFileTime(&fTime);
468 }
469
470 /* try the certificates in the keys manager */
471 if(!res) {
472 tempCert = CertEnumCertificatesInStore(ctx->trusted, NULL);
473 if(tempCert) {
474 CertFreeCertificateContext(tempCert);
475 res = xmlSecMSCryptoBuildCertChainManually(cert, &fTime, ctx->trusted, ctx->untrusted, certs, store);
476 }
477 }
478
479 /* try the certificates in the system */
480 if(!res && !ctx->dont_use_system_trusted_certs) {
481 res = xmlSecBuildChainUsingWinapi(cert, &fTime, ctx->untrusted, certs);
482 }
483
484 /* done */
485 return res;
486 }
487
488 /**
489 * xmlSecMSCryptoX509StoreVerify:
490 * @store: the pointer to X509 certificate context store klass.
491 * @certs: the untrusted certificates stack.
492 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
493 *
494 * Verifies @certs list.
495 *
496 * Returns: pointer to the first verified certificate from @certs.
497 */
498 PCCERT_CONTEXT
xmlSecMSCryptoX509StoreVerify(xmlSecKeyDataStorePtr store,HCERTSTORE certs,xmlSecKeyInfoCtx * keyInfoCtx)499 xmlSecMSCryptoX509StoreVerify(xmlSecKeyDataStorePtr store, HCERTSTORE certs,
500 xmlSecKeyInfoCtx* keyInfoCtx) {
501 PCCERT_CONTEXT cert = NULL;
502
503 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), NULL);
504 xmlSecAssert2(certs != NULL, NULL);
505 xmlSecAssert2(keyInfoCtx != NULL, NULL);
506
507 while((cert = CertEnumCertificatesInStore(certs, cert)) != NULL){
508 PCCERT_CONTEXT nextCert = NULL;
509 unsigned char selected = 1;
510
511 xmlSecAssert2(cert->pCertInfo != NULL, NULL);
512
513 /* if cert is the issuer of any other cert in the list, then it is
514 * to be skipped except a case of a celf-signed cert*/
515 do {
516 nextCert = CertFindCertificateInStore(certs,
517 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
518 0,
519 CERT_FIND_ISSUER_NAME,
520 &(cert->pCertInfo->Subject),
521 nextCert);
522 if((nextCert != NULL) && !CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
523 &(nextCert->pCertInfo->Subject), &(nextCert->pCertInfo->Issuer))) {
524 selected = 0;
525 }
526 } while((selected == 1) && (nextCert != NULL));
527 if(nextCert != NULL) {
528 CertFreeCertificateContext(nextCert);
529 }
530
531 if(selected == 1) {
532 if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) != 0
533 || xmlSecMSCryptoX509StoreConstructCertsChain(store, cert, certs, keyInfoCtx)) {
534 return(cert);
535 }
536 }
537 }
538
539 return (NULL);
540 }
541
542 /**
543 * xmlSecMSCryptoX509StoreAdoptCert:
544 * @store: the pointer to X509 key data store klass.
545 * @cert: the pointer to PCCERT_CONTEXT X509 certificate.
546 * @type: the certificate type (trusted/untrusted).
547 *
548 * Adds trusted (root) or untrusted certificate to the store.
549 *
550 * Returns: 0 on success or a negative value if an error occurs.
551 */
552 int
xmlSecMSCryptoX509StoreAdoptCert(xmlSecKeyDataStorePtr store,PCCERT_CONTEXT pCert,xmlSecKeyDataType type)553 xmlSecMSCryptoX509StoreAdoptCert(xmlSecKeyDataStorePtr store, PCCERT_CONTEXT pCert, xmlSecKeyDataType type) {
554 xmlSecMSCryptoX509StoreCtxPtr ctx;
555 HCERTSTORE certStore;
556
557 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
558 xmlSecAssert2(pCert != NULL, -1);
559
560 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
561 xmlSecAssert2(ctx != NULL, -1);
562 xmlSecAssert2(ctx->trusted != NULL, -1);
563 xmlSecAssert2(ctx->untrusted != NULL, -1);
564
565 if(type == xmlSecKeyDataTypeTrusted) {
566 certStore = ctx->trusted;
567 } else if(type == xmlSecKeyDataTypeNone) {
568 certStore = ctx->untrusted;
569 } else {
570 xmlSecInvalidIntegerTypeError("type", type,
571 "xmlSecKeyDataTypeTrusted, xmlSecKeyDataTypeNone",
572 xmlSecKeyDataStoreGetName(store));
573 return(-1);
574 }
575
576 /* TODO: The context to be added here is not duplicated first,
577 * hopefully this will not lead to errors when closing the store
578 * and freeing the mem for all the context in the store.
579 */
580 xmlSecAssert2(certStore != NULL, -1);
581 if (!CertAddCertificateContextToStore(certStore, pCert, CERT_STORE_ADD_ALWAYS, NULL)) {
582 xmlSecMSCryptoError("CertAddCertificateContextToStore",
583 xmlSecKeyDataStoreGetName(store));
584 return(-1);
585 }
586
587 return(0);
588 }
589
590
591 /**
592 * xmlSecMSCryptoX509StoreAdoptKeyStore:
593 * @store: the pointer to X509 key data store klass.
594 * @keyStore: the pointer to keys store.
595 *
596 * Adds @keyStore to the list of key stores.
597 *
598 * Returns: 0 on success or a negative value if an error occurs.
599 */
600 int
xmlSecMSCryptoX509StoreAdoptKeyStore(xmlSecKeyDataStorePtr store,HCERTSTORE keyStore)601 xmlSecMSCryptoX509StoreAdoptKeyStore (xmlSecKeyDataStorePtr store, HCERTSTORE keyStore) {
602 xmlSecMSCryptoX509StoreCtxPtr ctx;
603
604 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
605 xmlSecAssert2( keyStore != NULL, -1);
606
607 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
608 xmlSecAssert2(ctx != NULL, -1);
609 xmlSecAssert2(ctx->trusted != NULL, -1);
610
611 if(!CertAddStoreToCollection ( ctx->trusted , keyStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 2)) {
612 xmlSecMSCryptoError("CertAddStoreToCollection",
613 xmlSecKeyDataStoreGetName(store));
614 return(-1);
615 }
616
617 return(0);
618 }
619
620 /**
621 * xmlSecMSCryptoX509StoreAdoptTrustedStore:
622 * @store: the pointer to X509 key data store klass.
623 * @trustedStore: the pointer to certs store.
624 *
625 * Adds @trustedStore to the list of trusted certs stores.
626 *
627 * Returns: 0 on success or a negative value if an error occurs.
628 */
629 int
xmlSecMSCryptoX509StoreAdoptTrustedStore(xmlSecKeyDataStorePtr store,HCERTSTORE trustedStore)630 xmlSecMSCryptoX509StoreAdoptTrustedStore (xmlSecKeyDataStorePtr store, HCERTSTORE trustedStore) {
631 xmlSecMSCryptoX509StoreCtxPtr ctx;
632
633 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
634 xmlSecAssert2( trustedStore != NULL, -1);
635
636 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
637 xmlSecAssert2(ctx != NULL, -1);
638 xmlSecAssert2(ctx->trusted != NULL, -1);
639
640 if( !CertAddStoreToCollection ( ctx->trusted , trustedStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 3 ) ) {
641 xmlSecMSCryptoError("CertAddStoreToCollection",
642 xmlSecKeyDataStoreGetName(store));
643 return(-1);
644 }
645
646 return(0);
647 }
648
649 /**
650 * xmlSecMSCryptoX509StoreAdoptUntrustedStore:
651 * @store: the pointer to X509 key data store klass.
652 * @untrustedStore: the pointer to certs store.
653 *
654 * Adds @trustedStore to the list of un-trusted certs stores.
655 *
656 * Returns: 0 on success or a negative value if an error occurs.
657 */
658 int
xmlSecMSCryptoX509StoreAdoptUntrustedStore(xmlSecKeyDataStorePtr store,HCERTSTORE untrustedStore)659 xmlSecMSCryptoX509StoreAdoptUntrustedStore (xmlSecKeyDataStorePtr store, HCERTSTORE untrustedStore) {
660 xmlSecMSCryptoX509StoreCtxPtr ctx;
661
662 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
663 xmlSecAssert2( untrustedStore != NULL, -1);
664
665 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
666 xmlSecAssert2(ctx != NULL, -1);
667 xmlSecAssert2(ctx->untrusted != NULL, -1);
668
669 if( !CertAddStoreToCollection ( ctx->untrusted , untrustedStore , CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , 2 ) ) {
670 xmlSecMSCryptoError("CertAddStoreToCollection",
671 xmlSecKeyDataStoreGetName(store));
672 return(-1);
673 }
674
675 return(0);
676 }
677
678 /**
679 * xmlSecMSCryptoX509StoreEnableSystemTrustedCerts:
680 * @store: the pointer to X509 key data store klass.
681 * @val: the enable/disable flag
682 *
683 * Enables/disables the system trusted certs.
684 */
685 void
xmlSecMSCryptoX509StoreEnableSystemTrustedCerts(xmlSecKeyDataStorePtr store,int val)686 xmlSecMSCryptoX509StoreEnableSystemTrustedCerts (xmlSecKeyDataStorePtr store, int val) {
687 xmlSecMSCryptoX509StoreCtxPtr ctx;
688
689 xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
690
691 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
692 xmlSecAssert(ctx != NULL);
693 xmlSecAssert(ctx->untrusted != NULL);
694
695 /* it is other way around to make default value 0 mimic old behaviour */
696 ctx->dont_use_system_trusted_certs = !val;
697 }
698
699 static int
xmlSecMSCryptoX509StoreInitialize(xmlSecKeyDataStorePtr store)700 xmlSecMSCryptoX509StoreInitialize(xmlSecKeyDataStorePtr store) {
701 xmlSecMSCryptoX509StoreCtxPtr ctx;
702 HCERTSTORE hTrustedMemStore ;
703 HCERTSTORE hUntrustedMemStore ;
704
705 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId), -1);
706
707 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
708 xmlSecAssert2(ctx != NULL, -1);
709
710 memset(ctx, 0, sizeof(xmlSecMSCryptoX509StoreCtx));
711
712 /* create trusted certs store collection */
713 ctx->trusted = CertOpenStore(CERT_STORE_PROV_COLLECTION,
714 0,
715 0,
716 0,
717 NULL);
718 if(ctx->trusted == NULL) {
719 xmlSecMSCryptoError("CertOpenStore",
720 xmlSecKeyDataStoreGetName(store));
721 return(-1);
722 }
723
724 /* create trusted certs store */
725 hTrustedMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
726 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
727 0,
728 CERT_STORE_CREATE_NEW_FLAG,
729 NULL);
730 if(hTrustedMemStore == NULL) {
731 xmlSecMSCryptoError("CertOpenStore",
732 xmlSecKeyDataStoreGetName(store));
733 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
734 ctx->trusted = NULL ;
735 return(-1);
736 }
737
738 /* add the memory trusted certs store to trusted certs store collection */
739 if( !CertAddStoreToCollection( ctx->trusted, hTrustedMemStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1 ) ) {
740 xmlSecMSCryptoError("CertAddStoreToCollection",
741 xmlSecKeyDataStoreGetName(store));
742 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
743 CertCloseStore(hTrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
744 ctx->trusted = NULL ;
745 return(-1);
746 }
747 CertCloseStore(hTrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
748
749 /* create untrusted certs store collection */
750 ctx->untrusted = CertOpenStore(CERT_STORE_PROV_COLLECTION,
751 0,
752 0,
753 0,
754 NULL);
755 if(ctx->untrusted == NULL) {
756 xmlSecMSCryptoError("CertOpenStore",
757 xmlSecKeyDataStoreGetName(store));
758 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
759 ctx->trusted = NULL ;
760 return(-1);
761 }
762
763 /* create untrusted certs store */
764 hUntrustedMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
765 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
766 0,
767 CERT_STORE_CREATE_NEW_FLAG,
768 NULL);
769 if(hUntrustedMemStore == NULL) {
770 xmlSecMSCryptoError("CertOpenStore",
771 xmlSecKeyDataStoreGetName(store));
772 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
773 CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
774 ctx->trusted = NULL ;
775 ctx->untrusted = NULL ;
776 return(-1);
777 }
778
779 /* add the memory trusted certs store to untrusted certs store collection */
780 if( !CertAddStoreToCollection( ctx->untrusted, hUntrustedMemStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1 ) ) {
781 xmlSecMSCryptoError("CertAddStoreToCollection",
782 xmlSecKeyDataStoreGetName(store));
783 CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
784 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
785 CertCloseStore(hUntrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
786 ctx->trusted = NULL ;
787 ctx->untrusted = NULL ;
788 return(-1);
789 }
790 CertCloseStore(hUntrustedMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
791
792 return(0);
793 }
794
795 static void
xmlSecMSCryptoX509StoreFinalize(xmlSecKeyDataStorePtr store)796 xmlSecMSCryptoX509StoreFinalize(xmlSecKeyDataStorePtr store) {
797 xmlSecMSCryptoX509StoreCtxPtr ctx;
798 xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecMSCryptoX509StoreId));
799
800 ctx = xmlSecMSCryptoX509StoreGetCtx(store);
801 xmlSecAssert(ctx != NULL);
802
803 if (ctx->trusted) {
804 CertCloseStore(ctx->trusted, CERT_CLOSE_STORE_FORCE_FLAG);
805 }
806 if (ctx->untrusted) {
807 CertCloseStore(ctx->untrusted, CERT_CLOSE_STORE_FORCE_FLAG);
808 }
809
810 memset(ctx, 0, sizeof(xmlSecMSCryptoX509StoreCtx));
811 }
812
813
814 /*****************************************************************************
815 *
816 * Low-level x509 functions
817 *
818 *****************************************************************************/
819 /**
820 * xmlSecMSCryptoCertStrToName:
821 * @dwCertEncodingType: the encoding used.
822 * @pszX500: the string to convert.
823 * @dwStrType: the string type.
824 * @len: the result len.
825 *
826 * Converts input string to name by calling @CertStrToName function.
827 *
828 * Returns: a pointer to newly allocated string or NULL if an error occurs.
829 */
830 static BYTE*
xmlSecMSCryptoCertStrToName(DWORD dwCertEncodingType,LPTSTR pszX500,DWORD dwStrType,DWORD * len)831 xmlSecMSCryptoCertStrToName(DWORD dwCertEncodingType, LPTSTR pszX500, DWORD dwStrType, DWORD* len) {
832 BYTE* str = NULL;
833 LPCTSTR ppszError = NULL;
834
835 xmlSecAssert2(pszX500 != NULL, NULL);
836 xmlSecAssert2(len != NULL, NULL);
837
838 if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType,
839 NULL, NULL, len, &ppszError)) {
840 /* this might not be an error, string might just not exist */
841 return(NULL);
842 }
843
844 str = (BYTE *)xmlMalloc(sizeof(TCHAR) * ((*len) + 1));
845 if(str == NULL) {
846 xmlSecMallocError(sizeof(TCHAR) * ((*len) + 1), NULL);
847 return(NULL);
848 }
849 memset(str, 0, (*len) + 1);
850
851 if (!CertStrToName(dwCertEncodingType, pszX500, dwStrType,
852 NULL, str, len, NULL)) {
853 xmlSecMSCryptoError("CertStrToName", NULL);
854 xmlFree(str);
855 return(NULL);
856 }
857
858 return(str);
859 }
860
861
862 /**
863 * xmlSecMSCryptoX509FindCertBySubject:
864 * @store: the pointer to certs store
865 * @wcSubject: the cert subject (Unicode)
866 * @dwCertEncodingType: the cert encoding type
867 *
868 * Searches for a cert with given @subject in the @store
869 *
870 * Returns: cert handle on success or NULL otherwise
871 */
872 PCCERT_CONTEXT
xmlSecMSCryptoX509FindCertBySubject(HCERTSTORE store,const LPTSTR wcSubject,DWORD dwCertEncodingType)873 xmlSecMSCryptoX509FindCertBySubject(HCERTSTORE store, const LPTSTR wcSubject, DWORD dwCertEncodingType) {
874 PCCERT_CONTEXT res = NULL;
875 CERT_NAME_BLOB cnb;
876 BYTE* bdata;
877 DWORD len;
878
879 xmlSecAssert2(store != NULL, NULL);
880 xmlSecAssert2(wcSubject != NULL, NULL);
881
882 /* CASE 1: UTF8, DN */
883 if (NULL == res) {
884 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
885 wcSubject,
886 CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR,
887 &len);
888 if(bdata != NULL) {
889 cnb.cbData = len;
890 cnb.pbData = bdata;
891
892 res = CertFindCertificateInStore(store,
893 dwCertEncodingType,
894 0,
895 CERT_FIND_SUBJECT_NAME,
896 &cnb,
897 NULL);
898 xmlFree(bdata);
899 }
900 }
901
902 /* CASE 2: UTF8, REVERSE DN */
903 if (NULL == res) {
904 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
905 wcSubject,
906 CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
907 &len);
908 if(bdata != NULL) {
909 cnb.cbData = len;
910 cnb.pbData = bdata;
911
912 res = CertFindCertificateInStore(store,
913 dwCertEncodingType,
914 0,
915 CERT_FIND_SUBJECT_NAME,
916 &cnb,
917 NULL);
918 xmlFree(bdata);
919 }
920 }
921
922 /* CASE 3: UNICODE, DN */
923 if (NULL == res) {
924 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
925 wcSubject,
926 CERT_OID_NAME_STR,
927 &len);
928 if(bdata != NULL) {
929 cnb.cbData = len;
930 cnb.pbData = bdata;
931
932 res = CertFindCertificateInStore(store,
933 dwCertEncodingType,
934 0,
935 CERT_FIND_SUBJECT_NAME,
936 &cnb,
937 NULL);
938 xmlFree(bdata);
939 }
940 }
941
942 /* CASE 4: UNICODE, REVERSE DN */
943 if (NULL == res) {
944 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
945 wcSubject,
946 CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
947 &len);
948 if(bdata != NULL) {
949 cnb.cbData = len;
950 cnb.pbData = bdata;
951
952 res = CertFindCertificateInStore(store,
953 dwCertEncodingType,
954 0,
955 CERT_FIND_SUBJECT_NAME,
956 &cnb,
957 NULL);
958 xmlFree(bdata);
959 }
960 }
961
962
963 /* done */
964 return (res);
965 }
966
967 /**
968 * xmlSecMSCryptoX509FindCertByIssuer:
969 * @store: the pointer to certs store
970 * @wcIssuer: the cert issuer (Unicode)
971 * @issuerSerialBn: the cert issuer serial
972 * @dwCertEncodingType: the cert encoding type
973 *
974 * Searches for a cert with given @subject in the @store
975 *
976 * Returns: cert handle on success or NULL otherwise
977 */
978 static PCCERT_CONTEXT
xmlSecMSCryptoX509FindCertByIssuer(HCERTSTORE store,const LPTSTR wcIssuer,xmlSecBnPtr issuerSerialBn,DWORD dwCertEncodingType)979 xmlSecMSCryptoX509FindCertByIssuer(HCERTSTORE store, const LPTSTR wcIssuer,
980 xmlSecBnPtr issuerSerialBn, DWORD dwCertEncodingType) {
981
982 PCCERT_CONTEXT res = NULL;
983 CERT_INFO certInfo;
984 BYTE* bdata;
985 DWORD len;
986
987
988 xmlSecAssert2(store != NULL, NULL);
989 xmlSecAssert2(wcIssuer != NULL, NULL);
990 xmlSecAssert2(issuerSerialBn != NULL, NULL);
991
992 certInfo.SerialNumber.cbData = xmlSecBnGetSize(issuerSerialBn);
993 certInfo.SerialNumber.pbData = xmlSecBnGetData(issuerSerialBn);
994
995
996 /* CASE 1: UTF8, DN */
997 if (NULL == res) {
998 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
999 wcIssuer,
1000 CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR,
1001 &len);
1002 if(bdata != NULL) {
1003 certInfo.Issuer.cbData = len;
1004 certInfo.Issuer.pbData = bdata;
1005
1006 res = CertFindCertificateInStore(store,
1007 dwCertEncodingType,
1008 0,
1009 CERT_FIND_SUBJECT_CERT,
1010 &certInfo,
1011 NULL);
1012 xmlFree(bdata);
1013 }
1014 }
1015
1016 /* CASE 2: UTF8, REVERSE DN */
1017 if (NULL == res) {
1018 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
1019 wcIssuer,
1020 CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG | CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
1021 &len);
1022 if(bdata != NULL) {
1023 certInfo.Issuer.cbData = len;
1024 certInfo.Issuer.pbData = bdata;
1025
1026 res = CertFindCertificateInStore(store,
1027 dwCertEncodingType,
1028 0,
1029 CERT_FIND_SUBJECT_CERT,
1030 &certInfo,
1031 NULL);
1032 xmlFree(bdata);
1033 }
1034 }
1035
1036 /* CASE 3: UNICODE, DN */
1037 if (NULL == res) {
1038 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
1039 wcIssuer,
1040 CERT_OID_NAME_STR,
1041 &len);
1042 if(bdata != NULL) {
1043 certInfo.Issuer.cbData = len;
1044 certInfo.Issuer.pbData = bdata;
1045
1046 res = CertFindCertificateInStore(store,
1047 dwCertEncodingType,
1048 0,
1049 CERT_FIND_SUBJECT_CERT,
1050 &certInfo,
1051 NULL);
1052 xmlFree(bdata);
1053 }
1054 }
1055
1056 /* CASE 4: UNICODE, REVERSE DN */
1057 if (NULL == res) {
1058 bdata = xmlSecMSCryptoCertStrToName(dwCertEncodingType,
1059 wcIssuer,
1060 CERT_OID_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
1061 &len);
1062 if(bdata != NULL) {
1063 certInfo.Issuer.cbData = len;
1064 certInfo.Issuer.pbData = bdata;
1065
1066 res = CertFindCertificateInStore(store,
1067 dwCertEncodingType,
1068 0,
1069 CERT_FIND_SUBJECT_CERT,
1070 &certInfo,
1071 NULL);
1072 xmlFree(bdata);
1073 }
1074 }
1075
1076
1077 /* done */
1078 return (res);
1079 }
1080
1081 static LPTSTR
xmlSecMSCryptoX509GetCertName(const xmlChar * name)1082 xmlSecMSCryptoX509GetCertName(const xmlChar * name) {
1083 xmlChar *name2 = NULL;
1084 xmlChar *p = NULL;
1085 LPTSTR res = NULL;
1086
1087 xmlSecAssert2(name != 0, NULL);
1088
1089 /* MSCrypto doesn't support "emailAddress" attribute (see NSS as well).
1090 * This code is not bullet proof and may produce incorrect results if someone has
1091 * "emailAddress=" string in one of the fields, but it is best I can suggest to fix
1092 * this problem.
1093 */
1094 name2 = xmlStrdup(name);
1095 if(name2 == NULL) {
1096 xmlSecStrdupError(name, NULL);
1097 return(NULL);
1098 }
1099 while( (p = (xmlChar*)xmlStrstr(name2, BAD_CAST "emailAddress=")) != NULL) {
1100 memcpy(p, " E=", 13);
1101 }
1102
1103 /* get name */
1104 res = xmlSecWin32ConvertUtf8ToTstr(name2);
1105 if(res == NULL) {
1106 xmlSecInternalError("xmlSecWin32ConvertUtf8ToTstr", NULL);
1107 xmlFree(name2);
1108 return(NULL);
1109 }
1110
1111 /* done */
1112 xmlFree(name2);
1113 return(res);
1114 }
1115
1116 static PCCERT_CONTEXT
xmlSecMSCryptoX509FindCert(HCERTSTORE store,const xmlChar * subjectName,const xmlChar * issuerName,const xmlChar * issuerSerial,const xmlChar * ski)1117 xmlSecMSCryptoX509FindCert(HCERTSTORE store,
1118 const xmlChar *subjectName,
1119 const xmlChar *issuerName,
1120 const xmlChar *issuerSerial,
1121 const xmlChar *ski) {
1122 PCCERT_CONTEXT pCert = NULL;
1123 int ret;
1124
1125 xmlSecAssert2(store != 0, NULL);
1126
1127 if((pCert == NULL) && (NULL != subjectName)) {
1128 LPTSTR wcSubjectName = NULL;
1129
1130 /* get unicode subject name */
1131 wcSubjectName = xmlSecMSCryptoX509GetCertName(subjectName);
1132 if(wcSubjectName == NULL) {
1133 xmlSecInternalError("xmlSecMSCryptoX509GetCertName(subjectName)", NULL);
1134 return(NULL);
1135 }
1136
1137 /* search */
1138 pCert = xmlSecMSCryptoX509FindCertBySubject(store,
1139 wcSubjectName,
1140 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
1141
1142
1143 /* cleanup */
1144 xmlFree(wcSubjectName);
1145 }
1146
1147 if((pCert == NULL) && (NULL != issuerName) && (NULL != issuerSerial)) {
1148 xmlSecBn issuerSerialBn;
1149 LPTSTR wcIssuerName = NULL;
1150
1151 /* get serial number */
1152 ret = xmlSecBnInitialize(&issuerSerialBn, 0);
1153 if(ret < 0) {
1154 xmlSecInternalError("xmlSecBnInitialize", NULL);
1155 return(NULL);
1156 }
1157
1158 ret = xmlSecBnFromDecString(&issuerSerialBn, issuerSerial);
1159 if(ret < 0) {
1160 xmlSecInternalError("xmlSecBnInitialize", NULL);
1161 xmlSecBnFinalize(&issuerSerialBn);
1162 return(NULL);
1163 }
1164
1165 /* I have no clue why at a sudden a swap is needed to
1166 * convert from lsb... This code is purely based upon
1167 * trial and error :( WK
1168 */
1169 ret = xmlSecBnReverse(&issuerSerialBn);
1170 if(ret < 0) {
1171 xmlSecInternalError("xmlSecBnReverse", NULL);
1172 xmlSecBnFinalize(&issuerSerialBn);
1173 return(NULL);
1174 }
1175
1176 /* get issuer name */
1177 wcIssuerName = xmlSecMSCryptoX509GetCertName(issuerName);
1178 if(wcIssuerName == NULL) {
1179 xmlSecInternalError("xmlSecMSCryptoX509GetCertName(issuerName)", NULL);
1180 xmlSecBnFinalize(&issuerSerialBn);
1181 return(NULL);
1182 }
1183
1184 /* search */
1185 pCert = xmlSecMSCryptoX509FindCertByIssuer(store,
1186 wcIssuerName,
1187 &issuerSerialBn,
1188 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING);
1189
1190 xmlFree(wcIssuerName);
1191
1192 /* cleanup */
1193 xmlSecBnFinalize(&issuerSerialBn);
1194 }
1195
1196 if((pCert == NULL) && (ski != NULL)) {
1197 CRYPT_HASH_BLOB blob;
1198 xmlChar* binSki;
1199 int binSkiLen;
1200
1201 binSki = xmlStrdup(ski);
1202 if(binSki == NULL) {
1203 xmlSecStrdupError(ski, NULL);
1204 return (NULL);
1205 }
1206
1207 /* trick: base64 decode "in place" */
1208 binSkiLen = xmlSecBase64Decode(binSki, (xmlSecByte*)binSki, xmlStrlen(binSki));
1209 if(binSkiLen < 0) {
1210 xmlSecInternalError("xmlSecBase64Decode", NULL);
1211 xmlFree(binSki);
1212 return(NULL);
1213 }
1214
1215 blob.pbData = binSki;
1216 blob.cbData = binSkiLen;
1217 pCert = CertFindCertificateInStore(store,
1218 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
1219 0,
1220 CERT_FIND_KEY_IDENTIFIER,
1221 &blob,
1222 NULL);
1223 xmlFree(binSki);
1224 }
1225
1226 return(pCert);
1227 }
1228
1229
1230 /**
1231 * xmlSecMSCryptoX509GetNameString:
1232 * @pCertContext: the pointer to cert
1233 * @dwType: the type (see CertGetNameString description in MSDN)
1234 * @dwFlags: the flags (see CertGetNameString description in MSDN)
1235 * @pvTypePara: the type parameter (see CertGetNameString description in MSDN)
1236 *
1237 * Gets the name string for certificate (see CertGetNameString description in MSDN).
1238 *
1239 * Returns: name string (should be freed with xmlFree) or NULL if failed.
1240 */
1241 xmlChar *
xmlSecMSCryptoX509GetNameString(PCCERT_CONTEXT pCertContext,DWORD dwType,DWORD dwFlags,void * pvTypePara)1242 xmlSecMSCryptoX509GetNameString(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void *pvTypePara) {
1243 LPTSTR name = NULL;
1244 xmlChar * res = NULL;
1245 DWORD dwSize;
1246
1247 xmlSecAssert2(pCertContext != NULL, NULL);
1248
1249 /* get size first */
1250 dwSize = CertGetNameString(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
1251 if(dwSize <= 0) {
1252 xmlSecMSCryptoError("CertGetNameString", NULL);
1253 return (NULL);
1254 }
1255
1256 /* allocate buffer */
1257 name = (LPTSTR)xmlMalloc(sizeof(TCHAR) * (dwSize + 1));
1258 if(name == NULL) {
1259 xmlSecMallocError(sizeof(TCHAR) * (dwSize + 1), NULL);
1260 return (NULL);
1261 }
1262
1263 /* actually get the name */
1264 dwSize = CertGetNameString(pCertContext, dwType, dwFlags, pvTypePara, name, dwSize);
1265 if(dwSize <= 0) {
1266 xmlSecMSCryptoError("CertGetNameString", NULL);
1267 xmlFree(name);
1268 return (NULL);
1269 }
1270
1271 res = xmlSecWin32ConvertTstrToUtf8(name);
1272 if(res == NULL) {
1273 xmlSecInternalError("xmlSecWin32ConvertTstrToUtf8", NULL);
1274 xmlFree(name);
1275 return (NULL);
1276 }
1277 /* done */
1278 xmlFree(name);
1279 return (res);
1280 }
1281
1282 #endif /* XMLSEC_NO_X509 */
1283
1284
1285