1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  *
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.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <ipxe/list.h>
31 #include <ipxe/base16.h>
32 #include <ipxe/asn1.h>
33 #include <ipxe/crypto.h>
34 #include <ipxe/md5.h>
35 #include <ipxe/sha1.h>
36 #include <ipxe/sha256.h>
37 #include <ipxe/rsa.h>
38 #include <ipxe/rootcert.h>
39 #include <ipxe/certstore.h>
40 #include <ipxe/socket.h>
41 #include <ipxe/in.h>
42 #include <ipxe/image.h>
43 #include <ipxe/ocsp.h>
44 #include <ipxe/x509.h>
45 #include <config/crypto.h>
46 
47 /** @file
48  *
49  * X.509 certificates
50  *
51  * The structure of X.509v3 certificates is documented in RFC 5280
52  * section 4.1.
53  */
54 
55 /* Disambiguate the various error causes */
56 #define ENOTSUP_ALGORITHM \
57 	__einfo_error ( EINFO_ENOTSUP_ALGORITHM )
58 #define EINFO_ENOTSUP_ALGORITHM \
59 	__einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
60 #define ENOTSUP_EXTENSION \
61 	__einfo_error ( EINFO_ENOTSUP_EXTENSION )
62 #define EINFO_ENOTSUP_EXTENSION \
63 	__einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
64 #define EINVAL_ALGORITHM \
65 	__einfo_error ( EINFO_EINVAL_ALGORITHM )
66 #define EINFO_EINVAL_ALGORITHM \
67 	__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
68 #define EINVAL_ALGORITHM_MISMATCH \
69 	__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
70 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
71 	__einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )
72 #define EINVAL_PATH_LEN \
73 	__einfo_error ( EINFO_EINVAL_PATH_LEN )
74 #define EINFO_EINVAL_PATH_LEN \
75 	__einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )
76 #define EINVAL_VERSION \
77 	__einfo_error ( EINFO_EINVAL_VERSION )
78 #define EINFO_EINVAL_VERSION \
79 	__einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )
80 #define EACCES_WRONG_ISSUER \
81 	__einfo_error ( EINFO_EACCES_WRONG_ISSUER )
82 #define EINFO_EACCES_WRONG_ISSUER \
83 	__einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )
84 #define EACCES_NOT_CA \
85 	__einfo_error ( EINFO_EACCES_NOT_CA )
86 #define EINFO_EACCES_NOT_CA \
87 	__einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )
88 #define EACCES_KEY_USAGE \
89 	__einfo_error ( EINFO_EACCES_KEY_USAGE )
90 #define EINFO_EACCES_KEY_USAGE \
91 	__einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )
92 #define EACCES_EXPIRED \
93 	__einfo_error ( EINFO_EACCES_EXPIRED )
94 #define EINFO_EACCES_EXPIRED \
95 	__einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )
96 #define EACCES_PATH_LEN \
97 	__einfo_error ( EINFO_EACCES_PATH_LEN )
98 #define EINFO_EACCES_PATH_LEN \
99 	__einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )
100 #define EACCES_UNTRUSTED \
101 	__einfo_error ( EINFO_EACCES_UNTRUSTED )
102 #define EINFO_EACCES_UNTRUSTED \
103 	__einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
104 #define EACCES_OUT_OF_ORDER \
105 	__einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
106 #define EINFO_EACCES_OUT_OF_ORDER \
107 	__einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
108 #define EACCES_EMPTY \
109 	__einfo_error ( EINFO_EACCES_EMPTY )
110 #define EINFO_EACCES_EMPTY \
111 	__einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
112 #define EACCES_OCSP_REQUIRED \
113 	__einfo_error ( EINFO_EACCES_OCSP_REQUIRED )
114 #define EINFO_EACCES_OCSP_REQUIRED \
115 	__einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )
116 #define EACCES_WRONG_NAME \
117 	__einfo_error ( EINFO_EACCES_WRONG_NAME )
118 #define EINFO_EACCES_WRONG_NAME \
119 	__einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )
120 #define EACCES_USELESS \
121 	__einfo_error ( EINFO_EACCES_USELESS )
122 #define EINFO_EACCES_USELESS \
123 	__einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )
124 
125 /**
126  * Get X.509 certificate display name
127  *
128  * @v cert		X.509 certificate
129  * @ret name		Display name
130  */
x509_name(struct x509_certificate * cert)131 const char * x509_name ( struct x509_certificate *cert ) {
132 	struct asn1_cursor *common_name = &cert->subject.common_name;
133 	struct digest_algorithm *digest = &sha1_algorithm;
134 	static char buf[64];
135 	uint8_t fingerprint[ digest->digestsize ];
136 	size_t len;
137 
138 	len = common_name->len;
139 	if ( len ) {
140 		/* Certificate has a commonName: use that */
141 		if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
142 			len = ( sizeof ( buf ) - 1 /* NUL */ );
143 		memcpy ( buf, common_name->data, len );
144 		buf[len] = '\0';
145 	} else {
146 		/* Certificate has no commonName: use SHA-1 fingerprint */
147 		x509_fingerprint ( cert, digest, fingerprint );
148 		base16_encode ( fingerprint, sizeof ( fingerprint ),
149 				buf, sizeof ( buf ) );
150 	}
151 	return buf;
152 }
153 
154 /** "commonName" object identifier */
155 static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
156 
157 /** "commonName" object identifier cursor */
158 static struct asn1_cursor oid_common_name_cursor =
159 	ASN1_OID_CURSOR ( oid_common_name );
160 
161 /**
162  * Parse X.509 certificate version
163  *
164  * @v cert		X.509 certificate
165  * @v raw		ASN.1 cursor
166  * @ret rc		Return status code
167  */
x509_parse_version(struct x509_certificate * cert,const struct asn1_cursor * raw)168 static int x509_parse_version ( struct x509_certificate *cert,
169 				const struct asn1_cursor *raw ) {
170 	struct asn1_cursor cursor;
171 	int version;
172 	int rc;
173 
174 	/* Enter version */
175 	memcpy ( &cursor, raw, sizeof ( cursor ) );
176 	asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
177 
178 	/* Parse integer */
179 	if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) {
180 		DBGC ( cert, "X509 %p cannot parse version: %s\n",
181 		       cert, strerror ( rc ) );
182 		DBGC_HDA ( cert, 0, raw->data, raw->len );
183 		return rc;
184 	}
185 
186 	/* Sanity check */
187 	if ( version < 0 ) {
188 		DBGC ( cert, "X509 %p invalid version %d\n", cert, version );
189 		DBGC_HDA ( cert, 0, raw->data, raw->len );
190 		return -EINVAL_VERSION;
191 	}
192 
193 	/* Record version */
194 	cert->version = version;
195 	DBGC2 ( cert, "X509 %p is a version %d certificate\n",
196 		cert, ( cert->version + 1 ) );
197 
198 	return 0;
199 }
200 
201 /**
202  * Parse X.509 certificate serial number
203  *
204  * @v cert		X.509 certificate
205  * @v raw		ASN.1 cursor
206  * @ret rc		Return status code
207  */
x509_parse_serial(struct x509_certificate * cert,const struct asn1_cursor * raw)208 static int x509_parse_serial ( struct x509_certificate *cert,
209 			       const struct asn1_cursor *raw ) {
210 	struct x509_serial *serial = &cert->serial;
211 	int rc;
212 
213 	/* Record raw serial number */
214 	memcpy ( &serial->raw, raw, sizeof ( serial->raw ) );
215 	if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) {
216 		DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n",
217 		       cert, strerror ( rc ) );
218 		return rc;
219 	}
220 	DBGC2 ( cert, "X509 %p issuer is:\n", cert );
221 	DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len );
222 
223 	return 0;
224 }
225 
226 /**
227  * Parse X.509 certificate issuer
228  *
229  * @v cert		X.509 certificate
230  * @v raw		ASN.1 cursor
231  * @ret rc		Return status code
232  */
x509_parse_issuer(struct x509_certificate * cert,const struct asn1_cursor * raw)233 static int x509_parse_issuer ( struct x509_certificate *cert,
234 			       const struct asn1_cursor *raw ) {
235 	struct x509_issuer *issuer = &cert->issuer;
236 	int rc;
237 
238 	/* Record raw issuer */
239 	memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) );
240 	if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) {
241 		DBGC ( cert, "X509 %p cannot shrink issuer: %s\n",
242 		       cert, strerror ( rc ) );
243 		return rc;
244 	}
245 	DBGC2 ( cert, "X509 %p issuer is:\n", cert );
246 	DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len );
247 
248 	return 0;
249 }
250 
251 /**
252  * Parse X.509 certificate validity
253  *
254  * @v cert		X.509 certificate
255  * @v raw		ASN.1 cursor
256  * @ret rc		Return status code
257  */
x509_parse_validity(struct x509_certificate * cert,const struct asn1_cursor * raw)258 static int x509_parse_validity ( struct x509_certificate *cert,
259 				 const struct asn1_cursor *raw ) {
260 	struct x509_validity *validity = &cert->validity;
261 	struct x509_time *not_before = &validity->not_before;
262 	struct x509_time *not_after = &validity->not_after;
263 	struct asn1_cursor cursor;
264 	int rc;
265 
266 	/* Enter validity */
267 	memcpy ( &cursor, raw, sizeof ( cursor ) );
268 	asn1_enter ( &cursor, ASN1_SEQUENCE );
269 
270 	/* Parse notBefore */
271 	if ( ( rc = asn1_generalized_time ( &cursor,
272 					    &not_before->time ) ) != 0 ) {
273 		DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
274 		       cert, strerror ( rc ) );
275 		return rc;
276 	}
277 	DBGC2 ( cert, "X509 %p valid from time %lld\n",
278 		cert, not_before->time );
279 	asn1_skip_any ( &cursor );
280 
281 	/* Parse notAfter */
282 	if ( ( rc = asn1_generalized_time ( &cursor,
283 					    &not_after->time ) ) != 0 ) {
284 		DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
285 		       cert, strerror ( rc ) );
286 		return rc;
287 	}
288 	DBGC2 ( cert, "X509 %p valid until time %lld\n",
289 		cert, not_after->time );
290 
291 	return 0;
292 }
293 
294 /**
295  * Parse X.509 certificate common name
296  *
297  * @v cert		X.509 certificate
298  * @v raw		ASN.1 cursor
299  * @ret rc		Return status code
300  */
x509_parse_common_name(struct x509_certificate * cert,const struct asn1_cursor * raw)301 static int x509_parse_common_name ( struct x509_certificate *cert,
302 				    const struct asn1_cursor *raw ) {
303 	struct asn1_cursor cursor;
304 	struct asn1_cursor oid_cursor;
305 	struct asn1_cursor name_cursor;
306 	int rc;
307 
308 	/* Enter name */
309 	memcpy ( &cursor, raw, sizeof ( cursor ) );
310 	asn1_enter ( &cursor, ASN1_SEQUENCE );
311 
312 	/* Scan through name list */
313 	for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {
314 
315 		/* Check for "commonName" OID */
316 		memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
317 		asn1_enter ( &oid_cursor, ASN1_SET );
318 		asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
319 		memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) );
320 		asn1_enter ( &oid_cursor, ASN1_OID );
321 		if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0)
322 			continue;
323 		asn1_skip_any ( &name_cursor );
324 		if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) {
325 			DBGC ( cert, "X509 %p cannot locate name:\n", cert );
326 			DBGC_HDA ( cert, 0, raw->data, raw->len );
327 			return rc;
328 		}
329 
330 		/* Record common name */
331 		memcpy ( &cert->subject.common_name, &name_cursor,
332 			 sizeof ( cert->subject.common_name ) );
333 
334 		return 0;
335 	}
336 
337 	/* Certificates may not have a commonName */
338 	DBGC2 ( cert, "X509 %p no commonName found:\n", cert );
339 	return 0;
340 }
341 
342 /**
343  * Parse X.509 certificate subject
344  *
345  * @v cert		X.509 certificate
346  * @v raw		ASN.1 cursor
347  * @ret rc		Return status code
348  */
x509_parse_subject(struct x509_certificate * cert,const struct asn1_cursor * raw)349 static int x509_parse_subject ( struct x509_certificate *cert,
350 				const struct asn1_cursor *raw ) {
351 	struct x509_subject *subject = &cert->subject;
352 	int rc;
353 
354 	/* Record raw subject */
355 	memcpy ( &subject->raw, raw, sizeof ( subject->raw ) );
356 	asn1_shrink_any ( &subject->raw );
357 	DBGC2 ( cert, "X509 %p subject is:\n", cert );
358 	DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );
359 
360 	/* Parse common name */
361 	if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 )
362 		return rc;
363 	DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert,
364 		x509_name ( cert ) );
365 
366 	return 0;
367 }
368 
369 /**
370  * Parse X.509 certificate public key information
371  *
372  * @v cert		X.509 certificate
373  * @v raw		ASN.1 cursor
374  * @ret rc		Return status code
375  */
x509_parse_public_key(struct x509_certificate * cert,const struct asn1_cursor * raw)376 static int x509_parse_public_key ( struct x509_certificate *cert,
377 				   const struct asn1_cursor *raw ) {
378 	struct x509_public_key *public_key = &cert->subject.public_key;
379 	struct asn1_algorithm **algorithm = &public_key->algorithm;
380 	struct asn1_bit_string *raw_bits = &public_key->raw_bits;
381 	struct asn1_cursor cursor;
382 	int rc;
383 
384 	/* Record raw subjectPublicKeyInfo */
385 	memcpy ( &cursor, raw, sizeof ( cursor ) );
386 	asn1_shrink_any ( &cursor );
387 	memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) );
388 	DBGC2 ( cert, "X509 %p public key is:\n", cert );
389 	DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len );
390 
391 	/* Enter subjectPublicKeyInfo */
392 	asn1_enter ( &cursor, ASN1_SEQUENCE );
393 
394 	/* Parse algorithm */
395 	if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) {
396 		DBGC ( cert, "X509 %p could not parse public key algorithm: "
397 		       "%s\n", cert, strerror ( rc ) );
398 		return rc;
399 	}
400 	DBGC2 ( cert, "X509 %p public key algorithm is %s\n",
401 		cert, (*algorithm)->name );
402 	asn1_skip_any ( &cursor );
403 
404 	/* Parse bit string */
405 	if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
406 		DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
407 		       cert, strerror ( rc ) );
408 		return rc;
409 	}
410 
411 	return 0;
412 }
413 
414 /**
415  * Parse X.509 certificate basic constraints
416  *
417  * @v cert		X.509 certificate
418  * @v raw		ASN.1 cursor
419  * @ret rc		Return status code
420  */
x509_parse_basic_constraints(struct x509_certificate * cert,const struct asn1_cursor * raw)421 static int x509_parse_basic_constraints ( struct x509_certificate *cert,
422 					  const struct asn1_cursor *raw ) {
423 	struct x509_basic_constraints *basic = &cert->extensions.basic;
424 	struct asn1_cursor cursor;
425 	int ca = 0;
426 	int path_len;
427 	int rc;
428 
429 	/* Enter basicConstraints */
430 	memcpy ( &cursor, raw, sizeof ( cursor ) );
431 	asn1_enter ( &cursor, ASN1_SEQUENCE );
432 
433 	/* Parse "cA", if present */
434 	if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
435 		ca = asn1_boolean ( &cursor );
436 		if ( ca < 0 ) {
437 			rc = ca;
438 			DBGC ( cert, "X509 %p cannot parse cA: %s\n",
439 			       cert, strerror ( rc ) );
440 			DBGC_HDA ( cert, 0, raw->data, raw->len );
441 			return rc;
442 		}
443 		asn1_skip_any ( &cursor );
444 	}
445 	basic->ca = ca;
446 	DBGC2 ( cert, "X509 %p is %sa CA certificate\n",
447 		cert, ( basic->ca ? "" : "not " ) );
448 
449 	/* Ignore everything else unless "cA" is true */
450 	if ( ! ca )
451 		return 0;
452 
453 	/* Parse "pathLenConstraint", if present and applicable */
454 	basic->path_len = X509_PATH_LEN_UNLIMITED;
455 	if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
456 		if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
457 			DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
458 			       "%s\n", cert, strerror ( rc ) );
459 			DBGC_HDA ( cert, 0, raw->data, raw->len );
460 			return rc;
461 		}
462 		if ( path_len < 0 ) {
463 			DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n",
464 			       cert, path_len );
465 			DBGC_HDA ( cert, 0, raw->data, raw->len );
466 			return -EINVAL;
467 		}
468 		basic->path_len = path_len;
469 		DBGC2 ( cert, "X509 %p path length constraint is %d\n",
470 			cert, basic->path_len );
471 	}
472 
473 	return 0;
474 }
475 
476 /**
477  * Parse X.509 certificate key usage
478  *
479  * @v cert		X.509 certificate
480  * @v raw		ASN.1 cursor
481  * @ret rc		Return status code
482  */
x509_parse_key_usage(struct x509_certificate * cert,const struct asn1_cursor * raw)483 static int x509_parse_key_usage ( struct x509_certificate *cert,
484 				  const struct asn1_cursor *raw ) {
485 	struct x509_key_usage *usage = &cert->extensions.usage;
486 	struct asn1_bit_string bit_string;
487 	const uint8_t *bytes;
488 	size_t len;
489 	unsigned int i;
490 	int rc;
491 
492 	/* Mark extension as present */
493 	usage->present = 1;
494 
495 	/* Parse bit string */
496 	if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
497 		DBGC ( cert, "X509 %p could not parse key usage: %s\n",
498 		       cert, strerror ( rc ) );
499 		return rc;
500 	}
501 
502 	/* Parse key usage bits */
503 	bytes = bit_string.data;
504 	len = bit_string.len;
505 	if ( len > sizeof ( usage->bits ) )
506 		len = sizeof ( usage->bits );
507 	for ( i = 0 ; i < len ; i++ ) {
508 		usage->bits |= ( *(bytes++) << ( 8 * i ) );
509 	}
510 	DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits );
511 
512 	return 0;
513 }
514 
515 /** "id-kp-codeSigning" object identifier */
516 static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING };
517 
518 /** "id-kp-OCSPSigning" object identifier */
519 static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING };
520 
521 /** Supported key purposes */
522 static struct x509_key_purpose x509_key_purposes[] = {
523 	{
524 		.name = "codeSigning",
525 		.bits = X509_CODE_SIGNING,
526 		.oid = ASN1_OID_CURSOR ( oid_code_signing ),
527 	},
528 	{
529 		.name = "ocspSigning",
530 		.bits = X509_OCSP_SIGNING,
531 		.oid = ASN1_OID_CURSOR ( oid_ocsp_signing ),
532 	},
533 };
534 
535 /**
536  * Parse X.509 certificate key purpose identifier
537  *
538  * @v cert		X.509 certificate
539  * @v raw		ASN.1 cursor
540  * @ret rc		Return status code
541  */
x509_parse_key_purpose(struct x509_certificate * cert,const struct asn1_cursor * raw)542 static int x509_parse_key_purpose ( struct x509_certificate *cert,
543 				    const struct asn1_cursor *raw ) {
544 	struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
545 	struct x509_key_purpose *purpose;
546 	struct asn1_cursor cursor;
547 	unsigned int i;
548 	int rc;
549 
550 	/* Enter keyPurposeId */
551 	memcpy ( &cursor, raw, sizeof ( cursor ) );
552 	if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
553 		DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
554 		DBGC_HDA ( cert, 0, raw->data, raw->len );
555 		return rc;
556 	}
557 
558 	/* Identify key purpose */
559 	for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
560 			    sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
561 		purpose = &x509_key_purposes[i];
562 		if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
563 			DBGC2 ( cert, "X509 %p has key purpose %s\n",
564 				cert, purpose->name );
565 			ext_usage->bits |= purpose->bits;
566 			return 0;
567 		}
568 	}
569 
570 	/* Ignore unrecognised key purposes */
571 	return 0;
572 }
573 
574 /**
575  * Parse X.509 certificate extended key usage
576  *
577  * @v cert		X.509 certificate
578  * @v raw		ASN.1 cursor
579  * @ret rc		Return status code
580  */
x509_parse_extended_key_usage(struct x509_certificate * cert,const struct asn1_cursor * raw)581 static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
582 					   const struct asn1_cursor *raw ) {
583 	struct asn1_cursor cursor;
584 	int rc;
585 
586 	/* Enter extKeyUsage */
587 	memcpy ( &cursor, raw, sizeof ( cursor ) );
588 	asn1_enter ( &cursor, ASN1_SEQUENCE );
589 
590 	/* Parse each extended key usage in turn */
591 	while ( cursor.len ) {
592 		if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
593 			return rc;
594 		asn1_skip_any ( &cursor );
595 	}
596 
597 	return 0;
598 }
599 
600 /**
601  * Parse X.509 certificate OCSP access method
602  *
603  * @v cert		X.509 certificate
604  * @v raw		ASN.1 cursor
605  * @ret rc		Return status code
606  */
x509_parse_ocsp(struct x509_certificate * cert,const struct asn1_cursor * raw)607 static int x509_parse_ocsp ( struct x509_certificate *cert,
608 			     const struct asn1_cursor *raw ) {
609 	struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
610 	struct asn1_cursor *uri = &ocsp->uri;
611 	int rc;
612 
613 	/* Enter accessLocation */
614 	memcpy ( uri, raw, sizeof ( *uri ) );
615 	if ( ( rc = asn1_enter ( uri, X509_GENERAL_NAME_URI ) ) != 0 ) {
616 		DBGC ( cert, "X509 %p OCSP does not contain "
617 		       "uniformResourceIdentifier:\n", cert );
618 		DBGC_HDA ( cert, 0, raw->data, raw->len );
619 		return rc;
620 	}
621 	DBGC2 ( cert, "X509 %p OCSP URI is:\n", cert );
622 	DBGC2_HDA ( cert, 0, uri->data, uri->len );
623 
624 	return 0;
625 }
626 
627 /** "id-ad-ocsp" object identifier */
628 static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
629 
630 /** Supported access methods */
631 static struct x509_access_method x509_access_methods[] = {
632 	{
633 		.name = "OCSP",
634 		.oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
635 		.parse = x509_parse_ocsp,
636 	},
637 };
638 
639 /**
640  * Identify X.509 access method by OID
641  *
642  * @v oid		OID
643  * @ret method		Access method, or NULL
644  */
645 static struct x509_access_method *
x509_find_access_method(const struct asn1_cursor * oid)646 x509_find_access_method ( const struct asn1_cursor *oid ) {
647 	struct x509_access_method *method;
648 	unsigned int i;
649 
650 	for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
651 			    sizeof ( x509_access_methods[0] ) ) ; i++ ) {
652 		method = &x509_access_methods[i];
653 		if ( asn1_compare ( &method->oid, oid ) == 0 )
654 			return method;
655 	}
656 
657 	return NULL;
658 }
659 
660 /**
661  * Parse X.509 certificate access description
662  *
663  * @v cert		X.509 certificate
664  * @v raw		ASN.1 cursor
665  * @ret rc		Return status code
666  */
x509_parse_access_description(struct x509_certificate * cert,const struct asn1_cursor * raw)667 static int x509_parse_access_description ( struct x509_certificate *cert,
668 					   const struct asn1_cursor *raw ) {
669 	struct asn1_cursor cursor;
670 	struct asn1_cursor subcursor;
671 	struct x509_access_method *method;
672 	int rc;
673 
674 	/* Enter keyPurposeId */
675 	memcpy ( &cursor, raw, sizeof ( cursor ) );
676 	asn1_enter ( &cursor, ASN1_SEQUENCE );
677 
678 	/* Try to identify access method */
679 	memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
680 	asn1_enter ( &subcursor, ASN1_OID );
681 	method = x509_find_access_method ( &subcursor );
682 	asn1_skip_any ( &cursor );
683 	DBGC2 ( cert, "X509 %p found access method %s\n",
684 		cert, ( method ? method->name : "<unknown>" ) );
685 
686 	/* Parse access location, if applicable */
687 	if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
688 		return rc;
689 
690 	return 0;
691 }
692 
693 /**
694  * Parse X.509 certificate authority information access
695  *
696  * @v cert		X.509 certificate
697  * @v raw		ASN.1 cursor
698  * @ret rc		Return status code
699  */
x509_parse_authority_info_access(struct x509_certificate * cert,const struct asn1_cursor * raw)700 static int x509_parse_authority_info_access ( struct x509_certificate *cert,
701 					      const struct asn1_cursor *raw ) {
702 	struct asn1_cursor cursor;
703 	int rc;
704 
705 	/* Enter authorityInfoAccess */
706 	memcpy ( &cursor, raw, sizeof ( cursor ) );
707 	asn1_enter ( &cursor, ASN1_SEQUENCE );
708 
709 	/* Parse each access description in turn */
710 	while ( cursor.len ) {
711 		if ( ( rc = x509_parse_access_description ( cert,
712 							    &cursor ) ) != 0 )
713 			return rc;
714 		asn1_skip_any ( &cursor );
715 	}
716 
717 	return 0;
718 }
719 
720 /**
721  * Parse X.509 certificate subject alternative name
722  *
723  * @v cert		X.509 certificate
724  * @v raw		ASN.1 cursor
725  * @ret rc		Return status code
726  */
x509_parse_subject_alt_name(struct x509_certificate * cert,const struct asn1_cursor * raw)727 static int x509_parse_subject_alt_name ( struct x509_certificate *cert,
728 					 const struct asn1_cursor *raw ) {
729 	struct x509_subject_alt_name *alt_name = &cert->extensions.alt_name;
730 	struct asn1_cursor *names = &alt_name->names;
731 	int rc;
732 
733 	/* Enter subjectAltName */
734 	memcpy ( names, raw, sizeof ( *names ) );
735 	if ( ( rc = asn1_enter ( names, ASN1_SEQUENCE ) ) != 0 ) {
736 		DBGC ( cert, "X509 %p invalid subjectAltName: %s\n",
737 		       cert, strerror ( rc ) );
738 		DBGC_HDA ( cert, 0, raw->data, raw->len );
739 		return rc;
740 	}
741 	DBGC2 ( cert, "X509 %p has subjectAltName:\n", cert );
742 	DBGC2_HDA ( cert, 0, names->data, names->len );
743 
744 	return 0;
745 }
746 
747 /** "id-ce-basicConstraints" object identifier */
748 static uint8_t oid_ce_basic_constraints[] =
749 	{ ASN1_OID_BASICCONSTRAINTS };
750 
751 /** "id-ce-keyUsage" object identifier */
752 static uint8_t oid_ce_key_usage[] =
753 	{ ASN1_OID_KEYUSAGE };
754 
755 /** "id-ce-extKeyUsage" object identifier */
756 static uint8_t oid_ce_ext_key_usage[] =
757 	{ ASN1_OID_EXTKEYUSAGE };
758 
759 /** "id-pe-authorityInfoAccess" object identifier */
760 static uint8_t oid_pe_authority_info_access[] =
761 	{ ASN1_OID_AUTHORITYINFOACCESS };
762 
763 /** "id-ce-subjectAltName" object identifier */
764 static uint8_t oid_ce_subject_alt_name[] =
765 	{ ASN1_OID_SUBJECTALTNAME };
766 
767 /** Supported certificate extensions */
768 static struct x509_extension x509_extensions[] = {
769 	{
770 		.name = "basicConstraints",
771 		.oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ),
772 		.parse = x509_parse_basic_constraints,
773 	},
774 	{
775 		.name = "keyUsage",
776 		.oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
777 		.parse = x509_parse_key_usage,
778 	},
779 	{
780 		.name = "extKeyUsage",
781 		.oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
782 		.parse = x509_parse_extended_key_usage,
783 	},
784 	{
785 		.name = "authorityInfoAccess",
786 		.oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
787 		.parse = x509_parse_authority_info_access,
788 	},
789 	{
790 		.name = "subjectAltName",
791 		.oid = ASN1_OID_CURSOR ( oid_ce_subject_alt_name ),
792 		.parse = x509_parse_subject_alt_name,
793 	},
794 };
795 
796 /**
797  * Identify X.509 extension by OID
798  *
799  * @v oid		OID
800  * @ret extension	Extension, or NULL
801  */
802 static struct x509_extension *
x509_find_extension(const struct asn1_cursor * oid)803 x509_find_extension ( const struct asn1_cursor *oid ) {
804 	struct x509_extension *extension;
805 	unsigned int i;
806 
807 	for ( i = 0 ; i < ( sizeof ( x509_extensions ) /
808 			    sizeof ( x509_extensions[0] ) ) ; i++ ) {
809 		extension = &x509_extensions[i];
810 		if ( asn1_compare ( &extension->oid, oid ) == 0 )
811 			return extension;
812 	}
813 
814 	return NULL;
815 }
816 
817 /**
818  * Parse X.509 certificate extension
819  *
820  * @v cert		X.509 certificate
821  * @v raw		ASN.1 cursor
822  * @ret rc		Return status code
823  */
x509_parse_extension(struct x509_certificate * cert,const struct asn1_cursor * raw)824 static int x509_parse_extension ( struct x509_certificate *cert,
825 				  const struct asn1_cursor *raw ) {
826 	struct asn1_cursor cursor;
827 	struct asn1_cursor subcursor;
828 	struct x509_extension *extension;
829 	int is_critical = 0;
830 	int rc;
831 
832 	/* Enter extension */
833 	memcpy ( &cursor, raw, sizeof ( cursor ) );
834 	asn1_enter ( &cursor, ASN1_SEQUENCE );
835 
836 	/* Try to identify extension */
837 	memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
838 	asn1_enter ( &subcursor, ASN1_OID );
839 	extension = x509_find_extension ( &subcursor );
840 	asn1_skip_any ( &cursor );
841 	DBGC2 ( cert, "X509 %p found extension %s\n",
842 		cert, ( extension ? extension->name : "<unknown>" ) );
843 
844 	/* Identify criticality */
845 	if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
846 		is_critical = asn1_boolean ( &cursor );
847 		if ( is_critical < 0 ) {
848 			rc = is_critical;
849 			DBGC ( cert, "X509 %p cannot parse extension "
850 			       "criticality: %s\n", cert, strerror ( rc ) );
851 			DBGC_HDA ( cert, 0, raw->data, raw->len );
852 			return rc;
853 		}
854 		asn1_skip_any ( &cursor );
855 	}
856 
857 	/* Handle unknown extensions */
858 	if ( ! extension ) {
859 		if ( is_critical ) {
860 			/* Fail if we cannot handle a critical extension */
861 			DBGC ( cert, "X509 %p cannot handle critical "
862 			       "extension:\n", cert );
863 			DBGC_HDA ( cert, 0, raw->data, raw->len );
864 			return -ENOTSUP_EXTENSION;
865 		} else {
866 			/* Ignore unknown non-critical extensions */
867 			return 0;
868 		}
869 	};
870 
871 	/* Extract extnValue */
872 	if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
873 		DBGC ( cert, "X509 %p extension missing extnValue:\n", cert );
874 		DBGC_HDA ( cert, 0, raw->data, raw->len );
875 		return rc;
876 	}
877 
878 	/* Parse extension */
879 	if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 )
880 		return rc;
881 
882 	return 0;
883 }
884 
885 /**
886  * Parse X.509 certificate extensions, if present
887  *
888  * @v cert		X.509 certificate
889  * @v raw		ASN.1 cursor
890  * @ret rc		Return status code
891  */
x509_parse_extensions(struct x509_certificate * cert,const struct asn1_cursor * raw)892 static int x509_parse_extensions ( struct x509_certificate *cert,
893 				   const struct asn1_cursor *raw ) {
894 	struct asn1_cursor cursor;
895 	int rc;
896 
897 	/* Enter extensions, if present */
898 	memcpy ( &cursor, raw, sizeof ( cursor ) );
899 	asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) );
900 	asn1_enter ( &cursor, ASN1_SEQUENCE );
901 
902 	/* Parse each extension in turn */
903 	while ( cursor.len ) {
904 		if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 )
905 			return rc;
906 		asn1_skip_any ( &cursor );
907 	}
908 
909 	return 0;
910 }
911 
912 /**
913  * Parse X.509 certificate tbsCertificate
914  *
915  * @v cert		X.509 certificate
916  * @v raw		ASN.1 cursor
917  * @ret rc		Return status code
918  */
x509_parse_tbscertificate(struct x509_certificate * cert,const struct asn1_cursor * raw)919 static int x509_parse_tbscertificate ( struct x509_certificate *cert,
920 				       const struct asn1_cursor *raw ) {
921 	struct asn1_algorithm **algorithm = &cert->signature_algorithm;
922 	struct asn1_cursor cursor;
923 	int rc;
924 
925 	/* Record raw tbsCertificate */
926 	memcpy ( &cursor, raw, sizeof ( cursor ) );
927 	asn1_shrink_any ( &cursor );
928 	memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) );
929 
930 	/* Enter tbsCertificate */
931 	asn1_enter ( &cursor, ASN1_SEQUENCE );
932 
933 	/* Parse version, if present */
934 	if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
935 		if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 )
936 			return rc;
937 		asn1_skip_any ( &cursor );
938 	}
939 
940 	/* Parse serialNumber */
941 	if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 )
942 		return rc;
943 	asn1_skip_any ( &cursor );
944 
945 	/* Parse signature */
946 	if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
947 		DBGC ( cert, "X509 %p could not parse signature algorithm: "
948 		       "%s\n", cert, strerror ( rc ) );
949 		return rc;
950 	}
951 	DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n",
952 		cert, (*algorithm)->name );
953 	asn1_skip_any ( &cursor );
954 
955 	/* Parse issuer */
956 	if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 )
957 		return rc;
958 	asn1_skip_any ( &cursor );
959 
960 	/* Parse validity */
961 	if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 )
962 		return rc;
963 	asn1_skip_any ( &cursor );
964 
965 	/* Parse subject */
966 	if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 )
967 		return rc;
968 	asn1_skip_any ( &cursor );
969 
970 	/* Parse subjectPublicKeyInfo */
971 	if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 )
972 		return rc;
973 	asn1_skip_any ( &cursor );
974 
975 	/* Parse extensions, if present */
976 	if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 )
977 		return rc;
978 
979 	return 0;
980 }
981 
982 /**
983  * Parse X.509 certificate from ASN.1 data
984  *
985  * @v cert		X.509 certificate
986  * @v raw		ASN.1 cursor
987  * @ret rc		Return status code
988  */
x509_parse(struct x509_certificate * cert,const struct asn1_cursor * raw)989 int x509_parse ( struct x509_certificate *cert,
990 		 const struct asn1_cursor *raw ) {
991 	struct x509_signature *signature = &cert->signature;
992 	struct asn1_algorithm **signature_algorithm = &signature->algorithm;
993 	struct asn1_bit_string *signature_value = &signature->value;
994 	struct asn1_cursor cursor;
995 	int rc;
996 
997 	/* Record raw certificate */
998 	memcpy ( &cursor, raw, sizeof ( cursor ) );
999 	memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );
1000 
1001 	/* Enter certificate */
1002 	asn1_enter ( &cursor, ASN1_SEQUENCE );
1003 
1004 	/* Parse tbsCertificate */
1005 	if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 )
1006 		return rc;
1007 	asn1_skip_any ( &cursor );
1008 
1009 	/* Parse signatureAlgorithm */
1010 	if ( ( rc = asn1_signature_algorithm ( &cursor,
1011 					       signature_algorithm ) ) != 0 ) {
1012 		DBGC ( cert, "X509 %p could not parse signature algorithm: "
1013 		       "%s\n", cert, strerror ( rc ) );
1014 		return rc;
1015 	}
1016 	DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n",
1017 		cert, (*signature_algorithm)->name );
1018 	asn1_skip_any ( &cursor );
1019 
1020 	/* Parse signatureValue */
1021 	if ( ( rc = asn1_integral_bit_string ( &cursor,
1022 					       signature_value ) ) != 0 ) {
1023 		DBGC ( cert, "X509 %p could not parse signature value: %s\n",
1024 		       cert, strerror ( rc ) );
1025 		return rc;
1026 	}
1027 	DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
1028 	DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
1029 
1030 	/* Check that algorithm in tbsCertificate matches algorithm in
1031 	 * signature
1032 	 */
1033 	if ( signature->algorithm != (*signature_algorithm) ) {
1034 		DBGC ( cert, "X509 %p signature algorithm %s does not match "
1035 		       "signatureAlgorithm %s\n",
1036 		       cert, signature->algorithm->name,
1037 		       (*signature_algorithm)->name );
1038 		return -EINVAL_ALGORITHM_MISMATCH;
1039 	}
1040 
1041 	return 0;
1042 }
1043 
1044 /**
1045  * Create X.509 certificate
1046  *
1047  * @v data		Raw certificate data
1048  * @v len		Length of raw data
1049  * @ret cert		X.509 certificate
1050  * @ret rc		Return status code
1051  *
1052  * On success, the caller holds a reference to the X.509 certificate,
1053  * and is responsible for ultimately calling x509_put().
1054  */
x509_certificate(const void * data,size_t len,struct x509_certificate ** cert)1055 int x509_certificate ( const void *data, size_t len,
1056 		       struct x509_certificate **cert ) {
1057 	struct asn1_cursor cursor;
1058 	void *raw;
1059 	int rc;
1060 
1061 	/* Initialise cursor */
1062 	cursor.data = data;
1063 	cursor.len = len;
1064 	asn1_shrink_any ( &cursor );
1065 
1066 	/* Return stored certificate, if present */
1067 	if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {
1068 
1069 		/* Add caller's reference */
1070 		x509_get ( *cert );
1071 		return 0;
1072 	}
1073 
1074 	/* Allocate and initialise certificate */
1075 	*cert = zalloc ( sizeof ( **cert ) + cursor.len );
1076 	if ( ! *cert )
1077 		return -ENOMEM;
1078 	ref_init ( &(*cert)->refcnt, NULL );
1079 	raw = ( *cert + 1 );
1080 
1081 	/* Copy raw data */
1082 	memcpy ( raw, cursor.data, cursor.len );
1083 	cursor.data = raw;
1084 
1085 	/* Parse certificate */
1086 	if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
1087 		x509_put ( *cert );
1088 		*cert = NULL;
1089 		return rc;
1090 	}
1091 
1092 	/* Add certificate to store */
1093 	certstore_add ( *cert );
1094 
1095 	return 0;
1096 }
1097 
1098 /**
1099  * Check X.509 certificate signature
1100  *
1101  * @v cert		X.509 certificate
1102  * @v public_key	X.509 public key
1103  * @ret rc		Return status code
1104  */
x509_check_signature(struct x509_certificate * cert,struct x509_public_key * public_key)1105 static int x509_check_signature ( struct x509_certificate *cert,
1106 				  struct x509_public_key *public_key ) {
1107 	struct x509_signature *signature = &cert->signature;
1108 	struct asn1_algorithm *algorithm = signature->algorithm;
1109 	struct digest_algorithm *digest = algorithm->digest;
1110 	struct pubkey_algorithm *pubkey = algorithm->pubkey;
1111 	uint8_t digest_ctx[ digest->ctxsize ];
1112 	uint8_t digest_out[ digest->digestsize ];
1113 	uint8_t pubkey_ctx[ pubkey->ctxsize ];
1114 	int rc;
1115 
1116 	/* Sanity check */
1117 	assert ( cert->signature_algorithm == cert->signature.algorithm );
1118 
1119 	/* Calculate certificate digest */
1120 	digest_init ( digest, digest_ctx );
1121 	digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
1122 	digest_final ( digest, digest_ctx, digest_out );
1123 	DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) );
1124 	DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
1125 
1126 	/* Check that signature public key algorithm matches signer */
1127 	if ( public_key->algorithm->pubkey != pubkey ) {
1128 		DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
1129 		       "match signer's algorithm %s\n",
1130 		       cert, x509_name ( cert ), algorithm->name,
1131 		       public_key->algorithm->name );
1132 		rc = -EINVAL_ALGORITHM_MISMATCH;
1133 		goto err_mismatch;
1134 	}
1135 
1136 	/* Verify signature using signer's public key */
1137 	if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
1138 				  public_key->raw.len ) ) != 0 ) {
1139 		DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
1140 		       "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
1141 		goto err_pubkey_init;
1142 	}
1143 	if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
1144 				    signature->value.data,
1145 				    signature->value.len ) ) != 0 ) {
1146 		DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
1147 		       "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
1148 		goto err_pubkey_verify;
1149 	}
1150 
1151 	/* Success */
1152 	rc = 0;
1153 
1154  err_pubkey_verify:
1155 	pubkey_final ( pubkey, pubkey_ctx );
1156  err_pubkey_init:
1157  err_mismatch:
1158 	return rc;
1159 }
1160 
1161 /**
1162  * Check X.509 certificate against issuer certificate
1163  *
1164  * @v cert		X.509 certificate
1165  * @v issuer		X.509 issuer certificate
1166  * @ret rc		Return status code
1167  */
x509_check_issuer(struct x509_certificate * cert,struct x509_certificate * issuer)1168 int x509_check_issuer ( struct x509_certificate *cert,
1169 			struct x509_certificate *issuer ) {
1170 	struct x509_public_key *public_key = &issuer->subject.public_key;
1171 	int rc;
1172 
1173 	/* Check issuer.  In theory, this should be a full X.500 DN
1174 	 * comparison, which would require support for a plethora of
1175 	 * abominations such as TeletexString (which allows the
1176 	 * character set to be changed mid-string using escape codes).
1177 	 * In practice, we assume that anyone who deliberately changes
1178 	 * the encoding of the issuer DN is probably a masochist who
1179 	 * will rather enjoy the process of figuring out exactly why
1180 	 * their certificate doesn't work.
1181 	 *
1182 	 * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
1183 	 * for some enjoyable ranting on this subject.
1184 	 */
1185 	if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
1186 		DBGC ( cert, "X509 %p \"%s\" issuer does not match ",
1187 		       cert, x509_name ( cert ) );
1188 		DBGC ( cert, "X509 %p \"%s\" subject\n",
1189 		       issuer, x509_name ( issuer ) );
1190 		DBGC_HDA ( cert, 0, cert->issuer.raw.data,
1191 			   cert->issuer.raw.len );
1192 		DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
1193 			   issuer->subject.raw.len );
1194 		return -EACCES_WRONG_ISSUER;
1195 	}
1196 
1197 	/* Check that issuer is allowed to sign certificates */
1198 	if ( ! issuer->extensions.basic.ca ) {
1199 		DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
1200 		       issuer, x509_name ( issuer ) );
1201 		DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n",
1202 		       cert, x509_name ( cert ) );
1203 		return -EACCES_NOT_CA;
1204 	}
1205 	if ( issuer->extensions.usage.present &&
1206 	     ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
1207 		DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
1208 		       issuer, x509_name ( issuer ) );
1209 		DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n",
1210 		       cert, x509_name ( cert ) );
1211 		return -EACCES_KEY_USAGE;
1212 	}
1213 
1214 	/* Check signature */
1215 	if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
1216 		return rc;
1217 
1218 	return 0;
1219 }
1220 
1221 /**
1222  * Calculate X.509 certificate fingerprint
1223  *
1224  * @v cert		X.509 certificate
1225  * @v digest		Digest algorithm
1226  * @v fingerprint	Fingerprint buffer
1227  */
x509_fingerprint(struct x509_certificate * cert,struct digest_algorithm * digest,void * fingerprint)1228 void x509_fingerprint ( struct x509_certificate *cert,
1229 			struct digest_algorithm *digest,
1230 			void *fingerprint ) {
1231 	uint8_t ctx[ digest->ctxsize ];
1232 
1233 	/* Calculate fingerprint */
1234 	digest_init ( digest, ctx );
1235 	digest_update ( digest, ctx, cert->raw.data, cert->raw.len );
1236 	digest_final ( digest, ctx, fingerprint );
1237 }
1238 
1239 /**
1240  * Check X.509 root certificate
1241  *
1242  * @v cert		X.509 certificate
1243  * @v root		X.509 root certificate list
1244  * @ret rc		Return status code
1245  */
x509_check_root(struct x509_certificate * cert,struct x509_root * root)1246 int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
1247 	struct digest_algorithm *digest = root->digest;
1248 	uint8_t fingerprint[ digest->digestsize ];
1249 	const uint8_t *root_fingerprint = root->fingerprints;
1250 	unsigned int i;
1251 
1252 	/* Calculate certificate fingerprint */
1253 	x509_fingerprint ( cert, digest, fingerprint );
1254 
1255 	/* Check fingerprint against all root certificates */
1256 	for ( i = 0 ; i < root->count ; i++ ) {
1257 		if ( memcmp ( fingerprint, root_fingerprint,
1258 			      sizeof ( fingerprint ) ) == 0 ) {
1259 			DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
1260 			       cert, x509_name ( cert ) );
1261 			return 0;
1262 		}
1263 		root_fingerprint += sizeof ( fingerprint );
1264 	}
1265 
1266 	DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
1267 		cert, x509_name ( cert ) );
1268 	return -ENOENT;
1269 }
1270 
1271 /**
1272  * Check X.509 certificate validity period
1273  *
1274  * @v cert		X.509 certificate
1275  * @v time		Time at which to check certificate
1276  * @ret rc		Return status code
1277  */
x509_check_time(struct x509_certificate * cert,time_t time)1278 int x509_check_time ( struct x509_certificate *cert, time_t time ) {
1279 	struct x509_validity *validity = &cert->validity;
1280 
1281 	/* Check validity period */
1282 	if ( validity->not_before.time > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
1283 		DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
1284 		       cert, x509_name ( cert ), time );
1285 		return -EACCES_EXPIRED;
1286 	}
1287 	if ( validity->not_after.time < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
1288 		DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
1289 		       cert, x509_name ( cert ), time );
1290 		return -EACCES_EXPIRED;
1291 	}
1292 
1293 	DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
1294 		cert, x509_name ( cert ), time );
1295 	return 0;
1296 }
1297 
1298 /**
1299  * Validate X.509 certificate
1300  *
1301  * @v cert		X.509 certificate
1302  * @v issuer		Issuing X.509 certificate (or NULL)
1303  * @v time		Time at which to validate certificate
1304  * @v root		Root certificate list, or NULL to use default
1305  * @ret rc		Return status code
1306  *
1307  * The issuing certificate must have already been validated.
1308  *
1309  * Validation results are cached: if a certificate has already been
1310  * successfully validated then @c issuer, @c time, and @c root will be
1311  * ignored.
1312  */
x509_validate(struct x509_certificate * cert,struct x509_certificate * issuer,time_t time,struct x509_root * root)1313 int x509_validate ( struct x509_certificate *cert,
1314 		    struct x509_certificate *issuer,
1315 		    time_t time, struct x509_root *root ) {
1316 	unsigned int max_path_remaining;
1317 	int rc;
1318 
1319 	/* Use default root certificate store if none specified */
1320 	if ( ! root )
1321 		root = &root_certificates;
1322 
1323 	/* Return success if certificate has already been validated */
1324 	if ( x509_is_valid ( cert ) )
1325 		return 0;
1326 
1327 	/* Fail if certificate is invalid at specified time */
1328 	if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
1329 		return rc;
1330 
1331 	/* Succeed if certificate is a trusted root certificate */
1332 	if ( x509_check_root ( cert, root ) == 0 ) {
1333 		cert->flags |= X509_FL_VALIDATED;
1334 		cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
1335 		return 0;
1336 	}
1337 
1338 	/* Fail unless we have an issuer */
1339 	if ( ! issuer ) {
1340 		DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
1341 			cert, x509_name ( cert ) );
1342 		return -EACCES_UNTRUSTED;
1343 	}
1344 
1345 	/* Fail unless issuer has already been validated */
1346 	if ( ! x509_is_valid ( issuer ) ) {
1347 		DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
1348 		DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n",
1349 		       issuer, x509_name ( issuer ) );
1350 		return -EACCES_OUT_OF_ORDER;
1351 	}
1352 
1353 	/* Fail if issuing certificate cannot validate this certificate */
1354 	if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
1355 		return rc;
1356 
1357 	/* Fail if path length constraint is violated */
1358 	if ( issuer->path_remaining == 0 ) {
1359 		DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
1360 		DBGC ( cert, "issuer %p \"%s\" path length exceeded\n",
1361 		       issuer, x509_name ( issuer ) );
1362 		return -EACCES_PATH_LEN;
1363 	}
1364 
1365 	/* Fail if OCSP is required */
1366 	if ( ocsp_required ( cert ) ) {
1367 		DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n",
1368 		       cert, x509_name ( cert ) );
1369 		return -EACCES_OCSP_REQUIRED;
1370 	}
1371 
1372 	/* Calculate effective path length */
1373 	cert->path_remaining = ( issuer->path_remaining - 1 );
1374 	max_path_remaining = ( cert->extensions.basic.path_len + 1 );
1375 	if ( cert->path_remaining > max_path_remaining )
1376 		cert->path_remaining = max_path_remaining;
1377 
1378 	/* Mark certificate as valid */
1379 	cert->flags |= X509_FL_VALIDATED;
1380 
1381 	DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
1382 	       cert, x509_name ( cert ) );
1383 	DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) );
1384 	return 0;
1385 }
1386 
1387 /**
1388  * Check X.509 certificate alternative dNSName
1389  *
1390  * @v cert		X.509 certificate
1391  * @v raw		ASN.1 cursor
1392  * @v name		Name
1393  * @ret rc		Return status code
1394  */
x509_check_dnsname(struct x509_certificate * cert,const struct asn1_cursor * raw,const char * name)1395 static int x509_check_dnsname ( struct x509_certificate *cert,
1396 				const struct asn1_cursor *raw,
1397 				const char *name ) {
1398 	const char *fullname = name;
1399 	const char *dnsname = raw->data;
1400 	size_t len = raw->len;
1401 
1402 	/* Check for wildcards */
1403 	if ( ( len >= 2 ) && ( dnsname[0] == '*' ) && ( dnsname[1] == '.' ) ) {
1404 
1405 		/* Skip initial "*." */
1406 		dnsname += 2;
1407 		len -= 2;
1408 
1409 		/* Skip initial portion of name to be tested */
1410 		name = strchr ( name, '.' );
1411 		if ( ! name )
1412 			return -ENOENT;
1413 		name++;
1414 	}
1415 
1416 	/* Compare names */
1417 	if ( ! ( ( strlen ( name ) == len ) &&
1418 		 ( memcmp ( name, dnsname, len ) == 0 ) ) )
1419 		return -ENOENT;
1420 
1421 	if ( name != fullname ) {
1422 		DBGC2 ( cert, "X509 %p \"%s\" found wildcard match for "
1423 			"\"*.%s\"\n", cert, x509_name ( cert ), name );
1424 	}
1425 	return 0;
1426 }
1427 
1428 /**
1429  * Check X.509 certificate alternative iPAddress
1430  *
1431  * @v cert		X.509 certificate
1432  * @v raw		ASN.1 cursor
1433  * @v name		Name
1434  * @ret rc		Return status code
1435  */
x509_check_ipaddress(struct x509_certificate * cert,const struct asn1_cursor * raw,const char * name)1436 static int x509_check_ipaddress ( struct x509_certificate *cert,
1437 				  const struct asn1_cursor *raw,
1438 				  const char *name ) {
1439 	struct sockaddr sa;
1440 	sa_family_t family;
1441 	const void *address;
1442 	int rc;
1443 
1444 	/* Determine address family */
1445 	if ( raw->len == sizeof ( struct in_addr ) ) {
1446 		struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa );
1447 		family = AF_INET;
1448 		address = &sin->sin_addr;
1449 	} else if ( raw->len == sizeof ( struct in6_addr ) ) {
1450 		struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa );
1451 		family = AF_INET6;
1452 		address = &sin6->sin6_addr;
1453 	} else {
1454 		DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected "
1455 		       "length %zd\n", cert, x509_name ( cert ), raw->len );
1456 		DBGC_HDA ( cert, 0, raw->data, raw->len );
1457 		return -EINVAL;
1458 	}
1459 
1460 	/* Attempt to convert name to a socket address */
1461 	if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) {
1462 		DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as "
1463 			"iPAddress: %s\n", cert, x509_name ( cert ), name,
1464 			strerror ( rc ) );
1465 		return rc;
1466 	}
1467 	if ( sa.sa_family != family )
1468 		return -ENOENT;
1469 
1470 	/* Compare addresses */
1471 	if ( memcmp ( address, raw->data, raw->len ) != 0 )
1472 		return -ENOENT;
1473 
1474 	DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n",
1475 		cert, x509_name ( cert ), sock_ntoa ( &sa ) );
1476 	return 0;
1477 }
1478 
1479 /**
1480  * Check X.509 certificate alternative name
1481  *
1482  * @v cert		X.509 certificate
1483  * @v raw		ASN.1 cursor
1484  * @v name		Name
1485  * @ret rc		Return status code
1486  */
x509_check_alt_name(struct x509_certificate * cert,const struct asn1_cursor * raw,const char * name)1487 static int x509_check_alt_name ( struct x509_certificate *cert,
1488 				 const struct asn1_cursor *raw,
1489 				 const char *name ) {
1490 	struct asn1_cursor alt_name;
1491 	unsigned int type;
1492 
1493 	/* Enter generalName */
1494 	memcpy ( &alt_name, raw, sizeof ( alt_name ) );
1495 	type = asn1_type ( &alt_name );
1496 	asn1_enter_any ( &alt_name );
1497 
1498 	/* Check this name */
1499 	switch ( type ) {
1500 	case X509_GENERAL_NAME_DNS :
1501 		return x509_check_dnsname ( cert, &alt_name, name );
1502 	case X509_GENERAL_NAME_IP :
1503 		return x509_check_ipaddress ( cert, &alt_name, name );
1504 	default:
1505 		DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n",
1506 			cert, x509_name ( cert ), type );
1507 		DBGC2_HDA ( cert, 0, alt_name.data, alt_name.len );
1508 		return -ENOTSUP;
1509 	}
1510 }
1511 
1512 /**
1513  * Check X.509 certificate name
1514  *
1515  * @v cert		X.509 certificate
1516  * @v name		Name
1517  * @ret rc		Return status code
1518  */
x509_check_name(struct x509_certificate * cert,const char * name)1519 int x509_check_name ( struct x509_certificate *cert, const char *name ) {
1520 	struct asn1_cursor *common_name = &cert->subject.common_name;
1521 	struct asn1_cursor alt_name;
1522 	int rc;
1523 
1524 	/* Check commonName */
1525 	if ( x509_check_dnsname ( cert, common_name, name ) == 0 ) {
1526 		DBGC2 ( cert, "X509 %p \"%s\" commonName matches \"%s\"\n",
1527 			cert, x509_name ( cert ), name );
1528 		return 0;
1529 	}
1530 
1531 	/* Check any subjectAlternativeNames */
1532 	memcpy ( &alt_name, &cert->extensions.alt_name.names,
1533 		 sizeof ( alt_name ) );
1534 	for ( ; alt_name.len ; asn1_skip_any ( &alt_name ) ) {
1535 		if ( ( rc = x509_check_alt_name ( cert, &alt_name,
1536 						  name ) ) == 0 ) {
1537 			DBGC2 ( cert, "X509 %p \"%s\" subjectAltName matches "
1538 				"\"%s\"\n", cert, x509_name ( cert ), name );
1539 			return 0;
1540 		}
1541 	}
1542 
1543 	DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n",
1544 	       cert, x509_name ( cert ), name );
1545 	return -EACCES_WRONG_NAME;
1546 }
1547 
1548 /**
1549  * Free X.509 certificate chain
1550  *
1551  * @v refcnt		Reference count
1552  */
x509_free_chain(struct refcnt * refcnt)1553 static void x509_free_chain ( struct refcnt *refcnt ) {
1554 	struct x509_chain *chain =
1555 		container_of ( refcnt, struct x509_chain, refcnt );
1556 	struct x509_link *link;
1557 	struct x509_link *tmp;
1558 
1559 	DBGC2 ( chain, "X509 chain %p freed\n", chain );
1560 
1561 	/* Free each link in the chain */
1562 	list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
1563 		x509_put ( link->cert );
1564 		list_del ( &link->list );
1565 		free ( link );
1566 	}
1567 
1568 	/* Free chain */
1569 	free ( chain );
1570 }
1571 
1572 /**
1573  * Allocate X.509 certificate chain
1574  *
1575  * @ret chain		X.509 certificate chain, or NULL
1576  */
x509_alloc_chain(void)1577 struct x509_chain * x509_alloc_chain ( void ) {
1578 	struct x509_chain *chain;
1579 
1580 	/* Allocate chain */
1581 	chain = zalloc ( sizeof ( *chain ) );
1582 	if ( ! chain )
1583 		return NULL;
1584 
1585 	/* Initialise chain */
1586 	ref_init ( &chain->refcnt, x509_free_chain );
1587 	INIT_LIST_HEAD ( &chain->links );
1588 
1589 	DBGC2 ( chain, "X509 chain %p allocated\n", chain );
1590 	return chain;
1591 }
1592 
1593 /**
1594  * Append X.509 certificate to X.509 certificate chain
1595  *
1596  * @v chain		X.509 certificate chain
1597  * @v cert		X.509 certificate
1598  * @ret rc		Return status code
1599  */
x509_append(struct x509_chain * chain,struct x509_certificate * cert)1600 int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
1601 	struct x509_link *link;
1602 
1603 	/* Allocate link */
1604 	link = zalloc ( sizeof ( *link ) );
1605 	if ( ! link )
1606 		return -ENOMEM;
1607 
1608 	/* Add link to chain */
1609 	link->cert = x509_get ( cert );
1610 	list_add_tail ( &link->list, &chain->links );
1611 	DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
1612 	       chain, cert, x509_name ( cert ) );
1613 
1614 	return 0;
1615 }
1616 
1617 /**
1618  * Append X.509 certificate to X.509 certificate chain
1619  *
1620  * @v chain		X.509 certificate chain
1621  * @v data		Raw certificate data
1622  * @v len		Length of raw data
1623  * @ret rc		Return status code
1624  */
x509_append_raw(struct x509_chain * chain,const void * data,size_t len)1625 int x509_append_raw ( struct x509_chain *chain, const void *data,
1626 		      size_t len ) {
1627 	struct x509_certificate *cert;
1628 	int rc;
1629 
1630 	/* Parse certificate */
1631 	if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 )
1632 		goto err_parse;
1633 
1634 	/* Append certificate to chain */
1635 	if ( ( rc = x509_append ( chain, cert ) ) != 0 )
1636 		goto err_append;
1637 
1638 	/* Drop reference to certificate */
1639 	x509_put ( cert );
1640 
1641 	return 0;
1642 
1643  err_append:
1644 	x509_put ( cert );
1645  err_parse:
1646 	return rc;
1647 }
1648 
1649 /**
1650  * Identify X.509 certificate by subject
1651  *
1652  * @v certs		X.509 certificate list
1653  * @v subject		Subject
1654  * @ret cert		X.509 certificate, or NULL if not found
1655  */
1656 static struct x509_certificate *
x509_find_subject(struct x509_chain * certs,const struct asn1_cursor * subject)1657 x509_find_subject ( struct x509_chain *certs,
1658 		    const struct asn1_cursor *subject ) {
1659 	struct x509_link *link;
1660 	struct x509_certificate *cert;
1661 
1662 	/* Scan through certificate list */
1663 	list_for_each_entry ( link, &certs->links, list ) {
1664 
1665 		/* Check subject */
1666 		cert = link->cert;
1667 		if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
1668 			return cert;
1669 	}
1670 
1671 	return NULL;
1672 }
1673 
1674 /**
1675  * Append X.509 certificates to X.509 certificate chain
1676  *
1677  * @v chain		X.509 certificate chain
1678  * @v certs		X.509 certificate list
1679  * @ret rc		Return status code
1680  *
1681  * Certificates will be automatically appended to the chain based upon
1682  * the subject and issuer names.
1683  */
x509_auto_append(struct x509_chain * chain,struct x509_chain * certs)1684 int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
1685 	struct x509_certificate *cert;
1686 	struct x509_certificate *previous;
1687 	int rc;
1688 
1689 	/* Get current certificate */
1690 	cert = x509_last ( chain );
1691 	if ( ! cert ) {
1692 		DBGC ( chain, "X509 chain %p has no certificates\n", chain );
1693 		return -EACCES_EMPTY;
1694 	}
1695 
1696 	/* Append certificates, in order */
1697 	while ( 1 ) {
1698 
1699 		/* Find issuing certificate */
1700 		previous = cert;
1701 		cert = x509_find_subject ( certs, &cert->issuer.raw );
1702 		if ( ! cert )
1703 			break;
1704 		if ( cert == previous )
1705 			break;
1706 
1707 		/* Append certificate to chain */
1708 		if ( ( rc = x509_append ( chain, cert ) ) != 0 )
1709 			return rc;
1710 	}
1711 
1712 	return 0;
1713 }
1714 
1715 /**
1716  * Validate X.509 certificate chain
1717  *
1718  * @v chain		X.509 certificate chain
1719  * @v time		Time at which to validate certificates
1720  * @v store		Certificate store, or NULL to use default
1721  * @v root		Root certificate list, or NULL to use default
1722  * @ret rc		Return status code
1723  */
x509_validate_chain(struct x509_chain * chain,time_t time,struct x509_chain * store,struct x509_root * root)1724 int x509_validate_chain ( struct x509_chain *chain, time_t time,
1725 			  struct x509_chain *store, struct x509_root *root ) {
1726 	struct x509_certificate *issuer = NULL;
1727 	struct x509_link *link;
1728 	int rc;
1729 
1730 	/* Use default certificate store if none specified */
1731 	if ( ! store )
1732 		store = &certstore;
1733 
1734 	/* Append any applicable certificates from the certificate store */
1735 	if ( ( rc = x509_auto_append ( chain, store ) ) != 0 )
1736 		return rc;
1737 
1738 	/* Find first certificate that can be validated as a
1739 	 * standalone (i.e.  is already valid, or can be validated as
1740 	 * a trusted root certificate).
1741 	 */
1742 	list_for_each_entry ( link, &chain->links, list ) {
1743 
1744 		/* Try validating this certificate as a standalone */
1745 		if ( ( rc = x509_validate ( link->cert, NULL, time,
1746 					    root ) ) != 0 )
1747 			continue;
1748 
1749 		/* Work back up to start of chain, performing pairwise
1750 		 * validation.
1751 		 */
1752 		issuer = link->cert;
1753 		list_for_each_entry_continue_reverse ( link, &chain->links,
1754 						       list ) {
1755 
1756 			/* Validate this certificate against its issuer */
1757 			if ( ( rc = x509_validate ( link->cert, issuer, time,
1758 						    root ) ) != 0 )
1759 				return rc;
1760 			issuer = link->cert;
1761 		}
1762 
1763 		return 0;
1764 	}
1765 
1766 	DBGC ( chain, "X509 chain %p found no usable certificates\n", chain );
1767 	return -EACCES_USELESS;
1768 }
1769 
1770 /**
1771  * Extract X.509 certificate object from image
1772  *
1773  * @v image		Image
1774  * @v offset		Offset within image
1775  * @ret cert		X.509 certificate
1776  * @ret next		Offset to next image, or negative error
1777  *
1778  * On success, the caller holds a reference to the X.509 certificate,
1779  * and is responsible for ultimately calling x509_put().
1780  */
image_x509(struct image * image,size_t offset,struct x509_certificate ** cert)1781 int image_x509 ( struct image *image, size_t offset,
1782 		 struct x509_certificate **cert ) {
1783 	struct asn1_cursor *cursor;
1784 	int next;
1785 	int rc;
1786 
1787 	/* Get ASN.1 object */
1788 	next = image_asn1 ( image, offset, &cursor );
1789 	if ( next < 0 ) {
1790 		rc = next;
1791 		goto err_asn1;
1792 	}
1793 
1794 	/* Parse certificate */
1795 	if ( ( rc = x509_certificate ( cursor->data, cursor->len,
1796 				       cert ) ) != 0 )
1797 		goto err_certificate;
1798 
1799 	/* Free ASN.1 object */
1800 	free ( cursor );
1801 
1802 	return next;
1803 
1804 	x509_put ( *cert );
1805  err_certificate:
1806 	free ( cursor );
1807  err_asn1:
1808 	return rc;
1809 }
1810 
1811 /* Drag in objects via x509_validate() */
1812 REQUIRING_SYMBOL ( x509_validate );
1813 
1814 /* Drag in certificate store */
1815 REQUIRE_OBJECT ( certstore );
1816 
1817 /* Drag in crypto configuration */
1818 REQUIRE_OBJECT ( config_crypto );
1819