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) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9 */
10 /**
11 * SECTION:x509vfy
12 * @Short_description: X509 certificates verification support functions for OpenSSL.
13 * @Stability: Private
14 *
15 */
16
17 #include "globals.h"
18
19 #ifndef XMLSEC_NO_X509
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <errno.h>
26
27 #include <libxml/tree.h>
28
29 #include <xmlsec/xmlsec.h>
30 #include <xmlsec/xmltree.h>
31 #include <xmlsec/keys.h>
32 #include <xmlsec/keyinfo.h>
33 #include <xmlsec/keysmngr.h>
34 #include <xmlsec/base64.h>
35 #include <xmlsec/errors.h>
36
37 #include <xmlsec/openssl/crypto.h>
38 #include <xmlsec/openssl/evp.h>
39 #include <xmlsec/openssl/x509.h>
40 #include "openssl_compat.h"
41
42 #include <openssl/evp.h>
43 #include <openssl/x509.h>
44 #include <openssl/x509_vfy.h>
45 #include <openssl/x509v3.h>
46
47 #ifdef OPENSSL_IS_BORINGSSL
48 typedef size_t x509_size_t;
49 #else /* OPENSSL_IS_BORINGSSL */
50 typedef int x509_size_t;
51 #endif /* OPENSSL_IS_BORINGSSL */
52
53 /**************************************************************************
54 *
55 * Internal OpenSSL X509 store CTX
56 *
57 *************************************************************************/
58 typedef struct _xmlSecOpenSSLX509StoreCtx xmlSecOpenSSLX509StoreCtx,
59 *xmlSecOpenSSLX509StoreCtxPtr;
60 struct _xmlSecOpenSSLX509StoreCtx {
61 X509_STORE* xst;
62 STACK_OF(X509)* untrusted;
63 STACK_OF(X509_CRL)* crls;
64 X509_VERIFY_PARAM * vpm;
65 };
66
67 /****************************************************************************
68 *
69 * xmlSecOpenSSLKeyDataStoreX509Id:
70 *
71 * xmlSecOpenSSLX509StoreCtx is located after xmlSecTransform
72 *
73 ***************************************************************************/
74 #define xmlSecOpenSSLX509StoreGetCtx(store) \
75 ((xmlSecOpenSSLX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
76 sizeof(xmlSecKeyDataStoreKlass)))
77 #define xmlSecOpenSSLX509StoreSize \
78 (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecOpenSSLX509StoreCtx))
79
80 static int xmlSecOpenSSLX509StoreInitialize (xmlSecKeyDataStorePtr store);
81 static void xmlSecOpenSSLX509StoreFinalize (xmlSecKeyDataStorePtr store);
82
83 static xmlSecKeyDataStoreKlass xmlSecOpenSSLX509StoreKlass = {
84 sizeof(xmlSecKeyDataStoreKlass),
85 xmlSecOpenSSLX509StoreSize,
86
87 /* data */
88 xmlSecNameX509Store, /* const xmlChar* name; */
89
90 /* constructors/destructor */
91 xmlSecOpenSSLX509StoreInitialize, /* xmlSecKeyDataStoreInitializeMethod initialize; */
92 xmlSecOpenSSLX509StoreFinalize, /* xmlSecKeyDataStoreFinalizeMethod finalize; */
93
94 /* reserved for the future */
95 NULL, /* void* reserved0; */
96 NULL, /* void* reserved1; */
97 };
98
99 static int xmlSecOpenSSLX509VerifyCRL (X509_STORE* xst,
100 X509_CRL *crl );
101 static X509* xmlSecOpenSSLX509FindCert (STACK_OF(X509) *certs,
102 xmlChar *subjectName,
103 xmlChar *issuerName,
104 xmlChar *issuerSerial,
105 xmlChar *ski);
106 static X509* xmlSecOpenSSLX509FindNextChainCert (STACK_OF(X509) *chain,
107 X509 *cert);
108 static int xmlSecOpenSSLX509VerifyCertAgainstCrls (STACK_OF(X509_CRL) *crls,
109 X509* cert);
110 static X509_NAME* xmlSecOpenSSLX509NameRead (xmlSecByte *str,
111 int len);
112 static int xmlSecOpenSSLX509NameStringRead (xmlSecByte **str,
113 int *strLen,
114 xmlSecByte *res,
115 int resLen,
116 xmlSecByte delim,
117 int ingoreTrailingSpaces);
118 static int xmlSecOpenSSLX509NamesCompare (X509_NAME *a,
119 X509_NAME *b);
120 static STACK_OF(X509_NAME_ENTRY)* xmlSecOpenSSLX509_NAME_ENTRIES_copy (X509_NAME *a);
121 static int xmlSecOpenSSLX509_NAME_ENTRIES_cmp (STACK_OF(X509_NAME_ENTRY) * a,
122 STACK_OF(X509_NAME_ENTRY) * b);
123 static int xmlSecOpenSSLX509_NAME_ENTRY_cmp (const X509_NAME_ENTRY * const *a,
124 const X509_NAME_ENTRY * const *b);
125
126
127 /**
128 * xmlSecOpenSSLX509StoreGetKlass:
129 *
130 * The OpenSSL X509 certificates key data store klass.
131 *
132 * Returns: pointer to OpenSSL X509 certificates key data store klass.
133 */
134 xmlSecKeyDataStoreId
xmlSecOpenSSLX509StoreGetKlass(void)135 xmlSecOpenSSLX509StoreGetKlass(void) {
136 return(&xmlSecOpenSSLX509StoreKlass);
137 }
138
139 /**
140 * xmlSecOpenSSLX509StoreFindCert:
141 * @store: the pointer to X509 key data store klass.
142 * @subjectName: the desired certificate name.
143 * @issuerName: the desired certificate issuer name.
144 * @issuerSerial: the desired certificate issuer serial number.
145 * @ski: the desired certificate SKI.
146 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
147 *
148 * Searches @store for a certificate that matches given criteria.
149 *
150 * Returns: pointer to found certificate or NULL if certificate is not found
151 * or an error occurs.
152 */
153 X509*
xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store,xmlChar * subjectName,xmlChar * issuerName,xmlChar * issuerSerial,xmlChar * ski,xmlSecKeyInfoCtx * keyInfoCtx)154 xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
155 xmlChar *issuerName, xmlChar *issuerSerial,
156 xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
157 xmlSecOpenSSLX509StoreCtxPtr ctx;
158 X509* res = NULL;
159
160 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
161 xmlSecAssert2(keyInfoCtx != NULL, NULL);
162
163 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
164 xmlSecAssert2(ctx != NULL, NULL);
165
166 if((res == NULL) && (ctx->untrusted != NULL)) {
167 res = xmlSecOpenSSLX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
168 }
169 return(res);
170 }
171
172 /**
173 * xmlSecOpenSSLX509StoreVerify:
174 * @store: the pointer to X509 key data store klass.
175 * @certs: the untrusted certificates stack.
176 * @crls: the crls stack.
177 * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context.
178 *
179 * Verifies @certs list.
180 *
181 * Returns: pointer to the first verified certificate from @certs.
182 */
183 X509*
xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store,XMLSEC_STACK_OF_X509 * certs,XMLSEC_STACK_OF_X509_CRL * crls,xmlSecKeyInfoCtx * keyInfoCtx)184 xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs,
185 XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) {
186 xmlSecOpenSSLX509StoreCtxPtr ctx;
187 STACK_OF(X509)* certs2 = NULL;
188 STACK_OF(X509_CRL)* crls2 = NULL;
189 X509 * res = NULL;
190 X509 * cert;
191 X509 * err_cert = NULL;
192 X509_STORE_CTX *xsc;
193 int err = 0;
194 x509_size_t i;
195 int ret;
196
197 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
198 xmlSecAssert2(certs != NULL, NULL);
199 xmlSecAssert2(keyInfoCtx != NULL, NULL);
200
201 xsc = X509_STORE_CTX_new();
202 if(xsc == NULL) {
203 xmlSecOpenSSLError("X509_STORE_CTX_new",
204 xmlSecKeyDataStoreGetName(store));
205 goto done;
206 }
207
208 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
209 xmlSecAssert2(ctx != NULL, NULL);
210 xmlSecAssert2(ctx->xst != NULL, NULL);
211
212 /* dup certs */
213 certs2 = sk_X509_dup(certs);
214 if(certs2 == NULL) {
215 xmlSecOpenSSLError("sk_X509_dup",
216 xmlSecKeyDataStoreGetName(store));
217 goto done;
218 }
219
220 /* add untrusted certs from the store */
221 if(ctx->untrusted != NULL) {
222 for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) {
223 ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i));
224 if(ret < 1) {
225 xmlSecOpenSSLError("sk_X509_push",
226 xmlSecKeyDataStoreGetName(store));
227 goto done;
228 }
229 }
230 }
231
232 /* dup crls but remove all non-verified */
233 if(crls != NULL) {
234 crls2 = sk_X509_CRL_dup(crls);
235 if(crls2 == NULL) {
236 xmlSecOpenSSLError("sk_X509_CRL_dup",
237 xmlSecKeyDataStoreGetName(store));
238 goto done;
239 }
240
241 for(i = 0; i < sk_X509_CRL_num(crls2); ) {
242 ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i));
243 if(ret == 1) {
244 ++i;
245 } else if(ret == 0) {
246 (void)sk_X509_CRL_delete(crls2, i);
247 } else {
248 xmlSecInternalError("xmlSecOpenSSLX509VerifyCRL",
249 xmlSecKeyDataStoreGetName(store));
250 goto done;
251 }
252 }
253 }
254
255 /* remove all revoked certs */
256 for(i = 0; i < sk_X509_num(certs2);) {
257 cert = sk_X509_value(certs2, i);
258
259 if(crls2 != NULL) {
260 ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert);
261 if(ret == 0) {
262 (void)sk_X509_delete(certs2, i);
263 continue;
264 } else if(ret != 1) {
265 xmlSecInternalError("xmlSecOpenSSLX509VerifyCertAgainstCrls",
266 xmlSecKeyDataStoreGetName(store));
267 goto done;
268 }
269 }
270
271 if(ctx->crls != NULL) {
272 ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert);
273 if(ret == 0) {
274 (void)sk_X509_delete(certs2, i);
275 continue;
276 } else if(ret != 1) {
277 xmlSecInternalError("xmlSecOpenSSLX509VerifyCertAgainstCrls",
278 xmlSecKeyDataStoreGetName(store));
279 goto done;
280 }
281 }
282 ++i;
283 }
284
285 /* get one cert after another and try to verify */
286 for(i = 0; i < sk_X509_num(certs2); ++i) {
287 cert = sk_X509_value(certs2, i);
288 if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) {
289
290 ret = X509_STORE_CTX_init(xsc, ctx->xst, cert, certs2);
291 if(ret != 1) {
292 xmlSecOpenSSLError("X509_STORE_CTX_init",
293 xmlSecKeyDataStoreGetName(store));
294 goto done;
295 }
296
297 if(keyInfoCtx->certsVerificationTime > 0) {
298 X509_STORE_CTX_set_time(xsc, 0, keyInfoCtx->certsVerificationTime);
299 }
300
301 {
302 X509_VERIFY_PARAM * vpm = NULL;
303 unsigned long vpm_flags = 0;
304
305 vpm = X509_VERIFY_PARAM_new();
306 if(vpm == NULL) {
307 xmlSecOpenSSLError("X509_VERIFY_PARAM_new",
308 xmlSecKeyDataStoreGetName(store));
309 goto done;
310 }
311 vpm_flags = X509_VERIFY_PARAM_get_flags(vpm);
312 vpm_flags &= (~X509_V_FLAG_CRL_CHECK);
313
314 if(keyInfoCtx->certsVerificationTime > 0) {
315 vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
316 X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
317 }
318
319 X509_VERIFY_PARAM_set_depth(vpm, keyInfoCtx->certsVerificationDepth);
320 X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
321 X509_STORE_CTX_set0_param(xsc, vpm);
322 }
323
324
325 if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
326 ret = X509_verify_cert(xsc);
327 } else {
328 ret = 1;
329 }
330 err_cert = X509_STORE_CTX_get_current_cert(xsc);
331 err = X509_STORE_CTX_get_error(xsc);
332
333 X509_STORE_CTX_cleanup (xsc);
334
335 if(ret == 1) {
336 res = cert;
337 goto done;
338 } else if(ret < 0) {
339 /* real error */
340 xmlSecOpenSSLError("X509_verify_cert", xmlSecKeyDataStoreGetName(store));
341 goto done;
342 } else if(ret == 0) {
343 const char* err_msg;
344 char subject[256], issuer[256];
345
346 X509_NAME_oneline(X509_get_subject_name(err_cert), subject, sizeof(subject));
347 X509_NAME_oneline(X509_get_issuer_name(err_cert), issuer, sizeof(issuer));
348 err_msg = X509_verify_cert_error_string(err);
349
350 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
351 xmlSecKeyDataStoreGetName(store),
352 "X509_verify_cert: subject=%s; issuer=%s; err=%d; msg=%s",
353 subject, issuer, err, xmlSecErrorsSafeString(err_msg));
354 }
355 }
356 }
357
358 /* if we came here then we found nothing. do we have any error? */
359 if((err != 0) && (err_cert != NULL)) {
360 const char* err_msg;
361 char subject[256], issuer[256];
362
363 X509_NAME_oneline(X509_get_subject_name(err_cert), subject, sizeof(subject));
364 X509_NAME_oneline(X509_get_issuer_name(err_cert), issuer, sizeof(issuer));
365 err_msg = X509_verify_cert_error_string(err);
366
367 switch (err) {
368 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
369 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
370 xmlSecKeyDataStoreGetName(store),
371 "subject=%s; issuer=%s; err=%d; msg=%s",
372 subject, issuer, err, xmlSecErrorsSafeString(err_msg));
373 break;
374 case X509_V_ERR_CERT_NOT_YET_VALID:
375 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
376 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
377 xmlSecKeyDataStoreGetName(store),
378 "subject=%s; issuer=%s; err=%d; msg=%s",
379 subject, issuer, err, xmlSecErrorsSafeString(err_msg));
380 break;
381 case X509_V_ERR_CERT_HAS_EXPIRED:
382 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
383 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
384 xmlSecKeyDataStoreGetName(store),
385 "subject=%s; issuer=%s; err=%d; msg=%s",
386 subject, issuer, err, xmlSecErrorsSafeString(err_msg));
387 break;
388 default:
389 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
390 xmlSecKeyDataStoreGetName(store),
391 "subject=%s; issuer=%s; err=%d; msg=%s",
392 subject, issuer, err, xmlSecErrorsSafeString(err_msg));
393 break;
394 }
395 }
396
397 done:
398 if(certs2 != NULL) {
399 sk_X509_free(certs2);
400 }
401 if(crls2 != NULL) {
402 sk_X509_CRL_free(crls2);
403 }
404 if(xsc != NULL) {
405 X509_STORE_CTX_free(xsc);
406 }
407 return(res);
408 }
409
410 /**
411 * xmlSecOpenSSLX509StoreAdoptCert:
412 * @store: the pointer to X509 key data store klass.
413 * @cert: the pointer to OpenSSL X509 certificate.
414 * @type: the certificate type (trusted/untrusted).
415 *
416 * Adds trusted (root) or untrusted certificate to the store.
417 *
418 * Returns: 0 on success or a negative value if an error occurs.
419 */
420 int
xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store,X509 * cert,xmlSecKeyDataType type)421 xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store, X509* cert, xmlSecKeyDataType type) {
422 xmlSecOpenSSLX509StoreCtxPtr ctx;
423 int ret;
424
425 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
426 xmlSecAssert2(cert != NULL, -1);
427
428 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
429 xmlSecAssert2(ctx != NULL, -1);
430
431 if((type & xmlSecKeyDataTypeTrusted) != 0) {
432 xmlSecAssert2(ctx->xst != NULL, -1);
433
434 ret = X509_STORE_add_cert(ctx->xst, cert);
435 if(ret != 1) {
436 xmlSecOpenSSLError("X509_STORE_add_cert",
437 xmlSecKeyDataStoreGetName(store));
438 return(-1);
439 }
440 /* add cert increments the reference */
441 X509_free(cert);
442 } else {
443 xmlSecAssert2(ctx->untrusted != NULL, -1);
444
445 ret = sk_X509_push(ctx->untrusted, cert);
446 if(ret < 1) {
447 xmlSecOpenSSLError("sk_X509_push",
448 xmlSecKeyDataStoreGetName(store));
449 return(-1);
450 }
451 }
452 return(0);
453 }
454
455 /**
456 * xmlSecOpenSSLX509StoreAdoptCrl:
457 * @store: the pointer to X509 key data store klass.
458 * @crl: the pointer to OpenSSL X509_CRL.
459 *
460 * Adds X509 CRL to the store.
461 *
462 * Returns: 0 on success or a negative value if an error occurs.
463 */
464 int
xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store,X509_CRL * crl)465 xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store, X509_CRL* crl) {
466 xmlSecOpenSSLX509StoreCtxPtr ctx;
467 int ret;
468
469 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
470 xmlSecAssert2(crl != NULL, -1);
471
472 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
473 xmlSecAssert2(ctx != NULL, -1);
474 xmlSecAssert2(ctx->crls != NULL, -1);
475
476 ret = sk_X509_CRL_push(ctx->crls, crl);
477 if(ret < 1) {
478 xmlSecOpenSSLError("sk_X509_CRL_push",
479 xmlSecKeyDataStoreGetName(store));
480 return(-1);
481 }
482
483 return (0);
484 }
485
486 /**
487 * xmlSecOpenSSLX509StoreAddCertsPath:
488 * @store: the pointer to OpenSSL x509 store.
489 * @path: the path to the certs dir.
490 *
491 * Adds all certs in the @path to the list of trusted certs
492 * in @store.
493 *
494 * Returns: 0 on success or a negative value otherwise.
495 */
496 int
xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store,const char * path)497 xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store, const char *path) {
498 xmlSecOpenSSLX509StoreCtxPtr ctx;
499 X509_LOOKUP *lookup = NULL;
500
501 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
502 xmlSecAssert2(path != NULL, -1);
503
504 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
505 xmlSecAssert2(ctx != NULL, -1);
506 xmlSecAssert2(ctx->xst != NULL, -1);
507
508 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
509 if(lookup == NULL) {
510 xmlSecOpenSSLError("X509_STORE_add_lookup",
511 xmlSecKeyDataStoreGetName(store));
512 return(-1);
513 }
514 if(!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
515 xmlSecOpenSSLError2("X509_LOOKUP_add_dir",
516 xmlSecKeyDataStoreGetName(store),
517 "path='%s'",
518 xmlSecErrorsSafeString(path));
519 return(-1);
520 }
521 return(0);
522 }
523
524 /**
525 * xmlSecOpenSSLX509StoreAddCertsFile:
526 * @store: the pointer to OpenSSL x509 store.
527 * @filename: the certs file.
528 *
529 * Adds all certs in @file to the list of trusted certs
530 * in @store. It is possible for @file to contain multiple certs.
531 *
532 * Returns: 0 on success or a negative value otherwise.
533 */
534 int
xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store,const char * filename)535 xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store, const char *filename) {
536 xmlSecOpenSSLX509StoreCtxPtr ctx;
537 X509_LOOKUP *lookup = NULL;
538
539 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
540 xmlSecAssert2(filename != NULL, -1);
541
542 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
543 xmlSecAssert2(ctx != NULL, -1);
544 xmlSecAssert2(ctx->xst != NULL, -1);
545
546 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_file());
547 if(lookup == NULL) {
548 xmlSecOpenSSLError("X509_STORE_add_lookup",
549 xmlSecKeyDataStoreGetName(store));
550 return(-1);
551 }
552 if(!X509_LOOKUP_load_file(lookup, filename, X509_FILETYPE_PEM)) {
553 xmlSecOpenSSLError2("X509_LOOKUP_load_file",
554 xmlSecKeyDataStoreGetName(store),
555 "filename='%s'",
556 xmlSecErrorsSafeString(filename));
557 return(-1);
558 }
559 return(0);
560 }
561
562 static int
xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store)563 xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) {
564 const xmlChar* path;
565 X509_LOOKUP *lookup = NULL;
566
567 xmlSecOpenSSLX509StoreCtxPtr ctx;
568 xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
569
570 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
571 xmlSecAssert2(ctx != NULL, -1);
572
573 memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
574
575 ctx->xst = X509_STORE_new();
576 if(ctx->xst == NULL) {
577 xmlSecOpenSSLError("X509_STORE_new",
578 xmlSecKeyDataStoreGetName(store));
579 return(-1);
580 }
581
582 if(!X509_STORE_set_default_paths(ctx->xst)) {
583 xmlSecOpenSSLError("X509_STORE_set_default_paths",
584 xmlSecKeyDataStoreGetName(store));
585 return(-1);
586 }
587
588
589 lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
590 if(lookup == NULL) {
591 xmlSecOpenSSLError("X509_STORE_add_lookup",
592 xmlSecKeyDataStoreGetName(store));
593 return(-1);
594 }
595
596 path = xmlSecOpenSSLGetDefaultTrustedCertsFolder();
597 if(path != NULL) {
598 if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) {
599 xmlSecOpenSSLError2("X509_LOOKUP_add_dir",
600 xmlSecKeyDataStoreGetName(store),
601 "path='%s'",
602 xmlSecErrorsSafeString(path));
603 return(-1);
604 }
605 } else {
606 if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) {
607 xmlSecOpenSSLError("X509_LOOKUP_add_dir",
608 xmlSecKeyDataStoreGetName(store));
609 return(-1);
610 }
611 }
612
613 ctx->untrusted = sk_X509_new_null();
614 if(ctx->untrusted == NULL) {
615 xmlSecOpenSSLError("sk_X509_new_null",
616 xmlSecKeyDataStoreGetName(store));
617 return(-1);
618 }
619
620 ctx->crls = sk_X509_CRL_new_null();
621 if(ctx->crls == NULL) {
622 xmlSecOpenSSLError("sk_X509_CRL_new_null",
623 xmlSecKeyDataStoreGetName(store));
624 return(-1);
625 }
626
627 ctx->vpm = X509_VERIFY_PARAM_new();
628 if(ctx->vpm == NULL) {
629 xmlSecOpenSSLError("X509_VERIFY_PARAM_new",
630 xmlSecKeyDataStoreGetName(store));
631 return(-1);
632 }
633 X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */
634 X509_STORE_set1_param(ctx->xst, ctx->vpm);
635
636
637 return(0);
638 }
639
640 static void
xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store)641 xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store) {
642 xmlSecOpenSSLX509StoreCtxPtr ctx;
643 xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId));
644
645 ctx = xmlSecOpenSSLX509StoreGetCtx(store);
646 xmlSecAssert(ctx != NULL);
647
648
649 if(ctx->xst != NULL) {
650 X509_STORE_free(ctx->xst);
651 }
652 if(ctx->untrusted != NULL) {
653 sk_X509_pop_free(ctx->untrusted, X509_free);
654 }
655 if(ctx->crls != NULL) {
656 sk_X509_CRL_pop_free(ctx->crls, X509_CRL_free);
657 }
658 if(ctx->vpm != NULL) {
659 X509_VERIFY_PARAM_free(ctx->vpm);
660 }
661
662 memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
663 }
664
665
666 /*****************************************************************************
667 *
668 * Low-level x509 functions
669 *
670 *****************************************************************************/
671 static int
xmlSecOpenSSLX509VerifyCRL(X509_STORE * xst,X509_CRL * crl)672 xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
673 X509_STORE_CTX *xsc = NULL;
674 X509_OBJECT *xobj = NULL;
675 EVP_PKEY *pkey = NULL;
676 int ret;
677
678 xmlSecAssert2(xst != NULL, -1);
679 xmlSecAssert2(crl != NULL, -1);
680
681 xsc = X509_STORE_CTX_new();
682 if(xsc == NULL) {
683 xmlSecOpenSSLError("X509_STORE_CTX_new", NULL);
684 goto err;
685 }
686 xobj = (X509_OBJECT *)X509_OBJECT_new();
687 if(xobj == NULL) {
688 xmlSecOpenSSLError("X509_OBJECT_new", NULL);
689 goto err;
690 }
691
692 ret = X509_STORE_CTX_init(xsc, xst, NULL, NULL);
693 if(ret != 1) {
694 xmlSecOpenSSLError("X509_STORE_CTX_init", NULL);
695 goto err;
696 }
697 ret = X509_STORE_CTX_get_by_subject(xsc, X509_LU_X509,
698 X509_CRL_get_issuer(crl), xobj);
699 if(ret <= 0) {
700 xmlSecOpenSSLError("X509_STORE_CTX_get_by_subject", NULL);
701 goto err;
702 }
703 pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
704 if(pkey == NULL) {
705 xmlSecOpenSSLError("X509_get_pubkey", NULL);
706 goto err;
707 }
708 ret = X509_CRL_verify(crl, pkey);
709 EVP_PKEY_free(pkey);
710 if(ret != 1) {
711 xmlSecOpenSSLError("X509_CRL_verify", NULL);
712 }
713 X509_STORE_CTX_free(xsc);
714 X509_OBJECT_free(xobj);
715 return((ret == 1) ? 1 : 0);
716
717 err:
718 X509_STORE_CTX_free(xsc);
719 X509_OBJECT_free(xobj);
720 return(-1);
721 }
722
723 static X509*
xmlSecOpenSSLX509FindCert(STACK_OF (X509)* certs,xmlChar * subjectName,xmlChar * issuerName,xmlChar * issuerSerial,xmlChar * ski)724 xmlSecOpenSSLX509FindCert(STACK_OF(X509) *certs, xmlChar *subjectName,
725 xmlChar *issuerName, xmlChar *issuerSerial,
726 xmlChar *ski) {
727 X509 *cert = NULL;
728 x509_size_t i;
729
730 xmlSecAssert2(certs != NULL, NULL);
731
732 /* todo: may be this is not the fastest way to search certs */
733 if(subjectName != NULL) {
734 X509_NAME *nm;
735 X509_NAME *subj;
736
737 nm = xmlSecOpenSSLX509NameRead(subjectName, xmlStrlen(subjectName));
738 if(nm == NULL) {
739 xmlSecInternalError2("xmlSecOpenSSLX509NameRead", NULL,
740 "subject=%s", xmlSecErrorsSafeString(subjectName));
741 return(NULL);
742 }
743
744 for(i = 0; i < sk_X509_num(certs); ++i) {
745 cert = sk_X509_value(certs, i);
746 subj = X509_get_subject_name(cert);
747 if(xmlSecOpenSSLX509NamesCompare(nm, subj) == 0) {
748 X509_NAME_free(nm);
749 return(cert);
750 }
751 }
752 X509_NAME_free(nm);
753 } else if((issuerName != NULL) && (issuerSerial != NULL)) {
754 X509_NAME *nm;
755 X509_NAME *issuer;
756 BIGNUM *bn;
757 ASN1_INTEGER *serial;
758
759 nm = xmlSecOpenSSLX509NameRead(issuerName, xmlStrlen(issuerName));
760 if(nm == NULL) {
761 xmlSecInternalError2("xmlSecOpenSSLX509NameRead", NULL,
762 "issuer=%s", xmlSecErrorsSafeString(issuerName));
763 return(NULL);
764 }
765
766 bn = BN_new();
767 if(bn == NULL) {
768 xmlSecOpenSSLError("BN_new", NULL);
769 X509_NAME_free(nm);
770 return(NULL);
771 }
772 if(BN_dec2bn(&bn, (char*)issuerSerial) == 0) {
773 xmlSecOpenSSLError("BN_dec2bn", NULL);
774 BN_free(bn);
775 X509_NAME_free(nm);
776 return(NULL);
777 }
778
779 serial = BN_to_ASN1_INTEGER(bn, NULL);
780 if(serial == NULL) {
781 xmlSecOpenSSLError("BN_to_ASN1_INTEGER", NULL);
782 BN_free(bn);
783 X509_NAME_free(nm);
784 return(NULL);
785 }
786 BN_free(bn);
787
788
789 for(i = 0; i < sk_X509_num(certs); ++i) {
790 cert = sk_X509_value(certs, i);
791 if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serial) != 0) {
792 continue;
793 }
794 issuer = X509_get_issuer_name(cert);
795 if(xmlSecOpenSSLX509NamesCompare(nm, issuer) == 0) {
796 ASN1_INTEGER_free(serial);
797 X509_NAME_free(nm);
798 return(cert);
799 }
800 }
801
802 X509_NAME_free(nm);
803 ASN1_INTEGER_free(serial);
804 } else if(ski != NULL) {
805 int len;
806 int index;
807 X509_EXTENSION *ext;
808 ASN1_OCTET_STRING *keyId;
809
810 /* our usual trick with base64 decode */
811 len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski));
812 if(len < 0) {
813 xmlSecInternalError2("xmlSecBase64Decode", NULL,
814 "ski=%s", xmlSecErrorsSafeString(ski));
815 return(NULL);
816 }
817 for(i = 0; i < sk_X509_num(certs); ++i) {
818 cert = sk_X509_value(certs, i);
819 index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
820 if(index < 0) {
821 continue;
822 }
823 ext = X509_get_ext(cert, index);
824 if(ext == NULL) {
825 continue;
826 }
827 keyId = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext);
828 if(keyId == NULL) {
829 continue;
830 }
831 if((keyId->length == len) && (memcmp(keyId->data, ski, len) == 0)) {
832 ASN1_OCTET_STRING_free(keyId);
833 return(cert);
834 }
835 ASN1_OCTET_STRING_free(keyId);
836 }
837 }
838
839 return(NULL);
840 }
841
842 static X509*
xmlSecOpenSSLX509FindNextChainCert(STACK_OF (X509)* chain,X509 * cert)843 xmlSecOpenSSLX509FindNextChainCert(STACK_OF(X509) *chain, X509 *cert) {
844 unsigned long certSubjHash;
845 x509_size_t i;
846
847 xmlSecAssert2(chain != NULL, NULL);
848 xmlSecAssert2(cert != NULL, NULL);
849
850 certSubjHash = X509_subject_name_hash(cert);
851 for(i = 0; i < sk_X509_num(chain); ++i) {
852 if((sk_X509_value(chain, i) != cert) &&
853 (X509_issuer_name_hash(sk_X509_value(chain, i)) == certSubjHash)) {
854
855 return(sk_X509_value(chain, i));
856 }
857 }
858 return(NULL);
859 }
860
861 static int
xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF (X509_CRL)* crls,X509 * cert)862 xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF(X509_CRL) *crls, X509* cert) {
863 X509_NAME *issuer;
864 X509_CRL *crl = NULL;
865 X509_REVOKED *revoked;
866 x509_size_t i, n;
867 int ret;
868
869 xmlSecAssert2(crls != NULL, -1);
870 xmlSecAssert2(cert != NULL, -1);
871
872 /*
873 * Try to retrieve a CRL corresponding to the issuer of
874 * the current certificate
875 */
876 issuer = X509_get_issuer_name(cert);
877 n = sk_X509_CRL_num(crls);
878 for(i = 0; i < n; i++) {
879 crl = sk_X509_CRL_value(crls, i);
880 if(crl == NULL) {
881 continue;
882 }
883
884 if(xmlSecOpenSSLX509NamesCompare(X509_CRL_get_issuer(crl), issuer) == 0) {
885 break;
886 }
887 }
888 if((i >= n) || (crl == NULL)){
889 /* no crls for this issuer */
890 return(1);
891 }
892
893 /*
894 * Check date of CRL to make sure it's not expired
895 */
896 ret = X509_cmp_current_time(X509_CRL_get0_nextUpdate(crl));
897 if (ret == 0) {
898 /* crl expired */
899 return(1);
900 }
901
902 /*
903 * Check if the current certificate is revoked by this CRL
904 */
905 n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
906 for (i = 0; i < n; i++) {
907 revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
908 if (ASN1_INTEGER_cmp(X509_REVOKED_get0_serialNumber(revoked), X509_get_serialNumber(cert)) == 0) {
909 xmlSecOtherError(XMLSEC_ERRORS_R_CERT_REVOKED, NULL, NULL);
910 return(0);
911 }
912 }
913 return(1);
914 }
915
916 static X509_NAME *
xmlSecOpenSSLX509NameRead(xmlSecByte * str,int len)917 xmlSecOpenSSLX509NameRead(xmlSecByte *str, int len) {
918 xmlSecByte name[256];
919 xmlSecByte value[256];
920 int nameLen, valueLen;
921 X509_NAME *nm;
922 int type = MBSTRING_ASC;
923
924 xmlSecAssert2(str != NULL, NULL);
925
926 nm = X509_NAME_new();
927 if(nm == NULL) {
928 xmlSecOpenSSLError("X509_NAME_new", NULL);
929 return(NULL);
930 }
931
932 while(len > 0) {
933 /* skip spaces after comma or semicolon */
934 while((len > 0) && isspace(*str)) {
935 ++str; --len;
936 }
937
938 nameLen = xmlSecOpenSSLX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
939 if(nameLen < 0) {
940 xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
941 X509_NAME_free(nm);
942 return(NULL);
943 }
944 name[nameLen] = '\0';
945 if(len > 0) {
946 ++str; --len;
947 if((*str) == '\"') {
948 ++str; --len;
949 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
950 value, sizeof(value), '"', 1);
951 if(valueLen < 0) {
952 xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
953 X509_NAME_free(nm);
954 return(NULL);
955 }
956
957 /* skip quote */
958 if((len <= 0) || ((*str) != '\"')) {
959 xmlSecInvalidIntegerDataError("char", (*str), "quote '\"'", NULL);
960 X509_NAME_free(nm);
961 return(NULL);
962 }
963 ++str; --len;
964
965 /* skip spaces before comma or semicolon */
966 while((len > 0) && isspace(*str)) {
967 ++str; --len;
968 }
969 if((len > 0) && ((*str) != ',')) {
970 xmlSecInvalidIntegerDataError("char", (*str), "comma ','", NULL);
971 X509_NAME_free(nm);
972 return(NULL);
973 }
974 if(len > 0) {
975 ++str; --len;
976 }
977 type = MBSTRING_ASC;
978 } else if((*str) == '#') {
979 /* TODO: read octect values */
980 xmlSecNotImplementedError("reading octect values is not implemented yet");
981 X509_NAME_free(nm);
982 return(NULL);
983 } else {
984 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
985 value, sizeof(value), ',', 1);
986 if(valueLen < 0) {
987 xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
988 X509_NAME_free(nm);
989 return(NULL);
990 }
991 type = MBSTRING_ASC;
992 }
993 } else {
994 valueLen = 0;
995 }
996 value[valueLen] = '\0';
997 if(len > 0) {
998 ++str; --len;
999 }
1000 X509_NAME_add_entry_by_txt(nm, (char*)name, type, value, valueLen, -1, 0);
1001 }
1002
1003 return(nm);
1004 }
1005
1006 static int
xmlSecOpenSSLX509NameStringRead(xmlSecByte ** str,int * strLen,xmlSecByte * res,int resLen,xmlSecByte delim,int ingoreTrailingSpaces)1007 xmlSecOpenSSLX509NameStringRead(xmlSecByte **str, int *strLen,
1008 xmlSecByte *res, int resLen,
1009 xmlSecByte delim, int ingoreTrailingSpaces) {
1010 xmlSecByte *p, *q, *nonSpace;
1011
1012 xmlSecAssert2(str != NULL, -1);
1013 xmlSecAssert2(strLen != NULL, -1);
1014 xmlSecAssert2(res != NULL, -1);
1015
1016 p = (*str);
1017 nonSpace = q = res;
1018 while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) {
1019 if((*p) != '\\') {
1020 if(ingoreTrailingSpaces && !isspace(*p)) {
1021 nonSpace = q;
1022 }
1023 *(q++) = *(p++);
1024 } else {
1025 ++p;
1026 nonSpace = q;
1027 if(xmlSecIsHex((*p))) {
1028 if((p - (*str) + 1) >= (*strLen)) {
1029 xmlSecInvalidDataError("two hex digits expected", NULL);
1030 return(-1);
1031 }
1032 *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]);
1033 p += 2;
1034 } else {
1035 if(((++p) - (*str)) >= (*strLen)) {
1036 xmlSecInvalidDataError("escaped symbol missed", NULL);
1037 return(-1);
1038 }
1039 *(q++) = *(p++);
1040 }
1041 }
1042 }
1043 if(((p - (*str)) < (*strLen)) && ((*p) != delim)) {
1044 xmlSecInvalidSizeOtherError("buffer is too small", NULL);
1045 return(-1);
1046 }
1047 (*strLen) -= (int)(p - (*str));
1048 (*str) = p;
1049 return(int)((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res);
1050 }
1051
1052 /*
1053 * This function DOES NOT create duplicates for X509_NAME_ENTRY objects!
1054 */
STACK_OF(X509_NAME_ENTRY)1055 static STACK_OF(X509_NAME_ENTRY)*
1056 xmlSecOpenSSLX509_NAME_ENTRIES_copy(X509_NAME * a) {
1057 STACK_OF(X509_NAME_ENTRY) * res = NULL;
1058 int ii;
1059
1060 res = sk_X509_NAME_ENTRY_new(xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1061 if(res == NULL) {
1062 xmlSecOpenSSLError("sk_X509_NAME_ENTRY_new", NULL);
1063 return(NULL);
1064 }
1065
1066 for (ii = X509_NAME_entry_count(a) - 1; ii >= 0; --ii) {
1067 sk_X509_NAME_ENTRY_push(res, X509_NAME_get_entry(a, ii));
1068 }
1069
1070 return (res);
1071 }
1072
1073 static
xmlSecOpenSSLX509_NAME_ENTRIES_cmp(STACK_OF (X509_NAME_ENTRY)* a,STACK_OF (X509_NAME_ENTRY)* b)1074 int xmlSecOpenSSLX509_NAME_ENTRIES_cmp(STACK_OF(X509_NAME_ENTRY)* a, STACK_OF(X509_NAME_ENTRY)* b) {
1075 const X509_NAME_ENTRY *na;
1076 const X509_NAME_ENTRY *nb;
1077 int ii, ret;
1078
1079 xmlSecAssert2(a != NULL, -1);
1080 xmlSecAssert2(b != NULL, 1);
1081
1082 if (sk_X509_NAME_ENTRY_num(a) != sk_X509_NAME_ENTRY_num(b)) {
1083 return sk_X509_NAME_ENTRY_num(a) - sk_X509_NAME_ENTRY_num(b);
1084 }
1085
1086 for (ii = sk_X509_NAME_ENTRY_num(a) - 1; ii >= 0; --ii) {
1087 na = sk_X509_NAME_ENTRY_value(a, ii);
1088 nb = sk_X509_NAME_ENTRY_value(b, ii);
1089
1090 ret = xmlSecOpenSSLX509_NAME_ENTRY_cmp(&na, &nb);
1091 if(ret != 0) {
1092 return(ret);
1093 }
1094 }
1095
1096 return(0);
1097 }
1098
1099
1100 /**
1101 * xmlSecOpenSSLX509NamesCompare:
1102 *
1103 * We have to sort X509_NAME entries to get correct results.
1104 * This is ugly but OpenSSL does not support it
1105 */
1106 static int
xmlSecOpenSSLX509NamesCompare(X509_NAME * a,X509_NAME * b)1107 xmlSecOpenSSLX509NamesCompare(X509_NAME *a, X509_NAME *b) {
1108 STACK_OF(X509_NAME_ENTRY) *a1 = NULL;
1109 STACK_OF(X509_NAME_ENTRY) *b1 = NULL;
1110 int ret;
1111
1112 xmlSecAssert2(a != NULL, -1);
1113 xmlSecAssert2(b != NULL, 1);
1114
1115 a1 = xmlSecOpenSSLX509_NAME_ENTRIES_copy(a);
1116 if(a1 == NULL) {
1117 xmlSecInternalError("xmlSecOpenSSLX509_NAME_ENTRIES_copy", NULL);
1118 return(-1);
1119 }
1120 b1 = xmlSecOpenSSLX509_NAME_ENTRIES_copy(b);
1121 if(b1 == NULL) {
1122 xmlSecInternalError("xmlSecOpenSSLX509_NAME_ENTRIES_copy", NULL);
1123 sk_X509_NAME_ENTRY_free(a1);
1124 return(1);
1125 }
1126
1127 /* sort both */
1128 (void)sk_X509_NAME_ENTRY_set_cmp_func(a1, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1129 sk_X509_NAME_ENTRY_sort(a1);
1130 (void)sk_X509_NAME_ENTRY_set_cmp_func(b1, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1131 sk_X509_NAME_ENTRY_sort(b1);
1132
1133 /* actually compare */
1134 ret = xmlSecOpenSSLX509_NAME_ENTRIES_cmp(a1, b1);
1135
1136 /* cleanup */
1137 sk_X509_NAME_ENTRY_free(a1);
1138 sk_X509_NAME_ENTRY_free(b1);
1139 return(ret);
1140 }
1141
1142 static int
xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const * a,const X509_NAME_ENTRY * const * b)1143 xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const *a, const X509_NAME_ENTRY * const *b) {
1144 ASN1_STRING *a_value, *b_value;
1145 ASN1_OBJECT *a_name, *b_name;
1146 int a_len, b_len;
1147 int ret;
1148
1149 xmlSecAssert2(a != NULL, -1);
1150 xmlSecAssert2(b != NULL, 1);
1151 xmlSecAssert2((*a) != NULL, -1);
1152 xmlSecAssert2((*b) != NULL, 1);
1153
1154
1155 /* first compare values */
1156 a_value = X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)(*a));
1157 b_value = X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)(*b));
1158
1159 if((a_value == NULL) && (b_value != NULL)) {
1160 return(-1);
1161 } else if((a_value != NULL) && (b_value == NULL)) {
1162 return(1);
1163 } else if((a_value == NULL) && (b_value == NULL)) {
1164 return(0);
1165 }
1166
1167 a_len = ASN1_STRING_length(a_value);
1168 b_len = ASN1_STRING_length(b_value);
1169 ret = a_len - b_len;
1170 if(ret != 0) {
1171 return(ret);
1172 }
1173
1174 if(a_len > 0) {
1175 ret = memcmp(ASN1_STRING_get0_data(a_value), ASN1_STRING_get0_data(b_value), a_len);
1176 if(ret != 0) {
1177 return(ret);
1178 }
1179 }
1180
1181 /* next compare names */
1182 a_name = X509_NAME_ENTRY_get_object((X509_NAME_ENTRY*)(*a));
1183 b_name = X509_NAME_ENTRY_get_object((X509_NAME_ENTRY*)(*b));
1184
1185 if((a_name == NULL) && (b_name != NULL)) {
1186 return(-1);
1187 } else if((a_name != NULL) && (b_name == NULL)) {
1188 return(1);
1189 } else if((a_name == NULL) && (b_name == NULL)) {
1190 return(0);
1191 }
1192
1193 return(OBJ_cmp(a_name, b_name));
1194 }
1195
1196 #endif /* XMLSEC_NO_X509 */
1197
1198
1199