]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_x509.c
Renamed key_encod{ing,der}_t and constants, prepare for generic credential encoding
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_x509.c
CommitLineData
5728c6aa
MW
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
52typedef struct private_openssl_x509_t private_openssl_x509_t;
53
54/**
55 * Private data of an openssl_x509_t object.
56 */
57struct 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 */
158static 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:
07c5aacc
MW
176 {
177 chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
178 if (chunk.len == 4)
179 {
180 return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
181 }
182 if (chunk.len == 16)
183 {
184 return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
185 }
186 return NULL;
187 }
5728c6aa
MW
188 case GEN_DIRNAME :
189 return openssl_x509_name2id(name->d.directoryName);
190 default:
191 return NULL;
192 }
193}
194
195METHOD(x509_t, get_flags, x509_flag_t,
196 private_openssl_x509_t *this)
197{
198 return this->flags;
199}
200
201METHOD(x509_t, get_serial, chunk_t,
202 private_openssl_x509_t *this)
203{
204 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
205}
206
207METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
208 private_openssl_x509_t *this)
209{
210 chunk_t fingerprint;
211
212 if (this->subjectKeyIdentifier.len)
213 {
214 return this->subjectKeyIdentifier;
215 }
da9724e6 216 if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
5728c6aa
MW
217 &fingerprint))
218 {
219 return fingerprint;
220 }
221 return chunk_empty;
222}
223
224METHOD(x509_t, get_authKeyIdentifier, chunk_t,
225 private_openssl_x509_t *this)
226{
227 if (this->authKeyIdentifier.len)
228 {
229 return this->authKeyIdentifier;
230 }
231 return chunk_empty;
232}
233
234METHOD(x509_t, get_pathLenConstraint, int,
235 private_openssl_x509_t *this)
236{
237 return this->pathlen;
238}
239
240METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
241 private_openssl_x509_t *this)
242{
243 return this->subjectAltNames->create_enumerator(this->subjectAltNames);
244}
245
246METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
247 private_openssl_x509_t *this)
248{
249 return this->crl_uris->create_enumerator(this->crl_uris);
250}
251
252METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
253 private_openssl_x509_t *this)
254{
255 return this->ocsp_uris->create_enumerator(this->ocsp_uris);
256}
257
258METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
259 private_openssl_x509_t *this)
260{
261 /* TODO */
262 return enumerator_create_empty();
263}
264
265METHOD(certificate_t, get_type, certificate_type_t,
266 private_openssl_x509_t *this)
267{
268 return CERT_X509;
269}
270
271METHOD(certificate_t, get_subject, identification_t*,
272 private_openssl_x509_t *this)
273{
274 return this->subject;
275}
276
277METHOD(certificate_t, get_issuer, identification_t*,
278 private_openssl_x509_t *this)
279{
280 return this->issuer;
281}
282
283METHOD(certificate_t, has_subject, id_match_t,
284 private_openssl_x509_t *this, identification_t *subject)
285{
286 identification_t *current;
287 enumerator_t *enumerator;
288 id_match_t match, best;
289
290 if (subject->get_type(subject) == ID_KEY_ID)
291 {
292 if (chunk_equals(this->hash, subject->get_encoding(subject)))
293 {
294 return ID_MATCH_PERFECT;
295 }
296 }
297 best = this->subject->matches(this->subject, subject);
298 enumerator = create_subjectAltName_enumerator(this);
299 while (enumerator->enumerate(enumerator, &current))
300 {
301 match = current->matches(current, subject);
302 if (match > best)
303 {
304 best = match;
305 }
306 }
307 enumerator->destroy(enumerator);
308 return best;
309}
310
311METHOD(certificate_t, has_issuer, id_match_t,
312 private_openssl_x509_t *this, identification_t *issuer)
313{
314 /* issuerAltNames currently not supported */
315 return this->issuer->matches(this->issuer, issuer);
316}
317
318METHOD(certificate_t, issued_by, bool,
319 private_openssl_x509_t *this, certificate_t *issuer)
320{
321 public_key_t *key;
322 bool valid;
323 x509_t *x509 = (x509_t*)issuer;
324 chunk_t tbs;
325
326 if (&this->public.x509.interface == issuer)
327 {
328 if (this->flags & X509_SELF_SIGNED)
329 {
330 return TRUE;
331 }
332 }
333 else
334 {
335 if (issuer->get_type(issuer) != CERT_X509)
336 {
337 return FALSE;
338 }
339 if (!(x509->get_flags(x509) & X509_CA))
340 {
341 return FALSE;
342 }
343 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
344 {
345 return FALSE;
346 }
347 }
348 if (this->scheme == SIGN_UNKNOWN)
349 {
350 return FALSE;
351 }
352 key = issuer->get_public_key(issuer);
353 if (!key)
354 {
355 return FALSE;
356 }
357 tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
358 valid = key->verify(key, this->scheme, tbs,
359 openssl_asn1_str2chunk(this->x509->signature));
360 free(tbs.ptr);
361 key->destroy(key);
362 return valid;
363}
364
365METHOD(certificate_t, get_public_key, public_key_t*,
366 private_openssl_x509_t *this)
367{
368 return this->pubkey->get_ref(this->pubkey);
369}
370
371METHOD(certificate_t, get_validity, bool,
372 private_openssl_x509_t *this,
373 time_t *when, time_t *not_before, time_t *not_after)
374{
375 time_t t;
376
377 if (when)
378 {
379 t = *when;
380 }
381 else
382 {
383 t = time(NULL);
384 }
385 if (not_before)
386 {
387 *not_before = this->notBefore;
388 }
389 if (not_after)
390 {
391 *not_after = this->notAfter;
392 }
393 return (t >= this->notBefore && t <= this->notAfter);
394}
395
5728c6aa
MW
396METHOD(certificate_t, get_encoding, chunk_t,
397 private_openssl_x509_t *this)
398{
399 return chunk_clone(this->encoding);
400}
401
402METHOD(certificate_t, equals, bool,
403 private_openssl_x509_t *this, certificate_t *other)
404{
405 chunk_t encoding;
406 bool equal;
407
408 if (this == (private_openssl_x509_t*)other)
409 {
410 return TRUE;
411 }
412 if (other->get_type(other) != CERT_X509)
413 {
414 return FALSE;
415 }
416 if (other->equals == (void*)equals)
417 { /* skip allocation if we have the same implementation */
418 encoding = ((private_openssl_x509_t*)other)->encoding;
419 return chunk_equals(this->encoding, encoding);
420 }
421 encoding = other->get_encoding(other);
422 equal = chunk_equals(this->encoding, encoding);
423 free(encoding.ptr);
424 return equal;
425}
426
427METHOD(certificate_t, get_ref, certificate_t*,
428 private_openssl_x509_t *this)
429{
430 ref_get(&this->ref);
431 return &this->public.x509.interface;
432}
433
434METHOD(certificate_t, destroy, void,
435 private_openssl_x509_t *this)
436{
437 if (ref_put(&this->ref))
438 {
439 if (this->x509)
440 {
441 X509_free(this->x509);
442 }
443 DESTROY_IF(this->subject);
444 DESTROY_IF(this->issuer);
445 DESTROY_IF(this->pubkey);
446 free(this->subjectKeyIdentifier.ptr);
447 free(this->authKeyIdentifier.ptr);
448 free(this->encoding.ptr);
449 free(this->hash.ptr);
450 this->subjectAltNames->destroy_offset(this->subjectAltNames,
451 offsetof(identification_t, destroy));
452 this->issuerAltNames->destroy_offset(this->issuerAltNames,
453 offsetof(identification_t, destroy));
454 this->crl_uris->destroy_function(this->crl_uris, free);
455 this->ocsp_uris->destroy_function(this->ocsp_uris, free);
456 free(this);
457 }
458}
459
460/**
461 * Create an empty certificate
462 */
463static private_openssl_x509_t *create_empty()
464{
465 private_openssl_x509_t *this;
466
467 INIT(this,
468 .public = {
469 .x509 = {
470 .interface = {
471 .get_type = _get_type,
472 .get_subject = _get_subject,
473 .get_issuer = _get_issuer,
474 .has_subject = _has_subject,
475 .has_issuer = _has_issuer,
476 .issued_by = _issued_by,
477 .get_public_key = _get_public_key,
478 .get_validity = _get_validity,
5728c6aa
MW
479 .get_encoding = _get_encoding,
480 .equals = _equals,
481 .get_ref = _get_ref,
482 .destroy = _destroy,
483 },
484 .get_flags = _get_flags,
485 .get_serial = _get_serial,
486 .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
487 .get_authKeyIdentifier = _get_authKeyIdentifier,
488 .get_pathLenConstraint = _get_pathLenConstraint,
489 .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
490 .create_crl_uri_enumerator = _create_crl_uri_enumerator,
491 .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
492 .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
493 },
494 },
495 .subjectAltNames = linked_list_create(),
496 .issuerAltNames = linked_list_create(),
497 .crl_uris = linked_list_create(),
498 .ocsp_uris = linked_list_create(),
499 .pathlen = X509_NO_PATH_LEN_CONSTRAINT,
500 .ref = 1,
501 );
502
503 return this;
504}
505
506/**
507 * parse an extionsion containing GENERAL_NAMES into a list
508 */
509static bool parse_generalNames_ext(linked_list_t *list,
510 X509_EXTENSION *ext)
511{
512 GENERAL_NAMES *names;
513 GENERAL_NAME *name;
514 identification_t *id;
515 int i, num;
516
517 names = X509V3_EXT_d2i(ext);
518 if (!names)
519 {
520 return FALSE;
521 }
522
523 num = sk_GENERAL_NAME_num(names);
524 for (i = 0; i < num; i++)
525 {
526 name = sk_GENERAL_NAME_value(names, i);
527 id = general_name2id(name);
528 if (id)
529 {
530 list->insert_last(list, id);
531 }
532 GENERAL_NAME_free(name);
533 }
534 sk_GENERAL_NAME_free(names);
535 return TRUE;
536}
537
538/**
539 * parse basic constraints
540 */
541static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
542 X509_EXTENSION *ext)
543{
544 BASIC_CONSTRAINTS *constraints;
545
546 constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
547 if (constraints)
548 {
549 if (constraints->ca)
550 {
551 this->flags |= X509_CA;
552 }
553 if (constraints->pathlen)
554 {
555 this->pathlen = ASN1_INTEGER_get(constraints->pathlen);
556 }
557 BASIC_CONSTRAINTS_free(constraints);
558 return TRUE;
559 }
560 return FALSE;
561}
562
563/**
564 * Parse CRL distribution points
565 */
566static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
567 X509_EXTENSION *ext)
568{
569 CRL_DIST_POINTS *cdps;
570 DIST_POINT *cdp;
571 identification_t *id;
572 char *uri;
573 int i, j, point_num, name_num;
574
575 cdps = X509V3_EXT_d2i(ext);
576 if (!cdps)
577 {
578 return FALSE;
579 }
580 point_num = sk_DIST_POINT_num(cdps);
581 for (i = 0; i < point_num; i++)
582 {
583 cdp = sk_DIST_POINT_value(cdps, i);
584 if (cdp)
585 {
586 if (cdp->distpoint && cdp->distpoint->type == 0 &&
587 cdp->distpoint->name.fullname)
588 {
589 name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
590 for (j = 0; j < name_num; j++)
591 {
592 id = general_name2id(sk_GENERAL_NAME_value(
593 cdp->distpoint->name.fullname, j));
594 if (id)
595 {
596 if (asprintf(&uri, "%Y", id) > 0)
597 {
598 this->crl_uris->insert_first(this->crl_uris, uri);
599 }
600 id->destroy(id);
601 }
602 }
603 }
604 DIST_POINT_free(cdp);
605 }
606 }
607 sk_DIST_POINT_free(cdps);
608 return TRUE;
609}
610
611/**
612 * Parse authorityInfoAccess with OCSP URIs
613 */
614static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
615 X509_EXTENSION *ext)
616{
617 AUTHORITY_INFO_ACCESS *infos;
618 ACCESS_DESCRIPTION *desc;
619 identification_t *id;
620 int i, num;
621 char *uri;
622
623 infos = X509V3_EXT_d2i(ext);
624 if (!infos)
625 {
626 return FALSE;
627 }
628 num = sk_ACCESS_DESCRIPTION_num(infos);
629 for (i = 0; i < num; i++)
630 {
631 desc = sk_ACCESS_DESCRIPTION_value(infos, i);
632 if (desc)
633 {
634 if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
635 {
636 id = general_name2id(desc->location);
637 if (id)
638 {
639 if (asprintf(&uri, "%Y", id) > 0)
640 {
641 this->ocsp_uris->insert_first(this->ocsp_uris, uri);
642 }
643 id->destroy(id);
644 }
645 }
646 ACCESS_DESCRIPTION_free(desc);
647 }
648 }
649 sk_ACCESS_DESCRIPTION_free(infos);
650 return TRUE;
651}
652
653/**
654 * Parse authorityKeyIdentifier extension
655 */
656static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
657 X509_EXTENSION *ext)
658{
659 AUTHORITY_KEYID *keyid;
660
661 keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
662 if (keyid)
663 {
664 free(this->authKeyIdentifier.ptr);
665 this->authKeyIdentifier = chunk_clone(
666 openssl_asn1_str2chunk(keyid->keyid));
667 AUTHORITY_KEYID_free(keyid);
668 return TRUE;
669 }
670 return FALSE;
671}
672
673/**
674 * Parse subjectKeyIdentifier extension
675 */
676static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
677 X509_EXTENSION *ext)
678{
f00a1015
MW
679 chunk_t ostr;
680
681 ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
682 /* quick and dirty unwrap of octet string */
683 if (ostr.len > 2 &&
684 ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
685 {
686 free(this->subjectKeyIdentifier.ptr);
687 this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
688 return TRUE;
689 }
690 return FALSE;
5728c6aa
MW
691}
692
693/**
694 * Parse X509 extensions we are interested in
695 */
696static bool parse_extensions(private_openssl_x509_t *this)
697{
698 STACK_OF(X509_EXTENSION) *extensions;
699 int i, num;
700
701 extensions = this->x509->cert_info->extensions;
702 if (extensions)
703 {
704 num = sk_X509_EXTENSION_num(extensions);
705
706 for (i = 0; i < num; i++)
707 {
708 X509_EXTENSION *ext;
709 bool ok;
710
711 ext = sk_X509_EXTENSION_value(extensions, i);
712 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
713 {
714 case NID_info_access:
715 ok = parse_authorityInfoAccess_ext(this, ext);
716 break;
717 case NID_authority_key_identifier:
718 ok = parse_authKeyIdentifier_ext(this, ext);
719 break;
720 case NID_subject_key_identifier:
721 ok = parse_subjectKeyIdentifier_ext(this, ext);
722 break;
723 case NID_subject_alt_name:
724 ok = parse_generalNames_ext(this->subjectAltNames, ext);
725 break;
726 case NID_issuer_alt_name:
727 ok = parse_generalNames_ext(this->issuerAltNames, ext);
728 break;
729 case NID_basic_constraints:
730 ok = parse_basicConstraints_ext(this, ext);
731 break;
732 case NID_crl_distribution_points:
733 ok = parse_crlDistributionPoints_ext(this, ext);
734 break;
735 default:
736 ok = TRUE;
737 break;
738 }
739 if (!ok)
740 {
741 return FALSE;
742 }
743 }
744 }
745 return TRUE;
746}
747
748/**
749 * Parse a DER encoded x509 certificate
750 */
751static bool parse_certificate(private_openssl_x509_t *this)
752{
753 const unsigned char *ptr = this->encoding.ptr;
754 hasher_t *hasher;
755 chunk_t chunk;
756
757 this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
758 if (!this->x509)
759 {
760 return FALSE;
761 }
762 this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
763 this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
764
765 switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
766 {
767 case OID_RSA_ENCRYPTION:
768 this->pubkey = lib->creds->create(lib->creds,
769 CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
770 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
771 BUILD_END);
772 break;
773 case OID_EC_PUBLICKEY:
774 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
775 * the curve parameters. */
776 chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
777 this->pubkey = lib->creds->create(lib->creds,
778 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
779 chunk, BUILD_END);
780 free(chunk.ptr);
781 break;
782 default:
783 DBG1(DBG_LIB, "unsupported public key algorithm");
784 break;
785 }
786 if (!this->subject || !this->issuer || !this->pubkey)
787 {
788 return FALSE;
789 }
790
791 this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
792 this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
793
794 if (!chunk_equals(
795 openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
796 openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
797 {
798 return FALSE;
799 }
800 this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
801 this->x509->sig_alg->algorithm));
802
803 if (!parse_extensions(this))
804 {
805 return TRUE;
806 }
807
808 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
809 if (!hasher)
810 {
811 return FALSE;
812 }
813 hasher->allocate_hash(hasher, this->encoding, &this->hash);
814 hasher->destroy(hasher);
815
816 if (issued_by(this, &this->public.x509.interface))
817 {
818 this->flags |= X509_SELF_SIGNED;
819 }
820 return TRUE;
821}
822
823openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
824{
825 chunk_t blob = chunk_empty;
826 x509_flag_t flags = 0;
827
828 while (TRUE)
829 {
830 switch (va_arg(args, builder_part_t))
831 {
832 case BUILD_BLOB_ASN1_DER:
833 blob = va_arg(args, chunk_t);
834 continue;
835 case BUILD_X509_FLAG:
836 flags |= va_arg(args, x509_flag_t);
837 continue;
838 case BUILD_END:
839 break;
840 default:
841 return NULL;
842 }
843 break;
844 }
845
846 if (blob.ptr)
847 {
848 private_openssl_x509_t *this;
849
850 this = create_empty();
851 this->encoding = chunk_clone(blob);
852 this->flags |= flags;
853 if (parse_certificate(this))
854 {
855 return &this->public;
856 }
857 DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
858 destroy(this);
859 }
860 return NULL;
861}