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