2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
29 #include <ipxe/tables.h>
30 #include <ipxe/asn1.h>
38 /* Disambiguate the various error causes */
39 #define EINVAL_ASN1_EMPTY \
40 __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
41 #define EINFO_EINVAL_ASN1_EMPTY \
42 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
43 #define EINVAL_ASN1_LEN_LEN \
44 __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
45 #define EINFO_EINVAL_ASN1_LEN_LEN \
46 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
47 #define EINVAL_ASN1_LEN \
48 __einfo_error ( EINFO_EINVAL_ASN1_LEN )
49 #define EINFO_EINVAL_ASN1_LEN \
50 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
51 #define EINVAL_ASN1_BOOLEAN \
52 __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
53 #define EINFO_EINVAL_ASN1_BOOLEAN \
54 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
55 #define EINVAL_ASN1_INTEGER \
56 __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
57 #define EINFO_EINVAL_ASN1_INTEGER \
58 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
59 #define EINVAL_ASN1_TIME \
60 __einfo_error ( EINFO_EINVAL_ASN1_TIME )
61 #define EINFO_EINVAL_ASN1_TIME \
62 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
63 #define EINVAL_ASN1_ALGORITHM \
64 __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
65 #define EINFO_EINVAL_ASN1_ALGORITHM \
66 __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
67 #define EINVAL_BIT_STRING \
68 __einfo_error ( EINFO_EINVAL_BIT_STRING )
69 #define EINFO_EINVAL_BIT_STRING \
70 __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
71 #define ENOTSUP_ALGORITHM \
72 __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
73 #define EINFO_ENOTSUP_ALGORITHM \
74 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
75 #define ENOTTY_ALGORITHM \
76 __einfo_error ( EINFO_ENOTTY_ALGORITHM )
77 #define EINFO_ENOTTY_ALGORITHM \
78 __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )
81 * Invalidate ASN.1 object cursor
83 * @v cursor ASN.1 object cursor
85 void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
86 static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
88 cursor->data = asn1_invalid_object;
93 * Start parsing ASN.1 object
95 * @v cursor ASN.1 object cursor
96 * @v type Expected type, or ASN1_ANY
97 * @ret len Length of object body, or negative error
99 * The object cursor will be updated to point to the start of the
100 * object body (i.e. the first byte following the length byte(s)), and
101 * the length of the object body (i.e. the number of bytes until the
102 * following object tag, if any) is returned.
104 static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
105 unsigned int len_len;
109 if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
111 DBGC ( cursor, "ASN1 %p too short\n", cursor );
112 return -EINVAL_ASN1_EMPTY;
115 /* Check the tag byte */
116 if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
117 DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
118 cursor, type, *( ( uint8_t * ) cursor->data ) );
124 /* Extract length of the length field and sanity check */
125 len_len = *( ( uint8_t * ) cursor->data );
126 if ( len_len & 0x80 ) {
127 len_len = ( len_len & 0x7f );
133 if ( cursor->len < len_len ) {
134 DBGC ( cursor, "ASN1 %p bad length field length %d (max "
135 "%zd)\n", cursor, len_len, cursor->len );
136 return -EINVAL_ASN1_LEN_LEN;
139 /* Extract the length and sanity check */
140 for ( len = 0 ; len_len ; len_len-- ) {
142 len |= *( ( uint8_t * ) cursor->data );
146 if ( cursor->len < len ) {
147 DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
148 cursor, len, cursor->len );
149 return -EINVAL_ASN1_LEN;
158 * @v cursor ASN.1 object cursor
159 * @v type Expected type, or ASN1_ANY
160 * @ret rc Return status code
162 * The object cursor will be updated to point to the body of the
163 * current ASN.1 object. If any error occurs, the object cursor will
166 int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
169 len = asn1_start ( cursor, type );
171 asn1_invalidate_cursor ( cursor );
176 DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
183 * Skip ASN.1 object if present
185 * @v cursor ASN.1 object cursor
186 * @v type Expected type, or ASN1_ANY
187 * @ret rc Return status code
189 * The object cursor will be updated to point to the next ASN.1
190 * object. If any error occurs, the object cursor will not be
193 int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
196 len = asn1_start ( cursor, type );
202 DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
205 if ( ! cursor->len ) {
206 DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
216 * @v cursor ASN.1 object cursor
217 * @v type Expected type, or ASN1_ANY
218 * @ret rc Return status code
220 * The object cursor will be updated to point to the next ASN.1
221 * object. If any error occurs, the object cursor will be
224 int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
227 if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
228 asn1_invalidate_cursor ( cursor );
236 * Shrink ASN.1 cursor to fit object
238 * @v cursor ASN.1 object cursor
239 * @v type Expected type, or ASN1_ANY
240 * @ret rc Return status code
242 * The object cursor will be shrunk to contain only the current ASN.1
243 * object. If any error occurs, the object cursor will be
246 int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
247 struct asn1_cursor temp;
251 /* Find end of object */
252 memcpy ( &temp, cursor, sizeof ( temp ) );
253 len = asn1_start ( &temp, type );
255 asn1_invalidate_cursor ( cursor );
258 end = ( temp.data + len );
260 /* Shrink original cursor to contain only its first object */
261 cursor->len = ( end - cursor->data );
267 * Enter ASN.1 object of any type
269 * @v cursor ASN.1 object cursor
270 * @ret rc Return status code
272 int asn1_enter_any ( struct asn1_cursor *cursor ) {
273 return asn1_enter ( cursor, ASN1_ANY );
277 * Skip ASN.1 object of any type
279 * @v cursor ASN.1 object cursor
280 * @ret rc Return status code
282 int asn1_skip_any ( struct asn1_cursor *cursor ) {
283 return asn1_skip ( cursor, ASN1_ANY );
287 * Shrink ASN.1 object of any type
289 * @v cursor ASN.1 object cursor
290 * @ret rc Return status code
292 int asn1_shrink_any ( struct asn1_cursor *cursor ) {
293 return asn1_shrink ( cursor, ASN1_ANY );
297 * Parse value of ASN.1 boolean
299 * @v cursor ASN.1 object cursor
300 * @ret value Value, or negative error
302 int asn1_boolean ( const struct asn1_cursor *cursor ) {
303 struct asn1_cursor contents;
306 } __attribute__ (( packed )) *boolean;
309 memcpy ( &contents, cursor, sizeof ( contents ) );
310 asn1_enter ( &contents, ASN1_BOOLEAN );
311 if ( contents.len != sizeof ( *boolean ) )
312 return -EINVAL_ASN1_BOOLEAN;
315 boolean = contents.data;
316 return boolean->value;
320 * Parse value of ASN.1 integer
322 * @v cursor ASN.1 object cursor
323 * @v value Value to fill in
324 * @ret rc Return status code
326 int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
327 struct asn1_cursor contents;
332 memcpy ( &contents, cursor, sizeof ( contents ) );
333 if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
335 if ( contents.len < 1 )
336 return -EINVAL_ASN1_INTEGER;
338 /* Initialise value according to sign byte */
339 *value = *( ( int8_t * ) contents.data );
344 while ( contents.len ) {
345 high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
346 if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
347 DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
348 return -EINVAL_ASN1_INTEGER;
350 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
359 * Parse ASN.1 bit string
361 * @v cursor ASN.1 cursor
362 * @v bits Bit string to fill in
363 * @ret rc Return status code
365 int asn1_bit_string ( const struct asn1_cursor *cursor,
366 struct asn1_bit_string *bits ) {
367 struct asn1_cursor contents;
371 } __attribute__ (( packed )) *bit_string;
378 /* Enter bit string */
379 memcpy ( &contents, cursor, sizeof ( contents ) );
380 if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) {
381 DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor );
382 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
386 /* Validity checks */
387 if ( contents.len < sizeof ( *bit_string ) ) {
388 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
389 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
390 return -EINVAL_BIT_STRING;
392 bit_string = contents.data;
393 len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) );
394 unused = bit_string->unused;
395 unused_mask = ( 0xff >> ( 8 - unused ) );
396 last = ( bit_string->data + len - 1 );
397 if ( ( unused >= 8 ) ||
398 ( ( unused > 0 ) && ( len == 0 ) ) ||
399 ( ( *last & unused_mask ) != 0 ) ) {
400 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
401 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
402 return -EINVAL_BIT_STRING;
405 /* Populate bit string */
406 bits->data = &bit_string->data;
408 bits->unused = unused;
414 * Parse ASN.1 bit string that must be an integral number of bytes
416 * @v cursor ASN.1 cursor
417 * @v bits Bit string to fill in
418 * @ret rc Return status code
420 int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
421 struct asn1_bit_string *bits ) {
424 /* Parse bit string */
425 if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
428 /* Check that there are no unused bits at end of string */
429 if ( bits->unused ) {
430 DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
432 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
433 return -EINVAL_BIT_STRING;
440 * Compare two ASN.1 objects
442 * @v cursor1 ASN.1 object cursor
443 * @v cursor2 ASN.1 object cursor
444 * @ret difference Difference as returned by memcmp()
446 * Note that invalid and empty cursors will compare as equal with each
449 int asn1_compare ( const struct asn1_cursor *cursor1,
450 const struct asn1_cursor *cursor2 ) {
453 difference = ( cursor2->len - cursor1->len );
454 return ( difference ? difference :
455 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
459 * Identify ASN.1 algorithm by OID
461 * @v cursor ASN.1 object cursor
463 * @ret algorithm Algorithm, or NULL
465 static struct asn1_algorithm *
466 asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
467 struct asn1_algorithm *algorithm;
469 for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
470 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
478 * Parse ASN.1 OID-identified algorithm
480 * @v cursor ASN.1 object cursor
481 * @ret algorithm Algorithm
482 * @ret rc Return status code
484 int asn1_algorithm ( const struct asn1_cursor *cursor,
485 struct asn1_algorithm **algorithm ) {
486 struct asn1_cursor contents;
489 /* Enter signatureAlgorithm */
490 memcpy ( &contents, cursor, sizeof ( contents ) );
491 asn1_enter ( &contents, ASN1_SEQUENCE );
493 /* Enter algorithm */
494 if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
495 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
497 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
498 return -EINVAL_ASN1_ALGORITHM;
501 /* Identify algorithm */
502 *algorithm = asn1_find_algorithm ( &contents );
503 if ( ! *algorithm ) {
504 DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
505 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
506 return -ENOTSUP_ALGORITHM;
513 * Parse ASN.1 OID-identified public-key algorithm
515 * @v cursor ASN.1 object cursor
516 * @ret algorithm Algorithm
517 * @ret rc Return status code
519 int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
520 struct asn1_algorithm **algorithm ) {
523 /* Parse algorithm */
524 if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
527 /* Check algorithm has a public key */
528 if ( ! (*algorithm)->pubkey ) {
529 DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
530 "algorithm:\n", cursor, (*algorithm)->name );
531 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
532 return -ENOTTY_ALGORITHM;
539 * Parse ASN.1 OID-identified digest algorithm
541 * @v cursor ASN.1 object cursor
542 * @ret algorithm Algorithm
543 * @ret rc Return status code
545 int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
546 struct asn1_algorithm **algorithm ) {
549 /* Parse algorithm */
550 if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
553 /* Check algorithm has a digest */
554 if ( ! (*algorithm)->digest ) {
555 DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
556 "algorithm:\n", cursor, (*algorithm)->name );
557 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
558 return -ENOTTY_ALGORITHM;
565 * Parse ASN.1 OID-identified signature algorithm
567 * @v cursor ASN.1 object cursor
568 * @ret algorithm Algorithm
569 * @ret rc Return status code
571 int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
572 struct asn1_algorithm **algorithm ) {
575 /* Parse algorithm */
576 if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
579 /* Check algorithm has a public key */
580 if ( ! (*algorithm)->pubkey ) {
581 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
582 "algorithm:\n", cursor, (*algorithm)->name );
583 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
584 return -ENOTTY_ALGORITHM;
587 /* Check algorithm has a digest */
588 if ( ! (*algorithm)->digest ) {
589 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
590 "algorithm:\n", cursor, (*algorithm)->name );
591 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
592 return -ENOTTY_ALGORITHM;
599 * Parse ASN.1 GeneralizedTime
601 * @v cursor ASN.1 cursor
602 * @v time Time to fill in
603 * @ret rc Return status code
605 * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
606 * formats for UTCTime and GeneralizedTime, and mandates the
607 * interpretation of centuryless year values.
609 int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
610 struct asn1_cursor contents;
611 unsigned int have_century;
622 } __attribute__ (( packed )) named;
633 /* Determine time format utcTime/generalizedTime */
634 memcpy ( &contents, cursor, sizeof ( contents ) );
635 type = asn1_type ( &contents );
640 case ASN1_GENERALIZED_TIME:
644 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
646 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
647 return -EINVAL_ASN1_TIME;
650 /* Enter utcTime/generalizedTime */
651 if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
652 DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
653 ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
654 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
658 /* Parse digit string a pair at a time */
659 memset ( &pairs, 0, sizeof ( pairs ) );
660 data = contents.data;
661 remaining = contents.len;
662 for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
663 if ( remaining < 2 ) {
664 /* Some certificates violate the X.509 RFC by
665 * omitting the "seconds" value.
667 if ( i == ( sizeof ( pairs.raw ) - 1 ) )
669 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
670 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
671 return -EINVAL_ASN1_TIME;
675 if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
676 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
677 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
678 return -EINVAL_ASN1_TIME;
680 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
685 /* Determine century if applicable */
686 if ( ! have_century )
687 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
689 /* Check for trailing "Z" */
690 if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
691 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
692 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
693 return -EINVAL_ASN1_TIME;
697 tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
699 tm.tm_mon = ( pairs.named.month - 1 );
700 tm.tm_mday = pairs.named.day;
701 tm.tm_hour = pairs.named.hour;
702 tm.tm_min = pairs.named.minute;
703 tm.tm_sec = pairs.named.second;
705 /* Convert to seconds since the Epoch */
706 *time = mktime ( &tm );
712 * Construct ASN.1 header
714 * @v header ASN.1 builder header
716 * @v len Content length
717 * @ret header_len Header length
719 static size_t asn1_header ( struct asn1_builder_header *header,
720 unsigned int type, size_t len ) {
721 unsigned int header_len = 2;
722 unsigned int len_len = 0;
725 /* Construct header */
728 header->length[0] = len;
730 for ( temp = len ; temp ; temp >>= 8 )
732 header->length[0] = ( 0x80 | len_len );
733 header_len += len_len;
734 for ( temp = len ; temp ; temp >>= 8 )
735 header->length[len_len--] = ( temp & 0xff );
744 * @v builder ASN.1 builder
745 * @v extra Extra space to prepend
746 * @ret rc Return status code
748 static int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
752 /* As with the ASN1 parsing functions, make errors permanent */
753 if ( builder->len && ! builder->data )
756 /* Reallocate data buffer */
757 new_len = ( builder->len + extra );
758 new = realloc ( builder->data, new_len );
760 free ( builder->data );
761 builder->data = NULL;
766 /* Move existing data to end of buffer */
767 memmove ( ( builder->data + extra ), builder->data, builder->len );
768 builder->len = new_len;
774 * Prepend raw data to ASN.1 builder
776 * @v builder ASN.1 builder
777 * @v data Data to prepend
778 * @v len Length of data to prepend
779 * @ret rc Return status code
781 int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
786 if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
789 /* Populate data buffer */
790 memcpy ( builder->data, data, len );
796 * Prepend data to ASN.1 builder
798 * @v builder ASN.1 builder
800 * @v data Data to prepend
801 * @v len Length of data to prepend
802 * @ret rc Return status code
804 int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
805 const void *data, size_t len ) {
806 struct asn1_builder_header header;
810 /* Construct header */
811 header_len = asn1_header ( &header, type, len );
814 if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
817 /* Populate data buffer */
818 memcpy ( builder->data, &header, header_len );
819 memcpy ( ( builder->data + header_len ), data, len );
827 * @v builder ASN.1 builder
829 * @ret rc Return status code
831 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
832 struct asn1_builder_header header;
836 /* Construct header */
837 header_len = asn1_header ( &header, type, builder->len );
840 if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
843 /* Populate data buffer */
844 memcpy ( builder->data, &header, header_len );