Browse Source

[crypto] Generalise x509_parse_time() to asn1_generalized_time()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
88c09b36cf
3 changed files with 126 additions and 116 deletions
  1. 113
    0
      src/crypto/asn1.c
  2. 10
    116
      src/crypto/x509.c
  3. 3
    0
      src/include/ipxe/asn1.h

+ 113
- 0
src/crypto/asn1.c View File

@@ -21,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
21 21
 #include <stdint.h>
22 22
 #include <stddef.h>
23 23
 #include <string.h>
24
+#include <ctype.h>
24 25
 #include <errno.h>
26
+#include <time.h>
25 27
 #include <ipxe/tables.h>
26 28
 #include <ipxe/asn1.h>
27 29
 
@@ -52,6 +54,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
52 54
 	__einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
53 55
 #define EINFO_EINVAL_ASN1_INTEGER \
54 56
 	__einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
57
+#define EINVAL_ASN1_TIME \
58
+	__einfo_error ( EINFO_EINVAL_ASN1_TIME )
59
+#define EINFO_EINVAL_ASN1_TIME \
60
+	__einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
55 61
 
56 62
 /**
57 63
  * Invalidate ASN.1 object cursor
@@ -400,3 +406,110 @@ struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) {
400 406
 
401 407
 	return algorithm;
402 408
 }
409
+
410
+/**
411
+ * Parse ASN.1 GeneralizedTime
412
+ *
413
+ * @v cursor		ASN.1 cursor
414
+ * @v time		Time to fill in
415
+ * @ret rc		Return status code
416
+ *
417
+ * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
418
+ * formats for UTCTime and GeneralizedTime, and mandates the
419
+ * interpretation of centuryless year values.
420
+ */
421
+int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
422
+	struct asn1_cursor contents;
423
+	unsigned int have_century;
424
+	unsigned int type;
425
+	union {
426
+		struct {
427
+			uint8_t century;
428
+			uint8_t year;
429
+			uint8_t month;
430
+			uint8_t day;
431
+			uint8_t hour;
432
+			uint8_t minute;
433
+			uint8_t second;
434
+		} __attribute__ (( packed )) named;
435
+		uint8_t raw[7];
436
+	} pairs;
437
+	struct tm tm;
438
+	const uint8_t *data;
439
+	size_t remaining;
440
+	unsigned int tens;
441
+	unsigned int units;
442
+	unsigned int i;
443
+	int rc;
444
+
445
+	/* Determine time format utcTime/generalizedTime */
446
+	memcpy ( &contents, cursor, sizeof ( contents ) );
447
+	type = asn1_type ( &contents );
448
+	switch ( type ) {
449
+	case ASN1_UTC_TIME:
450
+		have_century = 0;
451
+		break;
452
+	case ASN1_GENERALIZED_TIME:
453
+		have_century = 1;
454
+		break;
455
+	default:
456
+		DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
457
+		       cursor, type );
458
+		DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
459
+		return -EINVAL_ASN1_TIME;
460
+	}
461
+
462
+	/* Enter utcTime/generalizedTime */
463
+	if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
464
+		DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
465
+		       ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
466
+		DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
467
+		return rc;
468
+	}
469
+
470
+	/* Parse digit string a pair at a time */
471
+	data = contents.data;
472
+	remaining = contents.len;
473
+	for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
474
+		if ( remaining < 2 ) {
475
+			DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
476
+			DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
477
+			return -EINVAL_ASN1_TIME;
478
+		}
479
+		tens = data[0];
480
+		units = data[1];
481
+		if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
482
+			DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
483
+			DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
484
+			return -EINVAL_ASN1_TIME;
485
+		}
486
+		pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
487
+		data += 2;
488
+		remaining -= 2;
489
+	}
490
+
491
+	/* Determine century if applicable */
492
+	if ( ! have_century )
493
+		pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
494
+
495
+	/* Check for trailing "Z" */
496
+	if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
497
+		DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
498
+		DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
499
+		return -EINVAL_ASN1_TIME;
500
+	}
501
+
502
+	/* Fill in time */
503
+	tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
504
+		       pairs.named.year );
505
+	tm.tm_mon = ( pairs.named.month - 1 );
506
+	tm.tm_mday = pairs.named.day;
507
+	tm.tm_hour = pairs.named.hour;
508
+	tm.tm_min = pairs.named.minute;
509
+	tm.tm_sec = pairs.named.second;
510
+
511
+	/* Convert to seconds since the Epoch */
512
+	*time = mktime ( &tm );
513
+
514
+	return 0;
515
+}

+ 10
- 116
src/crypto/x509.c View File

@@ -20,8 +20,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21 21
 #include <stdlib.h>
22 22
 #include <string.h>
23
-#include <ctype.h>
24
-#include <time.h>
25 23
 #include <errno.h>
26 24
 #include <assert.h>
27 25
 #include <ipxe/list.h>
@@ -60,10 +58,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
60 58
 	__einfo_error ( EINFO_EINVAL_BIT_STRING )
61 59
 #define EINFO_EINVAL_BIT_STRING \
62 60
 	__einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" )
63
-#define EINVAL_TIME \
64
-	__einfo_error ( EINFO_EINVAL_TIME )
65
-#define EINFO_EINVAL_TIME \
66
-	__einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid time" )
67 61
 #define EINVAL_ALGORITHM_MISMATCH \
68 62
 	__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
69 63
 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
@@ -301,114 +295,6 @@ static int x509_parse_integral_bit_string ( struct x509_certificate *cert,
301 295
 	return 0;
302 296
 }
303 297
 
304
-/**
305
- * Parse X.509 certificate time
306
- *
307
- * @v cert		X.509 certificate
308
- * @v time		Time to fill in
309
- * @v raw		ASN.1 cursor
310
- * @ret rc		Return status code
311
- *
312
- * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
313
- * formats for UTCTime and GeneralizedTime, and mandates the
314
- * interpretation of centuryless year values.
315
- */
316
-static int x509_parse_time ( struct x509_certificate *cert,
317
-			     struct x509_time *time,
318
-			     const struct asn1_cursor *raw ) {
319
-	struct asn1_cursor cursor;
320
-	unsigned int have_century;
321
-	unsigned int type;
322
-	union {
323
-		struct {
324
-			uint8_t century;
325
-			uint8_t year;
326
-			uint8_t month;
327
-			uint8_t day;
328
-			uint8_t hour;
329
-			uint8_t minute;
330
-			uint8_t second;
331
-		} __attribute__ (( packed )) named;
332
-		uint8_t raw[7];
333
-	} pairs;
334
-	struct tm tm;
335
-	const uint8_t *data;
336
-	size_t remaining;
337
-	unsigned int tens;
338
-	unsigned int units;
339
-	unsigned int i;
340
-	int rc;
341
-
342
-	/* Determine time format utcTime/generalizedTime */
343
-	memcpy ( &cursor, raw, sizeof ( cursor ) );
344
-	type = asn1_type ( &cursor );
345
-	switch ( type ) {
346
-	case ASN1_UTC_TIME:
347
-		have_century = 0;
348
-		break;
349
-	case ASN1_GENERALIZED_TIME:
350
-		have_century = 1;
351
-		break;
352
-	default:
353
-		DBGC ( cert, "X509 %p invalid time type %02x\n", cert, type );
354
-		DBGC_HDA ( cert, 0, raw->data, raw->len );
355
-		return -EINVAL_TIME;
356
-	}
357
-
358
-	/* Enter utcTime/generalizedTime */
359
-	if ( ( rc = asn1_enter ( &cursor, type ) ) != 0 ) {
360
-		DBGC ( cert, "X509 %p cannot locate %s time:\n", cert,
361
-		       ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
362
-		DBGC_HDA ( cert, 0, raw->data, raw->len );
363
-		return rc;
364
-	}
365
-
366
-	/* Parse digit string a pair at a time */
367
-	data = cursor.data;
368
-	remaining = cursor.len;
369
-	for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
370
-		if ( remaining < 2 ) {
371
-			DBGC ( cert, "X509 %p invalid time:\n", cert );
372
-			DBGC_HDA ( cert, 0, raw->data, raw->len );
373
-			return -EINVAL_TIME;
374
-		}
375
-		tens = data[0];
376
-		units = data[1];
377
-		if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
378
-			DBGC ( cert, "X509 %p invalid time:\n", cert );
379
-			DBGC_HDA ( cert, 0, raw->data, raw->len );
380
-			return -EINVAL_TIME;
381
-		}
382
-		pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
383
-		data += 2;
384
-		remaining -= 2;
385
-	}
386
-
387
-	/* Determine century if applicable */
388
-	if ( ! have_century )
389
-		pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
390
-
391
-	/* Check for trailing "Z" */
392
-	if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
393
-		DBGC ( cert, "X509 %p invalid time:\n", cert );
394
-		DBGC_HDA ( cert, 0, raw->data, raw->len );
395
-		return -EINVAL_TIME;
396
-	}
397
-
398
-	/* Fill in time */
399
-	tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
400
-		       pairs.named.year );
401
-	tm.tm_mon = ( pairs.named.month - 1 );
402
-	tm.tm_mday = pairs.named.day;
403
-	tm.tm_hour = pairs.named.hour;
404
-	tm.tm_min = pairs.named.minute;
405
-	tm.tm_sec = pairs.named.second;
406
-
407
-	/* Convert to seconds since the Epoch */
408
-	time->time = mktime ( &tm );
409
-
410
-	return 0;
411
-}
412 298
 
413 299
 /**
414 300
  * Parse X.509 certificate version
@@ -520,15 +406,23 @@ static int x509_parse_validity ( struct x509_certificate *cert,
520 406
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
521 407
 
522 408
 	/* Parse notBefore */
523
-	if ( ( rc = x509_parse_time ( cert, not_before, &cursor ) ) != 0 )
409
+	if ( ( rc = asn1_generalized_time ( &cursor,
410
+					    &not_before->time ) ) != 0 ) {
411
+		DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
412
+		       cert, strerror ( rc ) );
524 413
 		return rc;
414
+	}
525 415
 	DBGC2 ( cert, "X509 %p valid from time %lld\n",
526 416
 		cert, not_before->time );
527 417
 	asn1_skip_any ( &cursor );
528 418
 
529 419
 	/* Parse notAfter */
530
-	if ( ( rc = x509_parse_time ( cert, not_after, &cursor ) ) != 0 )
420
+	if ( ( rc = asn1_generalized_time ( &cursor,
421
+					    &not_after->time ) ) != 0 ) {
422
+		DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
423
+		       cert, strerror ( rc ) );
531 424
 		return rc;
425
+	}
532 426
 	DBGC2 ( cert, "X509 %p valid until time %lld\n",
533 427
 		cert, not_after->time );
534 428
 

+ 3
- 0
src/include/ipxe/asn1.h View File

@@ -10,6 +10,7 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #include <stdint.h>
13
+#include <time.h>
13 14
 #include <ipxe/tables.h>
14 15
 
15 16
 /** An ASN.1 object cursor */
@@ -239,5 +240,7 @@ extern int asn1_compare ( const struct asn1_cursor *cursor1,
239 240
 			  const struct asn1_cursor *cursor2 );
240 241
 extern struct asn1_algorithm *
241 242
 asn1_algorithm ( const struct asn1_cursor *cursor );
243
+extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
244
+				   time_t *time );
242 245
 
243 246
 #endif /* _IPXE_ASN1_H */

Loading…
Cancel
Save