Implemented X.509 certificate reading using OpenSSL
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_x509.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 /*
17 * Copyright (C) 2010 secunet Security Networks AG
18 * Copyright (C) 2010 Thomas Egerer
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a copy
21 * of this software and associated documentation files (the "Software"), to deal
22 * in the Software without restriction, including without limitation the rights
23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 * copies of the Software, and to permit persons to whom the Software is
25 * furnished to do so, subject to the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be included in
28 * all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 * THE SOFTWARE.
37 */
38
39 #define _GNU_SOURCE
40 #include <stdio.h>
41 #include <openssl/x509.h>
42 #include <openssl/x509v3.h>
43
44 #include "openssl_x509.h"
45 #include "openssl_util.h"
46
47 #include <debug.h>
48 #include <asn1/oid.h>
49 #include <utils/linked_list.h>
50
51
52 typedef struct private_openssl_x509_t private_openssl_x509_t;
53
54 /**
55 * Private data of an openssl_x509_t object.
56 */
57 struct private_openssl_x509_t {
58
59 /**
60 * Public openssl_x509_t interface.
61 */
62 openssl_x509_t public;
63
64 /**
65 * OpenSSL certificate representation
66 */
67 X509 *x509;
68
69 /**
70 * DER encoded certificate
71 */
72 chunk_t encoding;
73
74 /**
75 * SHA1 hash of the certificate
76 */
77 chunk_t hash;
78
79 /**
80 * X509 flags
81 */
82 x509_flag_t flags;
83
84 /**
85 * Pathlen constraint
86 */
87 int pathlen;
88
89 /**
90 * certificate subject
91 */
92 identification_t *subject;
93
94 /**
95 * certificate issuer
96 */
97 identification_t *issuer;
98
99 /**
100 * Certificates public key
101 */
102 public_key_t *pubkey;
103
104 /**
105 * subjectKeyIdentifier as read from cert
106 */
107 chunk_t subjectKeyIdentifier;
108
109 /**
110 * authorityKeyIdentifier as read from cert
111 */
112 chunk_t authKeyIdentifier;
113
114 /**
115 * Start time of certificate validity
116 */
117 time_t notBefore;
118
119 /**
120 * End time of certificate validity
121 */
122 time_t notAfter;
123
124 /**
125 * Signature scheme of the certificate
126 */
127 signature_scheme_t scheme;
128
129 /**
130 * subjectAltNames
131 */
132 linked_list_t *subjectAltNames;
133
134 /**
135 * issuerAltNames
136 */
137 linked_list_t *issuerAltNames;
138
139 /**
140 * List of CRL URIs
141 */
142 linked_list_t *crl_uris;
143
144 /**
145 * List of OCSP URIs
146 */
147 linked_list_t *ocsp_uris;
148
149 /**
150 * References to this cert
151 */
152 refcount_t ref;
153 };
154
155 /**
156 * Convert a GeneralName to an identification_t.
157 */
158 static identification_t *general_name2id(GENERAL_NAME *name)
159 {
160 if (!name)
161 {
162 return NULL;
163 }
164 switch (name->type)
165 {
166 case GEN_EMAIL:
167 return identification_create_from_encoding(ID_RFC822_ADDR,
168 openssl_asn1_str2chunk(name->d.rfc822Name));
169 case GEN_DNS:
170 return identification_create_from_encoding(ID_FQDN,
171 openssl_asn1_str2chunk(name->d.dNSName));
172 case GEN_URI:
173 return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
174 openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
175 case GEN_IPADD:
176 return identification_create_from_encoding(ID_IPV4_ADDR,
177 openssl_asn1_str2chunk(name->d.iPAddress));
178 case GEN_DIRNAME :
179 return openssl_x509_name2id(name->d.directoryName);
180 default:
181 return NULL;
182 }
183 }
184
185 METHOD(x509_t, get_flags, x509_flag_t,
186 private_openssl_x509_t *this)
187 {
188 return this->flags;
189 }
190
191 METHOD(x509_t, get_serial, chunk_t,
192 private_openssl_x509_t *this)
193 {
194 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
195 }
196
197 METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
198 private_openssl_x509_t *this)
199 {
200 chunk_t fingerprint;
201
202 if (this->subjectKeyIdentifier.len)
203 {
204 return this->subjectKeyIdentifier;
205 }
206 if (this->pubkey->get_fingerprint(this->pubkey, KEY_ID_PUBKEY_SHA1,
207 &fingerprint))
208 {
209 return fingerprint;
210 }
211 return chunk_empty;
212 }
213
214 METHOD(x509_t, get_authKeyIdentifier, chunk_t,
215 private_openssl_x509_t *this)
216 {
217 if (this->authKeyIdentifier.len)
218 {
219 return this->authKeyIdentifier;
220 }
221 return chunk_empty;
222 }
223
224 METHOD(x509_t, get_pathLenConstraint, int,
225 private_openssl_x509_t *this)
226 {
227 return this->pathlen;
228 }
229
230 METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
231 private_openssl_x509_t *this)
232 {
233 return this->subjectAltNames->create_enumerator(this->subjectAltNames);
234 }
235
236 METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
237 private_openssl_x509_t *this)
238 {
239 return this->crl_uris->create_enumerator(this->crl_uris);
240 }
241
242 METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
243 private_openssl_x509_t *this)
244 {
245 return this->ocsp_uris->create_enumerator(this->ocsp_uris);
246 }
247
248 METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
249 private_openssl_x509_t *this)
250 {
251 /* TODO */
252 return enumerator_create_empty();
253 }
254
255 METHOD(certificate_t, get_type, certificate_type_t,
256 private_openssl_x509_t *this)
257 {
258 return CERT_X509;
259 }
260
261 METHOD(certificate_t, get_subject, identification_t*,
262 private_openssl_x509_t *this)
263 {
264 return this->subject;
265 }
266
267 METHOD(certificate_t, get_issuer, identification_t*,
268 private_openssl_x509_t *this)
269 {
270 return this->issuer;
271 }
272
273 METHOD(certificate_t, has_subject, id_match_t,
274 private_openssl_x509_t *this, identification_t *subject)
275 {
276 identification_t *current;
277 enumerator_t *enumerator;
278 id_match_t match, best;
279
280 if (subject->get_type(subject) == ID_KEY_ID)
281 {
282 if (chunk_equals(this->hash, subject->get_encoding(subject)))
283 {
284 return ID_MATCH_PERFECT;
285 }
286 }
287 best = this->subject->matches(this->subject, subject);
288 enumerator = create_subjectAltName_enumerator(this);
289 while (enumerator->enumerate(enumerator, &current))
290 {
291 match = current->matches(current, subject);
292 if (match > best)
293 {
294 best = match;
295 }
296 }
297 enumerator->destroy(enumerator);
298 return best;
299 }
300
301 METHOD(certificate_t, has_issuer, id_match_t,
302 private_openssl_x509_t *this, identification_t *issuer)
303 {
304 /* issuerAltNames currently not supported */
305 return this->issuer->matches(this->issuer, issuer);
306 }
307
308 METHOD(certificate_t, issued_by, bool,
309 private_openssl_x509_t *this, certificate_t *issuer)
310 {
311 public_key_t *key;
312 bool valid;
313 x509_t *x509 = (x509_t*)issuer;
314 chunk_t tbs;
315
316 if (&this->public.x509.interface == issuer)
317 {
318 if (this->flags & X509_SELF_SIGNED)
319 {
320 return TRUE;
321 }
322 }
323 else
324 {
325 if (issuer->get_type(issuer) != CERT_X509)
326 {
327 return FALSE;
328 }
329 if (!(x509->get_flags(x509) & X509_CA))
330 {
331 return FALSE;
332 }
333 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
334 {
335 return FALSE;
336 }
337 }
338 if (this->scheme == SIGN_UNKNOWN)
339 {
340 return FALSE;
341 }
342 key = issuer->get_public_key(issuer);
343 if (!key)
344 {
345 return FALSE;
346 }
347 tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
348 valid = key->verify(key, this->scheme, tbs,
349 openssl_asn1_str2chunk(this->x509->signature));
350 free(tbs.ptr);
351 key->destroy(key);
352 return valid;
353 }
354
355 METHOD(certificate_t, get_public_key, public_key_t*,
356 private_openssl_x509_t *this)
357 {
358 return this->pubkey->get_ref(this->pubkey);
359 }
360
361 METHOD(certificate_t, get_validity, bool,
362 private_openssl_x509_t *this,
363 time_t *when, time_t *not_before, time_t *not_after)
364 {
365 time_t t;
366
367 if (when)
368 {
369 t = *when;
370 }
371 else
372 {
373 t = time(NULL);
374 }
375 if (not_before)
376 {
377 *not_before = this->notBefore;
378 }
379 if (not_after)
380 {
381 *not_after = this->notAfter;
382 }
383 return (t >= this->notBefore && t <= this->notAfter);
384 }
385
386 METHOD(certificate_t, is_newer, bool,
387 private_openssl_x509_t *this, certificate_t *other)
388 {
389 time_t this_update, that_update, now = time(NULL);
390 bool new;
391
392 get_validity(this, &now, &this_update, NULL);
393 other->get_validity(other, &now, &that_update, NULL);
394 new = this_update > that_update;
395 DBG1(DBG_LIB, " certificate from %T is %s - existing certificate "
396 "from %T %s", &this_update, FALSE, new ? "newer":"not newer",
397 &that_update, FALSE, new ? "replaced":"retained");
398 return new;
399 }
400
401 METHOD(certificate_t, get_encoding, chunk_t,
402 private_openssl_x509_t *this)
403 {
404 return chunk_clone(this->encoding);
405 }
406
407 METHOD(certificate_t, equals, bool,
408 private_openssl_x509_t *this, certificate_t *other)
409 {
410 chunk_t encoding;
411 bool equal;
412
413 if (this == (private_openssl_x509_t*)other)
414 {
415 return TRUE;
416 }
417 if (other->get_type(other) != CERT_X509)
418 {
419 return FALSE;
420 }
421 if (other->equals == (void*)equals)
422 { /* skip allocation if we have the same implementation */
423 encoding = ((private_openssl_x509_t*)other)->encoding;
424 return chunk_equals(this->encoding, encoding);
425 }
426 encoding = other->get_encoding(other);
427 equal = chunk_equals(this->encoding, encoding);
428 free(encoding.ptr);
429 return equal;
430 }
431
432 METHOD(certificate_t, get_ref, certificate_t*,
433 private_openssl_x509_t *this)
434 {
435 ref_get(&this->ref);
436 return &this->public.x509.interface;
437 }
438
439 METHOD(certificate_t, destroy, void,
440 private_openssl_x509_t *this)
441 {
442 if (ref_put(&this->ref))
443 {
444 if (this->x509)
445 {
446 X509_free(this->x509);
447 }
448 DESTROY_IF(this->subject);
449 DESTROY_IF(this->issuer);
450 DESTROY_IF(this->pubkey);
451 free(this->subjectKeyIdentifier.ptr);
452 free(this->authKeyIdentifier.ptr);
453 free(this->encoding.ptr);
454 free(this->hash.ptr);
455 this->subjectAltNames->destroy_offset(this->subjectAltNames,
456 offsetof(identification_t, destroy));
457 this->issuerAltNames->destroy_offset(this->issuerAltNames,
458 offsetof(identification_t, destroy));
459 this->crl_uris->destroy_function(this->crl_uris, free);
460 this->ocsp_uris->destroy_function(this->ocsp_uris, free);
461 free(this);
462 }
463 }
464
465 /**
466 * Create an empty certificate
467 */
468 static private_openssl_x509_t *create_empty()
469 {
470 private_openssl_x509_t *this;
471
472 INIT(this,
473 .public = {
474 .x509 = {
475 .interface = {
476 .get_type = _get_type,
477 .get_subject = _get_subject,
478 .get_issuer = _get_issuer,
479 .has_subject = _has_subject,
480 .has_issuer = _has_issuer,
481 .issued_by = _issued_by,
482 .get_public_key = _get_public_key,
483 .get_validity = _get_validity,
484 .is_newer = _is_newer,
485 .get_encoding = _get_encoding,
486 .equals = _equals,
487 .get_ref = _get_ref,
488 .destroy = _destroy,
489 },
490 .get_flags = _get_flags,
491 .get_serial = _get_serial,
492 .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
493 .get_authKeyIdentifier = _get_authKeyIdentifier,
494 .get_pathLenConstraint = _get_pathLenConstraint,
495 .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
496 .create_crl_uri_enumerator = _create_crl_uri_enumerator,
497 .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
498 .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
499 },
500 },
501 .subjectAltNames = linked_list_create(),
502 .issuerAltNames = linked_list_create(),
503 .crl_uris = linked_list_create(),
504 .ocsp_uris = linked_list_create(),
505 .pathlen = X509_NO_PATH_LEN_CONSTRAINT,
506 .ref = 1,
507 );
508
509 return this;
510 }
511
512 /**
513 * parse an extionsion containing GENERAL_NAMES into a list
514 */
515 static bool parse_generalNames_ext(linked_list_t *list,
516 X509_EXTENSION *ext)
517 {
518 GENERAL_NAMES *names;
519 GENERAL_NAME *name;
520 identification_t *id;
521 int i, num;
522
523 names = X509V3_EXT_d2i(ext);
524 if (!names)
525 {
526 return FALSE;
527 }
528
529 num = sk_GENERAL_NAME_num(names);
530 for (i = 0; i < num; i++)
531 {
532 name = sk_GENERAL_NAME_value(names, i);
533 id = general_name2id(name);
534 if (id)
535 {
536 list->insert_last(list, id);
537 }
538 GENERAL_NAME_free(name);
539 }
540 sk_GENERAL_NAME_free(names);
541 return TRUE;
542 }
543
544 /**
545 * parse basic constraints
546 */
547 static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
548 X509_EXTENSION *ext)
549 {
550 BASIC_CONSTRAINTS *constraints;
551
552 constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
553 if (constraints)
554 {
555 if (constraints->ca)
556 {
557 this->flags |= X509_CA;
558 }
559 if (constraints->pathlen)
560 {
561 this->pathlen = ASN1_INTEGER_get(constraints->pathlen);
562 }
563 BASIC_CONSTRAINTS_free(constraints);
564 return TRUE;
565 }
566 return FALSE;
567 }
568
569 /**
570 * Parse CRL distribution points
571 */
572 static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
573 X509_EXTENSION *ext)
574 {
575 CRL_DIST_POINTS *cdps;
576 DIST_POINT *cdp;
577 identification_t *id;
578 char *uri;
579 int i, j, point_num, name_num;
580
581 cdps = X509V3_EXT_d2i(ext);
582 if (!cdps)
583 {
584 return FALSE;
585 }
586 point_num = sk_DIST_POINT_num(cdps);
587 for (i = 0; i < point_num; i++)
588 {
589 cdp = sk_DIST_POINT_value(cdps, i);
590 if (cdp)
591 {
592 if (cdp->distpoint && cdp->distpoint->type == 0 &&
593 cdp->distpoint->name.fullname)
594 {
595 name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
596 for (j = 0; j < name_num; j++)
597 {
598 id = general_name2id(sk_GENERAL_NAME_value(
599 cdp->distpoint->name.fullname, j));
600 if (id)
601 {
602 if (asprintf(&uri, "%Y", id) > 0)
603 {
604 this->crl_uris->insert_first(this->crl_uris, uri);
605 }
606 id->destroy(id);
607 }
608 }
609 }
610 DIST_POINT_free(cdp);
611 }
612 }
613 sk_DIST_POINT_free(cdps);
614 return TRUE;
615 }
616
617 /**
618 * Parse authorityInfoAccess with OCSP URIs
619 */
620 static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
621 X509_EXTENSION *ext)
622 {
623 AUTHORITY_INFO_ACCESS *infos;
624 ACCESS_DESCRIPTION *desc;
625 identification_t *id;
626 int i, num;
627 char *uri;
628
629 infos = X509V3_EXT_d2i(ext);
630 if (!infos)
631 {
632 return FALSE;
633 }
634 num = sk_ACCESS_DESCRIPTION_num(infos);
635 for (i = 0; i < num; i++)
636 {
637 desc = sk_ACCESS_DESCRIPTION_value(infos, i);
638 if (desc)
639 {
640 if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
641 {
642 id = general_name2id(desc->location);
643 if (id)
644 {
645 if (asprintf(&uri, "%Y", id) > 0)
646 {
647 this->ocsp_uris->insert_first(this->ocsp_uris, uri);
648 }
649 id->destroy(id);
650 }
651 }
652 ACCESS_DESCRIPTION_free(desc);
653 }
654 }
655 sk_ACCESS_DESCRIPTION_free(infos);
656 return TRUE;
657 }
658
659 /**
660 * Parse authorityKeyIdentifier extension
661 */
662 static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
663 X509_EXTENSION *ext)
664 {
665 AUTHORITY_KEYID *keyid;
666
667 keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
668 if (keyid)
669 {
670 free(this->authKeyIdentifier.ptr);
671 this->authKeyIdentifier = chunk_clone(
672 openssl_asn1_str2chunk(keyid->keyid));
673 AUTHORITY_KEYID_free(keyid);
674 return TRUE;
675 }
676 return FALSE;
677 }
678
679 /**
680 * Parse subjectKeyIdentifier extension
681 */
682 static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
683 X509_EXTENSION *ext)
684 {
685 free(this->subjectKeyIdentifier.ptr);
686 this->subjectKeyIdentifier = chunk_clone(openssl_asn1_str2chunk(
687 X509_EXTENSION_get_data(ext)));
688 return TRUE;
689 }
690
691 /**
692 * Parse X509 extensions we are interested in
693 */
694 static bool parse_extensions(private_openssl_x509_t *this)
695 {
696 STACK_OF(X509_EXTENSION) *extensions;
697 int i, num;
698
699 extensions = this->x509->cert_info->extensions;
700 if (extensions)
701 {
702 num = sk_X509_EXTENSION_num(extensions);
703
704 for (i = 0; i < num; i++)
705 {
706 X509_EXTENSION *ext;
707 bool ok;
708
709 ext = sk_X509_EXTENSION_value(extensions, i);
710 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
711 {
712 case NID_info_access:
713 ok = parse_authorityInfoAccess_ext(this, ext);
714 break;
715 case NID_authority_key_identifier:
716 ok = parse_authKeyIdentifier_ext(this, ext);
717 break;
718 case NID_subject_key_identifier:
719 ok = parse_subjectKeyIdentifier_ext(this, ext);
720 break;
721 case NID_subject_alt_name:
722 ok = parse_generalNames_ext(this->subjectAltNames, ext);
723 break;
724 case NID_issuer_alt_name:
725 ok = parse_generalNames_ext(this->issuerAltNames, ext);
726 break;
727 case NID_basic_constraints:
728 ok = parse_basicConstraints_ext(this, ext);
729 break;
730 case NID_crl_distribution_points:
731 ok = parse_crlDistributionPoints_ext(this, ext);
732 break;
733 default:
734 ok = TRUE;
735 break;
736 }
737 if (!ok)
738 {
739 return FALSE;
740 }
741 }
742 }
743 return TRUE;
744 }
745
746 /**
747 * Parse a DER encoded x509 certificate
748 */
749 static bool parse_certificate(private_openssl_x509_t *this)
750 {
751 const unsigned char *ptr = this->encoding.ptr;
752 hasher_t *hasher;
753 chunk_t chunk;
754
755 this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
756 if (!this->x509)
757 {
758 return FALSE;
759 }
760 this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
761 this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
762
763 switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
764 {
765 case OID_RSA_ENCRYPTION:
766 this->pubkey = lib->creds->create(lib->creds,
767 CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
768 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
769 BUILD_END);
770 break;
771 case OID_EC_PUBLICKEY:
772 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
773 * the curve parameters. */
774 chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
775 this->pubkey = lib->creds->create(lib->creds,
776 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
777 chunk, BUILD_END);
778 free(chunk.ptr);
779 break;
780 default:
781 DBG1(DBG_LIB, "unsupported public key algorithm");
782 break;
783 }
784 if (!this->subject || !this->issuer || !this->pubkey)
785 {
786 return FALSE;
787 }
788
789 this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
790 this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
791
792 if (!chunk_equals(
793 openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
794 openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
795 {
796 return FALSE;
797 }
798 this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
799 this->x509->sig_alg->algorithm));
800
801 if (!parse_extensions(this))
802 {
803 return TRUE;
804 }
805
806 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
807 if (!hasher)
808 {
809 return FALSE;
810 }
811 hasher->allocate_hash(hasher, this->encoding, &this->hash);
812 hasher->destroy(hasher);
813
814 if (issued_by(this, &this->public.x509.interface))
815 {
816 this->flags |= X509_SELF_SIGNED;
817 }
818 return TRUE;
819 }
820
821 openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
822 {
823 chunk_t blob = chunk_empty;
824 x509_flag_t flags = 0;
825
826 while (TRUE)
827 {
828 switch (va_arg(args, builder_part_t))
829 {
830 case BUILD_BLOB_ASN1_DER:
831 blob = va_arg(args, chunk_t);
832 continue;
833 case BUILD_X509_FLAG:
834 flags |= va_arg(args, x509_flag_t);
835 continue;
836 case BUILD_END:
837 break;
838 default:
839 return NULL;
840 }
841 break;
842 }
843
844 if (blob.ptr)
845 {
846 private_openssl_x509_t *this;
847
848 this = create_empty();
849 this->encoding = chunk_clone(blob);
850 this->flags |= flags;
851 if (parse_certificate(this))
852 {
853 return &this->public;
854 }
855 DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
856 destroy(this);
857 }
858 return NULL;
859 }