Explorar el Código

[crypto] Allow certificate chains to be long-lived data structures

At present, certificate chain validation is treated as an
instantaneous process that can be carried out using only data that is
already in memory.  This model does not allow for validation to
include non-instantaneous steps, such as downloading a cross-signing
certificate, or determining certificate revocation status via OCSP.

Redesign the internal representation of certificate chains to allow
chains to outlive the scope of the original source of certificates
(such as a TLS Certificate record).

Allow for certificates to be cached, so that each certificate needs to
be validated only once.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown hace 12 años
padre
commit
557f467bab
Se han modificado 9 ficheros con 1075 adiciones y 463 borrados
  1. 274
    109
      src/crypto/cms.c
  2. 362
    116
      src/crypto/x509.c
  3. 39
    14
      src/include/ipxe/cms.h
  4. 3
    0
      src/include/ipxe/tls.h
  5. 132
    24
      src/include/ipxe/x509.h
  6. 94
    67
      src/net/tls.c
  7. 25
    18
      src/tests/cms_test.c
  8. 134
    109
      src/tests/x509_test.c
  9. 12
    6
      src/usr/imgtrust.c

+ 274
- 109
src/crypto/cms.c Ver fichero

@@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
32 32
 #include <errno.h>
33 33
 #include <ipxe/asn1.h>
34 34
 #include <ipxe/x509.h>
35
+#include <ipxe/malloc.h>
35 36
 #include <ipxe/uaccess.h>
36 37
 #include <ipxe/cms.h>
37 38
 
@@ -44,14 +45,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
44 45
 	__einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )
45 46
 #define EINFO_EACCES_NON_CODE_SIGNING \
46 47
 	__einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )
47
-#define EACCES_INCOMPLETE \
48
-	__einfo_error ( EINFO_EACCES_INCOMPLETE )
49
-#define EINFO_EACCES_INCOMPLETE \
50
-	__einfo_uniqify ( EINFO_EACCES, 0x03, "Incomplete certificate chain" )
51 48
 #define EACCES_WRONG_NAME \
52 49
 	__einfo_error ( EINFO_EACCES_WRONG_NAME )
53 50
 #define EINFO_EACCES_WRONG_NAME \
54 51
 	__einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )
52
+#define EACCES_NO_SIGNATURES \
53
+	__einfo_error ( EINFO_EACCES_NO_SIGNATURES )
54
+#define EINFO_EACCES_NO_SIGNATURES \
55
+	__einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
55 56
 #define EINVAL_DIGEST \
56 57
 	__einfo_error ( EINFO_EINVAL_DIGEST )
57 58
 #define EINFO_EINVAL_DIGEST \
@@ -107,6 +108,113 @@ static int cms_parse_content_type ( struct cms_signature *sig,
107 108
 	return 0;
108 109
 }
109 110
 
111
+/**
112
+ * Parse CMS signature certificate list
113
+ *
114
+ * @v sig		CMS signature
115
+ * @v raw		ASN.1 cursor
116
+ * @ret rc		Return status code
117
+ */
118
+static int cms_parse_certificates ( struct cms_signature *sig,
119
+				    const struct asn1_cursor *raw ) {
120
+	struct asn1_cursor cursor;
121
+	struct x509_certificate *cert;
122
+	int rc;
123
+
124
+	/* Enter certificates */
125
+	memcpy ( &cursor, raw, sizeof ( cursor ) );
126
+	asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
127
+
128
+	/* Add each certificate */
129
+	while ( cursor.len ) {
130
+
131
+		/* Parse certificate */
132
+		if ( ( rc = x509_certificate ( cursor.data, cursor.len,
133
+					       &cert ) ) != 0 ) {
134
+			DBGC ( sig, "CMS %p could not parse certificate: %s\n",
135
+			       sig, strerror ( rc) );
136
+			DBGC_HDA ( sig, 0, cursor.data, cursor.len );
137
+			goto err_parse;
138
+		}
139
+		DBGC ( sig, "CMS %p found certificate %s\n",
140
+		       sig, cert->subject.name );
141
+
142
+		/* Add certificate to list */
143
+		if ( ( rc = x509_append ( sig->certificates, cert ) ) != 0 ) {
144
+			DBGC ( sig, "CMS %p could not append certificate: %s\n",
145
+			       sig, strerror ( rc ) );
146
+			goto err_append;
147
+		}
148
+
149
+		/* Drop reference to certificate */
150
+		x509_put ( cert );
151
+		cert = NULL;
152
+
153
+		/* Move to next certificate */
154
+		asn1_skip_any ( &cursor );
155
+	}
156
+
157
+	return 0;
158
+
159
+ err_append:
160
+	x509_put ( cert );
161
+ err_parse:
162
+	return rc;
163
+}
164
+
165
+/**
166
+ * Identify CMS signature certificate by issuer and serial number
167
+ *
168
+ * @v sig		CMS signature
169
+ * @v issuer		Issuer
170
+ * @v serial		Serial number
171
+ * @ret cert		X.509 certificate, or NULL if not found
172
+ */
173
+static struct x509_certificate *
174
+cms_find_issuer_serial ( struct cms_signature *sig,
175
+			 const struct asn1_cursor *issuer,
176
+			 const struct asn1_cursor *serial ) {
177
+	struct x509_link *link;
178
+	struct x509_certificate *cert;
179
+
180
+	/* Scan through certificate list */
181
+	list_for_each_entry ( link, &sig->certificates->links, list ) {
182
+
183
+		/* Check issuer and serial number */
184
+		cert = link->cert;
185
+		if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
186
+		     ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
187
+			return cert;
188
+	}
189
+
190
+	return NULL;
191
+}
192
+
193
+/**
194
+ * Identify CMS signature certificate by subject
195
+ *
196
+ * @v sig		CMS signature
197
+ * @v subject		Subject
198
+ * @ret cert		X.509 certificate, or NULL if not found
199
+ */
200
+static struct x509_certificate *
201
+cms_find_subject ( struct cms_signature *sig,
202
+		   const struct asn1_cursor *subject ) {
203
+	struct x509_link *link;
204
+	struct x509_certificate *cert;
205
+
206
+	/* Scan through certificate list */
207
+	list_for_each_entry ( link, &sig->certificates->links, list ) {
208
+
209
+		/* Check subject */
210
+		cert = link->cert;
211
+		if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
212
+			return cert;
213
+	}
214
+
215
+	return NULL;
216
+}
217
+
110 218
 /**
111 219
  * Parse CMS signature signer identifier
112 220
  *
@@ -119,34 +227,63 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig,
119 227
 					 struct cms_signer_info *info,
120 228
 					 const struct asn1_cursor *raw ) {
121 229
 	struct asn1_cursor cursor;
230
+	struct asn1_cursor serial;
231
+	struct asn1_cursor issuer;
232
+	struct x509_certificate *cert;
233
+	struct x509_certificate *previous;
122 234
 	int rc;
123 235
 
124 236
 	/* Enter issuerAndSerialNumber */
125 237
 	memcpy ( &cursor, raw, sizeof ( cursor ) );
126 238
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
127 239
 
128
-	/* Record issuer */
129
-	memcpy ( &info->issuer, &cursor, sizeof ( info->issuer ) );
130
-	if ( ( rc = asn1_shrink ( &info->issuer, ASN1_SEQUENCE ) ) != 0 ) {
240
+	/* Identify issuer */
241
+	memcpy ( &issuer, &cursor, sizeof ( issuer ) );
242
+	if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
131 243
 		DBGC ( sig, "CMS %p/%p could not locate issuer: %s\n",
132 244
 		       sig, info, strerror ( rc ) );
133 245
 		DBGC_HDA ( sig, 0, raw->data, raw->len );
134 246
 		return rc;
135 247
 	}
136 248
 	DBGC ( sig, "CMS %p/%p issuer is:\n", sig, info );
137
-	DBGC_HDA ( sig, 0, info->issuer.data, info->issuer.len );
249
+	DBGC_HDA ( sig, 0, issuer.data, issuer.len );
138 250
 	asn1_skip_any ( &cursor );
139 251
 
140
-	/* Record serialNumber */
141
-	memcpy ( &info->serial, &cursor, sizeof ( info->serial ) );
142
-	if ( ( rc = asn1_shrink ( &info->serial, ASN1_INTEGER ) ) != 0 ) {
252
+	/* Identify serialNumber */
253
+	memcpy ( &serial, &cursor, sizeof ( serial ) );
254
+	if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
143 255
 		DBGC ( sig, "CMS %p/%p could not locate serialNumber: %s\n",
144 256
 		       sig, info, strerror ( rc ) );
145 257
 		DBGC_HDA ( sig, 0, raw->data, raw->len );
146 258
 		return rc;
147 259
 	}
148 260
 	DBGC ( sig, "CMS %p/%p serial number is:\n", sig, info );
149
-	DBGC_HDA ( sig, 0, info->serial.data, info->serial.len );
261
+	DBGC_HDA ( sig, 0, serial.data, serial.len );
262
+
263
+	/* Identify certificate */
264
+	cert = cms_find_issuer_serial ( sig, &issuer, &serial );
265
+	if ( ! cert ) {
266
+		DBGC ( sig, "CMS %p/%p could not identify signer's "
267
+		       "certificate\n", sig, info );
268
+		return -ENOENT;
269
+	}
270
+
271
+	/* Create certificate chain */
272
+	do {
273
+		/* Add certificate to chain */
274
+		if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
275
+			DBGC ( sig, "CMS %p/%p could not append certificate: "
276
+			       "%s\n", sig, info, strerror ( rc ) );
277
+			return rc;
278
+		}
279
+		DBGC ( sig, "CMS %p/%p added certificate %s\n",
280
+		       sig, info, cert->subject.name );
281
+
282
+		/* Locate next certificate in chain, if any */
283
+		previous = cert;
284
+		cert = cms_find_subject ( sig, &cert->issuer.raw );
285
+
286
+	} while ( ( cert != NULL ) && ( cert != previous ) );
150 287
 
151 288
 	return 0;
152 289
 }
@@ -249,8 +386,11 @@ static int cms_parse_signature_value ( struct cms_signature *sig,
249 386
 	}
250 387
 
251 388
 	/* Record signature */
252
-	info->signature = cursor.data;
253 389
 	info->signature_len = cursor.len;
390
+	info->signature = malloc ( info->signature_len );
391
+	if ( ! info->signature )
392
+		return -ENOMEM;
393
+	memcpy ( info->signature, cursor.data, info->signature_len );
254 394
 	DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info );
255 395
 	DBGC_HDA ( sig, 0, info->signature, info->signature_len );
256 396
 
@@ -307,23 +447,21 @@ static int cms_parse_signer_info ( struct cms_signature *sig,
307 447
  * Parse CMS signature from ASN.1 data
308 448
  *
309 449
  * @v sig		CMS signature
310
- * @v data		Raw signature data
311
- * @v len		Length of raw data
450
+ * @v raw		ASN.1 cursor
312 451
  * @ret rc		Return status code
313 452
  */
314
-int cms_parse ( struct cms_signature *sig, const void *data, size_t len ) {
453
+static int cms_parse ( struct cms_signature *sig,
454
+		       const struct asn1_cursor *raw ) {
315 455
 	struct asn1_cursor cursor;
456
+	struct cms_signer_info *info;
316 457
 	int rc;
317 458
 
318
-	/* Initialise signature */
319
-	memset ( sig, 0, sizeof ( *sig ) );
320
-	cursor.data = data;
321
-	cursor.len = len;
322
-
323 459
 	/* Enter contentInfo */
460
+	memcpy ( &cursor, raw, sizeof ( cursor ) );
324 461
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
325 462
 
326 463
 	/* Parse contentType */
464
+
327 465
 	if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 )
328 466
 		return rc;
329 467
 	asn1_skip_any ( &cursor );
@@ -343,14 +481,9 @@ int cms_parse ( struct cms_signature *sig, const void *data, size_t len ) {
343 481
 	/* Skip encapContentInfo */
344 482
 	asn1_skip ( &cursor, ASN1_SEQUENCE );
345 483
 
346
-	/* Record certificates */
347
-	memcpy ( &sig->certificates, &cursor, sizeof ( sig->certificates ) );
348
-	if ( ( rc = asn1_enter ( &sig->certificates,
349
-				 ASN1_EXPLICIT_TAG ( 0 ) ) ) != 0 ) {
350
-		DBGC ( sig, "CMS %p could not locate certificates:\n", sig );
351
-		DBGC_HDA ( sig, 0, data, len );
484
+	/* Parse certificates */
485
+	if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 )
352 486
 		return rc;
353
-	}
354 487
 	asn1_skip_any ( &cursor );
355 488
 
356 489
 	/* Skip crls, if present */
@@ -359,77 +492,100 @@ int cms_parse ( struct cms_signature *sig, const void *data, size_t len ) {
359 492
 	/* Enter signerInfos */
360 493
 	asn1_enter ( &cursor, ASN1_SET );
361 494
 
362
-	/* Parse first signerInfo */
363
-	if ( ( rc = cms_parse_signer_info ( sig, &sig->info, &cursor ) ) != 0 )
364
-		return rc;
495
+	/* Add each signerInfo.  Errors are handled by ensuring that
496
+	 * cms_put() will always be able to free any allocated memory.
497
+	 */
498
+	while ( cursor.len ) {
499
+
500
+		/* Allocate signer information block */
501
+		info = zalloc ( sizeof ( *info ) );
502
+		if ( ! info )
503
+			return -ENOMEM;
504
+		list_add ( &info->list, &sig->info );
505
+
506
+		/* Allocate certificate chain */
507
+		info->chain = x509_alloc_chain();
508
+		if ( ! info->chain )
509
+			return -ENOMEM;
510
+
511
+		/* Parse signerInfo */
512
+		if ( ( rc = cms_parse_signer_info ( sig, info,
513
+						    &cursor ) ) != 0 )
514
+			return rc;
515
+		asn1_skip_any ( &cursor );
516
+	}
365 517
 
366 518
 	return 0;
367 519
 }
368 520
 
369
-/** CMS certificate chain context */
370
-struct cms_chain_context {
371
-	/** Signature */
372
-	struct cms_signature *sig;
373
-	/** Signer information */
521
+/**
522
+ * Free CMS signature
523
+ *
524
+ * @v refcnt		Reference count
525
+ */
526
+static void cms_free ( struct refcnt *refcnt ) {
527
+	struct cms_signature *sig =
528
+		container_of ( refcnt, struct cms_signature, refcnt );
374 529
 	struct cms_signer_info *info;
375
-};
530
+	struct cms_signer_info *tmp;
531
+
532
+	list_for_each_entry_safe ( info, tmp, &sig->info, list ) {
533
+		list_del ( &info->list );
534
+		x509_chain_put ( info->chain );
535
+		free ( info->signature );
536
+		free ( info );
537
+	}
538
+	x509_chain_put ( sig->certificates );
539
+	free ( sig );
540
+}
376 541
 
377 542
 /**
378
- * Parse next certificate in chain
543
+ * Create CMS signature
379 544
  *
380
- * @v cert		X.509 certificate to parse
381
- * @v previous		Previous X.509 certificate, or NULL
382
- * @v ctx		Chain context
545
+ * @v data		Raw signature data
546
+ * @v len		Length of raw data
547
+ * @ret sig		CMS signature
383 548
  * @ret rc		Return status code
549
+ *
550
+ * On success, the caller holds a reference to the CMS signature, and
551
+ * is responsible for ultimately calling cms_put().
384 552
  */
385
-static int cms_parse_next ( struct x509_certificate *cert,
386
-			    const struct x509_certificate *previous,
387
-			    void *ctx ) {
388
-	struct cms_chain_context *context = ctx;
389
-	struct cms_signature *sig = context->sig;
390
-	struct cms_signer_info *info = context->info;
553
+int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) {
391 554
 	struct asn1_cursor cursor;
392 555
 	int rc;
393 556
 
394
-	/* Search for relevant certificate */
395
-	memcpy ( &cursor, &sig->certificates, sizeof ( cursor ) );
396
-	while ( cursor.len ) {
557
+	/* Allocate and initialise signature */
558
+	*sig = zalloc ( sizeof ( **sig ) );
559
+	if ( ! *sig ) {
560
+		rc = -ENOMEM;
561
+		goto err_alloc;
562
+	}
563
+	ref_init ( &(*sig)->refcnt, cms_free );
564
+	INIT_LIST_HEAD ( &(*sig)->info );
565
+
566
+	/* Allocate certificate list */
567
+	(*sig)->certificates = x509_alloc_chain();
568
+	if ( ! (*sig)->certificates ) {
569
+		rc = -ENOMEM;
570
+		goto err_alloc_chain;
571
+	}
397 572
 
398
-		/* Parse certificate */
399
-		if ( ( rc = x509_parse ( cert, cursor.data,
400
-					 cursor.len ) ) != 0 ) {
401
-			DBGC ( sig, "CMS %p/%p could not parse certificate:\n",
402
-			       sig, info );
403
-			DBGC_HDA ( sig, 0, cursor.data, cursor.len );
404
-			return rc;
405
-		}
573
+	/* Initialise cursor */
574
+	cursor.data = data;
575
+	cursor.len = len;
576
+	asn1_shrink_any ( &cursor );
406 577
 
407
-		if ( previous == NULL ) {
408
-			/* First certificate: check issuer and serial
409
-			 * number against signer info
410
-			 */
411
-			if ( ( asn1_compare ( &info->issuer,
412
-					      &cert->issuer.raw ) == 0 ) &&
413
-			     ( asn1_compare ( &info->serial,
414
-					      &cert->serial.raw ) == 0 ) ) {
415
-				return 0;
416
-			}
417
-		} else {
418
-			/* Subsequent certificates: check subject
419
-			 * against previous certificate's issuer.
420
-			 */
421
-			if ( asn1_compare ( &previous->issuer.raw,
422
-					    &cert->subject.raw ) == 0 ) {
423
-				return 0;
424
-			}
425
-		}
578
+	/* Parse signature */
579
+	if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 )
580
+		goto err_parse;
426 581
 
427
-		/* Move to next certificate */
428
-		asn1_skip_any ( &cursor );
429
-	}
582
+	return 0;
430 583
 
431
-	DBGC ( sig, "CMS %p/%p reached end of certificate chain\n", sig, info );
432
-	return -EACCES_INCOMPLETE;
584
+ err_parse:
585
+ err_alloc_chain:
586
+	cms_put ( *sig );
587
+ err_alloc:
588
+	return rc;
433 589
 }
434 590
 
435 591
 /**
@@ -525,7 +681,6 @@ static int cms_verify_digest ( struct cms_signature *sig,
525 681
  * @v info		Signer information
526 682
  * @v data		Signed data
527 683
  * @v len		Length of signed data
528
- * @v name		Required common name, or NULL to allow any name
529 684
  * @v time		Time at which to validate certificates
530 685
  * @v root		Root certificate store, or NULL to use default
531 686
  * @ret rc		Return status code
@@ -533,48 +688,37 @@ static int cms_verify_digest ( struct cms_signature *sig,
533 688
 static int cms_verify_signer_info ( struct cms_signature *sig,
534 689
 				    struct cms_signer_info *info,
535 690
 				    userptr_t data, size_t len,
536
-				    const char *name, time_t time,
537
-				    struct x509_root *root ) {
538
-	struct cms_chain_context context;
539
-	struct x509_certificate cert;
691
+				    time_t time, struct x509_root *root ) {
692
+	struct x509_certificate *cert;
540 693
 	int rc;
541 694
 
542 695
 	/* Validate certificate chain */
543
-	context.sig = sig;
544
-	context.info = info;
545
-	if ( ( rc = x509_validate_chain ( cms_parse_next, &context, time, root,
546
-					  &cert ) ) != 0 ) {
696
+	if ( ( rc = x509_validate_chain ( info->chain, time, root ) ) != 0 ) {
547 697
 		DBGC ( sig, "CMS %p/%p could not validate chain: %s\n",
548 698
 		       sig, info, strerror ( rc ) );
549 699
 		return rc;
550 700
 	}
551 701
 
702
+	/* Extract code-signing certificate */
703
+	cert = x509_first ( info->chain );
704
+	assert ( cert != NULL );
705
+
552 706
 	/* Check that certificate can create digital signatures */
553
-	if ( ! ( cert.extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
707
+	if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
554 708
 		DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n",
555 709
 		       sig, info );
556 710
 		return -EACCES_NON_SIGNING;
557 711
 	}
558 712
 
559 713
 	/* Check that certificate can sign code */
560
-	if ( ! ( cert.extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
714
+	if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
561 715
 		DBGC ( sig, "CMS %p/%p certificate is not code-signing\n",
562 716
 		       sig, info );
563 717
 		return -EACCES_NON_CODE_SIGNING;
564 718
 	}
565 719
 
566
-	/* Check certificate name, if applicable */
567
-	if ( ( name != NULL ) &&
568
-	     ( ( cert.subject.name.len != strlen ( name ) ) ||
569
-	       ( memcmp ( cert.subject.name.data, name,
570
-			  cert.subject.name.len ) != 0 ) ) ) {
571
-		DBGC ( sig, "CMS %p/%p certificate name incorrect\n",
572
-		       sig, info );
573
-		return -EACCES_WRONG_NAME;
574
-	}
575
-
576 720
 	/* Verify digest */
577
-	if ( ( rc = cms_verify_digest ( sig, info, &cert, data, len ) ) != 0 )
721
+	if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 )
578 722
 		return rc;
579 723
 
580 724
 	return 0;
@@ -586,19 +730,40 @@ static int cms_verify_signer_info ( struct cms_signature *sig,
586 730
  * @v sig		CMS signature
587 731
  * @v data		Signed data
588 732
  * @v len		Length of signed data
589
- * @v name		Required common name, or NULL to allow any name
733
+ * @v name		Required common name, or NULL to check all signatures
590 734
  * @v time		Time at which to validate certificates
591 735
  * @v root		Root certificate store, or NULL to use default
592 736
  * @ret rc		Return status code
593 737
  */
594 738
 int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
595 739
 		 const char *name, time_t time, struct x509_root *root ) {
740
+	struct cms_signer_info *info;
741
+	struct x509_certificate *cert;
742
+	int count = 0;
596 743
 	int rc;
597 744
 
598
-	/* Verify using first signerInfo */
599
-	if ( ( rc = cms_verify_signer_info ( sig, &sig->info, data, len,
600
-					     name, time, root ) ) != 0 )
601
-		return rc;
745
+	/* Verify using all signerInfos */
746
+	list_for_each_entry ( info, &sig->info, list ) {
747
+		cert = x509_first ( info->chain );
748
+		if ( name && ( strcmp ( name, cert->subject.name ) != 0 ) )
749
+			continue;
750
+		if ( ( rc = cms_verify_signer_info ( sig, info, data, len,
751
+						     time, root ) ) != 0 )
752
+			return rc;
753
+		count++;
754
+	}
755
+
756
+	/* Check that we have verified at least one signature */
757
+	if ( count == 0 ) {
758
+		if ( name ) {
759
+			DBGC ( sig, "CMS %p had no signatures matching name "
760
+			       "%s\n", sig, name );
761
+			return -EACCES_WRONG_NAME;
762
+		} else {
763
+			DBGC ( sig, "CMS %p had no signatures\n", sig );
764
+			return -EACCES_NO_SIGNATURES;
765
+		}
766
+	}
602 767
 
603 768
 	return 0;
604 769
 }

+ 362
- 116
src/crypto/x509.c Ver fichero

@@ -18,11 +18,14 @@
18 18
 
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21
+#include <stdlib.h>
21 22
 #include <string.h>
22 23
 #include <ctype.h>
23 24
 #include <time.h>
24 25
 #include <errno.h>
25 26
 #include <assert.h>
27
+#include <ipxe/list.h>
28
+#include <ipxe/malloc.h>
26 29
 #include <ipxe/asn1.h>
27 30
 #include <ipxe/crypto.h>
28 31
 #include <ipxe/md5.h>
@@ -97,6 +100,58 @@ FILE_LICENCE ( GPL2_OR_LATER );
97 100
 	__einfo_error ( EINFO_EACCES_UNTRUSTED )
98 101
 #define EINFO_EACCES_UNTRUSTED \
99 102
 	__einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
103
+#define EACCES_OUT_OF_ORDER \
104
+	__einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
105
+#define EINFO_EACCES_OUT_OF_ORDER \
106
+	__einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
107
+#define EACCES_EMPTY \
108
+	__einfo_error ( EINFO_EACCES_EMPTY )
109
+#define EINFO_EACCES_EMPTY \
110
+	__einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
111
+
112
+/** Certificate cache */
113
+static LIST_HEAD ( x509_cache );
114
+
115
+/**
116
+ * Free X.509 certificate
117
+ *
118
+ * @v refcnt		Reference count
119
+ */
120
+static void x509_free ( struct refcnt *refcnt ) {
121
+	struct x509_certificate *cert =
122
+		container_of ( refcnt, struct x509_certificate, refcnt );
123
+
124
+	DBGC ( cert, "X509 %p freed\n", cert );
125
+	free ( cert->subject.name );
126
+	free ( cert->extensions.auth_info.ocsp.uri );
127
+	free ( cert );
128
+}
129
+
130
+/**
131
+ * Discard a cached certificate
132
+ *
133
+ * @ret discarded	Number of cached items discarded
134
+ */
135
+static unsigned int x509_discard ( void ) {
136
+	struct x509_certificate *cert;
137
+
138
+	/* Discard the least recently used certificate for which the
139
+	 * only reference is held by the cache itself.
140
+	 */
141
+	list_for_each_entry_reverse ( cert, &x509_cache, list ) {
142
+		if ( cert->refcnt.count == 0 ) {
143
+			list_del ( &cert->list );
144
+			x509_put ( cert );
145
+			return 1;
146
+		}
147
+	}
148
+	return 0;
149
+}
150
+
151
+/** X.509 cache discarder */
152
+struct cache_discarder x509_cache_discarder __cache_discarder = {
153
+	.discard = x509_discard,
154
+};
100 155
 
101 156
 /** "commonName" object identifier */
102 157
 static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
@@ -113,9 +168,9 @@ static struct asn1_cursor oid_common_name_cursor =
113 168
  * @v raw		ASN.1 cursor
114 169
  * @ret rc		Return status code
115 170
  */
116
-int x509_parse_pubkey_algorithm ( struct x509_certificate *cert,
117
-				  struct asn1_algorithm **algorithm,
118
-				  const struct asn1_cursor *raw ) {
171
+static int x509_parse_pubkey_algorithm ( struct x509_certificate *cert,
172
+					 struct asn1_algorithm **algorithm,
173
+					 const struct asn1_cursor *raw ) {
119 174
 
120 175
 	/* Parse algorithm */
121 176
 	*algorithm = asn1_algorithm ( raw );
@@ -486,8 +541,7 @@ static int x509_parse_validity ( struct x509_certificate *cert,
486 541
  * @v raw		ASN.1 cursor
487 542
  * @ret rc		Return status code
488 543
  */
489
-static int x509_parse_common_name ( struct x509_certificate *cert,
490
-				    struct x509_string *name,
544
+static int x509_parse_common_name ( struct x509_certificate *cert, char **name,
491 545
 				    const struct asn1_cursor *raw ) {
492 546
 	struct asn1_cursor cursor;
493 547
 	struct asn1_cursor oid_cursor;
@@ -500,6 +554,8 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
500 554
 
501 555
 	/* Scan through name list */
502 556
 	for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {
557
+
558
+		/* Check for "commonName" OID */
503 559
 		memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
504 560
 		asn1_enter ( &oid_cursor, ASN1_SET );
505 561
 		asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
@@ -513,8 +569,12 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
513 569
 			DBGC_HDA ( cert, 0, raw->data, raw->len );
514 570
 			return rc;
515 571
 		}
516
-		name->data = name_cursor.data;
517
-		name->len = name_cursor.len;
572
+
573
+		/* Allocate name */
574
+		*name = zalloc ( name_cursor.len + 1 /* NUL */ );
575
+		if ( ! *name )
576
+			return -ENOMEM;
577
+		memcpy ( *name, name_cursor.data, name_cursor.len );
518 578
 		return 0;
519 579
 	}
520 580
 
@@ -533,7 +593,7 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
533 593
 static int x509_parse_subject ( struct x509_certificate *cert,
534 594
 				const struct asn1_cursor *raw ) {
535 595
 	struct x509_subject *subject = &cert->subject;
536
-	struct x509_string *name = &subject->name;
596
+	char **name = &subject->name;
537 597
 	int rc;
538 598
 
539 599
 	/* Record raw subject */
@@ -545,8 +605,7 @@ static int x509_parse_subject ( struct x509_certificate *cert,
545 605
 	/* Parse common name */
546 606
 	if ( ( rc = x509_parse_common_name ( cert, name, raw ) ) != 0 )
547 607
 		return rc;
548
-	DBGC ( cert, "X509 %p common name is:\n", cert );
549
-	DBGC_HDA ( cert, 0, name->data, name->len );
608
+	DBGC ( cert, "X509 %p common name is \"%s\":\n", cert, *name );
550 609
 
551 610
 	return 0;
552 611
 }
@@ -625,7 +684,7 @@ static int x509_parse_basic_constraints ( struct x509_certificate *cert,
625 684
 		return 0;
626 685
 
627 686
 	/* Parse "pathLenConstraint", if present and applicable */
628
-	basic->path_len = -1U; /* Default is unlimited */
687
+	basic->path_len = X509_PATH_LEN_UNLIMITED;
629 688
 	if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
630 689
 		if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
631 690
 			DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
@@ -783,10 +842,11 @@ static int x509_parse_ocsp ( struct x509_certificate *cert,
783 842
 	}
784 843
 
785 844
 	/* Record URI */
786
-	ocsp->uri.data = cursor.data;
787
-	ocsp->uri.len = cursor.len;
788
-	DBGC ( cert, "X509 %p OCSP URI is:\n", cert );
789
-	DBGC_HDA ( cert, 0, ocsp->uri.data, ocsp->uri.len );
845
+	ocsp->uri = zalloc ( cursor.len + 1 /* NUL */ );
846
+	if ( ! ocsp->uri )
847
+		return -ENOMEM;
848
+	memcpy ( ocsp->uri, cursor.data, cursor.len );
849
+	DBGC ( cert, "X509 %p OCSP URI is %s:\n", cert, ocsp->uri );
790 850
 
791 851
 	return 0;
792 852
 }
@@ -1112,25 +1172,22 @@ static int x509_parse_tbscertificate ( struct x509_certificate *cert,
1112 1172
  * Parse X.509 certificate from ASN.1 data
1113 1173
  *
1114 1174
  * @v cert		X.509 certificate
1115
- * @v data		Raw certificate data
1116
- * @v len		Length of raw data
1175
+ * @v raw		ASN.1 cursor
1117 1176
  * @ret rc		Return status code
1118 1177
  */
1119
-int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
1178
+static int x509_parse ( struct x509_certificate *cert,
1179
+			const struct asn1_cursor *raw ) {
1120 1180
 	struct x509_signature *signature = &cert->signature;
1121 1181
 	struct asn1_algorithm **signature_algorithm = &signature->algorithm;
1122 1182
 	struct x509_bit_string *signature_value = &signature->value;
1123 1183
 	struct asn1_cursor cursor;
1124 1184
 	int rc;
1125 1185
 
1126
-	/* Initialise certificate */
1127
-	memset ( cert, 0, sizeof ( *cert ) );
1128
-	cert->raw.data = data;
1129
-	cert->raw.len = len;
1130
-	asn1_shrink_any ( &cert->raw );
1186
+	/* Record raw certificate */
1187
+	memcpy ( &cursor, raw, sizeof ( cursor ) );
1188
+	memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );
1131 1189
 
1132 1190
 	/* Enter certificate */
1133
-	memcpy ( &cursor, &cert->raw, sizeof ( cursor ) );
1134 1191
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
1135 1192
 
1136 1193
 	/* Parse tbsCertificate */
@@ -1168,7 +1225,72 @@ int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
1168 1225
 }
1169 1226
 
1170 1227
 /**
1171
- * Verify X.509 certificate signature
1228
+ * Create X.509 certificate
1229
+ *
1230
+ * @v data		Raw certificate data
1231
+ * @v len		Length of raw data
1232
+ * @ret cert		X.509 certificate
1233
+ * @ret rc		Return status code
1234
+ *
1235
+ * On success, the caller holds a reference to the X.509 certificate,
1236
+ * and is responsible for ultimately calling x509_put().
1237
+ */
1238
+int x509_certificate ( const void *data, size_t len,
1239
+		       struct x509_certificate **cert ) {
1240
+	struct asn1_cursor cursor;
1241
+	void *raw;
1242
+	int rc;
1243
+
1244
+	/* Initialise cursor */
1245
+	cursor.data = data;
1246
+	cursor.len = len;
1247
+	asn1_shrink_any ( &cursor );
1248
+
1249
+	/* Search for certificate within cache */
1250
+	list_for_each_entry ( (*cert), &x509_cache, list ) {
1251
+		if ( asn1_compare ( &cursor, &(*cert)->raw ) == 0 ) {
1252
+
1253
+			DBGC ( *cert, "X509 %p \"%s\" cache hit\n",
1254
+			       *cert, (*cert)->subject.name );
1255
+
1256
+			/* Mark as most recently used */
1257
+			list_del ( &(*cert)->list );
1258
+			list_add ( &(*cert)->list, &x509_cache );
1259
+
1260
+			/* Add caller's reference */
1261
+			x509_get ( *cert );
1262
+
1263
+			return 0;
1264
+		}
1265
+	}
1266
+
1267
+	/* Allocate and initialise certificate */
1268
+	*cert = zalloc ( sizeof ( **cert ) + cursor.len );
1269
+	if ( ! *cert )
1270
+		return -ENOMEM;
1271
+	ref_init ( &(*cert)->refcnt, x509_free );
1272
+	INIT_LIST_HEAD ( &(*cert)->list );
1273
+	raw = ( *cert + 1 );
1274
+
1275
+	/* Copy raw data */
1276
+	memcpy ( raw, cursor.data, cursor.len );
1277
+	cursor.data = raw;
1278
+
1279
+	/* Parse certificate */
1280
+	if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
1281
+		x509_put ( *cert );
1282
+		return rc;
1283
+	}
1284
+
1285
+	/* Add certificate to cache */
1286
+	x509_get ( *cert );
1287
+	list_add ( &(*cert)->list, &x509_cache );
1288
+
1289
+	return 0;
1290
+}
1291
+
1292
+/**
1293
+ * Check X.509 certificate signature
1172 1294
  *
1173 1295
  * @v cert		X.509 certificate
1174 1296
  * @v public_key	X.509 public key
@@ -1192,14 +1314,15 @@ static int x509_check_signature ( struct x509_certificate *cert,
1192 1314
 	digest_init ( digest, digest_ctx );
1193 1315
 	digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
1194 1316
 	digest_final ( digest, digest_ctx, digest_out );
1195
-	DBGC ( cert, "X509 %p digest:\n", cert );
1317
+	DBGC ( cert, "X509 %p \"%s\" digest:\n", cert, cert->subject.name );
1196 1318
 	DBGC_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
1197 1319
 
1198 1320
 	/* Check that signature public key algorithm matches signer */
1199 1321
 	if ( public_key->algorithm->pubkey != pubkey ) {
1200
-		DBGC ( cert, "X509 %p signature algorithm %s does not match "
1201
-		       "signer's algorithm %s\n",
1202
-		       cert, algorithm->name, public_key->algorithm->name );
1322
+		DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
1323
+		       "match signer's algorithm %s\n",
1324
+		       cert, cert->subject.name, algorithm->name,
1325
+		       public_key->algorithm->name );
1203 1326
 		rc = -EINVAL_ALGORITHM_MISMATCH;
1204 1327
 		goto err_mismatch;
1205 1328
 	}
@@ -1207,15 +1330,15 @@ static int x509_check_signature ( struct x509_certificate *cert,
1207 1330
 	/* Verify signature using signer's public key */
1208 1331
 	if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
1209 1332
 				  public_key->raw.len ) ) != 0 ) {
1210
-		DBGC ( cert, "X509 %p cannot initialise public key: %s\n",
1211
-		       cert, strerror ( rc ) );
1333
+		DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
1334
+		       "%s\n", cert, cert->subject.name, strerror ( rc ) );
1212 1335
 		goto err_pubkey_init;
1213 1336
 	}
1214 1337
 	if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
1215 1338
 				    signature->value.data,
1216 1339
 				    signature->value.len ) ) != 0 ) {
1217
-		DBGC ( cert, "X509 %p signature verification failed: %s\n",
1218
-		       cert, strerror ( rc ) );
1340
+		DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
1341
+		       "%s\n", cert, cert->subject.name, strerror ( rc ) );
1219 1342
 		goto err_pubkey_verify;
1220 1343
 	}
1221 1344
 
@@ -1230,14 +1353,14 @@ static int x509_check_signature ( struct x509_certificate *cert,
1230 1353
 }
1231 1354
 
1232 1355
 /**
1233
- * Validate X.509 certificate against issuer certificate
1356
+ * Check X.509 certificate against issuer certificate
1234 1357
  *
1235 1358
  * @v cert		X.509 certificate
1236 1359
  * @v issuer		X.509 issuer certificate
1237 1360
  * @ret rc		Return status code
1238 1361
  */
1239
-int x509_validate_issuer ( struct x509_certificate *cert,
1240
-			   struct x509_certificate *issuer ) {
1362
+int x509_check_issuer ( struct x509_certificate *cert,
1363
+			struct x509_certificate *issuer ) {
1241 1364
 	struct x509_public_key *public_key = &issuer->subject.public_key;
1242 1365
 	int rc;
1243 1366
 
@@ -1254,8 +1377,9 @@ int x509_validate_issuer ( struct x509_certificate *cert,
1254 1377
 	 * for some enjoyable ranting on this subject.
1255 1378
 	 */
1256 1379
 	if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
1257
-		DBGC ( cert, "X509 %p issuer does not match X509 %p subject\n",
1258
-		       cert, issuer );
1380
+		DBGC ( cert, "X509 %p \"%s\" issuer does not match X509 %p "
1381
+		       "\"%s\" subject\n", cert, cert->subject.name,
1382
+		       issuer, issuer->subject.name );
1259 1383
 		DBGC_HDA ( cert, 0, cert->issuer.raw.data,
1260 1384
 			   cert->issuer.raw.len );
1261 1385
 		DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
@@ -1265,14 +1389,16 @@ int x509_validate_issuer ( struct x509_certificate *cert,
1265 1389
 
1266 1390
 	/* Check that issuer is allowed to sign certificates */
1267 1391
 	if ( ! issuer->extensions.basic.ca ) {
1268
-		DBGC ( issuer, "X509 %p cannot sign X509 %p: not a CA "
1269
-		       "certificate\n", issuer, cert );
1392
+		DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
1393
+		       "not a CA certificate\n", issuer, issuer->subject.name,
1394
+		       cert, cert->subject.name );
1270 1395
 		return -EACCES_NOT_CA;
1271 1396
 	}
1272 1397
 	if ( issuer->extensions.usage.present &&
1273 1398
 	     ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
1274
-		DBGC ( issuer, "X509 %p cannot sign X509 %p: no keyCertSign "
1275
-		       "usage\n", issuer, cert );
1399
+		DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
1400
+		       "no keyCertSign usage\n", issuer, issuer->subject.name,
1401
+		       cert, cert->subject.name );
1276 1402
 		return -EACCES_KEY_USAGE;
1277 1403
 	}
1278 1404
 
@@ -1280,8 +1406,6 @@ int x509_validate_issuer ( struct x509_certificate *cert,
1280 1406
 	if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
1281 1407
 		return rc;
1282 1408
 
1283
-	DBGC ( cert, "X509 %p successfully validated using X509 %p\n",
1284
-	       cert, issuer );
1285 1409
 	return 0;
1286 1410
 }
1287 1411
 
@@ -1293,7 +1417,8 @@ int x509_validate_issuer ( struct x509_certificate *cert,
1293 1417
  * @v fingerprint	Fingerprint buffer
1294 1418
  */
1295 1419
 void x509_fingerprint ( struct x509_certificate *cert,
1296
-			struct digest_algorithm *digest, void *fingerprint ) {
1420
+			struct digest_algorithm *digest,
1421
+			void *fingerprint ) {
1297 1422
 	uint8_t ctx[ digest->ctxsize ];
1298 1423
 
1299 1424
 	/* Calculate fingerprint */
@@ -1303,14 +1428,13 @@ void x509_fingerprint ( struct x509_certificate *cert,
1303 1428
 }
1304 1429
 
1305 1430
 /**
1306
- * Validate X.509 root certificate
1431
+ * Check X.509 root certificate
1307 1432
  *
1308 1433
  * @v cert		X.509 certificate
1309 1434
  * @v root		X.509 root certificate store
1310 1435
  * @ret rc		Return status code
1311 1436
  */
1312
-int x509_validate_root ( struct x509_certificate *cert,
1313
-			 struct x509_root *root ) {
1437
+int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
1314 1438
 	struct digest_algorithm *digest = root->digest;
1315 1439
 	uint8_t fingerprint[ digest->digestsize ];
1316 1440
 	const uint8_t *root_fingerprint = root->fingerprints;
@@ -1323,122 +1447,244 @@ int x509_validate_root ( struct x509_certificate *cert,
1323 1447
 	for ( i = 0 ; i < root->count ; i++ ) {
1324 1448
 		if ( memcmp ( fingerprint, root_fingerprint,
1325 1449
 			      sizeof ( fingerprint ) ) == 0 ) {
1326
-			DBGC ( cert, "X509 %p is a root certificate\n", cert );
1450
+			DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
1451
+			       cert, cert->subject.name );
1327 1452
 			return 0;
1328 1453
 		}
1329 1454
 		root_fingerprint += sizeof ( fingerprint );
1330 1455
 	}
1331 1456
 
1332
-	DBGC ( cert, "X509 %p is not a root certificate\n", cert );
1457
+	DBGC ( cert, "X509 %p \"%s\" is not a root certificate\n",
1458
+	       cert, cert->subject.name );
1333 1459
 	return -ENOENT;
1334 1460
 }
1335 1461
 
1336 1462
 /**
1337
- * Validate X.509 certificate validity period
1463
+ * Check X.509 certificate validity period
1338 1464
  *
1339 1465
  * @v cert		X.509 certificate
1340
- * @v time		Time at which to validate certificate
1466
+ * @v time		Time at which to check certificate
1341 1467
  * @ret rc		Return status code
1342 1468
  */
1343
-int x509_validate_time ( struct x509_certificate *cert, time_t time ) {
1469
+int x509_check_time ( struct x509_certificate *cert, time_t time ) {
1344 1470
 	struct x509_validity *validity = &cert->validity;
1345 1471
 
1346 1472
 	/* Check validity period */
1347 1473
 	if ( time < validity->not_before.time ) {
1348
-		DBGC ( cert, "X509 %p is not yet valid (at time %lld)\n",
1349
-		       cert, time );
1474
+		DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
1475
+		       cert, cert->subject.name, time );
1350 1476
 		return -EACCES_EXPIRED;
1351 1477
 	}
1352 1478
 	if ( time > validity->not_after.time ) {
1353
-		DBGC ( cert, "X509 %p has expired (at time %lld)\n",
1354
-		       cert, time );
1479
+		DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
1480
+		       cert, cert->subject.name, time );
1355 1481
 		return -EACCES_EXPIRED;
1356 1482
 	}
1357 1483
 
1358
-	DBGC ( cert, "X509 %p is valid (at time %lld)\n", cert, time );
1484
+	DBGC ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
1485
+	       cert, cert->subject.name, time );
1359 1486
 	return 0;
1360 1487
 }
1361 1488
 
1362 1489
 /**
1363
- * Validate X.509 certificate chain
1490
+ * Validate X.509 certificate
1364 1491
  *
1365
- * @v parse_next	Parse next X.509 certificate in chain
1366
- * @v context		Context for parse_next()
1367
- * @v time		Time at which to validate certificates
1492
+ * @v cert		X.509 certificate
1493
+ * @v issuer		Issuing X.509 certificate (or NULL)
1494
+ * @v time		Time at which to validate certificate
1368 1495
  * @v root		Root certificate store, or NULL to use default
1369
- * @v first		Initial X.509 certificate to fill in, or NULL
1370 1496
  * @ret rc		Return status code
1497
+ *
1498
+ * The issuing certificate must have already been validated.
1499
+ *
1500
+ * Validation results are cached: if a certificate has already been
1501
+ * successfully validated then @c issuer, @c time, and @c root will be
1502
+ * ignored.
1371 1503
  */
1372
-int x509_validate_chain ( int ( * parse_next )
1373
-			  ( struct x509_certificate *cert,
1374
-			    const struct x509_certificate *previous,
1375
-			    void *context ),
1376
-			  void *context, time_t time, struct x509_root *root,
1377
-			  struct x509_certificate *first ) {
1378
-	struct x509_certificate temp[2];
1379
-	struct x509_certificate *current = &temp[0];
1380
-	struct x509_certificate *next = &temp[1];
1381
-	struct x509_certificate *swap;
1382
-	unsigned int path_len = 0;
1504
+static int x509_validate ( struct x509_certificate *cert,
1505
+			   struct x509_certificate *issuer,
1506
+			   time_t time, struct x509_root *root ) {
1507
+	unsigned int max_path_remaining;
1383 1508
 	int rc;
1384 1509
 
1385 1510
 	/* Use default root certificate store if none specified */
1386 1511
 	if ( ! root )
1387 1512
 		root = &root_certificates;
1388 1513
 
1389
-	/* Get first certificate in chain */
1390
-	if ( ( rc = parse_next ( current, NULL, context ) ) != 0 ) {
1391
-		DBGC ( context, "X509 chain %p could not get first "
1392
-		       "certificate: %s\n", context, strerror ( rc ) );
1514
+	/* Return success if certificate has already been validated */
1515
+	if ( cert->valid )
1516
+		return 0;
1517
+
1518
+	/* Fail if certificate is invalid at specified time */
1519
+	if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
1393 1520
 		return rc;
1521
+
1522
+	/* Succeed if certificate is a trusted root certificate */
1523
+	if ( x509_check_root ( cert, root ) == 0 ) {
1524
+		cert->valid = 1;
1525
+		cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
1526
+		return 0;
1394 1527
 	}
1395 1528
 
1396
-	/* Record first certificate, if applicable */
1397
-	if ( first )
1398
-		memcpy ( first, current, sizeof ( *first ) );
1529
+	/* Fail unless we have an issuer */
1530
+	if ( ! issuer ) {
1531
+		DBGC ( cert, "X509 %p \"%s\" has no issuer\n",
1532
+		       cert, cert->subject.name );
1533
+		return -EACCES_UNTRUSTED;
1534
+	}
1399 1535
 
1400
-	/* Process chain */
1401
-	while ( 1 ) {
1536
+	/* Fail unless issuer has already been validated */
1537
+	if ( ! issuer->valid ) {
1538
+		DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" has not yet "
1539
+		       "been validated\n", cert, cert->subject.name,
1540
+		       issuer, issuer->subject.name );
1541
+		return -EACCES_OUT_OF_ORDER;
1542
+	}
1402 1543
 
1403
-		/* Check that certificate is valid at specified time */
1404
-		if ( ( rc = x509_validate_time ( current, time ) ) != 0 )
1405
-			return rc;
1544
+	/* Fail if issuing certificate cannot validate this certificate */
1545
+	if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
1546
+		return rc;
1406 1547
 
1407
-		/* Succeed if we have reached a trusted root certificate */
1408
-		if ( x509_validate_root ( current, root ) == 0 )
1409
-			return 0;
1548
+	/* Fail if path length constraint is violated */
1549
+	if ( issuer->path_remaining == 0 ) {
1550
+		DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" path length "
1551
+		       "exceeded\n", cert, cert->subject.name,
1552
+		       issuer, issuer->subject.name );
1553
+		return -EACCES_PATH_LEN;
1554
+	}
1410 1555
 
1411
-		/* Fail if we have reached an untrusted root certificate */
1412
-		if ( asn1_compare ( &current->issuer.raw,
1413
-				    &current->subject.raw ) == 0 ) {
1414
-			DBGC ( context, "X509 chain %p reached untrusted root "
1415
-			       "certificate\n", context );
1416
-			return -EACCES_UNTRUSTED;
1417
-		}
1556
+	/* Calculate effective path length */
1557
+	cert->path_remaining = ( issuer->path_remaining - 1 );
1558
+	max_path_remaining = ( cert->extensions.basic.path_len + 1 );
1559
+	if ( cert->path_remaining > max_path_remaining )
1560
+		cert->path_remaining = max_path_remaining;
1418 1561
 
1419
-		/* Get next certificate in chain */
1420
-		if ( ( rc = parse_next ( next, current, context ) ) != 0 ) {
1421
-			DBGC ( context, "X509 chain %p could not get next "
1422
-			       "certificate: %s\n", context, strerror ( rc ) );
1423
-			return rc;
1424
-		}
1562
+	/* Mark certificate as valid */
1563
+	cert->valid = 1;
1425 1564
 
1426
-		/* Validate current certificate against next certificate */
1427
-		if ( ( rc = x509_validate_issuer ( current, next ) ) != 0 )
1428
-			return rc;
1565
+	DBGC ( cert, "X509 %p \"%s\" successfully validated using issuer %p "
1566
+	       "\"%s\"\n", cert, cert->subject.name,
1567
+	       issuer, issuer->subject.name );
1568
+	return 0;
1569
+}
1570
+
1571
+/**
1572
+ * Free X.509 certificate chain
1573
+ *
1574
+ * @v refcnt		Reference count
1575
+ */
1576
+static void x509_free_chain ( struct refcnt *refcnt ) {
1577
+	struct x509_chain *chain =
1578
+		container_of ( refcnt, struct x509_chain, refcnt );
1579
+	struct x509_link *link;
1580
+	struct x509_link *tmp;
1581
+
1582
+	DBGC ( chain, "X509 chain %p freed\n", chain );
1583
+
1584
+	/* Free each link in the chain */
1585
+	list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
1586
+		x509_put ( link->cert );
1587
+		list_del ( &link->list );
1588
+		free ( link );
1589
+	}
1590
+
1591
+	/* Free chain */
1592
+	free ( chain );
1593
+}
1594
+
1595
+/**
1596
+ * Allocate X.509 certificate chain
1597
+ *
1598
+ * @ret chain		X.509 certificate chain, or NULL
1599
+ */
1600
+struct x509_chain * x509_alloc_chain ( void ) {
1601
+	struct x509_chain *chain;
1602
+
1603
+	/* Allocate chain */
1604
+	chain = zalloc ( sizeof ( *chain ) );
1605
+	if ( ! chain )
1606
+		return NULL;
1607
+
1608
+	/* Initialise chain */
1609
+	ref_init ( &chain->refcnt, x509_free_chain );
1610
+	INIT_LIST_HEAD ( &chain->links );
1611
+
1612
+	DBGC ( chain, "X509 chain %p allocated\n", chain );
1613
+	return chain;
1614
+}
1615
+
1616
+/**
1617
+ * Append X.509 certificate to X.509 certificate chain
1618
+ *
1619
+ * @v chain		X.509 certificate chain
1620
+ * @v cert		X.509 certificate
1621
+ * @ret rc		Return status code
1622
+ */
1623
+int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
1624
+	struct x509_link *link;
1625
+
1626
+	/* Allocate link */
1627
+	link = zalloc ( sizeof ( *link ) );
1628
+	if ( ! link )
1629
+		return -ENOMEM;
1630
+
1631
+	/* Add link to chain */
1632
+	link->cert = x509_get ( cert );
1633
+	list_add_tail ( &link->list, &chain->links );
1634
+	DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
1635
+	       chain, cert, cert->subject.name );
1636
+
1637
+	return 0;
1638
+}
1639
+
1640
+/**
1641
+ * Validate X.509 certificate chain
1642
+ *
1643
+ * @v chain		X.509 certificate chain
1644
+ * @v time		Time at which to validate certificates
1645
+ * @v root		Root certificate store, or NULL to use default
1646
+ * @ret rc		Return status code
1647
+ */
1648
+int x509_validate_chain ( struct x509_chain *chain, time_t time,
1649
+			  struct x509_root *root ) {
1650
+	struct x509_certificate *issuer = NULL;
1651
+	struct x509_link *link;
1652
+	int rc;
1429 1653
 
1430
-		/* Validate path length constraint */
1431
-		if ( path_len > next->extensions.basic.path_len ) {
1432
-			DBGC ( context, "X509 chain %p path length %d exceeds "
1433
-			       "maximum %d\n", context, path_len,
1434
-			       next->extensions.basic.path_len );
1435
-			return -EACCES_PATH_LEN;
1654
+	/* Sanity check */
1655
+	if ( list_empty ( &chain->links ) ) {
1656
+		DBGC ( chain, "X509 chain %p is empty\n", chain );
1657
+		return -EACCES_EMPTY;
1658
+	}
1659
+
1660
+	/* Find first certificate that can be validated as a
1661
+	 * standalone (i.e.  is already valid, or can be validated as
1662
+	 * a trusted root certificate).
1663
+	 */
1664
+	list_for_each_entry ( link, &chain->links, list ) {
1665
+
1666
+		/* Try validating this certificate as a standalone */
1667
+		if ( ( rc = x509_validate ( link->cert, NULL, time,
1668
+					    root ) ) != 0 )
1669
+			continue;
1670
+
1671
+		/* Work back up to start of chain, performing pairwise
1672
+		 * validation.
1673
+		 */
1674
+		issuer = link->cert;
1675
+		list_for_each_entry_continue_reverse ( link, &chain->links,
1676
+						       list ) {
1677
+
1678
+			/* Validate this certificate against its issuer */
1679
+			if ( ( rc = x509_validate ( link->cert, issuer, time,
1680
+						    root ) ) != 0 )
1681
+				return rc;
1682
+			issuer = link->cert;
1436 1683
 		}
1437
-		path_len++;
1438 1684
 
1439
-		/* Move to next certificate in chain */
1440
-		swap = current;
1441
-		current = next;
1442
-		next = swap;
1685
+		return 0;
1443 1686
 	}
1687
+
1688
+	DBGC ( chain, "X509 chain %p found no valid certificates\n", chain );
1689
+	return -EACCES_UNTRUSTED;
1444 1690
 }

+ 39
- 14
src/include/ipxe/cms.h Ver fichero

@@ -13,37 +13,62 @@ FILE_LICENCE ( GPL2_OR_LATER );
13 13
 #include <ipxe/asn1.h>
14 14
 #include <ipxe/crypto.h>
15 15
 #include <ipxe/x509.h>
16
+#include <ipxe/refcnt.h>
16 17
 #include <ipxe/uaccess.h>
17 18
 
18 19
 /** CMS signer information */
19 20
 struct cms_signer_info {
20
-	/** Issuer name */
21
-	struct asn1_cursor issuer;
22
-	/** Serial number */
23
-	struct asn1_cursor serial;
21
+	/** List of signer information blocks */
22
+	struct list_head list;
23
+
24
+	/** Certificate chain */
25
+	struct x509_chain *chain;
26
+
24 27
 	/** Digest algorithm */
25 28
 	struct digest_algorithm *digest;
26 29
 	/** Public-key algorithm */
27 30
 	struct pubkey_algorithm *pubkey;
31
+
28 32
 	/** Signature */
29
-	const void *signature;
33
+	void *signature;
30 34
 	/** Length of signature */
31 35
 	size_t signature_len;
32 36
 };
33 37
 
34 38
 /** A CMS signature */
35 39
 struct cms_signature {
36
-	/** Raw certificate list */
37
-	struct asn1_cursor certificates;
38
-	/** Signer information
39
-	 *
40
-	 * We currently use only the first signer information block.
41
-	 */
42
-	struct cms_signer_info info;
40
+	/** Reference count */
41
+	struct refcnt refcnt;
42
+	/** List of all certificates */
43
+	struct x509_chain *certificates;
44
+	/** List of signer information blocks */
45
+	struct list_head info;
43 46
 };
44 47
 
45
-extern int cms_parse ( struct cms_signature *sig, const void *data,
46
-		       size_t len );
48
+/**
49
+ * Get reference to CMS signature
50
+ *
51
+ * @v sig		CMS signature
52
+ * @ret sig		CMS signature
53
+ */
54
+static inline __attribute__ (( always_inline )) struct cms_signature *
55
+cms_get ( struct cms_signature *sig ) {
56
+	ref_get ( &sig->refcnt );
57
+	return sig;
58
+}
59
+
60
+/**
61
+ * Drop reference to CMS signature
62
+ *
63
+ * @v sig		CMS signature
64
+ */
65
+static inline __attribute__ (( always_inline )) void
66
+cms_put ( struct cms_signature *sig ) {
67
+	ref_put ( &sig->refcnt );
68
+}
69
+
70
+extern int cms_signature ( const void *data, size_t len,
71
+			   struct cms_signature **sig );
47 72
 extern int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
48 73
 			const char *name, time_t time, struct x509_root *root );
49 74
 

+ 3
- 0
src/include/ipxe/tls.h Ver fichero

@@ -235,6 +235,9 @@ struct tls_session {
235 235
 	/** Public-key algorithm used for Certificate Verify (if sent) */
236 236
 	struct pubkey_algorithm *verify_pubkey;
237 237
 
238
+	/** Server certificate chain */
239
+	struct x509_chain *chain;
240
+
238 241
 	/** TX sequence number */
239 242
 	uint64_t tx_seq;
240 243
 	/** TX pending transmissions */

+ 132
- 24
src/include/ipxe/x509.h Ver fichero

@@ -13,6 +13,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
13 13
 #include <stddef.h>
14 14
 #include <time.h>
15 15
 #include <ipxe/asn1.h>
16
+#include <ipxe/refcnt.h>
17
+#include <ipxe/list.h>
16 18
 
17 19
 /** An X.509 bit string */
18 20
 struct x509_bit_string {
@@ -50,14 +52,6 @@ struct x509_validity {
50 52
 	struct x509_time not_after;
51 53
 };
52 54
 
53
-/** An X.509 string */
54
-struct x509_string {
55
-	/** String (not NUL-terminated) */
56
-	const void *data;
57
-	/** Length of name */
58
-	size_t len;
59
-};
60
-
61 55
 /** An X.509 certificate public key */
62 56
 struct x509_public_key {
63 57
 	/** Raw public key */
@@ -71,7 +65,7 @@ struct x509_subject {
71 65
 	/** Raw subject */
72 66
 	struct asn1_cursor raw;
73 67
 	/** Common name */
74
-	struct x509_string name;
68
+	char *name;
75 69
 	/** Public key information */
76 70
 	struct x509_public_key public_key;
77 71
 };
@@ -92,6 +86,13 @@ struct x509_basic_constraints {
92 86
 	unsigned int path_len;
93 87
 };
94 88
 
89
+/** Unlimited path length
90
+ *
91
+ * We use -2U, since this quantity represents one *fewer* than the
92
+ * maximum number of remaining certificates in a chain.
93
+ */
94
+#define X509_PATH_LEN_UNLIMITED -2U
95
+
95 96
 /** An X.509 certificate key usage */
96 97
 struct x509_key_usage {
97 98
 	/** Key usage extension is present */
@@ -131,7 +132,7 @@ enum x509_extended_key_usage_bits {
131 132
 /** X.509 certificate OCSP responder */
132 133
 struct x509_ocsp_responder {
133 134
 	/** URI */
134
-	struct x509_string uri;
135
+	char *uri;
135 136
 };
136 137
 
137 138
 /** X.509 certificate authority information access */
@@ -154,6 +155,16 @@ struct x509_extensions {
154 155
 
155 156
 /** An X.509 certificate */
156 157
 struct x509_certificate {
158
+	/** Reference count */
159
+	struct refcnt refcnt;
160
+	/** List of certificates in cache */
161
+	struct list_head list;
162
+
163
+	/** Certificate has been validated */
164
+	int valid;
165
+	/** Maximum number of subsequent certificates in chain */
166
+	unsigned int path_remaining;
167
+
157 168
 	/** Raw certificate */
158 169
 	struct asn1_cursor raw;
159 170
 	/** Version */
@@ -176,6 +187,80 @@ struct x509_certificate {
176 187
 	struct x509_extensions extensions;
177 188
 };
178 189
 
190
+/**
191
+ * Get reference to X.509 certificate
192
+ *
193
+ * @v cert		X.509 certificate
194
+ * @ret cert		X.509 certificate
195
+ */
196
+static inline __attribute__ (( always_inline )) struct x509_certificate *
197
+x509_get ( struct x509_certificate *cert ) {
198
+	ref_get ( &cert->refcnt );
199
+	return cert;
200
+}
201
+
202
+/**
203
+ * Drop reference to X.509 certificate
204
+ *
205
+ * @v cert		X.509 certificate
206
+ */
207
+static inline __attribute__ (( always_inline )) void
208
+x509_put ( struct x509_certificate *cert ) {
209
+	ref_put ( &cert->refcnt );
210
+}
211
+
212
+/** A link in an X.509 certificate chain */
213
+struct x509_link {
214
+	/** List of links */
215
+	struct list_head list;
216
+	/** Certificate */
217
+	struct x509_certificate *cert;
218
+};
219
+
220
+/** An X.509 certificate chain */
221
+struct x509_chain {
222
+	/** Reference count */
223
+	struct refcnt refcnt;
224
+	/** List of links */
225
+	struct list_head links;
226
+};
227
+
228
+/**
229
+ * Get reference to X.509 certificate chain
230
+ *
231
+ * @v chain		X.509 certificate chain
232
+ * @ret chain		X.509 certificate chain
233
+ */
234
+static inline __attribute__ (( always_inline )) struct x509_chain *
235
+x509_chain_get ( struct x509_chain *chain ) {
236
+	ref_get ( &chain->refcnt );
237
+	return chain;
238
+}
239
+
240
+/**
241
+ * Drop reference to X.509 certificate chain
242
+ *
243
+ * @v chain		X.509 certificate chain
244
+ */
245
+static inline __attribute__ (( always_inline )) void
246
+x509_chain_put ( struct x509_chain *chain ) {
247
+	ref_put ( &chain->refcnt );
248
+}
249
+
250
+/**
251
+ * Get first certificate in X.509 certificate chain
252
+ *
253
+ * @v chain		X.509 certificate chain
254
+ * @ret cert		X.509 certificate, or NULL
255
+ */
256
+static inline __attribute__ (( always_inline )) struct x509_certificate *
257
+x509_first ( struct x509_chain *chain ) {
258
+	struct x509_link *link;
259
+
260
+	link = list_first_entry ( &chain->links, struct x509_link, list );
261
+	return ( link ? link->cert : NULL );
262
+}
263
+
179 264
 /** An X.509 extension */
180 265
 struct x509_extension {
181 266
 	/** Name */
@@ -228,22 +313,45 @@ struct x509_root {
228 313
 	const void *fingerprints;
229 314
 };
230 315
 
231
-extern int x509_parse ( struct x509_certificate *cert,
232
-			const void *data, size_t len );
233
-extern int x509_validate_issuer ( struct x509_certificate *cert,
234
-				  struct x509_certificate *issuer );
316
+extern int x509_certificate ( const void *data, size_t len,
317
+			      struct x509_certificate **cert );
318
+
319
+extern struct x509_chain * x509_alloc_chain ( void );
320
+extern int x509_append ( struct x509_chain *chain,
321
+			 struct x509_certificate *cert );
322
+extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
323
+				 struct x509_root *root );
324
+
325
+/* Functions exposed only for unit testing */
326
+extern int x509_check_issuer ( struct x509_certificate *cert,
327
+			       struct x509_certificate *issuer );
235 328
 extern void x509_fingerprint ( struct x509_certificate *cert,
236 329
 			       struct digest_algorithm *digest,
237 330
 			       void *fingerprint );
238
-extern int x509_validate_root ( struct x509_certificate *cert,
239
-				struct x509_root *root );
240
-extern int x509_validate_time ( struct x509_certificate *cert, time_t time );
241
-extern int x509_validate_chain ( int ( * parse_next )
242
-				 ( struct x509_certificate *cert,
243
-				   const struct x509_certificate *previous,
244
-				   void *context ),
245
-				 void *context, time_t time,
246
-				 struct x509_root *root,
247
-				 struct x509_certificate *first );
331
+extern int x509_check_root ( struct x509_certificate *cert,
332
+			     struct x509_root *root );
333
+extern int x509_check_time ( struct x509_certificate *cert, time_t time );
334
+
335
+/**
336
+ * Invalidate X.509 certificate
337
+ *
338
+ * @v cert		X.509 certificate
339
+ */
340
+static inline void x509_invalidate ( struct x509_certificate *cert ) {
341
+	cert->valid = 0;
342
+	cert->path_remaining = 0;
343
+}
344
+
345
+/**
346
+ * Invalidate X.509 certificate chain
347
+ *
348
+ * @v chain		X.509 certificate chain
349
+ */
350
+static inline void x509_invalidate_chain ( struct x509_chain *chain ) {
351
+	struct x509_link *link;
352
+
353
+	list_for_each_entry ( link, &chain->links, list )
354
+		x509_invalidate ( link->cert );
355
+}
248 356
 
249 357
 #endif /* _IPXE_X509_H */

+ 94
- 67
src/net/tls.c Ver fichero

@@ -46,10 +46,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
46 46
 #include <ipxe/tls.h>
47 47
 
48 48
 /* Disambiguate the various error causes */
49
-#define EACCES_INCOMPLETE \
50
-	__einfo_error ( EINFO_EACCES_INCOMPLETE )
51
-#define EINFO_EACCES_INCOMPLETE \
52
-	__einfo_uniqify ( EINFO_EACCES, 0x01, "Incomplete certificate chain" )
53 49
 #define EACCES_WRONG_NAME \
54 50
 	__einfo_error ( EINFO_EACCES_WRONG_NAME )
55 51
 #define EINFO_EACCES_WRONG_NAME \
@@ -184,6 +180,7 @@ static void free_tls ( struct refcnt *refcnt ) {
184 180
 	tls_clear_cipher ( tls, &tls->rx_cipherspec );
185 181
 	tls_clear_cipher ( tls, &tls->rx_cipherspec_pending );
186 182
 	free ( tls->rx_data );
183
+	x509_chain_put ( tls->chain );
187 184
 
188 185
 	/* Free TLS structure itself */
189 186
 	free ( tls );	
@@ -899,7 +896,7 @@ static int tls_send_certificate ( struct tls_session *tls ) {
899 896
 			uint8_t data[ client_certificate.len ];
900 897
 		} __attribute__ (( packed )) certificates[num_certificates];
901 898
 	} __attribute__ (( packed )) *certificate;
902
-	struct x509_certificate cert;
899
+	struct x509_certificate *cert;
903 900
 	int rc;
904 901
 
905 902
 	/* If we have a certificate to send, determine the applicable
@@ -909,13 +906,16 @@ static int tls_send_certificate ( struct tls_session *tls ) {
909 906
 	if ( num_certificates ) {
910 907
 
911 908
 		/* Parse certificate to determine public-key algorithm */
912
-		if ( ( rc = x509_parse ( &cert, client_certificate.data,
913
-					 client_certificate.len ) ) != 0 ) {
909
+		if ( ( rc = x509_certificate ( client_certificate.data,
910
+					       client_certificate.len,
911
+					       &cert ) ) != 0 ) {
914 912
 			DBGC ( tls, "TLS %p could not parse client "
915 913
 			       "certificate: %s\n", tls, strerror ( rc ) );
916 914
 			return rc;
917 915
 		}
918
-		tls->verify_pubkey = cert.signature_algorithm->pubkey;
916
+		tls->verify_pubkey = cert->signature_algorithm->pubkey;
917
+		x509_put ( cert );
918
+		cert = NULL;
919 919
 
920 920
 		/* Schedule CertificateVerify transmission */
921 921
 		tls->tx_pending |= TLS_TX_CERTIFICATE_VERIFY;
@@ -1267,64 +1267,88 @@ static int tls_new_server_hello ( struct tls_session *tls,
1267 1267
 	return 0;
1268 1268
 }
1269 1269
 
1270
-/** TLS certificate chain context */
1271
-struct tls_certificate_context {
1272
-	/** TLS session */
1273
-	struct tls_session *tls;
1274
-	/** Current certificate */
1275
-	const void *current;
1276
-	/** End of certificates */
1277
-	const void *end;
1278
-};
1279
-
1280 1270
 /**
1281
- * Parse next certificate in TLS certificate list
1271
+ * Parse certificate chain
1282 1272
  *
1283
- * @v cert		X.509 certificate to fill in
1284
- * @v previous		Previous X.509 certificate, or NULL
1285
- * @v ctx		Context
1273
+ * @v tls		TLS session
1274
+ * @v data		Certificate chain
1275
+ * @v len		Length of certificate chain
1286 1276
  * @ret rc		Return status code
1287 1277
  */
1288
-static int tls_parse_next ( struct x509_certificate *cert,
1289
-			    const struct x509_certificate *previous __unused,
1290
-			    void *ctx ) {
1291
-	struct tls_certificate_context *context = ctx;
1292
-	struct tls_session *tls = context->tls;
1278
+static int tls_parse_chain ( struct tls_session *tls,
1279
+			     const void *data, size_t len ) {
1280
+	const void *end = ( data + len );
1293 1281
 	const struct {
1294 1282
 		uint8_t length[3];
1295
-		uint8_t certificate[0];
1296
-	} __attribute__ (( packed )) *current = context->current;
1297
-	const void *data;
1283
+		uint8_t data[0];
1284
+	} __attribute__ (( packed )) *certificate;
1285
+	size_t certificate_len;
1286
+	struct x509_certificate *cert;
1298 1287
 	const void *next;
1299
-	size_t len;
1300 1288
 	int rc;
1301 1289
 
1302
-	/* Return error at end of chain */
1303
-	if ( context->current >= context->end ) {
1304
-		DBGC ( tls, "TLS %p reached end of certificate chain\n", tls );
1305
-		return -EACCES_INCOMPLETE;
1306
-	}
1290
+	/* Free any existing certificate chain */
1291
+	x509_chain_put ( tls->chain );
1292
+	tls->chain = NULL;
1307 1293
 
1308
-	/* Extract current certificate and update context */
1309
-	data = current->certificate;
1310
-	len = tls_uint24 ( current->length );
1311
-	next = ( data + len );
1312
-	if ( next > context->end ) {
1313
-		DBGC ( tls, "TLS %p overlength certificate\n", tls );
1314
-		DBGC_HDA ( tls, 0, context->current,
1315
-			   ( context->end - context->current ) );
1316
-		return -EINVAL;
1294
+	/* Create certificate chain */
1295
+	tls->chain = x509_alloc_chain();
1296
+	if ( ! tls->chain ) {
1297
+		rc = -ENOMEM;
1298
+		goto err_alloc_chain;
1317 1299
 	}
1318
-	context->current = next;
1319 1300
 
1320
-	/* Parse current certificate */
1321
-	if ( ( rc = x509_parse ( cert, data, len ) ) != 0 ) {
1322
-		DBGC ( tls, "TLS %p could not parse certificate: %s\n",
1323
-		       tls, strerror ( rc ) );
1324
-		return rc;
1301
+	/* Add certificates to chain */
1302
+	while ( data < end ) {
1303
+
1304
+		/* Extract raw certificate data */
1305
+		certificate = data;
1306
+		certificate_len = tls_uint24 ( certificate->length );
1307
+		next = ( certificate->data + certificate_len );
1308
+		if ( next > end ) {
1309
+			DBGC ( tls, "TLS %p overlength certificate:\n", tls );
1310
+			DBGC_HDA ( tls, 0, data, ( end - data ) );
1311
+			rc = -EINVAL;
1312
+			goto err_overlength;
1313
+		}
1314
+
1315
+		/* Parse certificate */
1316
+		if ( ( rc = x509_certificate ( certificate->data,
1317
+					       certificate_len,
1318
+					       &cert ) ) != 0 ) {
1319
+			DBGC ( tls, "TLS %p could not parse certificate: %s\n",
1320
+			       tls, strerror ( rc ) );
1321
+			DBGC_HDA ( tls, 0, data, ( end - data ) );
1322
+			goto err_parse;
1323
+		}
1324
+		DBGC ( tls, "TLS %p found certificate %s\n",
1325
+		       tls, cert->subject.name );
1326
+
1327
+		/* Append certificate to chain */
1328
+		if ( ( rc = x509_append ( tls->chain, cert ) ) != 0 ) {
1329
+			DBGC ( tls, "TLS %p could not append certificate: %s\n",
1330
+			       tls, strerror ( rc ) );
1331
+			goto err_append;
1332
+		}
1333
+
1334
+		/* Drop reference to certificate */
1335
+		x509_put ( cert );
1336
+		cert = NULL;
1337
+
1338
+		/* Move to next certificate in list */
1339
+		data = next;
1325 1340
 	}
1326 1341
 
1327 1342
 	return 0;
1343
+
1344
+ err_append:
1345
+	x509_put ( cert );
1346
+ err_parse:
1347
+ err_overlength:
1348
+	x509_chain_put ( tls->chain );
1349
+	tls->chain = NULL;
1350
+ err_alloc_chain:
1351
+	return rc;
1328 1352
 }
1329 1353
 
1330 1354
 /**
@@ -1341,14 +1365,11 @@ static int tls_new_certificate ( struct tls_session *tls,
1341 1365
 		uint8_t length[3];
1342 1366
 		uint8_t certificates[0];
1343 1367
 	} __attribute__ (( packed )) *certificate = data;
1344
-	size_t elements_len = tls_uint24 ( certificate->length );
1345
-	const void *end = ( certificate->certificates + elements_len );
1368
+	size_t certificates_len = tls_uint24 ( certificate->length );
1369
+	const void *end = ( certificate->certificates + certificates_len );
1346 1370
 	struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
1347 1371
 	struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
1348
-	struct tls_certificate_context context;
1349
-	struct x509_certificate cert;
1350
-	struct x509_string *name = &cert.subject.name;
1351
-	struct x509_public_key *key = &cert.subject.public_key;
1372
+	struct x509_certificate *cert;
1352 1373
 	time_t now;
1353 1374
 	int rc;
1354 1375
 
@@ -1360,28 +1381,34 @@ static int tls_new_certificate ( struct tls_session *tls,
1360 1381
 		return -EINVAL;
1361 1382
 	}
1362 1383
 
1363
-	/* Parse first certificate and validate certificate chain */
1364
-	context.tls = tls;
1365
-	context.current = certificate->certificates;
1366
-	context.end = end;
1384
+	/* Parse certificate chain */
1385
+	if ( ( rc = tls_parse_chain ( tls, certificate->certificates,
1386
+				      certificates_len ) ) != 0 )
1387
+		return rc;
1388
+
1389
+	/* Validate certificate chain */
1367 1390
 	now = time ( NULL );
1368
-	if ( ( rc = x509_validate_chain ( tls_parse_next, &context,
1369
-					  now, NULL, &cert ) ) != 0 ) {
1391
+	if ( ( rc = x509_validate_chain ( tls->chain, now, NULL ) ) != 0 ) {
1370 1392
 		DBGC ( tls, "TLS %p could not validate certificate chain: %s\n",
1371 1393
 		       tls, strerror ( rc ) );
1372 1394
 		return rc;
1373 1395
 	}
1374 1396
 
1397
+	/* Extract first certificate */
1398
+	cert = x509_first ( tls->chain );
1399
+	assert ( cert != NULL );
1400
+
1375 1401
 	/* Verify server name */
1376
-	if ( ( name->len != strlen ( tls->name ) ) ||
1377
-	     ( memcmp ( name->data, tls->name, name->len ) != 0 ) ) {
1378
-		DBGC ( tls, "TLS %p server name incorrect\n", tls );
1402
+	if ( strcmp ( tls->name, cert->subject.name ) != 0 ) {
1403
+		DBGC ( tls, "TLS %p server name incorrect (expected %s, got "
1404
+		       "%s)\n", tls, tls->name, cert->subject.name );
1379 1405
 		return -EACCES_WRONG_NAME;
1380 1406
 	}
1381 1407
 
1382 1408
 	/* Initialise public key algorithm */
1383 1409
 	if ( ( rc = pubkey_init ( pubkey, cipherspec->pubkey_ctx,
1384
-				  key->raw.data, key->raw.len ) ) != 0 ) {
1410
+				  cert->subject.public_key.raw.data,
1411
+				  cert->subject.public_key.raw.len ) ) != 0 ) {
1385 1412
 		DBGC ( tls, "TLS %p cannot initialise public key: %s\n",
1386 1413
 		       tls, strerror ( rc ) );
1387 1414
 		return rc;

+ 25
- 18
src/tests/cms_test.c Ver fichero

@@ -52,6 +52,9 @@ struct cms_test_signature {
52 52
 	const void *data;
53 53
 	/** Length of data */
54 54
 	size_t len;
55
+
56
+	/** Parsed signature */
57
+	struct cms_signature *sig;
55 58
 };
56 59
 
57 60
 /** Define inline data */
@@ -1331,42 +1334,40 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug  3 23:38:31 2013 */
1331 1334
 /**
1332 1335
  * Report signature parsing test result
1333 1336
  *
1334
- * @v sig		Test signature
1337
+ * @v sgn		Test signature
1335 1338
  */
1336
-#define cms_parse_ok( sig ) do {					\
1337
-	struct cms_signature temp;					\
1338
-	ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 );	\
1339
+#define cms_signature_ok( sgn ) do {					\
1340
+	ok ( cms_signature ( (sgn)->data, (sgn)->len,			\
1341
+			     &(sgn)->sig ) == 0 );			\
1339 1342
 	} while ( 0 )
1340 1343
 
1341 1344
 /**
1342 1345
  * Report signature verification test result
1343 1346
  *
1344
- * @v sig		Test signature
1347
+ * @v sgn		Test signature
1345 1348
  * @v code		Test signed code
1346 1349
  * @v name		Test verification name
1347 1350
  * @v time		Test verification time
1348 1351
  * @v root		Test root certificate store
1349 1352
  */
1350
-#define cms_verify_ok( sig, code, name, time, root ) do {		\
1351
-	struct cms_signature temp;					\
1352
-	ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 );	\
1353
-	ok ( cms_verify ( &temp, virt_to_user ( (code)->data ),		\
1353
+#define cms_verify_ok( sgn, code, name, time, root ) do {		\
1354
+	x509_invalidate_chain ( (sgn)->sig->certificates );		\
1355
+	ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ),	\
1354 1356
 			  (code)->len, name, time, root ) == 0 );	\
1355 1357
 	} while ( 0 )
1356 1358
 
1357 1359
 /**
1358 1360
  * Report signature verification failure test result
1359 1361
  *
1360
- * @v sig		Test signature
1362
+ * @v sgn		Test signature
1361 1363
  * @v code		Test signed code
1362 1364
  * @v name		Test verification name
1363 1365
  * @v time		Test verification time
1364 1366
  * @v root		Test root certificate store
1365 1367
  */
1366
-#define cms_verify_fail_ok( sig, code, name, time, root ) do {		\
1367
-	struct cms_signature temp;					\
1368
-	ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 );	\
1369
-	ok ( cms_verify ( &temp, virt_to_user ( (code)->data ),		\
1368
+#define cms_verify_fail_ok( sgn, code, name, time, root ) do {		\
1369
+	x509_invalidate_chain ( (sgn)->sig->certificates );		\
1370
+	ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ),	\
1370 1371
 			  (code)->len, name, time, root ) != 0 );	\
1371 1372
 	} while ( 0 )
1372 1373
 
@@ -1377,10 +1378,10 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug  3 23:38:31 2013 */
1377 1378
 static void cms_test_exec ( void ) {
1378 1379
 
1379 1380
 	/* Check that all signatures can be parsed */
1380
-	cms_parse_ok ( &codesigned_sig );
1381
-	cms_parse_ok ( &brokenchain_sig );
1382
-	cms_parse_ok ( &genericsigned_sig );
1383
-	cms_parse_ok ( &nonsigned_sig );
1381
+	cms_signature_ok ( &codesigned_sig );
1382
+	cms_signature_ok ( &brokenchain_sig );
1383
+	cms_signature_ok ( &genericsigned_sig );
1384
+	cms_signature_ok ( &nonsigned_sig );
1384 1385
 
1385 1386
 	/* Check good signature */
1386 1387
 	cms_verify_ok ( &codesigned_sig, &test_code,
@@ -1415,6 +1416,12 @@ static void cms_test_exec ( void ) {
1415 1416
 	/* Check expired signature */
1416 1417
 	cms_verify_fail_ok ( &codesigned_sig, &test_code,
1417 1418
 			     NULL, test_expired, &test_root );
1419
+
1420
+	/* Drop signature references */
1421
+	cms_put ( nonsigned_sig.sig );
1422
+	cms_put ( genericsigned_sig.sig );
1423
+	cms_put ( brokenchain_sig.sig );
1424
+	cms_put ( codesigned_sig.sig );
1418 1425
 }
1419 1426
 
1420 1427
 /** CMS self-test */

+ 134
- 109
src/tests/x509_test.c Ver fichero

@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
31 31
 #include <string.h>
32 32
 #include <errno.h>
33 33
 #include <ipxe/x509.h>
34
+#include <ipxe/asn1.h>
34 35
 #include <ipxe/sha256.h>
35 36
 #include <ipxe/test.h>
36 37
 
@@ -45,6 +46,9 @@ struct x509_test_certificate {
45 46
 	size_t len;
46 47
 	/** Fingerprint */
47 48
 	const void *fingerprint;
49
+
50
+	/** Parsed certificate */
51
+	struct x509_certificate *cert;
48 52
 };
49 53
 
50 54
 /** An X.509 test certificate chain */
@@ -53,6 +57,9 @@ struct x509_test_chain {
53 57
 	struct x509_test_certificate **certs;
54 58
 	/** Number of certificates */
55 59
 	unsigned int count;
60
+
61
+	/** Parsed certificate chain */
62
+	struct x509_chain *chain;
56 63
 };
57 64
 
58 65
 /** Define inline certificate data */
@@ -683,172 +690,147 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug  3 23:38:31 2013 */
683 690
 /** Time at which CA test certificates are invalid */
684 691
 static time_t test_ca_expired = 2205014905ULL; /* Wed Nov 16 00:08:25 2039 */
685 692
 
686
-/** An X.509 test certificate chain context */
687
-struct x509_test_chain_context {
688
-	/** Test certificate chain */
689
-	struct x509_test_chain *chain;
690
-	/** Index within chain */
691
-	unsigned int index;
692
-};
693
-
694 693
 /**
695
- * Parse next certificate in chain
694
+ * Report certificate parsing test result
696 695
  *
697
- * @v cert		X.509 certificate to parse
698
- * @v previous		Previous X.509 certificate, or NULL
699
- * @v ctx		Chain context
700
- * @ret rc		Return status code
696
+ * @v crt		Test certificate
701 697
  */
702
-static int
703
-x509_test_parse_next ( struct x509_certificate *cert,
704
-		       const struct x509_certificate *previous __unused,
705
-		       void *ctx ) {
706
-	struct x509_test_chain_context *context = ctx;
707
-	struct x509_test_certificate *test_cert;
708
-
709
-	/* Return error at end of chain */
710
-	if ( context->index >= context->chain->count )
711
-		return -ENOENT;
712
-
713
-	/* Get next test certificate */
714
-	test_cert = context->chain->certs[ context->index++ ];
715
-
716
-	/* Parse certificate */
717
-	return x509_parse ( cert, test_cert->data, test_cert->len );
718
-}
698
+#define x509_certificate_ok( crt ) do {					\
699
+	ok ( x509_certificate ( (crt)->data, (crt)->len,		\
700
+				&(crt)->cert ) == 0 );			\
701
+	} while ( 0 )
719 702
 
720 703
 /**
721
- * Report certificate parsing test result
704
+ * Report cached certificate parsing test result
722 705
  *
723
- * @v cert		Test certificate
706
+ * @v crt		Test certificate
724 707
  */
725
-#define x509_parse_ok( cert ) do {					\
726
-	struct x509_certificate temp;					\
727
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
708
+#define x509_cached_ok( crt ) do {					\
709
+	struct x509_certificate *temp;					\
710
+	ok ( x509_certificate ( (crt)->data, (crt)->len,		\
711
+				&temp ) == 0 );				\
712
+	ok ( temp == (crt)->cert );					\
713
+	x509_put ( temp );						\
728 714
 	} while ( 0 )
729 715
 
730 716
 /**
731 717
  * Report certificate fingerprint test result
732 718
  *
733
- * @v cert		Test certificate
719
+ * @v crt		Test certificate
734 720
  */
735
-#define x509_fingerprint_ok( cert ) do {				\
736
-	struct x509_certificate temp;					\
721
+#define x509_fingerprint_ok( crt ) do {					\
737 722
 	uint8_t fingerprint[ x509_test_algorithm.digestsize ];		\
738
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
739
-	x509_fingerprint ( &temp, &x509_test_algorithm, fingerprint );	\
740
-	ok ( memcmp ( fingerprint, (cert)->fingerprint,			\
723
+	x509_fingerprint ( (crt)->cert, &x509_test_algorithm,		\
724
+			   fingerprint );				\
725
+	ok ( memcmp ( fingerprint, (crt)->fingerprint,			\
741 726
 		      sizeof ( fingerprint ) ) == 0 );			\
742 727
 	} while ( 0 )
743 728
 
744 729
 /**
745 730
  * Report certificate issuer validation test result
746 731
  *
747
- * @v cert		Test certificate
732
+ * @v crt		Test certificate
748 733
  * @v issuer		Test issuer
749 734
  */
750
-#define x509_validate_issuer_ok( cert, issuer ) do {			\
751
-	struct x509_certificate cert_temp;				\
752
-	struct x509_certificate issuer_temp;				\
753
-	ok ( x509_parse ( &cert_temp, (cert)->data,			\
754
-			  (cert)->len ) == 0 );				\
755
-	ok ( x509_parse ( &issuer_temp, (issuer)->data,			\
756
-			  (issuer)->len ) == 0 );			\
757
-	ok ( x509_validate_issuer ( &cert_temp, &issuer_temp ) == 0 );	\
735
+#define x509_check_issuer_ok( crt, issuer ) do {			\
736
+	ok ( x509_check_issuer ( (crt)->cert, (issuer)->cert ) == 0 );	\
758 737
 	} while ( 0 )
759 738
 
760 739
 /**
761 740
  * Report certificate issuer validation failure test result
762 741
  *
763
- * @v cert		Test certificate
742
+ * @v crt		Test certificate
764 743
  * @v issuer		Test issuer
765 744
  */
766
-#define x509_validate_issuer_fail_ok( cert, issuer ) do {		\
767
-	struct x509_certificate cert_temp;				\
768
-	struct x509_certificate issuer_temp;				\
769
-	ok ( x509_parse ( &cert_temp, (cert)->data,			\
770
-			  (cert)->len ) == 0 );				\
771
-	ok ( x509_parse ( &issuer_temp, (issuer)->data,			\
772
-			  (issuer)->len ) == 0 );			\
773
-	ok ( x509_validate_issuer ( &cert_temp, &issuer_temp ) != 0 );	\
745
+#define x509_check_issuer_fail_ok( crt, issuer ) do {			\
746
+	ok ( x509_check_issuer ( (crt)->cert, (issuer)->cert ) != 0 );	\
774 747
 	} while ( 0 )
775 748
 
776 749
 /**
777 750
  * Report certificate root validation test result
778 751
  *
779
- * @v cert		Test certificate
752
+ * @v crt		Test certificate
780 753
  * @v root		Test root certificate store
781 754
  */
782
-#define x509_validate_root_ok( cert, root ) do {			\
783
-	struct x509_certificate temp;					\
784
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
785
-	ok ( x509_validate_root ( &temp, root ) == 0 );			\
755
+#define x509_check_root_ok( crt, root ) do {				\
756
+	ok ( x509_check_root ( (crt)->cert, root ) == 0 );		\
786 757
 	} while ( 0 )
787 758
 
788 759
 /**
789 760
  * Report certificate root validation failure test result
790 761
  *
791
- * @v cert		Test certificate
762
+ * @v crt		Test certificate
792 763
  * @v root		Test root certificate store
793 764
  */
794
-#define x509_validate_root_fail_ok( cert, root ) do {			\
795
-	struct x509_certificate temp;					\
796
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
797
-	ok ( x509_validate_root ( &temp, root ) != 0 );			\
765
+#define x509_check_root_fail_ok( crt, root ) do {			\
766
+	ok ( x509_check_root ( (crt)->cert, root ) != 0 );		\
798 767
 	} while ( 0 )
799 768
 
800 769
 /**
801 770
  * Report certificate time validation test result
802 771
  *
803
- * @v cert		Test certificate
772
+ * @v crt		Test certificate
804 773
  * @v time		Test time
805 774
  */
806
-#define x509_validate_time_ok( cert, time ) do {			\
807
-	struct x509_certificate temp;					\
808
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
809
-	ok ( x509_validate_time ( &temp, time ) == 0 );			\
775
+#define x509_check_time_ok( crt, time ) do {				\
776
+	ok ( x509_check_time ( (crt)->cert, time ) == 0 );		\
810 777
 	} while ( 0 )
811 778
 
812 779
 /**
813 780
  * Report certificate time validation failure test result
814 781
  *
815
- * @v cert		Test certificate
782
+ * @v crt		Test certificate
816 783
  * @v time		Test time
817 784
  */
818
-#define x509_validate_time_fail_ok( cert, time ) do {			\
819
-	struct x509_certificate temp;					\
820
-	ok ( x509_parse ( &temp, (cert)->data, (cert)->len ) == 0 );	\
821
-	ok ( x509_validate_time ( &temp, time ) != 0 );			\
785
+#define x509_check_time_fail_ok( crt, time ) do {			\
786
+	ok ( x509_check_time ( (crt)->cert, time ) != 0 );		\
787
+	} while ( 0 )
788
+
789
+/**
790
+ * Report certificate chain parsing test result
791
+ *
792
+ * @v chn		Test certificate chain
793
+ */
794
+#define x509_chain_ok( chn ) do {					\
795
+	unsigned int i;							\
796
+	struct x509_certificate *first;					\
797
+	(chn)->chain = x509_alloc_chain();				\
798
+	ok ( (chn)->chain != NULL );					\
799
+	for ( i = 0 ; i < (chn)->count ; i++ ) {			\
800
+		ok ( x509_append ( (chn)->chain,			\
801
+				   (chn)->certs[i]->cert ) == 0 );	\
802
+	}								\
803
+	first = x509_first ( (chn)->chain );				\
804
+	ok ( first != NULL );						\
805
+	ok ( first->raw.len == (chn)->certs[0]->len );			\
806
+	ok ( memcmp ( first->raw.data, (chn)->certs[0]->data,		\
807
+		      first->raw.len ) == 0 );				\
822 808
 	} while ( 0 )
823 809
 
824 810
 /**
825 811
  * Report certificate chain validation test result
826 812
  *
827
- * @v chain		Test certificate chain
813
+ * @v chn		Test certificate chain
828 814
  * @v time		Test certificate validation time
829 815
  * @v root		Test root certificate store
830 816
  */
831
-#define x509_validate_chain_ok( chain, time, root ) do {		\
832
-	struct x509_test_chain_context context = { (chain), 0 };	\
833
-	struct x509_certificate temp;					\
834
-	ok ( x509_validate_chain ( x509_test_parse_next, &context,	\
835
-				   (time), (root), &temp ) == 0 );	\
836
-	ok ( temp.raw.data == (chain)->certs[0]->data );		\
837
-	ok ( temp.raw.len == (chain)->certs[0]->len );			\
817
+#define x509_validate_chain_ok( chn, time, root ) do {			\
818
+	x509_invalidate_chain ( (chn)->chain );				\
819
+	ok ( x509_validate_chain ( (chn)->chain, (time),		\
820
+				   (root) ) == 0 );			\
838 821
 	} while ( 0 )
839 822
 
840 823
 /**
841 824
  * Report certificate chain validation failure test result
842 825
  *
843
- * @v chain		Test certificate chain
826
+ * @v chn		Test certificate chain
844 827
  * @v time		Test certificate validation time
845 828
  * @v root		Test root certificate store
846 829
  */
847
-#define x509_validate_chain_fail_ok( chain, time, root ) do {		\
848
-	struct x509_test_chain_context context = { (chain), 0 };	\
849
-	struct x509_certificate temp;					\
850
-	ok ( x509_validate_chain ( x509_test_parse_next, &context,	\
851
-				   (time), (root), &temp ) != 0 );	\
830
+#define x509_validate_chain_fail_ok( chn, time, root ) do {		\
831
+	x509_invalidate_chain ( (chn)->chain );				\
832
+	ok ( x509_validate_chain ( (chn)->chain, (time),		\
833
+				   (root) ) != 0 );			\
852 834
 	} while ( 0 )
853 835
 
854 836
 /**
@@ -857,6 +839,24 @@ x509_test_parse_next ( struct x509_certificate *cert,
857 839
  */
858 840
 static void x509_test_exec ( void ) {
859 841
 
842
+	/* Parse all certificates */
843
+	x509_certificate_ok ( &root_crt );
844
+	x509_certificate_ok ( &intermediate_crt );
845
+	x509_certificate_ok ( &leaf_crt );
846
+	x509_certificate_ok ( &useless_crt );
847
+	x509_certificate_ok ( &server_crt );
848
+	x509_certificate_ok ( &not_ca_crt );
849
+	x509_certificate_ok ( &bad_path_len_crt );
850
+
851
+	/* Check cache functionality */
852
+	x509_cached_ok ( &root_crt );
853
+	x509_cached_ok ( &intermediate_crt );
854
+	x509_cached_ok ( &leaf_crt );
855
+	x509_cached_ok ( &useless_crt );
856
+	x509_cached_ok ( &server_crt );
857
+	x509_cached_ok ( &not_ca_crt );
858
+	x509_cached_ok ( &bad_path_len_crt );
859
+
860 860
 	/* Check all certificate fingerprints */
861 861
 	x509_fingerprint_ok ( &root_crt );
862 862
 	x509_fingerprint_ok ( &intermediate_crt );
@@ -867,26 +867,34 @@ static void x509_test_exec ( void ) {
867 867
 	x509_fingerprint_ok ( &bad_path_len_crt );
868 868
 
869 869
 	/* Check pairwise issuing */
870
-	x509_validate_issuer_ok ( &intermediate_crt, &root_crt );
871
-	x509_validate_issuer_ok ( &leaf_crt, &intermediate_crt );
872
-	x509_validate_issuer_ok ( &useless_crt, &leaf_crt );
873
-	x509_validate_issuer_ok ( &server_crt, &leaf_crt );
874
-	x509_validate_issuer_fail_ok ( &not_ca_crt, &server_crt );
875
-	x509_validate_issuer_ok ( &bad_path_len_crt, &useless_crt );
870
+	x509_check_issuer_ok ( &intermediate_crt, &root_crt );
871
+	x509_check_issuer_ok ( &leaf_crt, &intermediate_crt );
872
+	x509_check_issuer_ok ( &useless_crt, &leaf_crt );
873
+	x509_check_issuer_ok ( &server_crt, &leaf_crt );
874
+	x509_check_issuer_fail_ok ( &not_ca_crt, &server_crt );
875
+	x509_check_issuer_ok ( &bad_path_len_crt, &useless_crt );
876 876
 
877 877
 	/* Check root certificate stores */
878
-	x509_validate_root_ok ( &root_crt, &test_root );
879
-	x509_validate_root_fail_ok ( &intermediate_crt, &test_root );
880
-	x509_validate_root_ok ( &intermediate_crt, &intermediate_root );
881
-	x509_validate_root_fail_ok ( &root_crt, &intermediate_root );
882
-	x509_validate_root_fail_ok ( &root_crt, &dummy_root );
878
+	x509_check_root_ok ( &root_crt, &test_root );
879
+	x509_check_root_fail_ok ( &intermediate_crt, &test_root );
880
+	x509_check_root_ok ( &intermediate_crt, &intermediate_root );
881
+	x509_check_root_fail_ok ( &root_crt, &intermediate_root );
882
+	x509_check_root_fail_ok ( &root_crt, &dummy_root );
883 883
 
884 884
 	/* Check certificate validity periods */
885
-	x509_validate_time_ok ( &server_crt, test_time );
886
-	x509_validate_time_fail_ok ( &server_crt, test_expired );
887
-	x509_validate_time_ok ( &root_crt, test_time );
888
-	x509_validate_time_ok ( &root_crt, test_expired );
889
-	x509_validate_time_fail_ok ( &root_crt, test_ca_expired );
885
+	x509_check_time_ok ( &server_crt, test_time );
886
+	x509_check_time_fail_ok ( &server_crt, test_expired );
887
+	x509_check_time_ok ( &root_crt, test_time );
888
+	x509_check_time_ok ( &root_crt, test_expired );
889
+	x509_check_time_fail_ok ( &root_crt, test_ca_expired );
890
+
891
+	/* Parse all certificate chains */
892
+	x509_chain_ok ( &server_chain );
893
+	x509_chain_ok ( &broken_server_chain );
894
+	x509_chain_ok ( &incomplete_server_chain );
895
+	x509_chain_ok ( &not_ca_chain );
896
+	x509_chain_ok ( &useless_chain );
897
+	x509_chain_ok ( &bad_path_len_chain );
890 898
 
891 899
 	/* Check certificate chains */
892 900
 	x509_validate_chain_ok ( &server_chain, test_time, &test_root );
@@ -908,6 +916,23 @@ static void x509_test_exec ( void ) {
908 916
 	x509_validate_chain_ok ( &useless_chain, test_expired, &test_root );
909 917
 	x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
910 918
 				      &test_root );
919
+
920
+	/* Drop chain references */
921
+	x509_chain_put ( bad_path_len_chain.chain );
922
+	x509_chain_put ( useless_chain.chain );
923
+	x509_chain_put ( not_ca_chain.chain );
924
+	x509_chain_put ( incomplete_server_chain.chain );
925
+	x509_chain_put ( broken_server_chain.chain );
926
+	x509_chain_put ( server_chain.chain );
927
+
928
+	/* Drop certificate references */
929
+	x509_put ( bad_path_len_crt.cert );
930
+	x509_put ( not_ca_crt.cert );
931
+	x509_put ( server_crt.cert );
932
+	x509_put ( useless_crt.cert );
933
+	x509_put ( leaf_crt.cert );
934
+	x509_put ( intermediate_crt.cert );
935
+	x509_put ( root_crt.cert );
911 936
 }
912 937
 
913 938
 /** X.509 self-test */

+ 12
- 6
src/usr/imgtrust.c Ver fichero

@@ -45,7 +45,7 @@ int imgverify ( struct image *image, struct image *signature,
45 45
 		const char *name ) {
46 46
 	size_t len;
47 47
 	void *data;
48
-	struct cms_signature sig;
48
+	struct cms_signature *sig;
49 49
 	time_t now;
50 50
 	int rc;
51 51
 
@@ -62,25 +62,31 @@ int imgverify ( struct image *image, struct image *signature,
62 62
 	copy_from_user ( data, signature->data, 0, len );
63 63
 
64 64
 	/* Parse signature */
65
-	if ( ( rc = cms_parse ( &sig, data, len ) ) != 0 )
65
+	if ( ( rc = cms_signature ( data, len, &sig ) ) != 0 )
66 66
 		goto err_parse;
67 67
 
68
+	/* Free internal copy of signature */
69
+	free ( data );
70
+	data = NULL;
71
+
68 72
 	/* Use signature to verify image */
69 73
 	now = time ( NULL );
70
-	if ( ( rc = cms_verify ( &sig, image->data, image->len,
74
+	if ( ( rc = cms_verify ( sig, image->data, image->len,
71 75
 				 name, now, NULL ) ) != 0 )
72 76
 		goto err_verify;
73 77
 
78
+	/* Drop reference to signature */
79
+	cms_put ( sig );
80
+	sig = NULL;
81
+
74 82
 	/* Mark image as trusted */
75 83
 	image_trust ( image );
76 84
 	syslog ( LOG_NOTICE, "Image \"%s\" signature OK\n", image->name );
77 85
 
78
-	/* Free internal copy of signature */
79
-	free ( data );
80
-
81 86
 	return 0;
82 87
 
83 88
  err_verify:
89
+	cms_put ( sig );
84 90
  err_parse:
85 91
 	free ( data );
86 92
  err_alloc:

Loading…
Cancelar
Guardar