]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_x509.c
x509: Add support for IP address nameConstraints
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_x509.c
CommitLineData
5728c6aa 1/*
f781b9d3 2 * Copyright (C) 2011-2023 Tobias Brunner
5728c6aa 3 * Copyright (C) 2010 Martin Willi
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
5728c6aa
MW
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18/*
5e4b1ad2
MR
19 * Copyright (C) 2013 Michael Rossberg
20 * Copyright (C) 2013 Technische Universität Ilmenau
21 *
5728c6aa
MW
22 * Copyright (C) 2010 Thomas Egerer
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy
25 * of this software and associated documentation files (the "Software"), to deal
26 * in the Software without restriction, including without limitation the rights
27 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 * copies of the Software, and to permit persons to whom the Software is
29 * furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in
32 * all copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 * THE SOFTWARE.
41 */
42
43#define _GNU_SOURCE
44#include <stdio.h>
45#include <openssl/x509.h>
46#include <openssl/x509v3.h>
47
48#include "openssl_x509.h"
49#include "openssl_util.h"
50
f05b4272 51#include <utils/debug.h>
5728c6aa 52#include <asn1/oid.h>
12642a68 53#include <collections/linked_list.h>
5e4b1ad2 54#include <selectors/traffic_selector.h>
5728c6aa 55
5e4b1ad2
MR
56/* IP Addr block extension support was introduced with 0.9.8e */
57#if OPENSSL_VERSION_NUMBER < 0x0090805fL
58#define OPENSSL_NO_RFC3779
59#endif
5728c6aa 60
08d7e1f1
TB
61/* added with 1.0.2 */
62#if OPENSSL_VERSION_NUMBER < 0x10002000L
63static inline void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) {
64 if (psig) { *psig = x->signature; }
65 if (palg) { *palg = x->sig_alg; }
66}
67#endif
68
69/* added with 1.1.0 when X509 etc. was made opaque */
70#if OPENSSL_VERSION_NUMBER < 0x10100000L
71#define X509_get0_extensions(x509) ({ (x509)->cert_info->extensions; })
72#define X509_get0_tbs_sigalg(x509) ({ (x509)->cert_info->signature; })
73#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; })
74#define X509_PUBKEY_get0_param(oid, pk, len, pa, pub) X509_ALGOR_get0(oid, NULL, NULL, (pub)->algor)
75#define X509v3_addr_get_afi v3_addr_get_afi
76#define X509v3_addr_get_range v3_addr_get_range
77#define X509v3_addr_is_canonical v3_addr_is_canonical
a4abb263
TB
78#define X509_get0_notBefore X509_get_notBefore
79#define X509_get0_notAfter X509_get_notAfter
08d7e1f1
TB
80#endif
81
5728c6aa
MW
82typedef struct private_openssl_x509_t private_openssl_x509_t;
83
84/**
85 * Private data of an openssl_x509_t object.
86 */
87struct private_openssl_x509_t {
88
89 /**
90 * Public openssl_x509_t interface.
91 */
92 openssl_x509_t public;
93
94 /**
95 * OpenSSL certificate representation
96 */
97 X509 *x509;
98
99 /**
100 * DER encoded certificate
101 */
102 chunk_t encoding;
103
104 /**
105 * SHA1 hash of the certificate
106 */
107 chunk_t hash;
108
109 /**
110 * X509 flags
111 */
112 x509_flag_t flags;
113
114 /**
115 * Pathlen constraint
116 */
d390b3b9 117 u_char pathlen;
5728c6aa
MW
118
119 /**
120 * certificate subject
121 */
122 identification_t *subject;
123
124 /**
125 * certificate issuer
126 */
127 identification_t *issuer;
128
129 /**
130 * Certificates public key
131 */
132 public_key_t *pubkey;
133
134 /**
135 * subjectKeyIdentifier as read from cert
136 */
137 chunk_t subjectKeyIdentifier;
138
139 /**
140 * authorityKeyIdentifier as read from cert
141 */
142 chunk_t authKeyIdentifier;
143
144 /**
145 * Start time of certificate validity
146 */
147 time_t notBefore;
148
149 /**
150 * End time of certificate validity
151 */
152 time_t notAfter;
153
154 /**
155 * Signature scheme of the certificate
156 */
fb63012e 157 signature_params_t *scheme;
5728c6aa
MW
158
159 /**
160 * subjectAltNames
161 */
162 linked_list_t *subjectAltNames;
163
164 /**
165 * issuerAltNames
166 */
167 linked_list_t *issuerAltNames;
168
169 /**
a6478a04 170 * List of CRL URIs, as x509_cdp_t
5728c6aa
MW
171 */
172 linked_list_t *crl_uris;
173
174 /**
175 * List of OCSP URIs
176 */
177 linked_list_t *ocsp_uris;
178
5e4b1ad2
MR
179 /**
180 * List of ipAddrBlocks as traffic_selector_t
181 */
182 linked_list_t *ipAddrBlocks;
183
f781b9d3
TB
184 /**
185 * List of permitted name constraints
186 */
187 linked_list_t *permitted_names;
188
189 /**
190 * List of excluded name constraints
191 */
192 linked_list_t *excluded_names;
5e4b1ad2 193
5728c6aa
MW
194 /**
195 * References to this cert
196 */
197 refcount_t ref;
198};
199
200/**
201 * Convert a GeneralName to an identification_t.
202 */
203static identification_t *general_name2id(GENERAL_NAME *name)
204{
205 if (!name)
206 {
207 return NULL;
208 }
209 switch (name->type)
210 {
211 case GEN_EMAIL:
212 return identification_create_from_encoding(ID_RFC822_ADDR,
213 openssl_asn1_str2chunk(name->d.rfc822Name));
214 case GEN_DNS:
215 return identification_create_from_encoding(ID_FQDN,
216 openssl_asn1_str2chunk(name->d.dNSName));
217 case GEN_URI:
218 return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
219 openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
220 case GEN_IPADD:
07c5aacc
MW
221 {
222 chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
223 if (chunk.len == 4)
224 {
225 return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
226 }
227 if (chunk.len == 16)
228 {
229 return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
230 }
231 return NULL;
232 }
5728c6aa
MW
233 case GEN_DIRNAME :
234 return openssl_x509_name2id(name->d.directoryName);
a0a8aaaf
MW
235 case GEN_OTHERNAME:
236 if (OBJ_obj2nid(name->d.otherName->type_id) == NID_ms_upn &&
237 name->d.otherName->value->type == V_ASN1_UTF8STRING)
238 {
239 return identification_create_from_encoding(ID_RFC822_ADDR,
240 openssl_asn1_str2chunk(
241 name->d.otherName->value->value.utf8string));
242 }
243 return NULL;
5728c6aa
MW
244 default:
245 return NULL;
246 }
247}
248
249METHOD(x509_t, get_flags, x509_flag_t,
250 private_openssl_x509_t *this)
251{
252 return this->flags;
253}
254
255METHOD(x509_t, get_serial, chunk_t,
256 private_openssl_x509_t *this)
257{
258 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
259}
260
261METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
262 private_openssl_x509_t *this)
263{
264 chunk_t fingerprint;
265
266 if (this->subjectKeyIdentifier.len)
267 {
268 return this->subjectKeyIdentifier;
269 }
da9724e6 270 if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
5728c6aa
MW
271 &fingerprint))
272 {
273 return fingerprint;
274 }
275 return chunk_empty;
276}
277
278METHOD(x509_t, get_authKeyIdentifier, chunk_t,
279 private_openssl_x509_t *this)
280{
281 if (this->authKeyIdentifier.len)
282 {
283 return this->authKeyIdentifier;
284 }
285 return chunk_empty;
286}
287
d390b3b9 288METHOD(x509_t, get_constraint, u_int,
b3d359e5 289 private_openssl_x509_t *this, x509_constraint_t type)
a742d97f 290{
b3d359e5
MW
291 switch (type)
292 {
293 case X509_PATH_LEN:
294 return this->pathlen;
295 default:
296 return X509_NO_CONSTRAINT;
297 }
a742d97f
MW
298}
299
5728c6aa
MW
300METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
301 private_openssl_x509_t *this)
302{
303 return this->subjectAltNames->create_enumerator(this->subjectAltNames);
304}
305
306METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
307 private_openssl_x509_t *this)
308{
a6478a04 309 return this->crl_uris->create_enumerator(this->crl_uris);
5728c6aa
MW
310}
311
312METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
313 private_openssl_x509_t *this)
314{
315 return this->ocsp_uris->create_enumerator(this->ocsp_uris);
316}
317
5e4b1ad2
MR
318METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
319 private_openssl_x509_t *this)
320{
321 return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
322}
323
f781b9d3
TB
324METHOD(x509_t, create_name_constraint_enumerator, enumerator_t*,
325 private_openssl_x509_t *this, bool perm)
326{
327 if (perm)
328 {
329 return this->permitted_names->create_enumerator(this->permitted_names);
330 }
331 return this->excluded_names->create_enumerator(this->excluded_names);
332}
333
5728c6aa
MW
334METHOD(certificate_t, get_type, certificate_type_t,
335 private_openssl_x509_t *this)
336{
337 return CERT_X509;
338}
339
340METHOD(certificate_t, get_subject, identification_t*,
341 private_openssl_x509_t *this)
342{
343 return this->subject;
344}
345
346METHOD(certificate_t, get_issuer, identification_t*,
347 private_openssl_x509_t *this)
348{
349 return this->issuer;
350}
351
352METHOD(certificate_t, has_subject, id_match_t,
353 private_openssl_x509_t *this, identification_t *subject)
354{
355 identification_t *current;
356 enumerator_t *enumerator;
357 id_match_t match, best;
663e7355 358 chunk_t encoding;
5728c6aa
MW
359
360 if (subject->get_type(subject) == ID_KEY_ID)
361 {
663e7355
MW
362 encoding = subject->get_encoding(subject);
363
364 if (chunk_equals(this->hash, encoding))
365 {
366 return ID_MATCH_PERFECT;
367 }
368 if (this->subjectKeyIdentifier.len &&
369 chunk_equals(this->subjectKeyIdentifier, encoding))
370 {
371 return ID_MATCH_PERFECT;
372 }
373 if (this->pubkey &&
374 this->pubkey->has_fingerprint(this->pubkey, encoding))
5728c6aa
MW
375 {
376 return ID_MATCH_PERFECT;
377 }
ed1c4303
MW
378 if (chunk_equals(get_serial(this), encoding))
379 {
380 return ID_MATCH_PERFECT;
381 }
5728c6aa
MW
382 }
383 best = this->subject->matches(this->subject, subject);
384 enumerator = create_subjectAltName_enumerator(this);
385 while (enumerator->enumerate(enumerator, &current))
386 {
387 match = current->matches(current, subject);
388 if (match > best)
389 {
390 best = match;
391 }
392 }
393 enumerator->destroy(enumerator);
394 return best;
395}
396
397METHOD(certificate_t, has_issuer, id_match_t,
398 private_openssl_x509_t *this, identification_t *issuer)
399{
400 /* issuerAltNames currently not supported */
401 return this->issuer->matches(this->issuer, issuer);
402}
403
404METHOD(certificate_t, issued_by, bool,
a37f2d20 405 private_openssl_x509_t *this, certificate_t *issuer,
024b9795 406 signature_params_t **scheme)
5728c6aa
MW
407{
408 public_key_t *key;
409 bool valid;
410 x509_t *x509 = (x509_t*)issuer;
f0c25960 411 chunk_t keyid = chunk_empty;
8b4c2a1d
TB
412#if OPENSSL_VERSION_NUMBER >= 0x10100000L
413 const ASN1_BIT_STRING *sig;
414#else
08d7e1f1 415 ASN1_BIT_STRING *sig;
8b4c2a1d 416#endif
5728c6aa
MW
417 chunk_t tbs;
418
419 if (&this->public.x509.interface == issuer)
420 {
421 if (this->flags & X509_SELF_SIGNED)
422 {
024b9795
TB
423 valid = TRUE;
424 goto out;
5728c6aa
MW
425 }
426 }
427 else
428 {
429 if (issuer->get_type(issuer) != CERT_X509)
430 {
431 return FALSE;
432 }
433 if (!(x509->get_flags(x509) & X509_CA))
434 {
435 return FALSE;
436 }
61769fd1 437 }
f0c25960
AKR
438
439 /* compare keyIdentifiers if available, otherwise use DNs */
440 if (this->authKeyIdentifier.ptr)
61769fd1 441 {
f0c25960
AKR
442 keyid = x509->get_subjectKeyIdentifier(x509);
443 if (keyid.len && !chunk_equals(keyid, this->authKeyIdentifier))
444 {
445 return FALSE;
446 }
5728c6aa 447 }
f0c25960
AKR
448 if (!keyid.len)
449 {
450 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
451 {
452 return FALSE;
453 }
454 }
455
5728c6aa
MW
456 key = issuer->get_public_key(issuer);
457 if (!key)
458 {
459 return FALSE;
460 }
08d7e1f1
TB
461 /* i2d_re_X509_tbs() was added with 1.1.0 when X509 was made opaque */
462#if OPENSSL_VERSION_NUMBER >= 0x10100000L
463 tbs = openssl_i2chunk(re_X509_tbs, this->x509);
464#else
5728c6aa 465 tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
08d7e1f1
TB
466#endif
467 X509_get0_signature(&sig, NULL, this->x509);
fb63012e 468 valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs,
a413571f 469 openssl_asn1_str2chunk(sig));
5728c6aa
MW
470 free(tbs.ptr);
471 key->destroy(key);
024b9795
TB
472
473out:
a37f2d20
MW
474 if (valid && scheme)
475 {
fb63012e 476 *scheme = signature_params_clone(this->scheme);
a37f2d20 477 }
5728c6aa
MW
478 return valid;
479}
480
481METHOD(certificate_t, get_public_key, public_key_t*,
482 private_openssl_x509_t *this)
483{
484 return this->pubkey->get_ref(this->pubkey);
485}
486
487METHOD(certificate_t, get_validity, bool,
488 private_openssl_x509_t *this,
489 time_t *when, time_t *not_before, time_t *not_after)
490{
491 time_t t;
492
493 if (when)
494 {
495 t = *when;
496 }
497 else
498 {
499 t = time(NULL);
500 }
501 if (not_before)
502 {
503 *not_before = this->notBefore;
504 }
505 if (not_after)
506 {
507 *not_after = this->notAfter;
508 }
509 return (t >= this->notBefore && t <= this->notAfter);
510}
511
0406eeaa
MW
512METHOD(certificate_t, get_encoding, bool,
513 private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
5728c6aa 514{
0406eeaa
MW
515 if (type == CERT_ASN1_DER)
516 {
517 *encoding = chunk_clone(this->encoding);
518 return TRUE;
519 }
520 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
521 CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
5728c6aa
MW
522}
523
0406eeaa 524
5728c6aa
MW
525METHOD(certificate_t, equals, bool,
526 private_openssl_x509_t *this, certificate_t *other)
527{
528 chunk_t encoding;
529 bool equal;
530
531 if (this == (private_openssl_x509_t*)other)
532 {
533 return TRUE;
534 }
535 if (other->get_type(other) != CERT_X509)
536 {
537 return FALSE;
538 }
539 if (other->equals == (void*)equals)
540 { /* skip allocation if we have the same implementation */
541 encoding = ((private_openssl_x509_t*)other)->encoding;
542 return chunk_equals(this->encoding, encoding);
543 }
0406eeaa
MW
544 if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
545 {
546 return FALSE;
547 }
5728c6aa
MW
548 equal = chunk_equals(this->encoding, encoding);
549 free(encoding.ptr);
550 return equal;
551}
552
553METHOD(certificate_t, get_ref, certificate_t*,
554 private_openssl_x509_t *this)
555{
556 ref_get(&this->ref);
557 return &this->public.x509.interface;
558}
559
560METHOD(certificate_t, destroy, void,
561 private_openssl_x509_t *this)
562{
563 if (ref_put(&this->ref))
564 {
565 if (this->x509)
566 {
567 X509_free(this->x509);
568 }
fb63012e 569 signature_params_destroy(this->scheme);
5728c6aa
MW
570 DESTROY_IF(this->subject);
571 DESTROY_IF(this->issuer);
572 DESTROY_IF(this->pubkey);
573 free(this->subjectKeyIdentifier.ptr);
574 free(this->authKeyIdentifier.ptr);
575 free(this->encoding.ptr);
576 free(this->hash.ptr);
577 this->subjectAltNames->destroy_offset(this->subjectAltNames,
578 offsetof(identification_t, destroy));
579 this->issuerAltNames->destroy_offset(this->issuerAltNames,
580 offsetof(identification_t, destroy));
4e7b7db6
TB
581 this->crl_uris->destroy_function(this->crl_uris,
582 (void*)x509_cdp_destroy);
5728c6aa 583 this->ocsp_uris->destroy_function(this->ocsp_uris, free);
5e4b1ad2
MR
584 this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
585 offsetof(traffic_selector_t, destroy));
f781b9d3
TB
586 this->permitted_names->destroy_offset(this->permitted_names,
587 offsetof(identification_t, destroy));
588 this->excluded_names->destroy_offset(this->excluded_names,
589 offsetof(identification_t, destroy));
5728c6aa
MW
590 free(this);
591 }
592}
593
594/**
595 * Create an empty certificate
596 */
597static private_openssl_x509_t *create_empty()
598{
599 private_openssl_x509_t *this;
600
601 INIT(this,
602 .public = {
603 .x509 = {
604 .interface = {
605 .get_type = _get_type,
606 .get_subject = _get_subject,
607 .get_issuer = _get_issuer,
608 .has_subject = _has_subject,
609 .has_issuer = _has_issuer,
610 .issued_by = _issued_by,
611 .get_public_key = _get_public_key,
612 .get_validity = _get_validity,
5728c6aa
MW
613 .get_encoding = _get_encoding,
614 .equals = _equals,
615 .get_ref = _get_ref,
616 .destroy = _destroy,
617 },
618 .get_flags = _get_flags,
619 .get_serial = _get_serial,
620 .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
621 .get_authKeyIdentifier = _get_authKeyIdentifier,
b3d359e5 622 .get_constraint = _get_constraint,
5728c6aa
MW
623 .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
624 .create_crl_uri_enumerator = _create_crl_uri_enumerator,
625 .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
5e4b1ad2 626 .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
f781b9d3 627 .create_name_constraint_enumerator = _create_name_constraint_enumerator,
20bd7810 628 .create_cert_policy_enumerator = (void*)enumerator_create_empty,
5a0caa4b 629 .create_policy_mapping_enumerator = (void*)enumerator_create_empty,
5728c6aa
MW
630 },
631 },
632 .subjectAltNames = linked_list_create(),
633 .issuerAltNames = linked_list_create(),
634 .crl_uris = linked_list_create(),
635 .ocsp_uris = linked_list_create(),
5e4b1ad2 636 .ipAddrBlocks = linked_list_create(),
f781b9d3
TB
637 .permitted_names = linked_list_create(),
638 .excluded_names = linked_list_create(),
5dba5852 639 .pathlen = X509_NO_CONSTRAINT,
5728c6aa
MW
640 .ref = 1,
641 );
642
643 return this;
644}
645
646/**
b3ab7a48 647 * parse an extension containing GENERAL_NAMES into a list
5728c6aa
MW
648 */
649static bool parse_generalNames_ext(linked_list_t *list,
650 X509_EXTENSION *ext)
651{
652 GENERAL_NAMES *names;
653 GENERAL_NAME *name;
654 identification_t *id;
655 int i, num;
656
657 names = X509V3_EXT_d2i(ext);
658 if (!names)
659 {
660 return FALSE;
661 }
662
663 num = sk_GENERAL_NAME_num(names);
664 for (i = 0; i < num; i++)
665 {
666 name = sk_GENERAL_NAME_value(names, i);
667 id = general_name2id(name);
668 if (id)
669 {
670 list->insert_last(list, id);
671 }
672 GENERAL_NAME_free(name);
673 }
674 sk_GENERAL_NAME_free(names);
675 return TRUE;
676}
677
678/**
679 * parse basic constraints
680 */
681static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
682 X509_EXTENSION *ext)
683{
684 BASIC_CONSTRAINTS *constraints;
d390b3b9 685 long pathlen;
5728c6aa
MW
686
687 constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
688 if (constraints)
689 {
690 if (constraints->ca)
691 {
692 this->flags |= X509_CA;
693 }
694 if (constraints->pathlen)
695 {
28bcbc29 696
d390b3b9
AS
697 pathlen = ASN1_INTEGER_get(constraints->pathlen);
698 this->pathlen = (pathlen >= 0 && pathlen < 128) ?
699 pathlen : X509_NO_CONSTRAINT;
5728c6aa
MW
700 }
701 BASIC_CONSTRAINTS_free(constraints);
702 return TRUE;
703 }
704 return FALSE;
705}
706
28bcbc29
TB
707/**
708 * parse key usage
709 */
710static bool parse_keyUsage_ext(private_openssl_x509_t *this,
711 X509_EXTENSION *ext)
712{
713 ASN1_BIT_STRING *usage;
714
715 usage = X509V3_EXT_d2i(ext);
716 if (usage)
717 {
718 if (usage->length > 0)
719 {
720 int flags = usage->data[0];
721 if (usage->length > 1)
722 {
723 flags |= usage->data[1] << 8;
724 }
e793d65a 725 if (flags & X509v3_KU_CRL_SIGN)
28bcbc29 726 {
e793d65a
TB
727 this->flags |= X509_CRL_SIGN;
728 }
504e1232
TB
729 if (flags & X509v3_KU_DIGITAL_SIGNATURE ||
730 flags & X509v3_KU_NON_REPUDIATION)
731 {
732 this->flags |= X509_IKE_COMPLIANT;
733 }
e793d65a
TB
734 if (flags & X509v3_KU_KEY_CERT_SIGN)
735 {
b3ab7a48 736 /* we use the caBasicConstraint, MUST be set */
28bcbc29
TB
737 }
738 }
739 ASN1_BIT_STRING_free(usage);
740 return TRUE;
741 }
742 return FALSE;
743}
744
c3e7b3de
MW
745/**
746 * Parse ExtendedKeyUsage
747 */
748static bool parse_extKeyUsage_ext(private_openssl_x509_t *this,
749 X509_EXTENSION *ext)
750{
751 EXTENDED_KEY_USAGE *usage;
752 int i;
753
754 usage = X509V3_EXT_d2i(ext);
755 if (usage)
756 {
757 for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
758 {
759 switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
760 {
761 case NID_server_auth:
762 this->flags |= X509_SERVER_AUTH;
763 break;
764 case NID_client_auth:
765 this->flags |= X509_CLIENT_AUTH;
766 break;
767 case NID_OCSP_sign:
768 this->flags |= X509_OCSP_SIGNER;
769 break;
770 default:
771 break;
772 }
773 }
774 sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
775 return TRUE;
776 }
777 return FALSE;
778}
779
5728c6aa
MW
780/**
781 * Parse CRL distribution points
782 */
86c10a95
TB
783bool openssl_parse_crlDistributionPoints(X509_EXTENSION *ext,
784 linked_list_t *list)
5728c6aa
MW
785{
786 CRL_DIST_POINTS *cdps;
787 DIST_POINT *cdp;
a6478a04
MW
788 identification_t *id, *issuer;
789 x509_cdp_t *entry;
5728c6aa 790 char *uri;
86c10a95 791 int i, j, k, point_num, name_num, issuer_num, len;
5728c6aa
MW
792
793 cdps = X509V3_EXT_d2i(ext);
794 if (!cdps)
795 {
796 return FALSE;
797 }
798 point_num = sk_DIST_POINT_num(cdps);
799 for (i = 0; i < point_num; i++)
800 {
801 cdp = sk_DIST_POINT_value(cdps, i);
802 if (cdp)
803 {
804 if (cdp->distpoint && cdp->distpoint->type == 0 &&
805 cdp->distpoint->name.fullname)
806 {
807 name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
808 for (j = 0; j < name_num; j++)
809 {
810 id = general_name2id(sk_GENERAL_NAME_value(
811 cdp->distpoint->name.fullname, j));
812 if (id)
813 {
86c10a95
TB
814 len = asprintf(&uri, "%Y", id);
815 if (!len)
816 {
817 free(uri);
818 }
819 else if (len > 0)
5728c6aa 820 {
a6478a04
MW
821 if (cdp->CRLissuer)
822 {
823 issuer_num = sk_GENERAL_NAME_num(cdp->CRLissuer);
824 for (k = 0; k < issuer_num; k++)
825 {
826 issuer = general_name2id(
827 sk_GENERAL_NAME_value(cdp->CRLissuer, k));
828 if (issuer)
829 {
830 INIT(entry,
831 .uri = strdup(uri),
832 .issuer = issuer,
833 );
86c10a95 834 list->insert_last(list, entry);
a6478a04
MW
835 }
836 }
837 free(uri);
838 }
839 else
840 {
841 INIT(entry,
842 .uri = uri,
843 );
86c10a95 844 list->insert_last(list, entry);
a6478a04 845 }
5728c6aa
MW
846 }
847 id->destroy(id);
848 }
849 }
850 }
a6478a04 851
5728c6aa
MW
852 DIST_POINT_free(cdp);
853 }
854 }
855 sk_DIST_POINT_free(cdps);
856 return TRUE;
857}
858
859/**
860 * Parse authorityInfoAccess with OCSP URIs
861 */
862static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
863 X509_EXTENSION *ext)
864{
865 AUTHORITY_INFO_ACCESS *infos;
866 ACCESS_DESCRIPTION *desc;
867 identification_t *id;
86c10a95 868 int i, num, len;
5728c6aa
MW
869 char *uri;
870
871 infos = X509V3_EXT_d2i(ext);
872 if (!infos)
873 {
874 return FALSE;
875 }
876 num = sk_ACCESS_DESCRIPTION_num(infos);
877 for (i = 0; i < num; i++)
878 {
879 desc = sk_ACCESS_DESCRIPTION_value(infos, i);
880 if (desc)
881 {
882 if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
883 {
884 id = general_name2id(desc->location);
885 if (id)
886 {
86c10a95
TB
887 len = asprintf(&uri, "%Y", id);
888 if (!len)
889 {
890 free(uri);
891 }
892 else if (len > 0)
5728c6aa 893 {
93818392 894 this->ocsp_uris->insert_last(this->ocsp_uris, uri);
5728c6aa
MW
895 }
896 id->destroy(id);
897 }
898 }
899 ACCESS_DESCRIPTION_free(desc);
900 }
901 }
902 sk_ACCESS_DESCRIPTION_free(infos);
903 return TRUE;
904}
905
5e4b1ad2
MR
906#ifndef OPENSSL_NO_RFC3779
907
908/**
909 * Parse a single block of ipAddrBlock extension
910 */
911static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
912 IPAddressFamily *fam)
913{
914 const IPAddressOrRanges *list;
915 IPAddressOrRange *aor;
916 traffic_selector_t *ts;
917 ts_type_t type;
918 chunk_t from, to;
919 int i, afi;
920
921 if (fam->ipAddressChoice->type != IPAddressChoice_addressesOrRanges)
922 {
923 return;
924 }
925
08d7e1f1 926 afi = X509v3_addr_get_afi(fam);
5e4b1ad2
MR
927 switch (afi)
928 {
929 case IANA_AFI_IPV4:
930 from = chunk_alloca(4);
931 to = chunk_alloca(4);
932 type = TS_IPV4_ADDR_RANGE;
933 break;
934 case IANA_AFI_IPV6:
935 from = chunk_alloca(16);
936 to = chunk_alloca(16);
937 type = TS_IPV6_ADDR_RANGE;
938 break;
939 default:
940 return;
941 }
942
943 list = fam->ipAddressChoice->u.addressesOrRanges;
944 for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
945 {
946 aor = sk_IPAddressOrRange_value(list, i);
08d7e1f1 947 if (X509v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
5e4b1ad2
MR
948 {
949 ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
950 if (ts)
951 {
952 this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
953 }
954 }
955 }
956}
957
958/**
959 * Parse ipAddrBlock extension
960 */
961static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
962 X509_EXTENSION *ext)
963{
964 STACK_OF(IPAddressFamily) *blocks;
965 IPAddressFamily *fam;
966
967 blocks = (STACK_OF(IPAddressFamily)*)X509V3_EXT_d2i(ext);
968 if (!blocks)
969 {
970 return FALSE;
971 }
972
08d7e1f1 973 if (!X509v3_addr_is_canonical(blocks))
5e4b1ad2
MR
974 {
975 sk_IPAddressFamily_free(blocks);
976 return FALSE;
977 }
978
979 while (sk_IPAddressFamily_num(blocks) > 0)
980 {
981 fam = sk_IPAddressFamily_pop(blocks);
982 parse_ipAddrBlock_ext_fam(this, fam);
983 IPAddressFamily_free(fam);
984 }
985 sk_IPAddressFamily_free(blocks);
986
987 this->flags |= X509_IP_ADDR_BLOCKS;
988 return TRUE;
989}
990#endif /* !OPENSSL_NO_RFC3779 */
991
f781b9d3
TB
992/**
993 * Parse a "generalSubtree" structure (sequence of generalNames)
994 */
995static bool parse_generalSubtrees(linked_list_t *list,
996 STACK_OF(GENERAL_SUBTREE) *subtrees)
997{
998 GENERAL_SUBTREE *subtree;
999 identification_t *id;
1000 int i;
1001
1002 for (i = 0; i < sk_GENERAL_SUBTREE_num(subtrees); i++)
1003 {
1004 subtree = sk_GENERAL_SUBTREE_value(subtrees, i);
1005 id = general_name2id(subtree->base);
1006 if (id)
1007 {
1008 list->insert_last(list, id);
1009 }
1010 else
1011 {
1012 return FALSE;
1013 }
1014 }
1015 return TRUE;
1016}
1017
1018/**
1019 * Parse permitted/excluded nameConstraints
1020 */
1021static bool parse_nameConstraints_ext(private_openssl_x509_t *this,
1022 X509_EXTENSION *ext)
1023{
1024 NAME_CONSTRAINTS *nc;
1025 bool ok = FALSE;
1026
1027 nc = (NAME_CONSTRAINTS*)X509V3_EXT_d2i(ext);
1028 if (nc)
1029 {
1030 ok = parse_generalSubtrees(this->permitted_names, nc->permittedSubtrees) &&
1031 parse_generalSubtrees(this->excluded_names, nc->excludedSubtrees);
1032 NAME_CONSTRAINTS_free(nc);
1033 }
1034 return ok;
1035}
1036
5728c6aa
MW
1037/**
1038 * Parse authorityKeyIdentifier extension
1039 */
1040static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
1041 X509_EXTENSION *ext)
1042{
1043 AUTHORITY_KEYID *keyid;
1044
1045 keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
1046 if (keyid)
1047 {
1048 free(this->authKeyIdentifier.ptr);
1049 this->authKeyIdentifier = chunk_clone(
1050 openssl_asn1_str2chunk(keyid->keyid));
1051 AUTHORITY_KEYID_free(keyid);
1052 return TRUE;
1053 }
1054 return FALSE;
1055}
1056
1057/**
1058 * Parse subjectKeyIdentifier extension
1059 */
1060static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
1061 X509_EXTENSION *ext)
1062{
f00a1015
MW
1063 chunk_t ostr;
1064
1065 ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
1066 /* quick and dirty unwrap of octet string */
1067 if (ostr.len > 2 &&
1068 ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
1069 {
1070 free(this->subjectKeyIdentifier.ptr);
1071 this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
1072 return TRUE;
1073 }
1074 return FALSE;
5728c6aa
MW
1075}
1076
1077/**
1078 * Parse X509 extensions we are interested in
1079 */
1080static bool parse_extensions(private_openssl_x509_t *this)
1081{
8b4c2a1d 1082 const STACK_OF(X509_EXTENSION) *extensions;
d12a4f5d 1083 bool key_usage_parsed = FALSE;
5728c6aa
MW
1084 int i, num;
1085
08d7e1f1 1086 extensions = X509_get0_extensions(this->x509);
5728c6aa
MW
1087 if (extensions)
1088 {
1089 num = sk_X509_EXTENSION_num(extensions);
1090
1091 for (i = 0; i < num; i++)
1092 {
1093 X509_EXTENSION *ext;
1094 bool ok;
1095
1096 ext = sk_X509_EXTENSION_value(extensions, i);
1097 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
1098 {
1099 case NID_info_access:
1100 ok = parse_authorityInfoAccess_ext(this, ext);
1101 break;
1102 case NID_authority_key_identifier:
1103 ok = parse_authKeyIdentifier_ext(this, ext);
1104 break;
1105 case NID_subject_key_identifier:
1106 ok = parse_subjectKeyIdentifier_ext(this, ext);
1107 break;
1108 case NID_subject_alt_name:
1109 ok = parse_generalNames_ext(this->subjectAltNames, ext);
1110 break;
1111 case NID_issuer_alt_name:
1112 ok = parse_generalNames_ext(this->issuerAltNames, ext);
1113 break;
1114 case NID_basic_constraints:
1115 ok = parse_basicConstraints_ext(this, ext);
1116 break;
28bcbc29
TB
1117 case NID_key_usage:
1118 ok = parse_keyUsage_ext(this, ext);
d12a4f5d 1119 key_usage_parsed = TRUE;
28bcbc29 1120 break;
c3e7b3de
MW
1121 case NID_ext_key_usage:
1122 ok = parse_extKeyUsage_ext(this, ext);
1123 break;
5728c6aa 1124 case NID_crl_distribution_points:
86c10a95 1125 ok = openssl_parse_crlDistributionPoints(ext, this->crl_uris);
5728c6aa 1126 break;
5e4b1ad2
MR
1127#ifndef OPENSSL_NO_RFC3779
1128 case NID_sbgp_ipAddrBlock:
1129 ok = parse_ipAddrBlock_ext(this, ext);
1130 break;
1131#endif /* !OPENSSL_NO_RFC3779 */
f781b9d3
TB
1132 case NID_name_constraints:
1133 ok = parse_nameConstraints_ext(this, ext);
1134 break;
5728c6aa 1135 default:
c4fd3b2f
AS
1136 ok = X509_EXTENSION_get_critical(ext) == 0 ||
1137 !lib->settings->get_bool(lib->settings,
8dc6e716 1138 "%s.x509.enforce_critical", TRUE, lib->ns);
b0892d09
MW
1139 if (!ok)
1140 {
3f55f203
MW
1141 char buf[80] = "";
1142
1143 OBJ_obj2txt(buf, sizeof(buf),
1144 X509_EXTENSION_get_object(ext), 0);
1145 DBG1(DBG_LIB, "found unsupported critical X.509 "
1146 "extension: %s", buf);
b0892d09 1147 }
5728c6aa
MW
1148 break;
1149 }
1150 if (!ok)
1151 {
1152 return FALSE;
1153 }
1154 }
1155 }
d12a4f5d
TB
1156 if (!key_usage_parsed)
1157 {
1158 /* we are compliant with RFC 4945 without keyUsage extension */
1159 this->flags |= X509_IKE_COMPLIANT;
1160 /* allow CA certificates without keyUsage extension to sign CRLs */
1161 if (this->flags & X509_CA)
1162 {
1163 this->flags |= X509_CRL_SIGN;
1164 }
1165 }
5728c6aa
MW
1166 return TRUE;
1167}
1168
1169/**
1170 * Parse a DER encoded x509 certificate
1171 */
1172static bool parse_certificate(private_openssl_x509_t *this)
1173{
1174 const unsigned char *ptr = this->encoding.ptr;
1175 hasher_t *hasher;
fb63012e
TB
1176 chunk_t chunk, sig_scheme, sig_scheme_tbs;
1177 ASN1_OBJECT *oid;
8b4c2a1d
TB
1178#if OPENSSL_VERSION_NUMBER >= 0x10100000L
1179 const X509_ALGOR *alg;
1180#else
08d7e1f1 1181 X509_ALGOR *alg;
8b4c2a1d 1182#endif
85a35fc9 1183 key_type_t ed_type = KEY_ED448;
5728c6aa
MW
1184
1185 this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
1186 if (!this->x509)
1187 {
1188 return FALSE;
1189 }
a6850b84
MW
1190 if (X509_get_version(this->x509) < 0 || X509_get_version(this->x509) > 2)
1191 {
1192 DBG1(DBG_LIB, "unsupported x509 version: %d",
1193 X509_get_version(this->x509) + 1);
1194 return FALSE;
1195 }
1196
5728c6aa
MW
1197 this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
1198 this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
1199
08d7e1f1
TB
1200 if (!X509_PUBKEY_get0_param(&oid, NULL, NULL, NULL,
1201 X509_get_X509_PUBKEY(this->x509)))
1202 {
1203 return FALSE;
1204 }
1205 switch (openssl_asn1_known_oid(oid))
5728c6aa 1206 {
364395d2
TB
1207 case OID_RSASSA_PSS:
1208 /* TODO: we should treat such keys special and use the params as
1209 * restrictions regarding the use of this key (or rather the
1210 * associated private key) */
5728c6aa
MW
1211 case OID_RSA_ENCRYPTION:
1212 this->pubkey = lib->creds->create(lib->creds,
1213 CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
1214 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
1215 BUILD_END);
1216 break;
1217 case OID_EC_PUBLICKEY:
1218 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
1219 * the curve parameters. */
1220 chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
1221 this->pubkey = lib->creds->create(lib->creds,
1222 CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
1223 chunk, BUILD_END);
1224 free(chunk.ptr);
1225 break;
85a35fc9
TB
1226 case OID_ED25519:
1227 ed_type = KEY_ED25519;
1228 /* fall-through */
1229 case OID_ED448:
1230 /* for EdDSA, the parsers expect the full subjectPublicKeyInfo */
1231 chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
1232 this->pubkey = lib->creds->create(lib->creds,
1233 CRED_PUBLIC_KEY, ed_type, BUILD_BLOB_ASN1_DER,
1234 chunk, BUILD_END);
1235 free(chunk.ptr);
1236 break;
5728c6aa
MW
1237 default:
1238 DBG1(DBG_LIB, "unsupported public key algorithm");
1239 break;
1240 }
1241 if (!this->subject || !this->issuer || !this->pubkey)
1242 {
1243 return FALSE;
1244 }
1245
a4abb263
TB
1246 this->notBefore = openssl_asn1_to_time(X509_get0_notBefore(this->x509));
1247 this->notAfter = openssl_asn1_to_time(X509_get0_notAfter(this->x509));
5728c6aa 1248
08d7e1f1
TB
1249 /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL
1250 * versions, at least on Ubuntu 14.04 it is not actually defined */
1251 X509_get0_signature(NULL, &alg, this->x509);
8b4c2a1d 1252 sig_scheme = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
08d7e1f1 1253 alg = X509_get0_tbs_sigalg(this->x509);
8b4c2a1d 1254 sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, (X509_ALGOR*)alg);
fb63012e
TB
1255 if (!chunk_equals(sig_scheme, sig_scheme_tbs))
1256 {
1257 free(sig_scheme_tbs.ptr);
1258 free(sig_scheme.ptr);
1259 return FALSE;
1260 }
1261 free(sig_scheme_tbs.ptr);
1262
1263 INIT(this->scheme);
1264 if (!signature_params_parse(sig_scheme, 0, this->scheme))
5728c6aa 1265 {
fb63012e
TB
1266 DBG1(DBG_ASN, "unable to parse signature algorithm");
1267 free(sig_scheme.ptr);
5728c6aa
MW
1268 return FALSE;
1269 }
fb63012e 1270 free(sig_scheme.ptr);
5728c6aa
MW
1271
1272 if (!parse_extensions(this))
1273 {
c4fd3b2f 1274 return FALSE;
5728c6aa
MW
1275 }
1276
1277 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
87dd205b 1278 if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))
5728c6aa 1279 {
87dd205b 1280 DESTROY_IF(hasher);
5728c6aa
MW
1281 return FALSE;
1282 }
5728c6aa
MW
1283 hasher->destroy(hasher);
1284
a37f2d20 1285 if (issued_by(this, &this->public.x509.interface, NULL))
5728c6aa
MW
1286 {
1287 this->flags |= X509_SELF_SIGNED;
1288 }
1289 return TRUE;
1290}
1291
1292openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
1293{
1294 chunk_t blob = chunk_empty;
1295 x509_flag_t flags = 0;
1296
1297 while (TRUE)
1298 {
1299 switch (va_arg(args, builder_part_t))
1300 {
1301 case BUILD_BLOB_ASN1_DER:
1302 blob = va_arg(args, chunk_t);
1303 continue;
1304 case BUILD_X509_FLAG:
1305 flags |= va_arg(args, x509_flag_t);
1306 continue;
1307 case BUILD_END:
1308 break;
1309 default:
1310 return NULL;
1311 }
1312 break;
1313 }
1314
1315 if (blob.ptr)
1316 {
1317 private_openssl_x509_t *this;
1318
1319 this = create_empty();
1320 this->encoding = chunk_clone(blob);
1321 this->flags |= flags;
1322 if (parse_certificate(this))
1323 {
1324 return &this->public;
1325 }
1326 DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
1327 destroy(this);
1328 }
1329 return NULL;
1330}