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
 #include <stdint.h>
21
 #include <stdint.h>
22
 #include <stddef.h>
22
 #include <stddef.h>
23
 #include <string.h>
23
 #include <string.h>
24
+#include <ctype.h>
24
 #include <errno.h>
25
 #include <errno.h>
26
+#include <time.h>
25
 #include <ipxe/tables.h>
27
 #include <ipxe/tables.h>
26
 #include <ipxe/asn1.h>
28
 #include <ipxe/asn1.h>
27
 
29
 
52
 	__einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
54
 	__einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
53
 #define EINFO_EINVAL_ASN1_INTEGER \
55
 #define EINFO_EINVAL_ASN1_INTEGER \
54
 	__einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
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
  * Invalidate ASN.1 object cursor
63
  * Invalidate ASN.1 object cursor
400
 
406
 
401
 	return algorithm;
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
 
20
 
21
 #include <stdlib.h>
21
 #include <stdlib.h>
22
 #include <string.h>
22
 #include <string.h>
23
-#include <ctype.h>
24
-#include <time.h>
25
 #include <errno.h>
23
 #include <errno.h>
26
 #include <assert.h>
24
 #include <assert.h>
27
 #include <ipxe/list.h>
25
 #include <ipxe/list.h>
60
 	__einfo_error ( EINFO_EINVAL_BIT_STRING )
58
 	__einfo_error ( EINFO_EINVAL_BIT_STRING )
61
 #define EINFO_EINVAL_BIT_STRING \
59
 #define EINFO_EINVAL_BIT_STRING \
62
 	__einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" )
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
 #define EINVAL_ALGORITHM_MISMATCH \
61
 #define EINVAL_ALGORITHM_MISMATCH \
68
 	__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
62
 	__einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
69
 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
63
 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
301
 	return 0;
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
  * Parse X.509 certificate version
300
  * Parse X.509 certificate version
520
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
406
 	asn1_enter ( &cursor, ASN1_SEQUENCE );
521
 
407
 
522
 	/* Parse notBefore */
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
 		return rc;
413
 		return rc;
414
+	}
525
 	DBGC2 ( cert, "X509 %p valid from time %lld\n",
415
 	DBGC2 ( cert, "X509 %p valid from time %lld\n",
526
 		cert, not_before->time );
416
 		cert, not_before->time );
527
 	asn1_skip_any ( &cursor );
417
 	asn1_skip_any ( &cursor );
528
 
418
 
529
 	/* Parse notAfter */
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
 		return rc;
424
 		return rc;
425
+	}
532
 	DBGC2 ( cert, "X509 %p valid until time %lld\n",
426
 	DBGC2 ( cert, "X509 %p valid until time %lld\n",
533
 		cert, not_after->time );
427
 		cert, not_after->time );
534
 
428
 

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

10
 FILE_LICENCE ( GPL2_OR_LATER );
10
 FILE_LICENCE ( GPL2_OR_LATER );
11
 
11
 
12
 #include <stdint.h>
12
 #include <stdint.h>
13
+#include <time.h>
13
 #include <ipxe/tables.h>
14
 #include <ipxe/tables.h>
14
 
15
 
15
 /** An ASN.1 object cursor */
16
 /** An ASN.1 object cursor */
239
 			  const struct asn1_cursor *cursor2 );
240
 			  const struct asn1_cursor *cursor2 );
240
 extern struct asn1_algorithm *
241
 extern struct asn1_algorithm *
241
 asn1_algorithm ( const struct asn1_cursor *cursor );
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
 #endif /* _IPXE_ASN1_H */
246
 #endif /* _IPXE_ASN1_H */

Loading…
Cancel
Save