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