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