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