7 * This is free software; see Copyright file in the source
8 * distribution for preciese wording.
10 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
14 #ifndef XMLSEC_NO_X509
22 #include <libxml/tree.h>
23 #include <openssl/evp.h>
24 #include <openssl/x509.h>
25 #include <openssl/x509_vfy.h>
26 #include <openssl/x509v3.h>
28 #include <xmlsec/xmlsec.h>
29 #include <xmlsec/xmltree.h>
30 #include <xmlsec/keys.h>
31 #include <xmlsec/keyinfo.h>
32 #include <xmlsec/keysmngr.h>
33 #include <xmlsec/base64.h>
34 #include <xmlsec/errors.h>
36 #include <xmlsec/openssl/crypto.h>
37 #include <xmlsec/openssl/evp.h>
38 #include <xmlsec/openssl/x509.h>
40 /**************************************************************************
42 * Internal OpenSSL X509 store CTX
44 *************************************************************************/
45 typedef struct _xmlSecOpenSSLX509StoreCtx xmlSecOpenSSLX509StoreCtx,
46 *xmlSecOpenSSLX509StoreCtxPtr;
47 struct _xmlSecOpenSSLX509StoreCtx {
49 STACK_OF(X509)* untrusted;
50 STACK_OF(X509_CRL)* crls;
52 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
53 X509_VERIFY_PARAM * vpm;
54 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
57 /****************************************************************************
59 * xmlSecOpenSSLKeyDataStoreX509Id:
61 * xmlSecOpenSSLX509StoreCtx is located after xmlSecTransform
63 ***************************************************************************/
64 #define xmlSecOpenSSLX509StoreGetCtx(store) \
65 ((xmlSecOpenSSLX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
66 sizeof(xmlSecKeyDataStoreKlass)))
67 #define xmlSecOpenSSLX509StoreSize \
68 (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecOpenSSLX509StoreCtx))
70 static int xmlSecOpenSSLX509StoreInitialize (xmlSecKeyDataStorePtr store);
71 static void xmlSecOpenSSLX509StoreFinalize (xmlSecKeyDataStorePtr store);
73 static xmlSecKeyDataStoreKlass xmlSecOpenSSLX509StoreKlass = {
74 sizeof(xmlSecKeyDataStoreKlass),
75 xmlSecOpenSSLX509StoreSize,
78 xmlSecNameX509Store, /* const xmlChar* name; */
80 /* constructors/destructor */
81 xmlSecOpenSSLX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
82 xmlSecOpenSSLX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
84 /* reserved for the future */
85 NULL, /* void* reserved0; */
86 NULL, /* void* reserved1; */
89 static int xmlSecOpenSSLX509VerifyCRL (X509_STORE* xst,
91 static X509* xmlSecOpenSSLX509FindCert (STACK_OF(X509) *certs,
94 xmlChar *issuerSerial,
96 static X509* xmlSecOpenSSLX509FindNextChainCert (STACK_OF(X509) *chain,
98 static int xmlSecOpenSSLX509VerifyCertAgainstCrls (STACK_OF(X509_CRL) *crls,
100 static X509_NAME* xmlSecOpenSSLX509NameRead (xmlSecByte *str,
102 static int xmlSecOpenSSLX509NameStringRead (xmlSecByte **str,
107 int ingoreTrailingSpaces);
108 static int xmlSecOpenSSLX509NamesCompare (X509_NAME *a,
110 static int xmlSecOpenSSLX509_NAME_cmp (const X509_NAME *a,
112 static int xmlSecOpenSSLX509_NAME_ENTRY_cmp (const X509_NAME_ENTRY **a,
113 const X509_NAME_ENTRY **b);
116 * xmlSecOpenSSLX509StoreGetKlass:
118 * The OpenSSL X509 certificates key data store klass.
120 * Returns: pointer to OpenSSL X509 certificates key data store klass.
123 xmlSecOpenSSLX509StoreGetKlass(void) {
124 return(&xmlSecOpenSSLX509StoreKlass);
128 * xmlSecOpenSSLX509StoreFindCert:
129 * @store: the pointer to X509 key data store klass.
130 * @subjectName: the desired certificate name.
131 * @issuerName: the desired certificate issuer name.
132 * @issuerSerial: the desired certificate issuer serial number.
133 * @ski: the desired certificate SKI.
134 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
136 * Searches @store for a certificate that matches given criteria.
138 * Returns: pointer to found certificate or NULL if certificate is not found
139 * or an error occurs.
142 xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
143 xmlChar *issuerName, xmlChar *issuerSerial,
144 xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
145 xmlSecOpenSSLX509StoreCtxPtr ctx;
148 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
149 xmlSecAssert2(keyInfoCtx != NULL, NULL);
151 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
152 xmlSecAssert2(ctx != NULL, NULL);
154 if((res == NULL) && (ctx->untrusted != NULL)) {
155 res = xmlSecOpenSSLX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
161 * xmlSecOpenSSLX509StoreVerify:
162 * @store: the pointer to X509 key data store klass.
163 * @certs: the untrusted certificates stack.
164 * @crls: the crls stack.
165 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
167 * Verifies @certs list.
169 * Returns: pointer to the first verified certificate from @certs.
172 xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs,
173 XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) {
174 xmlSecOpenSSLX509StoreCtxPtr ctx;
175 STACK_OF(X509)* certs2 = NULL;
176 STACK_OF(X509_CRL)* crls2 = NULL;
179 X509 *err_cert = NULL;
185 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
186 xmlSecAssert2(certs != NULL, NULL);
187 xmlSecAssert2(keyInfoCtx != NULL, NULL);
189 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
190 xmlSecAssert2(ctx != NULL, NULL);
191 xmlSecAssert2(ctx->xst != NULL, NULL);
194 certs2 = sk_X509_dup(certs);
196 xmlSecError(XMLSEC_ERRORS_HERE,
197 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
199 XMLSEC_ERRORS_R_CRYPTO_FAILED,
200 XMLSEC_ERRORS_NO_MESSAGE);
204 /* add untrusted certs from the store */
205 if(ctx->untrusted != NULL) {
206 for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) {
207 ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i));
209 xmlSecError(XMLSEC_ERRORS_HERE,
210 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
212 XMLSEC_ERRORS_R_CRYPTO_FAILED,
213 XMLSEC_ERRORS_NO_MESSAGE);
219 /* dup crls but remove all non-verified */
221 crls2 = sk_X509_CRL_dup(crls);
223 xmlSecError(XMLSEC_ERRORS_HERE,
224 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
226 XMLSEC_ERRORS_R_CRYPTO_FAILED,
227 XMLSEC_ERRORS_NO_MESSAGE);
231 for(i = 0; i < sk_X509_CRL_num(crls2); ) {
232 ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i));
235 } else if(ret == 0) {
236 sk_X509_CRL_delete(crls2, i);
238 xmlSecError(XMLSEC_ERRORS_HERE,
239 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
240 "xmlSecOpenSSLX509VerifyCRL",
241 XMLSEC_ERRORS_R_XMLSEC_FAILED,
242 XMLSEC_ERRORS_NO_MESSAGE);
248 /* remove all revoked certs */
249 for(i = 0; i < sk_X509_num(certs2);) {
250 cert = sk_X509_value(certs2, i);
253 ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert);
255 sk_X509_delete(certs2, i);
257 } else if(ret != 1) {
258 xmlSecError(XMLSEC_ERRORS_HERE,
259 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
260 "xmlSecOpenSSLX509VerifyCertAgainstCrls",
261 XMLSEC_ERRORS_R_XMLSEC_FAILED,
262 XMLSEC_ERRORS_NO_MESSAGE);
267 if(ctx->crls != NULL) {
268 ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert);
270 sk_X509_delete(certs2, i);
272 } else if(ret != 1) {
273 xmlSecError(XMLSEC_ERRORS_HERE,
274 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
275 "xmlSecOpenSSLX509VerifyCertAgainstCrls",
276 XMLSEC_ERRORS_R_XMLSEC_FAILED,
277 XMLSEC_ERRORS_NO_MESSAGE);
284 /* get one cert after another and try to verify */
285 for(i = 0; i < sk_X509_num(certs2); ++i) {
286 cert = sk_X509_value(certs2, i);
287 if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) {
290 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
291 X509_VERIFY_PARAM * vpm = NULL;
292 unsigned long vpm_flags = 0;
294 vpm = X509_VERIFY_PARAM_new();
296 xmlSecError(XMLSEC_ERRORS_HERE,
297 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
298 "X509_VERIFY_PARAM_new",
299 XMLSEC_ERRORS_R_CRYPTO_FAILED,
300 XMLSEC_ERRORS_NO_MESSAGE);
303 vpm_flags = vpm->flags;
305 vpm_flags &= (~X509_V_FLAG_X509_STRICT);
307 vpm_flags &= (~X509_V_FLAG_CRL_CHECK);
309 X509_VERIFY_PARAM_set_depth(vpm, 9);
310 X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
311 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
313 X509_STORE_CTX_init (&xsc, ctx->xst, cert, certs2);
315 if(keyInfoCtx->certsVerificationTime > 0) {
316 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
317 vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
318 X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
319 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
320 X509_STORE_CTX_set_time(&xsc, 0, keyInfoCtx->certsVerificationTime);
323 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
324 X509_STORE_CTX_set0_param(&xsc, vpm);
325 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
327 ret = X509_verify_cert(&xsc);
328 err_cert = X509_STORE_CTX_get_current_cert(&xsc);
329 err = X509_STORE_CTX_get_error(&xsc);
330 depth = X509_STORE_CTX_get_error_depth(&xsc);
331 X509_STORE_CTX_cleanup (&xsc);
333 if(ret != 1 && keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN){
335 keyInfoCtx->flags2 |= XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN;
345 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
346 err_msg = X509_verify_cert_error_string(err);
347 xmlSecError(XMLSEC_ERRORS_HERE,
348 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
350 XMLSEC_ERRORS_R_CRYPTO_FAILED,
351 "subj=%s;err=%d;msg=%s",
352 xmlSecErrorsSafeString(buf),
354 xmlSecErrorsSafeString(err_msg));
356 } else if(ret == 0) {
360 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
361 err_msg = X509_verify_cert_error_string(err);
362 xmlSecError(XMLSEC_ERRORS_HERE,
363 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
365 XMLSEC_ERRORS_R_CRYPTO_FAILED,
366 "subj=%s;err=%d;msg=%s",
367 xmlSecErrorsSafeString(buf),
369 xmlSecErrorsSafeString(err_msg));
374 /* if we came here then we found nothing. do we have any error? */
375 if((err != 0) && (err_cert != NULL)) {
378 err_msg = X509_verify_cert_error_string(err);
380 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
381 X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf);
382 xmlSecError(XMLSEC_ERRORS_HERE,
383 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
385 XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
386 "err=%d;msg=%s;issuer=%s",
388 xmlSecErrorsSafeString(err_msg),
389 xmlSecErrorsSafeString(buf));
391 case X509_V_ERR_CERT_NOT_YET_VALID:
392 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
393 xmlSecError(XMLSEC_ERRORS_HERE,
394 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
396 XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
397 "err=%d;msg=%s", err,
398 xmlSecErrorsSafeString(err_msg));
400 case X509_V_ERR_CERT_HAS_EXPIRED:
401 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
402 xmlSecError(XMLSEC_ERRORS_HERE,
403 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
405 XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
406 "err=%d;msg=%s", err,
407 xmlSecErrorsSafeString(err_msg));
410 xmlSecError(XMLSEC_ERRORS_HERE,
411 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
413 XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
414 "err=%d;msg=%s", err,
415 xmlSecErrorsSafeString(err_msg));
421 sk_X509_free(certs2);
424 sk_X509_CRL_free(crls2);
430 * xmlSecOpenSSLX509StoreAdoptCert:
431 * @store: the pointer to X509 key data store klass.
432 * @cert: the pointer to OpenSSL X509 certificate.
433 * @type: the certificate type (trusted/untrusted).
435 * Adds trusted (root) or untrusted certificate to the store.
437 * Returns: 0 on success or a negative value if an error occurs.
440 xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store, X509* cert, xmlSecKeyDataType type) {
441 xmlSecOpenSSLX509StoreCtxPtr ctx;
444 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
445 xmlSecAssert2(cert != NULL, -1);
447 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
448 xmlSecAssert2(ctx != NULL, -1);
450 if((type & xmlSecKeyDataTypeTrusted) != 0) {
451 xmlSecAssert2(ctx->xst != NULL, -1);
453 ret = X509_STORE_add_cert(ctx->xst, cert);
455 xmlSecError(XMLSEC_ERRORS_HERE,
456 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
457 "X509_STORE_add_cert",
458 XMLSEC_ERRORS_R_CRYPTO_FAILED,
459 XMLSEC_ERRORS_NO_MESSAGE);
462 /* add cert increments the reference */
465 xmlSecAssert2(ctx->untrusted != NULL, -1);
467 ret = sk_X509_push(ctx->untrusted, cert);
469 xmlSecError(XMLSEC_ERRORS_HERE,
470 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
472 XMLSEC_ERRORS_R_CRYPTO_FAILED,
473 XMLSEC_ERRORS_NO_MESSAGE);
481 * xmlSecOpenSSLX509StoreAdoptCrl:
482 * @store: the pointer to X509 key data store klass.
483 * @crl: the pointer to OpenSSL X509_CRL.
485 * Adds X509 CRL to the store.
487 * Returns: 0 on success or a negative value if an error occurs.
490 xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store, X509_CRL* crl) {
491 xmlSecOpenSSLX509StoreCtxPtr ctx;
494 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
495 xmlSecAssert2(crl != NULL, -1);
497 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
498 xmlSecAssert2(ctx != NULL, -1);
499 xmlSecAssert2(ctx->crls != NULL, -1);
501 ret = sk_X509_CRL_push(ctx->crls, crl);
503 xmlSecError(XMLSEC_ERRORS_HERE,
504 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
506 XMLSEC_ERRORS_R_CRYPTO_FAILED,
507 XMLSEC_ERRORS_NO_MESSAGE);
515 * xmlSecOpenSSLX509StoreAddCertsPath:
516 * @store: the pointer to OpenSSL x509 store.
517 * @path: the path to the certs dir.
519 * Adds all certs in the @path to the list of trusted certs
522 * Returns: 0 on success or a negative value otherwise.
525 xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store, const char *path) {
526 xmlSecOpenSSLX509StoreCtxPtr ctx;
527 X509_LOOKUP *lookup = NULL;
529 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
530 xmlSecAssert2(path != NULL, -1);
532 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
533 xmlSecAssert2(ctx != NULL, -1);
534 xmlSecAssert2(ctx->xst != NULL, -1);
536 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
538 xmlSecError(XMLSEC_ERRORS_HERE,
539 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
540 "X509_STORE_add_lookup",
541 XMLSEC_ERRORS_R_CRYPTO_FAILED,
542 XMLSEC_ERRORS_NO_MESSAGE);
545 if(!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
546 xmlSecError(XMLSEC_ERRORS_HERE,
547 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
548 "X509_LOOKUP_add_dir",
549 XMLSEC_ERRORS_R_CRYPTO_FAILED,
551 xmlSecErrorsSafeString(path)
559 * xmlSecOpenSSLX509StoreAddCertsFile:
560 * @store: the pointer to OpenSSL x509 store.
561 * @file: the certs file.
563 * Adds all certs in @file to the list of trusted certs
564 * in @store. It is possible for @file to contain multiple certs.
566 * Returns: 0 on success or a negative value otherwise.
569 xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store, const char *file) {
570 xmlSecOpenSSLX509StoreCtxPtr ctx;
571 X509_LOOKUP *lookup = NULL;
573 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
574 xmlSecAssert2(file != NULL, -1);
576 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
577 xmlSecAssert2(ctx != NULL, -1);
578 xmlSecAssert2(ctx->xst != NULL, -1);
580 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_file());
582 xmlSecError(XMLSEC_ERRORS_HERE,
583 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
584 "X509_STORE_add_lookup",
585 XMLSEC_ERRORS_R_CRYPTO_FAILED,
586 XMLSEC_ERRORS_NO_MESSAGE);
589 if(!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) {
590 xmlSecError(XMLSEC_ERRORS_HERE,
591 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
592 "X509_LOOKUP_load_file",
593 XMLSEC_ERRORS_R_CRYPTO_FAILED,
595 xmlSecErrorsSafeString(file)
603 xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) {
605 X509_LOOKUP *lookup = NULL;
607 xmlSecOpenSSLX509StoreCtxPtr ctx;
608 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
610 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
611 xmlSecAssert2(ctx != NULL, -1);
613 memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
615 ctx->xst = X509_STORE_new();
616 if(ctx->xst == NULL) {
617 xmlSecError(XMLSEC_ERRORS_HERE,
618 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
620 XMLSEC_ERRORS_R_CRYPTO_FAILED,
621 XMLSEC_ERRORS_NO_MESSAGE);
625 if(!X509_STORE_set_default_paths(ctx->xst)) {
626 xmlSecError(XMLSEC_ERRORS_HERE,
627 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
628 "X509_STORE_set_default_paths",
629 XMLSEC_ERRORS_R_CRYPTO_FAILED,
630 XMLSEC_ERRORS_NO_MESSAGE);
635 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
637 xmlSecError(XMLSEC_ERRORS_HERE,
638 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
639 "X509_STORE_add_lookup",
640 XMLSEC_ERRORS_R_CRYPTO_FAILED,
641 XMLSEC_ERRORS_NO_MESSAGE);
645 path = xmlSecOpenSSLGetDefaultTrustedCertsFolder();
647 if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) {
648 xmlSecError(XMLSEC_ERRORS_HERE,
649 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
650 "X509_LOOKUP_add_dir",
651 XMLSEC_ERRORS_R_CRYPTO_FAILED,
653 xmlSecErrorsSafeString(path)
658 if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) {
659 xmlSecError(XMLSEC_ERRORS_HERE,
660 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
661 "X509_LOOKUP_add_dir",
662 XMLSEC_ERRORS_R_CRYPTO_FAILED,
663 XMLSEC_ERRORS_NO_MESSAGE
669 ctx->untrusted = sk_X509_new_null();
670 if(ctx->untrusted == NULL) {
671 xmlSecError(XMLSEC_ERRORS_HERE,
672 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
674 XMLSEC_ERRORS_R_CRYPTO_FAILED,
675 XMLSEC_ERRORS_NO_MESSAGE);
679 ctx->crls = sk_X509_CRL_new_null();
680 if(ctx->crls == NULL) {
681 xmlSecError(XMLSEC_ERRORS_HERE,
682 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
683 "sk_X509_CRL_new_null",
684 XMLSEC_ERRORS_R_CRYPTO_FAILED,
685 XMLSEC_ERRORS_NO_MESSAGE);
689 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
690 ctx->vpm = X509_VERIFY_PARAM_new();
691 if(ctx->vpm == NULL) {
692 xmlSecError(XMLSEC_ERRORS_HERE,
693 xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
694 "X509_VERIFY_PARAM_new",
695 XMLSEC_ERRORS_R_CRYPTO_FAILED,
696 XMLSEC_ERRORS_NO_MESSAGE);
699 X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */
700 X509_STORE_set1_param(ctx->xst, ctx->vpm);
702 #else /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
703 ctx->xst->depth = 9; /* the default cert verification path in openssl */
704 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
710 xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store) {
711 xmlSecOpenSSLX509StoreCtxPtr ctx;
712 xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId));
714 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
715 xmlSecAssert(ctx != NULL);
718 if(ctx->xst != NULL) {
719 X509_STORE_free(ctx->xst);
721 if(ctx->untrusted != NULL) {
722 sk_X509_pop_free(ctx->untrusted, X509_free);
724 if(ctx->crls != NULL) {
725 sk_X509_CRL_pop_free(ctx->crls, X509_CRL_free);
727 #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
728 if(ctx->vpm != NULL) {
729 X509_VERIFY_PARAM_free(ctx->vpm);
731 #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
733 memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
737 /*****************************************************************************
739 * Low-level x509 functions
741 *****************************************************************************/
743 xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
749 xmlSecAssert2(xst != NULL, -1);
750 xmlSecAssert2(crl != NULL, -1);
752 X509_STORE_CTX_init(&xsc, xst, NULL, NULL);
753 ret = X509_STORE_get_by_subject(&xsc, X509_LU_X509,
754 X509_CRL_get_issuer(crl), &xobj);
756 xmlSecError(XMLSEC_ERRORS_HERE,
758 "X509_STORE_get_by_subject",
759 XMLSEC_ERRORS_R_CRYPTO_FAILED,
760 XMLSEC_ERRORS_NO_MESSAGE);
763 pkey = X509_get_pubkey(xobj.data.x509);
764 X509_OBJECT_free_contents(&xobj);
766 xmlSecError(XMLSEC_ERRORS_HERE,
769 XMLSEC_ERRORS_R_CRYPTO_FAILED,
770 XMLSEC_ERRORS_NO_MESSAGE);
773 ret = X509_CRL_verify(crl, pkey);
776 xmlSecError(XMLSEC_ERRORS_HERE,
779 XMLSEC_ERRORS_R_CRYPTO_FAILED,
780 XMLSEC_ERRORS_NO_MESSAGE);
782 X509_STORE_CTX_cleanup (&xsc);
783 return((ret == 1) ? 1 : 0);
787 xmlSecOpenSSLX509FindCert(STACK_OF(X509) *certs, xmlChar *subjectName,
788 xmlChar *issuerName, xmlChar *issuerSerial,
793 xmlSecAssert2(certs != NULL, NULL);
795 /* todo: may be this is not the fastest way to search certs */
796 if(subjectName != NULL) {
800 nm = xmlSecOpenSSLX509NameRead(subjectName, xmlStrlen(subjectName));
802 xmlSecError(XMLSEC_ERRORS_HERE,
804 "xmlSecOpenSSLX509NameRead",
805 XMLSEC_ERRORS_R_XMLSEC_FAILED,
807 xmlSecErrorsSafeString(subjectName));
811 for(i = 0; i < sk_X509_num(certs); ++i) {
812 cert = sk_X509_value(certs, i);
813 subj = X509_get_subject_name(cert);
814 if(xmlSecOpenSSLX509NamesCompare(nm, subj) == 0) {
820 } else if((issuerName != NULL) && (issuerSerial != NULL)) {
824 ASN1_INTEGER *serial;
826 nm = xmlSecOpenSSLX509NameRead(issuerName, xmlStrlen(issuerName));
828 xmlSecError(XMLSEC_ERRORS_HERE,
830 "xmlSecOpenSSLX509NameRead",
831 XMLSEC_ERRORS_R_XMLSEC_FAILED,
833 xmlSecErrorsSafeString(issuerName));
839 xmlSecError(XMLSEC_ERRORS_HERE,
842 XMLSEC_ERRORS_R_CRYPTO_FAILED,
843 XMLSEC_ERRORS_NO_MESSAGE);
847 if(BN_dec2bn(&bn, (char*)issuerSerial) == 0) {
848 xmlSecError(XMLSEC_ERRORS_HERE,
851 XMLSEC_ERRORS_R_CRYPTO_FAILED,
852 XMLSEC_ERRORS_NO_MESSAGE);
858 serial = BN_to_ASN1_INTEGER(bn, NULL);
860 xmlSecError(XMLSEC_ERRORS_HERE,
862 "BN_to_ASN1_INTEGER",
863 XMLSEC_ERRORS_R_CRYPTO_FAILED,
864 XMLSEC_ERRORS_NO_MESSAGE);
872 for(i = 0; i < sk_X509_num(certs); ++i) {
873 cert = sk_X509_value(certs, i);
874 if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serial) != 0) {
877 issuer = X509_get_issuer_name(cert);
878 if(xmlSecOpenSSLX509NamesCompare(nm, issuer) == 0) {
879 ASN1_INTEGER_free(serial);
886 ASN1_INTEGER_free(serial);
887 } else if(ski != NULL) {
891 ASN1_OCTET_STRING *keyId;
893 /* our usual trick with base64 decode */
894 len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski));
896 xmlSecError(XMLSEC_ERRORS_HERE,
898 "xmlSecBase64Decode",
899 XMLSEC_ERRORS_R_XMLSEC_FAILED,
901 xmlSecErrorsSafeString(ski));
904 for(i = 0; i < sk_X509_num(certs); ++i) {
905 cert = sk_X509_value(certs, i);
906 index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
907 if((index >= 0) && (ext = X509_get_ext(cert, index))) {
908 keyId = X509V3_EXT_d2i(ext);
909 if((keyId != NULL) && (keyId->length == len) &&
910 (memcmp(keyId->data, ski, len) == 0)) {
911 M_ASN1_OCTET_STRING_free(keyId);
914 M_ASN1_OCTET_STRING_free(keyId);
923 xmlSecOpenSSLX509FindNextChainCert(STACK_OF(X509) *chain, X509 *cert) {
924 unsigned long certSubjHash;
927 xmlSecAssert2(chain != NULL, NULL);
928 xmlSecAssert2(cert != NULL, NULL);
930 certSubjHash = X509_subject_name_hash(cert);
931 for(i = 0; i < sk_X509_num(chain); ++i) {
932 if((sk_X509_value(chain, i) != cert) &&
933 (X509_issuer_name_hash(sk_X509_value(chain, i)) == certSubjHash)) {
935 return(sk_X509_value(chain, i));
942 xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF(X509_CRL) *crls, X509* cert) {
944 X509_CRL *crl = NULL;
945 X509_REVOKED *revoked;
949 xmlSecAssert2(crls != NULL, -1);
950 xmlSecAssert2(cert != NULL, -1);
953 * Try to retrieve a CRL corresponding to the issuer of
954 * the current certificate
956 n = sk_X509_CRL_num(crls);
957 for(i = 0; i < n; i++) {
958 crl = sk_X509_CRL_value(crls, i);
963 issuer = X509_CRL_get_issuer(crl);
964 if(xmlSecOpenSSLX509NamesCompare(X509_CRL_get_issuer(crl), issuer) == 0) {
968 if((i >= n) || (crl == NULL)){
969 /* no crls for this issuer */
974 * Check date of CRL to make sure it's not expired
976 ret = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
983 * Check if the current certificate is revoked by this CRL
985 n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
986 for (i = 0; i < n; i++) {
987 revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
988 if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(cert)) == 0) {
989 xmlSecError(XMLSEC_ERRORS_HERE,
992 XMLSEC_ERRORS_R_CERT_REVOKED,
993 XMLSEC_ERRORS_NO_MESSAGE);
1001 xmlSecOpenSSLX509NameRead(xmlSecByte *str, int len) {
1002 xmlSecByte name[256];
1003 xmlSecByte value[256];
1004 int nameLen, valueLen;
1006 int type = MBSTRING_ASC;
1008 xmlSecAssert2(str != NULL, NULL);
1010 nm = X509_NAME_new();
1012 xmlSecError(XMLSEC_ERRORS_HERE,
1015 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1016 XMLSEC_ERRORS_NO_MESSAGE);
1021 /* skip spaces after comma or semicolon */
1022 while((len > 0) && isspace(*str)) {
1026 nameLen = xmlSecOpenSSLX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
1028 xmlSecError(XMLSEC_ERRORS_HERE,
1030 "xmlSecOpenSSLX509NameStringRead",
1031 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1032 XMLSEC_ERRORS_NO_MESSAGE);
1036 name[nameLen] = '\0';
1039 if((*str) == '\"') {
1041 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
1042 value, sizeof(value), '"', 1);
1044 xmlSecError(XMLSEC_ERRORS_HERE,
1046 "xmlSecOpenSSLX509NameStringRead",
1047 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1048 XMLSEC_ERRORS_NO_MESSAGE);
1054 if((len <= 0) || ((*str) != '\"')) {
1055 xmlSecError(XMLSEC_ERRORS_HERE,
1058 XMLSEC_ERRORS_R_INVALID_DATA,
1059 "quote is expected:%s",
1060 xmlSecErrorsSafeString(str));
1066 /* skip spaces before comma or semicolon */
1067 while((len > 0) && isspace(*str)) {
1070 if((len > 0) && ((*str) != ',')) {
1071 xmlSecError(XMLSEC_ERRORS_HERE,
1074 XMLSEC_ERRORS_R_INVALID_DATA,
1075 "comma is expected:%s",
1076 xmlSecErrorsSafeString(str));
1083 type = MBSTRING_ASC;
1084 } else if((*str) == '#') {
1085 /* TODO: read octect values */
1086 xmlSecError(XMLSEC_ERRORS_HERE,
1089 XMLSEC_ERRORS_R_INVALID_DATA,
1090 "reading octect values is not implemented yet");
1094 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
1095 value, sizeof(value), ',', 1);
1097 xmlSecError(XMLSEC_ERRORS_HERE,
1099 "xmlSecOpenSSLX509NameStringRead",
1100 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1101 XMLSEC_ERRORS_NO_MESSAGE);
1105 type = MBSTRING_ASC;
1110 value[valueLen] = '\0';
1114 X509_NAME_add_entry_by_txt(nm, (char*)name, type, value, valueLen, -1, 0);
1121 xmlSecOpenSSLX509NameStringRead(xmlSecByte **str, int *strLen,
1122 xmlSecByte *res, int resLen,
1123 xmlSecByte delim, int ingoreTrailingSpaces) {
1124 xmlSecByte *p, *q, *nonSpace;
1126 xmlSecAssert2(str != NULL, -1);
1127 xmlSecAssert2(strLen != NULL, -1);
1128 xmlSecAssert2(res != NULL, -1);
1132 while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) {
1134 if(ingoreTrailingSpaces && !isspace(*p)) nonSpace = q;
1139 if(xmlSecIsHex((*p))) {
1140 if((p - (*str) + 1) >= (*strLen)) {
1141 xmlSecError(XMLSEC_ERRORS_HERE,
1144 XMLSEC_ERRORS_R_INVALID_DATA,
1145 "two hex digits expected");
1148 *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]);
1151 if(((++p) - (*str)) >= (*strLen)) {
1152 xmlSecError(XMLSEC_ERRORS_HERE,
1155 XMLSEC_ERRORS_R_INVALID_DATA,
1156 "escaped symbol missed");
1163 if(((p - (*str)) < (*strLen)) && ((*p) != delim)) {
1164 xmlSecError(XMLSEC_ERRORS_HERE,
1167 XMLSEC_ERRORS_R_INVALID_SIZE,
1168 "buffer is too small");
1171 (*strLen) -= (p - (*str));
1173 return((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res);
1177 int xmlSecOpenSSLX509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) {
1179 const X509_NAME_ENTRY *na,*nb;
1181 xmlSecAssert2(a != NULL, -1);
1182 xmlSecAssert2(b != NULL, 1);
1184 if (sk_X509_NAME_ENTRY_num(a->entries) != sk_X509_NAME_ENTRY_num(b->entries)) {
1185 return sk_X509_NAME_ENTRY_num(a->entries) - sk_X509_NAME_ENTRY_num(b->entries);
1188 for (i=sk_X509_NAME_ENTRY_num(a->entries)-1; i>=0; i--) {
1189 na=sk_X509_NAME_ENTRY_value(a->entries,i);
1190 nb=sk_X509_NAME_ENTRY_value(b->entries,i);
1192 ret = xmlSecOpenSSLX509_NAME_ENTRY_cmp(&na, &nb);
1203 * xmlSecOpenSSLX509NamesCompare:
1205 * We have to sort X509_NAME entries to get correct results.
1206 * This is ugly but OpenSSL does not support it
1209 xmlSecOpenSSLX509NamesCompare(X509_NAME *a, X509_NAME *b) {
1210 X509_NAME *a1 = NULL;
1211 X509_NAME *b1 = NULL;
1214 xmlSecAssert2(a != NULL, -1);
1215 xmlSecAssert2(b != NULL, 1);
1217 a1 = X509_NAME_dup(a);
1219 xmlSecError(XMLSEC_ERRORS_HERE,
1222 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1223 XMLSEC_ERRORS_NO_MESSAGE);
1226 b1 = X509_NAME_dup(b);
1228 xmlSecError(XMLSEC_ERRORS_HERE,
1231 XMLSEC_ERRORS_R_CRYPTO_FAILED,
1232 XMLSEC_ERRORS_NO_MESSAGE);
1237 sk_X509_NAME_ENTRY_set_cmp_func(a1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1238 sk_X509_NAME_ENTRY_sort(a1->entries);
1239 sk_X509_NAME_ENTRY_set_cmp_func(b1->entries, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1240 sk_X509_NAME_ENTRY_sort(b1->entries);
1242 /* actually compare */
1243 ret = xmlSecOpenSSLX509_NAME_cmp(a1, b1);
1252 xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY **a, const X509_NAME_ENTRY **b) {
1255 xmlSecAssert2(a != NULL, -1);
1256 xmlSecAssert2(b != NULL, 1);
1257 xmlSecAssert2((*a) != NULL, -1);
1258 xmlSecAssert2((*b) != NULL, 1);
1260 /* first compare values */
1261 if(((*a)->value == NULL) && ((*b)->value != NULL)) {
1263 } else if(((*a)->value != NULL) && ((*b)->value == NULL)) {
1265 } else if(((*a)->value == NULL) && ((*b)->value == NULL)) {
1269 ret = (*a)->value->length - (*b)->value->length;
1274 ret = memcmp((*a)->value->data, (*b)->value->data, (*a)->value->length);
1279 /* next compare names */
1280 return(OBJ_cmp((*a)->object, (*b)->object));
1284 #endif /* XMLSEC_NO_X509 */