80e421ab66b50461aa09f229e708e1db82c0861d
[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, as crl_uri_t
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 * CRL URIs with associated issuer
157 */
158 typedef struct {
159 identification_t *issuer;
160 linked_list_t *uris;
161 } crl_uri_t;
162
163 /**
164 * Create a new issuer entry
165 */
166 static crl_uri_t *crl_uri_create()
167 {
168 crl_uri_t *this;
169
170 INIT(this,
171 .uris = linked_list_create(),
172 );
173 return this;
174 }
175
176 /**
177 * Destroy a CRL URI struct
178 */
179 static void crl_uri_destroy(crl_uri_t *this)
180 {
181 this->uris->destroy_function(this->uris, free);
182 DESTROY_IF(this->issuer);
183 free(this);
184 }
185
186 /**
187 * Convert a GeneralName to an identification_t.
188 */
189 static identification_t *general_name2id(GENERAL_NAME *name)
190 {
191 if (!name)
192 {
193 return NULL;
194 }
195 switch (name->type)
196 {
197 case GEN_EMAIL:
198 return identification_create_from_encoding(ID_RFC822_ADDR,
199 openssl_asn1_str2chunk(name->d.rfc822Name));
200 case GEN_DNS:
201 return identification_create_from_encoding(ID_FQDN,
202 openssl_asn1_str2chunk(name->d.dNSName));
203 case GEN_URI:
204 return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
205 openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
206 case GEN_IPADD:
207 {
208 chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
209 if (chunk.len == 4)
210 {
211 return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
212 }
213 if (chunk.len == 16)
214 {
215 return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
216 }
217 return NULL;
218 }
219 case GEN_DIRNAME :
220 return openssl_x509_name2id(name->d.directoryName);
221 case GEN_OTHERNAME:
222 if (OBJ_obj2nid(name->d.otherName->type_id) == NID_ms_upn &&
223 name->d.otherName->value->type == V_ASN1_UTF8STRING)
224 {
225 return identification_create_from_encoding(ID_RFC822_ADDR,
226 openssl_asn1_str2chunk(
227 name->d.otherName->value->value.utf8string));
228 }
229 return NULL;
230 default:
231 return NULL;
232 }
233 }
234
235 METHOD(x509_t, get_flags, x509_flag_t,
236 private_openssl_x509_t *this)
237 {
238 return this->flags;
239 }
240
241 METHOD(x509_t, get_serial, chunk_t,
242 private_openssl_x509_t *this)
243 {
244 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
245 }
246
247 METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
248 private_openssl_x509_t *this)
249 {
250 chunk_t fingerprint;
251
252 if (this->subjectKeyIdentifier.len)
253 {
254 return this->subjectKeyIdentifier;
255 }
256 if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
257 &fingerprint))
258 {
259 return fingerprint;
260 }
261 return chunk_empty;
262 }
263
264 METHOD(x509_t, get_authKeyIdentifier, chunk_t,
265 private_openssl_x509_t *this)
266 {
267 if (this->authKeyIdentifier.len)
268 {
269 return this->authKeyIdentifier;
270 }
271 return chunk_empty;
272 }
273
274 METHOD(x509_t, get_pathLenConstraint, int,
275 private_openssl_x509_t *this)
276 {
277 return this->pathlen;
278 }
279
280 METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
281 private_openssl_x509_t *this)
282 {
283 return this->subjectAltNames->create_enumerator(this->subjectAltNames);
284 }
285
286 /**
287 * Convert enumerator value from entry to (uri, issuer)
288 */
289 static bool crl_enum_filter(identification_t *issuer_in,
290 char **uri_in, char **uri_out,
291 void *none_in, identification_t **issuer_out)
292 {
293 *uri_out = *uri_in;
294 if (issuer_out)
295 {
296 *issuer_out = issuer_in;
297 }
298 return TRUE;
299 }
300
301 /**
302 * Create inner enumerator over URIs
303 */
304 static enumerator_t *crl_enum_create(crl_uri_t *entry)
305 {
306 return enumerator_create_filter(entry->uris->create_enumerator(entry->uris),
307 (void*)crl_enum_filter, entry->issuer, NULL);
308 }
309
310 METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
311 private_openssl_x509_t *this)
312 {
313 return enumerator_create_nested(
314 this->crl_uris->create_enumerator(this->crl_uris),
315 (void*)crl_enum_create, NULL, NULL);
316 }
317
318 METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
319 private_openssl_x509_t *this)
320 {
321 return this->ocsp_uris->create_enumerator(this->ocsp_uris);
322 }
323
324 METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
325 private_openssl_x509_t *this)
326 {
327 /* TODO */
328 return enumerator_create_empty();
329 }
330
331 METHOD(certificate_t, get_type, certificate_type_t,
332 private_openssl_x509_t *this)
333 {
334 return CERT_X509;
335 }
336
337 METHOD(certificate_t, get_subject, identification_t*,
338 private_openssl_x509_t *this)
339 {
340 return this->subject;
341 }
342
343 METHOD(certificate_t, get_issuer, identification_t*,
344 private_openssl_x509_t *this)
345 {
346 return this->issuer;
347 }
348
349 METHOD(certificate_t, has_subject, id_match_t,
350 private_openssl_x509_t *this, identification_t *subject)
351 {
352 identification_t *current;
353 enumerator_t *enumerator;
354 id_match_t match, best;
355 chunk_t encoding;
356
357 if (subject->get_type(subject) == ID_KEY_ID)
358 {
359 encoding = subject->get_encoding(subject);
360
361 if (chunk_equals(this->hash, encoding))
362 {
363 return ID_MATCH_PERFECT;
364 }
365 if (this->subjectKeyIdentifier.len &&
366 chunk_equals(this->subjectKeyIdentifier, encoding))
367 {
368 return ID_MATCH_PERFECT;
369 }
370 if (this->pubkey &&
371 this->pubkey->has_fingerprint(this->pubkey, encoding))
372 {
373 return ID_MATCH_PERFECT;
374 }
375 }
376 best = this->subject->matches(this->subject, subject);
377 enumerator = create_subjectAltName_enumerator(this);
378 while (enumerator->enumerate(enumerator, &current))
379 {
380 match = current->matches(current, subject);
381 if (match > best)
382 {
383 best = match;
384 }
385 }
386 enumerator->destroy(enumerator);
387 return best;
388 }
389
390 METHOD(certificate_t, has_issuer, id_match_t,
391 private_openssl_x509_t *this, identification_t *issuer)
392 {
393 /* issuerAltNames currently not supported */
394 return this->issuer->matches(this->issuer, issuer);
395 }
396
397 METHOD(certificate_t, issued_by, bool,
398 private_openssl_x509_t *this, certificate_t *issuer)
399 {
400 public_key_t *key;
401 bool valid;
402 x509_t *x509 = (x509_t*)issuer;
403 chunk_t tbs;
404
405 if (&this->public.x509.interface == issuer)
406 {
407 if (this->flags & X509_SELF_SIGNED)
408 {
409 return TRUE;
410 }
411 }
412 else
413 {
414 if (issuer->get_type(issuer) != CERT_X509)
415 {
416 return FALSE;
417 }
418 if (!(x509->get_flags(x509) & X509_CA))
419 {
420 return FALSE;
421 }
422 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
423 {
424 return FALSE;
425 }
426 }
427 if (this->scheme == SIGN_UNKNOWN)
428 {
429 return FALSE;
430 }
431 key = issuer->get_public_key(issuer);
432 if (!key)
433 {
434 return FALSE;
435 }
436 tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
437 valid = key->verify(key, this->scheme, tbs,
438 openssl_asn1_str2chunk(this->x509->signature));
439 free(tbs.ptr);
440 key->destroy(key);
441 return valid;
442 }
443
444 METHOD(certificate_t, get_public_key, public_key_t*,
445 private_openssl_x509_t *this)
446 {
447 return this->pubkey->get_ref(this->pubkey);
448 }
449
450 METHOD(certificate_t, get_validity, bool,
451 private_openssl_x509_t *this,
452 time_t *when, time_t *not_before, time_t *not_after)
453 {
454 time_t t;
455
456 if (when)
457 {
458 t = *when;
459 }
460 else
461 {
462 t = time(NULL);
463 }
464 if (not_before)
465 {
466 *not_before = this->notBefore;
467 }
468 if (not_after)
469 {
470 *not_after = this->notAfter;
471 }
472 return (t >= this->notBefore && t <= this->notAfter);
473 }
474
475 METHOD(certificate_t, get_encoding, bool,
476 private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
477 {
478 if (type == CERT_ASN1_DER)
479 {
480 *encoding = chunk_clone(this->encoding);
481 return TRUE;
482 }
483 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
484 CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
485 }
486
487
488 METHOD(certificate_t, equals, bool,
489 private_openssl_x509_t *this, certificate_t *other)
490 {
491 chunk_t encoding;
492 bool equal;
493
494 if (this == (private_openssl_x509_t*)other)
495 {
496 return TRUE;
497 }
498 if (other->get_type(other) != CERT_X509)
499 {
500 return FALSE;
501 }
502 if (other->equals == (void*)equals)
503 { /* skip allocation if we have the same implementation */
504 encoding = ((private_openssl_x509_t*)other)->encoding;
505 return chunk_equals(this->encoding, encoding);
506 }
507 if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
508 {
509 return FALSE;
510 }
511 equal = chunk_equals(this->encoding, encoding);
512 free(encoding.ptr);
513 return equal;
514 }
515
516 METHOD(certificate_t, get_ref, certificate_t*,
517 private_openssl_x509_t *this)
518 {
519 ref_get(&this->ref);
520 return &this->public.x509.interface;
521 }
522
523 METHOD(certificate_t, destroy, void,
524 private_openssl_x509_t *this)
525 {
526 if (ref_put(&this->ref))
527 {
528 if (this->x509)
529 {
530 X509_free(this->x509);
531 }
532 DESTROY_IF(this->subject);
533 DESTROY_IF(this->issuer);
534 DESTROY_IF(this->pubkey);
535 free(this->subjectKeyIdentifier.ptr);
536 free(this->authKeyIdentifier.ptr);
537 free(this->encoding.ptr);
538 free(this->hash.ptr);
539 this->subjectAltNames->destroy_offset(this->subjectAltNames,
540 offsetof(identification_t, destroy));
541 this->issuerAltNames->destroy_offset(this->issuerAltNames,
542 offsetof(identification_t, destroy));
543 this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy);
544 this->ocsp_uris->destroy_function(this->ocsp_uris, free);
545 free(this);
546 }
547 }
548
549 /**
550 * Create an empty certificate
551 */
552 static private_openssl_x509_t *create_empty()
553 {
554 private_openssl_x509_t *this;
555
556 INIT(this,
557 .public = {
558 .x509 = {
559 .interface = {
560 .get_type = _get_type,
561 .get_subject = _get_subject,
562 .get_issuer = _get_issuer,
563 .has_subject = _has_subject,
564 .has_issuer = _has_issuer,
565 .issued_by = _issued_by,
566 .get_public_key = _get_public_key,
567 .get_validity = _get_validity,
568 .get_encoding = _get_encoding,
569 .equals = _equals,
570 .get_ref = _get_ref,
571 .destroy = _destroy,
572 },
573 .get_flags = _get_flags,
574 .get_serial = _get_serial,
575 .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
576 .get_authKeyIdentifier = _get_authKeyIdentifier,
577 .get_pathLenConstraint = _get_pathLenConstraint,
578 .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
579 .create_crl_uri_enumerator = _create_crl_uri_enumerator,
580 .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
581 .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
582 .create_name_constraint_enumerator = (void*)enumerator_create_empty,
583 },
584 },
585 .subjectAltNames = linked_list_create(),
586 .issuerAltNames = linked_list_create(),
587 .crl_uris = linked_list_create(),
588 .ocsp_uris = linked_list_create(),
589 .pathlen = X509_NO_PATH_LEN_CONSTRAINT,
590 .ref = 1,
591 );
592
593 return this;
594 }
595
596 /**
597 * parse an extionsion containing GENERAL_NAMES into a list
598 */
599 static bool parse_generalNames_ext(linked_list_t *list,
600 X509_EXTENSION *ext)
601 {
602 GENERAL_NAMES *names;
603 GENERAL_NAME *name;
604 identification_t *id;
605 int i, num;
606
607 names = X509V3_EXT_d2i(ext);
608 if (!names)
609 {
610 return FALSE;
611 }
612
613 num = sk_GENERAL_NAME_num(names);
614 for (i = 0; i < num; i++)
615 {
616 name = sk_GENERAL_NAME_value(names, i);
617 id = general_name2id(name);
618 if (id)
619 {
620 list->insert_last(list, id);
621 }
622 GENERAL_NAME_free(name);
623 }
624 sk_GENERAL_NAME_free(names);
625 return TRUE;
626 }
627
628 /**
629 * parse basic constraints
630 */
631 static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
632 X509_EXTENSION *ext)
633 {
634 BASIC_CONSTRAINTS *constraints;
635
636 constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
637 if (constraints)
638 {
639 if (constraints->ca)
640 {
641 this->flags |= X509_CA;
642 }
643 if (constraints->pathlen)
644 {
645 this->pathlen = ASN1_INTEGER_get(constraints->pathlen);
646 }
647 BASIC_CONSTRAINTS_free(constraints);
648 return TRUE;
649 }
650 return FALSE;
651 }
652
653 /**
654 * Parse CRL distribution points
655 */
656 static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
657 X509_EXTENSION *ext)
658 {
659 CRL_DIST_POINTS *cdps;
660 DIST_POINT *cdp;
661 identification_t *id;
662 char *uri;
663 int i, j, point_num, name_num;
664
665 cdps = X509V3_EXT_d2i(ext);
666 if (!cdps)
667 {
668 return FALSE;
669 }
670 point_num = sk_DIST_POINT_num(cdps);
671 for (i = 0; i < point_num; i++)
672 {
673 cdp = sk_DIST_POINT_value(cdps, i);
674 if (cdp)
675 {
676 crl_uri_t *entry;
677
678 entry = crl_uri_create();
679 this->crl_uris->insert_last(this->crl_uris, entry);
680
681 if (cdp->distpoint && cdp->distpoint->type == 0 &&
682 cdp->distpoint->name.fullname)
683 {
684 name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
685 for (j = 0; j < name_num; j++)
686 {
687 id = general_name2id(sk_GENERAL_NAME_value(
688 cdp->distpoint->name.fullname, j));
689 if (id)
690 {
691 if (asprintf(&uri, "%Y", id) > 0)
692 {
693 entry->uris->insert_last(entry->uris, uri);
694 }
695 id->destroy(id);
696 }
697 }
698 }
699 if (cdp->CRLissuer)
700 {
701 name_num = sk_GENERAL_NAME_num(cdp->CRLissuer);
702 for (j = 0; j < name_num; j++)
703 {
704 id = general_name2id(sk_GENERAL_NAME_value(cdp->CRLissuer, j));
705 if (id)
706 { /* get only one */
707 entry->issuer = id;
708 break;
709 }
710 }
711 }
712 DIST_POINT_free(cdp);
713 }
714 }
715 sk_DIST_POINT_free(cdps);
716 return TRUE;
717 }
718
719 /**
720 * Parse authorityInfoAccess with OCSP URIs
721 */
722 static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
723 X509_EXTENSION *ext)
724 {
725 AUTHORITY_INFO_ACCESS *infos;
726 ACCESS_DESCRIPTION *desc;
727 identification_t *id;
728 int i, num;
729 char *uri;
730
731 infos = X509V3_EXT_d2i(ext);
732 if (!infos)
733 {
734 return FALSE;
735 }
736 num = sk_ACCESS_DESCRIPTION_num(infos);
737 for (i = 0; i < num; i++)
738 {
739 desc = sk_ACCESS_DESCRIPTION_value(infos, i);
740 if (desc)
741 {
742 if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
743 {
744 id = general_name2id(desc->location);
745 if (id)
746 {
747 if (asprintf(&uri, "%Y", id) > 0)
748 {
749 this->ocsp_uris->insert_first(this->ocsp_uris, uri);
750 }
751 id->destroy(id);
752 }
753 }
754 ACCESS_DESCRIPTION_free(desc);
755 }
756 }
757 sk_ACCESS_DESCRIPTION_free(infos);
758 return TRUE;
759 }
760
761 /**
762 * Parse authorityKeyIdentifier extension
763 */
764 static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
765 X509_EXTENSION *ext)
766 {
767 AUTHORITY_KEYID *keyid;
768
769 keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
770 if (keyid)
771 {
772 free(this->authKeyIdentifier.ptr);
773 this->authKeyIdentifier = chunk_clone(
774 openssl_asn1_str2chunk(keyid->keyid));
775 AUTHORITY_KEYID_free(keyid);
776 return TRUE;
777 }
778 return FALSE;
779 }
780
781 /**
782 * Parse subjectKeyIdentifier extension
783 */
784 static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
785 X509_EXTENSION *ext)
786 {
787 chunk_t ostr;
788
789 ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
790 /* quick and dirty unwrap of octet string */
791 if (ostr.len > 2 &&
792 ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
793 {
794 free(this->subjectKeyIdentifier.ptr);
795 this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
796 return TRUE;
797 }
798 return FALSE;
799 }
800
801 /**
802 * Parse X509 extensions we are interested in
803 */
804 static bool parse_extensions(private_openssl_x509_t *this)
805 {
806 STACK_OF(X509_EXTENSION) *extensions;
807 int i, num;
808
809 extensions = this->x509->cert_info->extensions;
810 if (extensions)
811 {
812 num = sk_X509_EXTENSION_num(extensions);
813
814 for (i = 0; i < num; i++)
815 {
816 X509_EXTENSION *ext;
817 bool ok;
818
819 ext = sk_X509_EXTENSION_value(extensions, i);
820 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
821 {
822 case NID_info_access:
823 ok = parse_authorityInfoAccess_ext(this, ext);
824 break;
825 case NID_authority_key_identifier:
826 ok = parse_authKeyIdentifier_ext(this, ext);
827 break;
828 case NID_subject_key_identifier:
829 ok = parse_subjectKeyIdentifier_ext(this, ext);
830 break;
831 case NID_subject_alt_name:
832 ok = parse_generalNames_ext(this->subjectAltNames, ext);
833 break;
834 case NID_issuer_alt_name:
835 ok = parse_generalNames_ext(this->issuerAltNames, ext);
836 break;
837 case NID_basic_constraints:
838 ok = parse_basicConstraints_ext(this, ext);
839 break;
840 case NID_crl_distribution_points:
841 ok = parse_crlDistributionPoints_ext(this, ext);
842 break;
843 default:
844 ok = X509_EXTENSION_get_critical(ext) != 0;
845 if (!ok)
846 {
847 DBG1(DBG_LIB, "found unsupported critical X.509 extension");
848 }
849 break;
850 }
851 if (!ok)
852 {
853 return FALSE;
854 }
855 }
856 }
857 return TRUE;
858 }
859
860 /**
861 * Parse ExtendedKeyUsage
862 */
863 static void parse_extKeyUsage(private_openssl_x509_t *this)
864 {
865 EXTENDED_KEY_USAGE *usage;
866 int i;
867
868 usage = X509_get_ext_d2i(this->x509, NID_ext_key_usage, NULL, NULL);
869 if (usage)
870 {
871 for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
872 {
873 switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
874 {
875 case NID_server_auth:
876 this->flags |= X509_SERVER_AUTH;
877 break;
878 case NID_client_auth:
879 this->flags |= X509_CLIENT_AUTH;
880 break;
881 case NID_OCSP_sign:
882 this->flags |= X509_OCSP_SIGNER;
883 break;
884 default:
885 break;
886 }
887 }
888 sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
889 }
890 }
891
892 /**
893 * Parse a DER encoded x509 certificate
894 */
895 static bool parse_certificate(private_openssl_x509_t *this)
896 {
897 const unsigned char *ptr = this->encoding.ptr;
898 hasher_t *hasher;
899 chunk_t chunk;
900
901 this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
902 if (!this->x509)
903 {
904 return FALSE;
905 }
906 if (X509_get_version(this->x509) < 0 || X509_get_version(this->x509) > 2)
907 {
908 DBG1(DBG_LIB, "unsupported x509 version: %d",
909 X509_get_version(this->x509) + 1);
910 return FALSE;
911 }
912
913 this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
914 this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
915
916 switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
917 {
918 case OID_RSA_ENCRYPTION:
919 this->pubkey = lib->creds->create(lib->creds,
920 CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
921 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
922 BUILD_END);
923 break;
924 case OID_EC_PUBLICKEY:
925 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
926 * the curve parameters. */
927 chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
928 this->pubkey = lib->creds->create(lib->creds,
929 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
930 chunk, BUILD_END);
931 free(chunk.ptr);
932 break;
933 default:
934 DBG1(DBG_LIB, "unsupported public key algorithm");
935 break;
936 }
937 if (!this->subject || !this->issuer || !this->pubkey)
938 {
939 return FALSE;
940 }
941
942 this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
943 this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
944
945 if (!chunk_equals(
946 openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
947 openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
948 {
949 return FALSE;
950 }
951 this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
952 this->x509->sig_alg->algorithm));
953
954 if (!parse_extensions(this))
955 {
956 return TRUE;
957 }
958 parse_extKeyUsage(this);
959
960 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
961 if (!hasher)
962 {
963 return FALSE;
964 }
965 hasher->allocate_hash(hasher, this->encoding, &this->hash);
966 hasher->destroy(hasher);
967
968 if (issued_by(this, &this->public.x509.interface))
969 {
970 this->flags |= X509_SELF_SIGNED;
971 }
972 return TRUE;
973 }
974
975 openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
976 {
977 chunk_t blob = chunk_empty;
978 x509_flag_t flags = 0;
979
980 while (TRUE)
981 {
982 switch (va_arg(args, builder_part_t))
983 {
984 case BUILD_BLOB_ASN1_DER:
985 blob = va_arg(args, chunk_t);
986 continue;
987 case BUILD_X509_FLAG:
988 flags |= va_arg(args, x509_flag_t);
989 continue;
990 case BUILD_END:
991 break;
992 default:
993 return NULL;
994 }
995 break;
996 }
997
998 if (blob.ptr)
999 {
1000 private_openssl_x509_t *this;
1001
1002 this = create_empty();
1003 this->encoding = chunk_clone(blob);
1004 this->flags |= flags;
1005 if (parse_certificate(this))
1006 {
1007 return &this->public;
1008 }
1009 DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
1010 destroy(this);
1011 }
1012 return NULL;
1013 }