2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
30 #include <ipxe/list.h>
31 #include <ipxe/base16.h>
32 #include <ipxe/asn1.h>
33 #include <ipxe/crypto.h>
35 #include <ipxe/sha1.h>
36 #include <ipxe/sha256.h>
38 #include <ipxe/rootcert.h>
39 #include <ipxe/certstore.h>
40 #include <ipxe/socket.h>
42 #include <ipxe/x509.h>
43 #include <config/crypto.h>
49 * The structure of X.509v3 certificates is documented in RFC 5280
53 /* Disambiguate the various error causes */
54 #define ENOTSUP_ALGORITHM \
55 __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
56 #define EINFO_ENOTSUP_ALGORITHM \
57 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
58 #define ENOTSUP_EXTENSION \
59 __einfo_error ( EINFO_ENOTSUP_EXTENSION )
60 #define EINFO_ENOTSUP_EXTENSION \
61 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
62 #define EINVAL_ALGORITHM \
63 __einfo_error ( EINFO_EINVAL_ALGORITHM )
64 #define EINFO_EINVAL_ALGORITHM \
65 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
66 #define EINVAL_ALGORITHM_MISMATCH \
67 __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
68 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
69 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )
70 #define EINVAL_PATH_LEN \
71 __einfo_error ( EINFO_EINVAL_PATH_LEN )
72 #define EINFO_EINVAL_PATH_LEN \
73 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )
74 #define EINVAL_VERSION \
75 __einfo_error ( EINFO_EINVAL_VERSION )
76 #define EINFO_EINVAL_VERSION \
77 __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )
78 #define EACCES_WRONG_ISSUER \
79 __einfo_error ( EINFO_EACCES_WRONG_ISSUER )
80 #define EINFO_EACCES_WRONG_ISSUER \
81 __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )
82 #define EACCES_NOT_CA \
83 __einfo_error ( EINFO_EACCES_NOT_CA )
84 #define EINFO_EACCES_NOT_CA \
85 __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )
86 #define EACCES_KEY_USAGE \
87 __einfo_error ( EINFO_EACCES_KEY_USAGE )
88 #define EINFO_EACCES_KEY_USAGE \
89 __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )
90 #define EACCES_EXPIRED \
91 __einfo_error ( EINFO_EACCES_EXPIRED )
92 #define EINFO_EACCES_EXPIRED \
93 __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )
94 #define EACCES_PATH_LEN \
95 __einfo_error ( EINFO_EACCES_PATH_LEN )
96 #define EINFO_EACCES_PATH_LEN \
97 __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )
98 #define EACCES_UNTRUSTED \
99 __einfo_error ( EINFO_EACCES_UNTRUSTED )
100 #define EINFO_EACCES_UNTRUSTED \
101 __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
102 #define EACCES_OUT_OF_ORDER \
103 __einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
104 #define EINFO_EACCES_OUT_OF_ORDER \
105 __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
106 #define EACCES_EMPTY \
107 __einfo_error ( EINFO_EACCES_EMPTY )
108 #define EINFO_EACCES_EMPTY \
109 __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
110 #define EACCES_OCSP_REQUIRED \
111 __einfo_error ( EINFO_EACCES_OCSP_REQUIRED )
112 #define EINFO_EACCES_OCSP_REQUIRED \
113 __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )
114 #define EACCES_WRONG_NAME \
115 __einfo_error ( EINFO_EACCES_WRONG_NAME )
116 #define EINFO_EACCES_WRONG_NAME \
117 __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )
118 #define EACCES_USELESS \
119 __einfo_error ( EINFO_EACCES_USELESS )
120 #define EINFO_EACCES_USELESS \
121 __einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )
124 * Get X.509 certificate name (for debugging)
126 * @v cert X.509 certificate
127 * @ret name Name (for debugging)
129 const char * x509_name ( struct x509_certificate *cert ) {
130 struct asn1_cursor *common_name = &cert->subject.common_name;
131 struct digest_algorithm *digest = &sha1_algorithm;
133 uint8_t fingerprint[ digest->digestsize ];
136 len = common_name->len;
138 /* Certificate has a commonName: use that */
139 if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
140 len = ( sizeof ( buf ) - 1 /* NUL */ );
141 memcpy ( buf, common_name->data, len );
144 /* Certificate has no commonName: use SHA-1 fingerprint */
145 x509_fingerprint ( cert, digest, fingerprint );
146 base16_encode ( fingerprint, sizeof ( fingerprint ),
147 buf, sizeof ( buf ) );
152 /** "commonName" object identifier */
153 static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
155 /** "commonName" object identifier cursor */
156 static struct asn1_cursor oid_common_name_cursor =
157 ASN1_OID_CURSOR ( oid_common_name );
160 * Parse X.509 certificate version
162 * @v cert X.509 certificate
163 * @v raw ASN.1 cursor
164 * @ret rc Return status code
166 static int x509_parse_version ( struct x509_certificate *cert,
167 const struct asn1_cursor *raw ) {
168 struct asn1_cursor cursor;
173 memcpy ( &cursor, raw, sizeof ( cursor ) );
174 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
177 if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) {
178 DBGC ( cert, "X509 %p cannot parse version: %s\n",
179 cert, strerror ( rc ) );
180 DBGC_HDA ( cert, 0, raw->data, raw->len );
186 DBGC ( cert, "X509 %p invalid version %d\n", cert, version );
187 DBGC_HDA ( cert, 0, raw->data, raw->len );
188 return -EINVAL_VERSION;
192 cert->version = version;
193 DBGC2 ( cert, "X509 %p is a version %d certificate\n",
194 cert, ( cert->version + 1 ) );
200 * Parse X.509 certificate serial number
202 * @v cert X.509 certificate
203 * @v raw ASN.1 cursor
204 * @ret rc Return status code
206 static int x509_parse_serial ( struct x509_certificate *cert,
207 const struct asn1_cursor *raw ) {
208 struct x509_serial *serial = &cert->serial;
211 /* Record raw serial number */
212 memcpy ( &serial->raw, raw, sizeof ( serial->raw ) );
213 if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) {
214 DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n",
215 cert, strerror ( rc ) );
218 DBGC2 ( cert, "X509 %p issuer is:\n", cert );
219 DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len );
225 * Parse X.509 certificate issuer
227 * @v cert X.509 certificate
228 * @v raw ASN.1 cursor
229 * @ret rc Return status code
231 static int x509_parse_issuer ( struct x509_certificate *cert,
232 const struct asn1_cursor *raw ) {
233 struct x509_issuer *issuer = &cert->issuer;
236 /* Record raw issuer */
237 memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) );
238 if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) {
239 DBGC ( cert, "X509 %p cannot shrink issuer: %s\n",
240 cert, strerror ( rc ) );
243 DBGC2 ( cert, "X509 %p issuer is:\n", cert );
244 DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len );
250 * Parse X.509 certificate validity
252 * @v cert X.509 certificate
253 * @v raw ASN.1 cursor
254 * @ret rc Return status code
256 static int x509_parse_validity ( struct x509_certificate *cert,
257 const struct asn1_cursor *raw ) {
258 struct x509_validity *validity = &cert->validity;
259 struct x509_time *not_before = &validity->not_before;
260 struct x509_time *not_after = &validity->not_after;
261 struct asn1_cursor cursor;
265 memcpy ( &cursor, raw, sizeof ( cursor ) );
266 asn1_enter ( &cursor, ASN1_SEQUENCE );
268 /* Parse notBefore */
269 if ( ( rc = asn1_generalized_time ( &cursor,
270 ¬_before->time ) ) != 0 ) {
271 DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
272 cert, strerror ( rc ) );
275 DBGC2 ( cert, "X509 %p valid from time %lld\n",
276 cert, not_before->time );
277 asn1_skip_any ( &cursor );
280 if ( ( rc = asn1_generalized_time ( &cursor,
281 ¬_after->time ) ) != 0 ) {
282 DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
283 cert, strerror ( rc ) );
286 DBGC2 ( cert, "X509 %p valid until time %lld\n",
287 cert, not_after->time );
293 * Parse X.509 certificate common name
295 * @v cert X.509 certificate
296 * @v raw ASN.1 cursor
297 * @ret rc Return status code
299 static int x509_parse_common_name ( struct x509_certificate *cert,
300 const struct asn1_cursor *raw ) {
301 struct asn1_cursor cursor;
302 struct asn1_cursor oid_cursor;
303 struct asn1_cursor name_cursor;
307 memcpy ( &cursor, raw, sizeof ( cursor ) );
308 asn1_enter ( &cursor, ASN1_SEQUENCE );
310 /* Scan through name list */
311 for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {
313 /* Check for "commonName" OID */
314 memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
315 asn1_enter ( &oid_cursor, ASN1_SET );
316 asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
317 memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) );
318 asn1_enter ( &oid_cursor, ASN1_OID );
319 if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0)
321 asn1_skip_any ( &name_cursor );
322 if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) {
323 DBGC ( cert, "X509 %p cannot locate name:\n", cert );
324 DBGC_HDA ( cert, 0, raw->data, raw->len );
328 /* Record common name */
329 memcpy ( &cert->subject.common_name, &name_cursor,
330 sizeof ( cert->subject.common_name ) );
335 /* Certificates may not have a commonName */
336 DBGC2 ( cert, "X509 %p no commonName found:\n", cert );
341 * Parse X.509 certificate subject
343 * @v cert X.509 certificate
344 * @v raw ASN.1 cursor
345 * @ret rc Return status code
347 static int x509_parse_subject ( struct x509_certificate *cert,
348 const struct asn1_cursor *raw ) {
349 struct x509_subject *subject = &cert->subject;
352 /* Record raw subject */
353 memcpy ( &subject->raw, raw, sizeof ( subject->raw ) );
354 asn1_shrink_any ( &subject->raw );
355 DBGC2 ( cert, "X509 %p subject is:\n", cert );
356 DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );
358 /* Parse common name */
359 if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 )
361 DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert,
362 x509_name ( cert ) );
368 * Parse X.509 certificate public key information
370 * @v cert X.509 certificate
371 * @v raw ASN.1 cursor
372 * @ret rc Return status code
374 static int x509_parse_public_key ( struct x509_certificate *cert,
375 const struct asn1_cursor *raw ) {
376 struct x509_public_key *public_key = &cert->subject.public_key;
377 struct asn1_algorithm **algorithm = &public_key->algorithm;
378 struct asn1_bit_string *raw_bits = &public_key->raw_bits;
379 struct asn1_cursor cursor;
382 /* Record raw subjectPublicKeyInfo */
383 memcpy ( &cursor, raw, sizeof ( cursor ) );
384 asn1_shrink_any ( &cursor );
385 memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) );
386 DBGC2 ( cert, "X509 %p public key is:\n", cert );
387 DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len );
389 /* Enter subjectPublicKeyInfo */
390 asn1_enter ( &cursor, ASN1_SEQUENCE );
392 /* Parse algorithm */
393 if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) {
394 DBGC ( cert, "X509 %p could not parse public key algorithm: "
395 "%s\n", cert, strerror ( rc ) );
398 DBGC2 ( cert, "X509 %p public key algorithm is %s\n",
399 cert, (*algorithm)->name );
400 asn1_skip_any ( &cursor );
402 /* Parse bit string */
403 if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
404 DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
405 cert, strerror ( rc ) );
413 * Parse X.509 certificate basic constraints
415 * @v cert X.509 certificate
416 * @v raw ASN.1 cursor
417 * @ret rc Return status code
419 static int x509_parse_basic_constraints ( struct x509_certificate *cert,
420 const struct asn1_cursor *raw ) {
421 struct x509_basic_constraints *basic = &cert->extensions.basic;
422 struct asn1_cursor cursor;
427 /* Enter basicConstraints */
428 memcpy ( &cursor, raw, sizeof ( cursor ) );
429 asn1_enter ( &cursor, ASN1_SEQUENCE );
431 /* Parse "cA", if present */
432 if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
433 ca = asn1_boolean ( &cursor );
436 DBGC ( cert, "X509 %p cannot parse cA: %s\n",
437 cert, strerror ( rc ) );
438 DBGC_HDA ( cert, 0, raw->data, raw->len );
441 asn1_skip_any ( &cursor );
444 DBGC2 ( cert, "X509 %p is %sa CA certificate\n",
445 cert, ( basic->ca ? "" : "not " ) );
447 /* Ignore everything else unless "cA" is true */
451 /* Parse "pathLenConstraint", if present and applicable */
452 basic->path_len = X509_PATH_LEN_UNLIMITED;
453 if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
454 if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
455 DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
456 "%s\n", cert, strerror ( rc ) );
457 DBGC_HDA ( cert, 0, raw->data, raw->len );
460 if ( path_len < 0 ) {
461 DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n",
463 DBGC_HDA ( cert, 0, raw->data, raw->len );
466 basic->path_len = path_len;
467 DBGC2 ( cert, "X509 %p path length constraint is %d\n",
468 cert, basic->path_len );
475 * Parse X.509 certificate key usage
477 * @v cert X.509 certificate
478 * @v raw ASN.1 cursor
479 * @ret rc Return status code
481 static int x509_parse_key_usage ( struct x509_certificate *cert,
482 const struct asn1_cursor *raw ) {
483 struct x509_key_usage *usage = &cert->extensions.usage;
484 struct asn1_bit_string bit_string;
485 const uint8_t *bytes;
490 /* Mark extension as present */
493 /* Parse bit string */
494 if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
495 DBGC ( cert, "X509 %p could not parse key usage: %s\n",
496 cert, strerror ( rc ) );
500 /* Parse key usage bits */
501 bytes = bit_string.data;
502 len = bit_string.len;
503 if ( len > sizeof ( usage->bits ) )
504 len = sizeof ( usage->bits );
505 for ( i = 0 ; i < len ; i++ ) {
506 usage->bits |= ( *(bytes++) << ( 8 * i ) );
508 DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits );
513 /** "id-kp-codeSigning" object identifier */
514 static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING };
516 /** "id-kp-OCSPSigning" object identifier */
517 static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING };
519 /** Supported key purposes */
520 static struct x509_key_purpose x509_key_purposes[] = {
522 .name = "codeSigning",
523 .bits = X509_CODE_SIGNING,
524 .oid = ASN1_OID_CURSOR ( oid_code_signing ),
527 .name = "ocspSigning",
528 .bits = X509_OCSP_SIGNING,
529 .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ),
534 * Parse X.509 certificate key purpose identifier
536 * @v cert X.509 certificate
537 * @v raw ASN.1 cursor
538 * @ret rc Return status code
540 static int x509_parse_key_purpose ( struct x509_certificate *cert,
541 const struct asn1_cursor *raw ) {
542 struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
543 struct x509_key_purpose *purpose;
544 struct asn1_cursor cursor;
548 /* Enter keyPurposeId */
549 memcpy ( &cursor, raw, sizeof ( cursor ) );
550 if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
551 DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
552 DBGC_HDA ( cert, 0, raw->data, raw->len );
556 /* Identify key purpose */
557 for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
558 sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
559 purpose = &x509_key_purposes[i];
560 if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
561 DBGC2 ( cert, "X509 %p has key purpose %s\n",
562 cert, purpose->name );
563 ext_usage->bits |= purpose->bits;
568 /* Ignore unrecognised key purposes */
573 * Parse X.509 certificate extended key usage
575 * @v cert X.509 certificate
576 * @v raw ASN.1 cursor
577 * @ret rc Return status code
579 static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
580 const struct asn1_cursor *raw ) {
581 struct asn1_cursor cursor;
584 /* Enter extKeyUsage */
585 memcpy ( &cursor, raw, sizeof ( cursor ) );
586 asn1_enter ( &cursor, ASN1_SEQUENCE );
588 /* Parse each extended key usage in turn */
589 while ( cursor.len ) {
590 if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
592 asn1_skip_any ( &cursor );
599 * Parse X.509 certificate OCSP access method
601 * @v cert X.509 certificate
602 * @v raw ASN.1 cursor
603 * @ret rc Return status code
605 static int x509_parse_ocsp ( struct x509_certificate *cert,
606 const struct asn1_cursor *raw ) {
607 struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
608 struct asn1_cursor *uri = &ocsp->uri;
611 /* Enter accessLocation */
612 memcpy ( uri, raw, sizeof ( *uri ) );
613 if ( ( rc = asn1_enter ( uri, X509_GENERAL_NAME_URI ) ) != 0 ) {
614 DBGC ( cert, "X509 %p OCSP does not contain "
615 "uniformResourceIdentifier:\n", cert );
616 DBGC_HDA ( cert, 0, raw->data, raw->len );
619 DBGC2 ( cert, "X509 %p OCSP URI is:\n", cert );
620 DBGC2_HDA ( cert, 0, uri->data, uri->len );
625 /** "id-ad-ocsp" object identifier */
626 static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
628 /** Supported access methods */
629 static struct x509_access_method x509_access_methods[] = {
632 .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
633 .parse = x509_parse_ocsp,
638 * Identify X.509 access method by OID
641 * @ret method Access method, or NULL
643 static struct x509_access_method *
644 x509_find_access_method ( const struct asn1_cursor *oid ) {
645 struct x509_access_method *method;
648 for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
649 sizeof ( x509_access_methods[0] ) ) ; i++ ) {
650 method = &x509_access_methods[i];
651 if ( asn1_compare ( &method->oid, oid ) == 0 )
659 * Parse X.509 certificate access description
661 * @v cert X.509 certificate
662 * @v raw ASN.1 cursor
663 * @ret rc Return status code
665 static int x509_parse_access_description ( struct x509_certificate *cert,
666 const struct asn1_cursor *raw ) {
667 struct asn1_cursor cursor;
668 struct asn1_cursor subcursor;
669 struct x509_access_method *method;
672 /* Enter keyPurposeId */
673 memcpy ( &cursor, raw, sizeof ( cursor ) );
674 asn1_enter ( &cursor, ASN1_SEQUENCE );
676 /* Try to identify access method */
677 memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
678 asn1_enter ( &subcursor, ASN1_OID );
679 method = x509_find_access_method ( &subcursor );
680 asn1_skip_any ( &cursor );
681 DBGC2 ( cert, "X509 %p found access method %s\n",
682 cert, ( method ? method->name : "<unknown>" ) );
684 /* Parse access location, if applicable */
685 if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
692 * Parse X.509 certificate authority information access
694 * @v cert X.509 certificate
695 * @v raw ASN.1 cursor
696 * @ret rc Return status code
698 static int x509_parse_authority_info_access ( struct x509_certificate *cert,
699 const struct asn1_cursor *raw ) {
700 struct asn1_cursor cursor;
703 /* Enter authorityInfoAccess */
704 memcpy ( &cursor, raw, sizeof ( cursor ) );
705 asn1_enter ( &cursor, ASN1_SEQUENCE );
707 /* Parse each access description in turn */
708 while ( cursor.len ) {
709 if ( ( rc = x509_parse_access_description ( cert,
712 asn1_skip_any ( &cursor );
719 * Parse X.509 certificate subject alternative name
721 * @v cert X.509 certificate
722 * @v raw ASN.1 cursor
723 * @ret rc Return status code
725 static int x509_parse_subject_alt_name ( struct x509_certificate *cert,
726 const struct asn1_cursor *raw ) {
727 struct x509_subject_alt_name *alt_name = &cert->extensions.alt_name;
728 struct asn1_cursor *names = &alt_name->names;
731 /* Enter subjectAltName */
732 memcpy ( names, raw, sizeof ( *names ) );
733 if ( ( rc = asn1_enter ( names, ASN1_SEQUENCE ) ) != 0 ) {
734 DBGC ( cert, "X509 %p invalid subjectAltName: %s\n",
735 cert, strerror ( rc ) );
736 DBGC_HDA ( cert, 0, raw->data, raw->len );
739 DBGC2 ( cert, "X509 %p has subjectAltName:\n", cert );
740 DBGC2_HDA ( cert, 0, names->data, names->len );
745 /** "id-ce-basicConstraints" object identifier */
746 static uint8_t oid_ce_basic_constraints[] =
747 { ASN1_OID_BASICCONSTRAINTS };
749 /** "id-ce-keyUsage" object identifier */
750 static uint8_t oid_ce_key_usage[] =
751 { ASN1_OID_KEYUSAGE };
753 /** "id-ce-extKeyUsage" object identifier */
754 static uint8_t oid_ce_ext_key_usage[] =
755 { ASN1_OID_EXTKEYUSAGE };
757 /** "id-pe-authorityInfoAccess" object identifier */
758 static uint8_t oid_pe_authority_info_access[] =
759 { ASN1_OID_AUTHORITYINFOACCESS };
761 /** "id-ce-subjectAltName" object identifier */
762 static uint8_t oid_ce_subject_alt_name[] =
763 { ASN1_OID_SUBJECTALTNAME };
765 /** Supported certificate extensions */
766 static struct x509_extension x509_extensions[] = {
768 .name = "basicConstraints",
769 .oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ),
770 .parse = x509_parse_basic_constraints,
774 .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
775 .parse = x509_parse_key_usage,
778 .name = "extKeyUsage",
779 .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
780 .parse = x509_parse_extended_key_usage,
783 .name = "authorityInfoAccess",
784 .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
785 .parse = x509_parse_authority_info_access,
788 .name = "subjectAltName",
789 .oid = ASN1_OID_CURSOR ( oid_ce_subject_alt_name ),
790 .parse = x509_parse_subject_alt_name,
795 * Identify X.509 extension by OID
798 * @ret extension Extension, or NULL
800 static struct x509_extension *
801 x509_find_extension ( const struct asn1_cursor *oid ) {
802 struct x509_extension *extension;
805 for ( i = 0 ; i < ( sizeof ( x509_extensions ) /
806 sizeof ( x509_extensions[0] ) ) ; i++ ) {
807 extension = &x509_extensions[i];
808 if ( asn1_compare ( &extension->oid, oid ) == 0 )
816 * Parse X.509 certificate extension
818 * @v cert X.509 certificate
819 * @v raw ASN.1 cursor
820 * @ret rc Return status code
822 static int x509_parse_extension ( struct x509_certificate *cert,
823 const struct asn1_cursor *raw ) {
824 struct asn1_cursor cursor;
825 struct asn1_cursor subcursor;
826 struct x509_extension *extension;
830 /* Enter extension */
831 memcpy ( &cursor, raw, sizeof ( cursor ) );
832 asn1_enter ( &cursor, ASN1_SEQUENCE );
834 /* Try to identify extension */
835 memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
836 asn1_enter ( &subcursor, ASN1_OID );
837 extension = x509_find_extension ( &subcursor );
838 asn1_skip_any ( &cursor );
839 DBGC2 ( cert, "X509 %p found extension %s\n",
840 cert, ( extension ? extension->name : "<unknown>" ) );
842 /* Identify criticality */
843 if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
844 is_critical = asn1_boolean ( &cursor );
845 if ( is_critical < 0 ) {
847 DBGC ( cert, "X509 %p cannot parse extension "
848 "criticality: %s\n", cert, strerror ( rc ) );
849 DBGC_HDA ( cert, 0, raw->data, raw->len );
852 asn1_skip_any ( &cursor );
855 /* Handle unknown extensions */
858 /* Fail if we cannot handle a critical extension */
859 DBGC ( cert, "X509 %p cannot handle critical "
860 "extension:\n", cert );
861 DBGC_HDA ( cert, 0, raw->data, raw->len );
862 return -ENOTSUP_EXTENSION;
864 /* Ignore unknown non-critical extensions */
869 /* Extract extnValue */
870 if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
871 DBGC ( cert, "X509 %p extension missing extnValue:\n", cert );
872 DBGC_HDA ( cert, 0, raw->data, raw->len );
876 /* Parse extension */
877 if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 )
884 * Parse X.509 certificate extensions, if present
886 * @v cert X.509 certificate
887 * @v raw ASN.1 cursor
888 * @ret rc Return status code
890 static int x509_parse_extensions ( struct x509_certificate *cert,
891 const struct asn1_cursor *raw ) {
892 struct asn1_cursor cursor;
895 /* Enter extensions, if present */
896 memcpy ( &cursor, raw, sizeof ( cursor ) );
897 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) );
898 asn1_enter ( &cursor, ASN1_SEQUENCE );
900 /* Parse each extension in turn */
901 while ( cursor.len ) {
902 if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 )
904 asn1_skip_any ( &cursor );
911 * Parse X.509 certificate tbsCertificate
913 * @v cert X.509 certificate
914 * @v raw ASN.1 cursor
915 * @ret rc Return status code
917 static int x509_parse_tbscertificate ( struct x509_certificate *cert,
918 const struct asn1_cursor *raw ) {
919 struct asn1_algorithm **algorithm = &cert->signature_algorithm;
920 struct asn1_cursor cursor;
923 /* Record raw tbsCertificate */
924 memcpy ( &cursor, raw, sizeof ( cursor ) );
925 asn1_shrink_any ( &cursor );
926 memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) );
928 /* Enter tbsCertificate */
929 asn1_enter ( &cursor, ASN1_SEQUENCE );
931 /* Parse version, if present */
932 if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
933 if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 )
935 asn1_skip_any ( &cursor );
938 /* Parse serialNumber */
939 if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 )
941 asn1_skip_any ( &cursor );
943 /* Parse signature */
944 if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
945 DBGC ( cert, "X509 %p could not parse signature algorithm: "
946 "%s\n", cert, strerror ( rc ) );
949 DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n",
950 cert, (*algorithm)->name );
951 asn1_skip_any ( &cursor );
954 if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 )
956 asn1_skip_any ( &cursor );
959 if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 )
961 asn1_skip_any ( &cursor );
964 if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 )
966 asn1_skip_any ( &cursor );
968 /* Parse subjectPublicKeyInfo */
969 if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 )
971 asn1_skip_any ( &cursor );
973 /* Parse extensions, if present */
974 if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 )
981 * Parse X.509 certificate from ASN.1 data
983 * @v cert X.509 certificate
984 * @v raw ASN.1 cursor
985 * @ret rc Return status code
987 int x509_parse ( struct x509_certificate *cert,
988 const struct asn1_cursor *raw ) {
989 struct x509_signature *signature = &cert->signature;
990 struct asn1_algorithm **signature_algorithm = &signature->algorithm;
991 struct asn1_bit_string *signature_value = &signature->value;
992 struct asn1_cursor cursor;
995 /* Record raw certificate */
996 memcpy ( &cursor, raw, sizeof ( cursor ) );
997 memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );
999 /* Enter certificate */
1000 asn1_enter ( &cursor, ASN1_SEQUENCE );
1002 /* Parse tbsCertificate */
1003 if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 )
1005 asn1_skip_any ( &cursor );
1007 /* Parse signatureAlgorithm */
1008 if ( ( rc = asn1_signature_algorithm ( &cursor,
1009 signature_algorithm ) ) != 0 ) {
1010 DBGC ( cert, "X509 %p could not parse signature algorithm: "
1011 "%s\n", cert, strerror ( rc ) );
1014 DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n",
1015 cert, (*signature_algorithm)->name );
1016 asn1_skip_any ( &cursor );
1018 /* Parse signatureValue */
1019 if ( ( rc = asn1_integral_bit_string ( &cursor,
1020 signature_value ) ) != 0 ) {
1021 DBGC ( cert, "X509 %p could not parse signature value: %s\n",
1022 cert, strerror ( rc ) );
1025 DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
1026 DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
1028 /* Check that algorithm in tbsCertificate matches algorithm in
1031 if ( signature->algorithm != (*signature_algorithm) ) {
1032 DBGC ( cert, "X509 %p signature algorithm %s does not match "
1033 "signatureAlgorithm %s\n",
1034 cert, signature->algorithm->name,
1035 (*signature_algorithm)->name );
1036 return -EINVAL_ALGORITHM_MISMATCH;
1043 * Create X.509 certificate
1045 * @v data Raw certificate data
1046 * @v len Length of raw data
1047 * @ret cert X.509 certificate
1048 * @ret rc Return status code
1050 * On success, the caller holds a reference to the X.509 certificate,
1051 * and is responsible for ultimately calling x509_put().
1053 int x509_certificate ( const void *data, size_t len,
1054 struct x509_certificate **cert ) {
1055 struct asn1_cursor cursor;
1059 /* Initialise cursor */
1062 asn1_shrink_any ( &cursor );
1064 /* Return stored certificate, if present */
1065 if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {
1067 /* Add caller's reference */
1072 /* Allocate and initialise certificate */
1073 *cert = zalloc ( sizeof ( **cert ) + cursor.len );
1076 ref_init ( &(*cert)->refcnt, NULL );
1077 raw = ( *cert + 1 );
1080 memcpy ( raw, cursor.data, cursor.len );
1083 /* Parse certificate */
1084 if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
1090 /* Add certificate to store */
1091 certstore_add ( *cert );
1097 * Check X.509 certificate signature
1099 * @v cert X.509 certificate
1100 * @v public_key X.509 public key
1101 * @ret rc Return status code
1103 static int x509_check_signature ( struct x509_certificate *cert,
1104 struct x509_public_key *public_key ) {
1105 struct x509_signature *signature = &cert->signature;
1106 struct asn1_algorithm *algorithm = signature->algorithm;
1107 struct digest_algorithm *digest = algorithm->digest;
1108 struct pubkey_algorithm *pubkey = algorithm->pubkey;
1109 uint8_t digest_ctx[ digest->ctxsize ];
1110 uint8_t digest_out[ digest->digestsize ];
1111 uint8_t pubkey_ctx[ pubkey->ctxsize ];
1115 assert ( cert->signature_algorithm == cert->signature.algorithm );
1117 /* Calculate certificate digest */
1118 digest_init ( digest, digest_ctx );
1119 digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
1120 digest_final ( digest, digest_ctx, digest_out );
1121 DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) );
1122 DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
1124 /* Check that signature public key algorithm matches signer */
1125 if ( public_key->algorithm->pubkey != pubkey ) {
1126 DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
1127 "match signer's algorithm %s\n",
1128 cert, x509_name ( cert ), algorithm->name,
1129 public_key->algorithm->name );
1130 rc = -EINVAL_ALGORITHM_MISMATCH;
1134 /* Verify signature using signer's public key */
1135 if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
1136 public_key->raw.len ) ) != 0 ) {
1137 DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
1138 "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
1139 goto err_pubkey_init;
1141 if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
1142 signature->value.data,
1143 signature->value.len ) ) != 0 ) {
1144 DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
1145 "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
1146 goto err_pubkey_verify;
1153 pubkey_final ( pubkey, pubkey_ctx );
1160 * Check X.509 certificate against issuer certificate
1162 * @v cert X.509 certificate
1163 * @v issuer X.509 issuer certificate
1164 * @ret rc Return status code
1166 int x509_check_issuer ( struct x509_certificate *cert,
1167 struct x509_certificate *issuer ) {
1168 struct x509_public_key *public_key = &issuer->subject.public_key;
1171 /* Check issuer. In theory, this should be a full X.500 DN
1172 * comparison, which would require support for a plethora of
1173 * abominations such as TeletexString (which allows the
1174 * character set to be changed mid-string using escape codes).
1175 * In practice, we assume that anyone who deliberately changes
1176 * the encoding of the issuer DN is probably a masochist who
1177 * will rather enjoy the process of figuring out exactly why
1178 * their certificate doesn't work.
1180 * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
1181 * for some enjoyable ranting on this subject.
1183 if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
1184 DBGC ( cert, "X509 %p \"%s\" issuer does not match ",
1185 cert, x509_name ( cert ) );
1186 DBGC ( cert, "X509 %p \"%s\" subject\n",
1187 issuer, x509_name ( issuer ) );
1188 DBGC_HDA ( cert, 0, cert->issuer.raw.data,
1189 cert->issuer.raw.len );
1190 DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
1191 issuer->subject.raw.len );
1192 return -EACCES_WRONG_ISSUER;
1195 /* Check that issuer is allowed to sign certificates */
1196 if ( ! issuer->extensions.basic.ca ) {
1197 DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
1198 issuer, x509_name ( issuer ) );
1199 DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n",
1200 cert, x509_name ( cert ) );
1201 return -EACCES_NOT_CA;
1203 if ( issuer->extensions.usage.present &&
1204 ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
1205 DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
1206 issuer, x509_name ( issuer ) );
1207 DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n",
1208 cert, x509_name ( cert ) );
1209 return -EACCES_KEY_USAGE;
1212 /* Check signature */
1213 if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
1220 * Calculate X.509 certificate fingerprint
1222 * @v cert X.509 certificate
1223 * @v digest Digest algorithm
1224 * @v fingerprint Fingerprint buffer
1226 void x509_fingerprint ( struct x509_certificate *cert,
1227 struct digest_algorithm *digest,
1228 void *fingerprint ) {
1229 uint8_t ctx[ digest->ctxsize ];
1231 /* Calculate fingerprint */
1232 digest_init ( digest, ctx );
1233 digest_update ( digest, ctx, cert->raw.data, cert->raw.len );
1234 digest_final ( digest, ctx, fingerprint );
1238 * Check X.509 root certificate
1240 * @v cert X.509 certificate
1241 * @v root X.509 root certificate list
1242 * @ret rc Return status code
1244 int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
1245 struct digest_algorithm *digest = root->digest;
1246 uint8_t fingerprint[ digest->digestsize ];
1247 const uint8_t *root_fingerprint = root->fingerprints;
1250 /* Calculate certificate fingerprint */
1251 x509_fingerprint ( cert, digest, fingerprint );
1253 /* Check fingerprint against all root certificates */
1254 for ( i = 0 ; i < root->count ; i++ ) {
1255 if ( memcmp ( fingerprint, root_fingerprint,
1256 sizeof ( fingerprint ) ) == 0 ) {
1257 DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
1258 cert, x509_name ( cert ) );
1261 root_fingerprint += sizeof ( fingerprint );
1264 DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
1265 cert, x509_name ( cert ) );
1270 * Check X.509 certificate validity period
1272 * @v cert X.509 certificate
1273 * @v time Time at which to check certificate
1274 * @ret rc Return status code
1276 int x509_check_time ( struct x509_certificate *cert, time_t time ) {
1277 struct x509_validity *validity = &cert->validity;
1279 /* Check validity period */
1280 if ( validity->not_before.time > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
1281 DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
1282 cert, x509_name ( cert ), time );
1283 return -EACCES_EXPIRED;
1285 if ( validity->not_after.time < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
1286 DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
1287 cert, x509_name ( cert ), time );
1288 return -EACCES_EXPIRED;
1291 DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
1292 cert, x509_name ( cert ), time );
1297 * Validate X.509 certificate
1299 * @v cert X.509 certificate
1300 * @v issuer Issuing X.509 certificate (or NULL)
1301 * @v time Time at which to validate certificate
1302 * @v root Root certificate list, or NULL to use default
1303 * @ret rc Return status code
1305 * The issuing certificate must have already been validated.
1307 * Validation results are cached: if a certificate has already been
1308 * successfully validated then @c issuer, @c time, and @c root will be
1311 int x509_validate ( struct x509_certificate *cert,
1312 struct x509_certificate *issuer,
1313 time_t time, struct x509_root *root ) {
1314 unsigned int max_path_remaining;
1317 /* Use default root certificate store if none specified */
1319 root = &root_certificates;
1321 /* Return success if certificate has already been validated */
1325 /* Fail if certificate is invalid at specified time */
1326 if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
1329 /* Succeed if certificate is a trusted root certificate */
1330 if ( x509_check_root ( cert, root ) == 0 ) {
1332 cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
1336 /* Fail unless we have an issuer */
1338 DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
1339 cert, x509_name ( cert ) );
1340 return -EACCES_UNTRUSTED;
1343 /* Fail unless issuer has already been validated */
1344 if ( ! issuer->valid ) {
1345 DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
1346 DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n",
1347 issuer, x509_name ( issuer ) );
1348 return -EACCES_OUT_OF_ORDER;
1351 /* Fail if issuing certificate cannot validate this certificate */
1352 if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
1355 /* Fail if path length constraint is violated */
1356 if ( issuer->path_remaining == 0 ) {
1357 DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
1358 DBGC ( cert, "issuer %p \"%s\" path length exceeded\n",
1359 issuer, x509_name ( issuer ) );
1360 return -EACCES_PATH_LEN;
1363 /* Fail if OCSP is required */
1364 if ( cert->extensions.auth_info.ocsp.uri.len &&
1365 ( ! cert->extensions.auth_info.ocsp.good ) ) {
1366 DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n",
1367 cert, x509_name ( cert ) );
1368 return -EACCES_OCSP_REQUIRED;
1371 /* Calculate effective path length */
1372 cert->path_remaining = ( issuer->path_remaining - 1 );
1373 max_path_remaining = ( cert->extensions.basic.path_len + 1 );
1374 if ( cert->path_remaining > max_path_remaining )
1375 cert->path_remaining = max_path_remaining;
1377 /* Mark certificate as valid */
1380 DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
1381 cert, x509_name ( cert ) );
1382 DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) );
1387 * Check X.509 certificate alternative dNSName
1389 * @v cert X.509 certificate
1390 * @v raw ASN.1 cursor
1392 * @ret rc Return status code
1394 static int x509_check_dnsname ( struct x509_certificate *cert,
1395 const struct asn1_cursor *raw,
1396 const char *name ) {
1397 const char *fullname = name;
1398 const char *dnsname = raw->data;
1399 size_t len = raw->len;
1401 /* Check for wildcards */
1402 if ( ( len >= 2 ) && ( dnsname[0] == '*' ) && ( dnsname[1] == '.' ) ) {
1404 /* Skip initial "*." */
1408 /* Skip initial portion of name to be tested */
1409 name = strchr ( name, '.' );
1416 if ( ! ( ( strlen ( name ) == len ) &&
1417 ( memcmp ( name, dnsname, len ) == 0 ) ) )
1420 if ( name != fullname ) {
1421 DBGC2 ( cert, "X509 %p \"%s\" found wildcard match for "
1422 "\"*.%s\"\n", cert, x509_name ( cert ), name );
1428 * Check X.509 certificate alternative iPAddress
1430 * @v cert X.509 certificate
1431 * @v raw ASN.1 cursor
1433 * @ret rc Return status code
1435 static int x509_check_ipaddress ( struct x509_certificate *cert,
1436 const struct asn1_cursor *raw,
1437 const char *name ) {
1440 const void *address;
1443 /* Determine address family */
1444 if ( raw->len == sizeof ( struct in_addr ) ) {
1445 struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa );
1447 address = &sin->sin_addr;
1448 } else if ( raw->len == sizeof ( struct in6_addr ) ) {
1449 struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa );
1451 address = &sin6->sin6_addr;
1453 DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected "
1454 "length %zd\n", cert, x509_name ( cert ), raw->len );
1455 DBGC_HDA ( cert, 0, raw->data, raw->len );
1459 /* Attempt to convert name to a socket address */
1460 if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) {
1461 DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as "
1462 "iPAddress: %s\n", cert, x509_name ( cert ), name,
1466 if ( sa.sa_family != family )
1469 /* Compare addresses */
1470 if ( memcmp ( address, raw->data, raw->len ) != 0 )
1473 DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n",
1474 cert, x509_name ( cert ), sock_ntoa ( &sa ) );
1479 * Check X.509 certificate alternative name
1481 * @v cert X.509 certificate
1482 * @v raw ASN.1 cursor
1484 * @ret rc Return status code
1486 static int x509_check_alt_name ( struct x509_certificate *cert,
1487 const struct asn1_cursor *raw,
1488 const char *name ) {
1489 struct asn1_cursor alt_name;
1492 /* Enter generalName */
1493 memcpy ( &alt_name, raw, sizeof ( alt_name ) );
1494 type = asn1_type ( &alt_name );
1495 asn1_enter_any ( &alt_name );
1497 /* Check this name */
1499 case X509_GENERAL_NAME_DNS :
1500 return x509_check_dnsname ( cert, &alt_name, name );
1501 case X509_GENERAL_NAME_IP :
1502 return x509_check_ipaddress ( cert, &alt_name, name );
1504 DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n",
1505 cert, x509_name ( cert ), type );
1506 DBGC2_HDA ( cert, 0, alt_name.data, alt_name.len );
1512 * Check X.509 certificate name
1514 * @v cert X.509 certificate
1516 * @ret rc Return status code
1518 int x509_check_name ( struct x509_certificate *cert, const char *name ) {
1519 struct asn1_cursor *common_name = &cert->subject.common_name;
1520 struct asn1_cursor alt_name;
1523 /* Check commonName */
1524 if ( x509_check_dnsname ( cert, common_name, name ) == 0 ) {
1525 DBGC2 ( cert, "X509 %p \"%s\" commonName matches \"%s\"\n",
1526 cert, x509_name ( cert ), name );
1530 /* Check any subjectAlternativeNames */
1531 memcpy ( &alt_name, &cert->extensions.alt_name.names,
1532 sizeof ( alt_name ) );
1533 for ( ; alt_name.len ; asn1_skip_any ( &alt_name ) ) {
1534 if ( ( rc = x509_check_alt_name ( cert, &alt_name,
1536 DBGC2 ( cert, "X509 %p \"%s\" subjectAltName matches "
1537 "\"%s\"\n", cert, x509_name ( cert ), name );
1542 DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n",
1543 cert, x509_name ( cert ), name );
1544 return -EACCES_WRONG_NAME;
1548 * Free X.509 certificate chain
1550 * @v refcnt Reference count
1552 static void x509_free_chain ( struct refcnt *refcnt ) {
1553 struct x509_chain *chain =
1554 container_of ( refcnt, struct x509_chain, refcnt );
1555 struct x509_link *link;
1556 struct x509_link *tmp;
1558 DBGC2 ( chain, "X509 chain %p freed\n", chain );
1560 /* Free each link in the chain */
1561 list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
1562 x509_put ( link->cert );
1563 list_del ( &link->list );
1572 * Allocate X.509 certificate chain
1574 * @ret chain X.509 certificate chain, or NULL
1576 struct x509_chain * x509_alloc_chain ( void ) {
1577 struct x509_chain *chain;
1579 /* Allocate chain */
1580 chain = zalloc ( sizeof ( *chain ) );
1584 /* Initialise chain */
1585 ref_init ( &chain->refcnt, x509_free_chain );
1586 INIT_LIST_HEAD ( &chain->links );
1588 DBGC2 ( chain, "X509 chain %p allocated\n", chain );
1593 * Append X.509 certificate to X.509 certificate chain
1595 * @v chain X.509 certificate chain
1596 * @v cert X.509 certificate
1597 * @ret rc Return status code
1599 int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
1600 struct x509_link *link;
1603 link = zalloc ( sizeof ( *link ) );
1607 /* Add link to chain */
1608 link->cert = x509_get ( cert );
1609 list_add_tail ( &link->list, &chain->links );
1610 DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
1611 chain, cert, x509_name ( cert ) );
1617 * Append X.509 certificate to X.509 certificate chain
1619 * @v chain X.509 certificate chain
1620 * @v data Raw certificate data
1621 * @v len Length of raw data
1622 * @ret rc Return status code
1624 int x509_append_raw ( struct x509_chain *chain, const void *data,
1626 struct x509_certificate *cert;
1629 /* Parse certificate */
1630 if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 )
1633 /* Append certificate to chain */
1634 if ( ( rc = x509_append ( chain, cert ) ) != 0 )
1637 /* Drop reference to certificate */
1649 * Identify X.509 certificate by subject
1651 * @v certs X.509 certificate list
1652 * @v subject Subject
1653 * @ret cert X.509 certificate, or NULL if not found
1655 static struct x509_certificate *
1656 x509_find_subject ( struct x509_chain *certs,
1657 const struct asn1_cursor *subject ) {
1658 struct x509_link *link;
1659 struct x509_certificate *cert;
1661 /* Scan through certificate list */
1662 list_for_each_entry ( link, &certs->links, list ) {
1666 if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
1674 * Append X.509 certificates to X.509 certificate chain
1676 * @v chain X.509 certificate chain
1677 * @v certs X.509 certificate list
1678 * @ret rc Return status code
1680 * Certificates will be automatically appended to the chain based upon
1681 * the subject and issuer names.
1683 int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
1684 struct x509_certificate *cert;
1685 struct x509_certificate *previous;
1688 /* Get current certificate */
1689 cert = x509_last ( chain );
1691 DBGC ( chain, "X509 chain %p has no certificates\n", chain );
1692 return -EACCES_EMPTY;
1695 /* Append certificates, in order */
1698 /* Find issuing certificate */
1700 cert = x509_find_subject ( certs, &cert->issuer.raw );
1703 if ( cert == previous )
1706 /* Append certificate to chain */
1707 if ( ( rc = x509_append ( chain, cert ) ) != 0 )
1715 * Validate X.509 certificate chain
1717 * @v chain X.509 certificate chain
1718 * @v time Time at which to validate certificates
1719 * @v store Certificate store, or NULL to use default
1720 * @v root Root certificate list, or NULL to use default
1721 * @ret rc Return status code
1723 int x509_validate_chain ( struct x509_chain *chain, time_t time,
1724 struct x509_chain *store, struct x509_root *root ) {
1725 struct x509_certificate *issuer = NULL;
1726 struct x509_link *link;
1729 /* Use default certificate store if none specified */
1733 /* Append any applicable certificates from the certificate store */
1734 if ( ( rc = x509_auto_append ( chain, store ) ) != 0 )
1737 /* Find first certificate that can be validated as a
1738 * standalone (i.e. is already valid, or can be validated as
1739 * a trusted root certificate).
1741 list_for_each_entry ( link, &chain->links, list ) {
1743 /* Try validating this certificate as a standalone */
1744 if ( ( rc = x509_validate ( link->cert, NULL, time,
1748 /* Work back up to start of chain, performing pairwise
1751 issuer = link->cert;
1752 list_for_each_entry_continue_reverse ( link, &chain->links,
1755 /* Validate this certificate against its issuer */
1756 if ( ( rc = x509_validate ( link->cert, issuer, time,
1759 issuer = link->cert;
1765 DBGC ( chain, "X509 chain %p found no usable certificates\n", chain );
1766 return -EACCES_USELESS;
1769 /* Drag in objects via x509_validate() */
1770 REQUIRING_SYMBOL ( x509_validate );
1772 /* Drag in certificate store */
1773 REQUIRE_OBJECT ( certstore );
1775 /* Drag in crypto configuration */
1776 REQUIRE_OBJECT ( config_crypto );