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