These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / crypto / asn1.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdint.h>
27 #include <stddef.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <ipxe/tables.h>
34 #include <ipxe/asn1.h>
35
36 /** @file
37  *
38  * ASN.1 encoding
39  *
40  */
41
42 /* Disambiguate the various error causes */
43 #define EINVAL_ASN1_EMPTY \
44         __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
45 #define EINFO_EINVAL_ASN1_EMPTY \
46         __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
47 #define EINVAL_ASN1_LEN_LEN \
48         __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
49 #define EINFO_EINVAL_ASN1_LEN_LEN \
50         __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
51 #define EINVAL_ASN1_LEN \
52         __einfo_error ( EINFO_EINVAL_ASN1_LEN )
53 #define EINFO_EINVAL_ASN1_LEN \
54         __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
55 #define EINVAL_ASN1_BOOLEAN \
56         __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
57 #define EINFO_EINVAL_ASN1_BOOLEAN \
58         __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
59 #define EINVAL_ASN1_INTEGER \
60         __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
61 #define EINFO_EINVAL_ASN1_INTEGER \
62         __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
63 #define EINVAL_ASN1_TIME \
64         __einfo_error ( EINFO_EINVAL_ASN1_TIME )
65 #define EINFO_EINVAL_ASN1_TIME \
66         __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
67 #define EINVAL_ASN1_ALGORITHM \
68         __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
69 #define EINFO_EINVAL_ASN1_ALGORITHM \
70         __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
71 #define EINVAL_BIT_STRING \
72         __einfo_error ( EINFO_EINVAL_BIT_STRING )
73 #define EINFO_EINVAL_BIT_STRING \
74         __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
75 #define ENOTSUP_ALGORITHM \
76         __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
77 #define EINFO_ENOTSUP_ALGORITHM \
78         __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
79 #define ENOTTY_ALGORITHM \
80         __einfo_error ( EINFO_ENOTTY_ALGORITHM )
81 #define EINFO_ENOTTY_ALGORITHM \
82         __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )
83
84 /**
85  * Invalidate ASN.1 object cursor
86  *
87  * @v cursor            ASN.1 object cursor
88  */
89 void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
90         static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
91
92         cursor->data = asn1_invalid_object;
93         cursor->len = 0;
94 }
95
96 /**
97  * Start parsing ASN.1 object
98  *
99  * @v cursor            ASN.1 object cursor
100  * @v type              Expected type, or ASN1_ANY
101  * @ret len             Length of object body, or negative error
102  *
103  * The object cursor will be updated to point to the start of the
104  * object body (i.e. the first byte following the length byte(s)), and
105  * the length of the object body (i.e. the number of bytes until the
106  * following object tag, if any) is returned.
107  */
108 static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
109         unsigned int len_len;
110         unsigned int len;
111
112         /* Sanity check */
113         if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
114                 if ( cursor->len )
115                         DBGC ( cursor, "ASN1 %p too short\n", cursor );
116                 return -EINVAL_ASN1_EMPTY;
117         }
118
119         /* Check the tag byte */
120         if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
121                 DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
122                        cursor, type, *( ( uint8_t * ) cursor->data ) );
123                 return -ENXIO;
124         }
125         cursor->data++;
126         cursor->len--;
127
128         /* Extract length of the length field and sanity check */
129         len_len = *( ( uint8_t * ) cursor->data );
130         if ( len_len & 0x80 ) {
131                 len_len = ( len_len & 0x7f );
132                 cursor->data++;
133                 cursor->len--;
134         } else {
135                 len_len = 1;
136         }
137         if ( cursor->len < len_len ) {
138                 DBGC ( cursor, "ASN1 %p bad length field length %d (max "
139                        "%zd)\n", cursor, len_len, cursor->len );
140                 return -EINVAL_ASN1_LEN_LEN;
141         }
142
143         /* Extract the length and sanity check */
144         for ( len = 0 ; len_len ; len_len-- ) {
145                 len <<= 8;
146                 len |= *( ( uint8_t * ) cursor->data );
147                 cursor->data++;
148                 cursor->len--;
149         }
150         if ( cursor->len < len ) {
151                 DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
152                        cursor, len, cursor->len );
153                 return -EINVAL_ASN1_LEN;
154         }
155
156         return len;
157 }
158
159 /**
160  * Enter ASN.1 object
161  *
162  * @v cursor            ASN.1 object cursor
163  * @v type              Expected type, or ASN1_ANY
164  * @ret rc              Return status code
165  *
166  * The object cursor will be updated to point to the body of the
167  * current ASN.1 object.  If any error occurs, the object cursor will
168  * be invalidated.
169  */
170 int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
171         int len;
172
173         len = asn1_start ( cursor, type );
174         if ( len < 0 ) {
175                 asn1_invalidate_cursor ( cursor );
176                 return len;
177         }
178
179         cursor->len = len;
180         DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
181                cursor, type, len );
182
183         return 0;
184 }
185
186 /**
187  * Skip ASN.1 object if present
188  *
189  * @v cursor            ASN.1 object cursor
190  * @v type              Expected type, or ASN1_ANY
191  * @ret rc              Return status code
192  *
193  * The object cursor will be updated to point to the next ASN.1
194  * object.  If any error occurs, the object cursor will not be
195  * modified.
196  */
197 int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
198         int len;
199
200         len = asn1_start ( cursor, type );
201         if ( len < 0 )
202                 return len;
203
204         cursor->data += len;
205         cursor->len -= len;
206         DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
207                cursor, type, len );
208
209         if ( ! cursor->len ) {
210                 DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
211                 return -ENOENT;
212         }
213
214         return 0;
215 }
216
217 /**
218  * Skip ASN.1 object
219  *
220  * @v cursor            ASN.1 object cursor
221  * @v type              Expected type, or ASN1_ANY
222  * @ret rc              Return status code
223  *
224  * The object cursor will be updated to point to the next ASN.1
225  * object.  If any error occurs, the object cursor will be
226  * invalidated.
227  */
228 int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
229         int rc;
230
231         if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
232                 asn1_invalidate_cursor ( cursor );
233                 return rc;
234         }
235
236         return 0;
237 }
238
239 /**
240  * Shrink ASN.1 cursor to fit object
241  *
242  * @v cursor            ASN.1 object cursor
243  * @v type              Expected type, or ASN1_ANY
244  * @ret rc              Return status code
245  *
246  * The object cursor will be shrunk to contain only the current ASN.1
247  * object.  If any error occurs, the object cursor will be
248  * invalidated.
249  */
250 int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
251         struct asn1_cursor temp;
252         const void *end;
253         int len;
254
255         /* Find end of object */
256         memcpy ( &temp, cursor, sizeof ( temp ) );
257         len = asn1_start ( &temp, type );
258         if ( len < 0 ) {
259                 asn1_invalidate_cursor ( cursor );
260                 return len;
261         }
262         end = ( temp.data + len );
263
264         /* Shrink original cursor to contain only its first object */
265         cursor->len = ( end - cursor->data );
266
267         return 0;
268 }
269
270 /**
271  * Enter ASN.1 object of any type
272  *
273  * @v cursor            ASN.1 object cursor
274  * @ret rc              Return status code
275  */
276 int asn1_enter_any ( struct asn1_cursor *cursor ) {
277         return asn1_enter ( cursor, ASN1_ANY );
278 }
279
280 /**
281  * Skip ASN.1 object of any type
282  *
283  * @v cursor            ASN.1 object cursor
284  * @ret rc              Return status code
285  */
286 int asn1_skip_any ( struct asn1_cursor *cursor ) {
287         return asn1_skip ( cursor, ASN1_ANY );
288 }
289
290 /**
291  * Shrink ASN.1 object of any type
292  *
293  * @v cursor            ASN.1 object cursor
294  * @ret rc              Return status code
295  */
296 int asn1_shrink_any ( struct asn1_cursor *cursor ) {
297         return asn1_shrink ( cursor, ASN1_ANY );
298 }
299
300 /**
301  * Parse value of ASN.1 boolean
302  *
303  * @v cursor            ASN.1 object cursor
304  * @ret value           Value, or negative error
305  */
306 int asn1_boolean ( const struct asn1_cursor *cursor ) {
307         struct asn1_cursor contents;
308         const struct {
309                 uint8_t value;
310         } __attribute__ (( packed )) *boolean;
311
312         /* Enter boolean */
313         memcpy ( &contents, cursor, sizeof ( contents ) );
314         asn1_enter ( &contents, ASN1_BOOLEAN );
315         if ( contents.len != sizeof ( *boolean ) )
316                 return -EINVAL_ASN1_BOOLEAN;
317
318         /* Extract value */
319         boolean = contents.data;
320         return boolean->value;
321 }
322
323 /**
324  * Parse value of ASN.1 integer
325  *
326  * @v cursor            ASN.1 object cursor
327  * @v value             Value to fill in
328  * @ret rc              Return status code
329  */
330 int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
331         struct asn1_cursor contents;
332         uint8_t high_byte;
333         int rc;
334
335         /* Enter integer */
336         memcpy ( &contents, cursor, sizeof ( contents ) );
337         if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
338                 return rc;
339         if ( contents.len < 1 )
340                 return -EINVAL_ASN1_INTEGER;
341
342         /* Initialise value according to sign byte */
343         *value = *( ( int8_t * ) contents.data );
344         contents.data++;
345         contents.len--;
346
347         /* Process value */
348         while ( contents.len ) {
349                 high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
350                 if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
351                         DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
352                         return -EINVAL_ASN1_INTEGER;
353                 }
354                 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
355                 contents.data++;
356                 contents.len--;
357         }
358
359         return 0;
360 }
361
362 /**
363  * Parse ASN.1 bit string
364  *
365  * @v cursor            ASN.1 cursor
366  * @v bits              Bit string to fill in
367  * @ret rc              Return status code
368  */
369 int asn1_bit_string ( const struct asn1_cursor *cursor,
370                       struct asn1_bit_string *bits ) {
371         struct asn1_cursor contents;
372         const struct {
373                 uint8_t unused;
374                 uint8_t data[0];
375         } __attribute__ (( packed )) *bit_string;
376         size_t len;
377         unsigned int unused;
378         uint8_t unused_mask;
379         const uint8_t *last;
380         int rc;
381
382         /* Enter bit string */
383         memcpy ( &contents, cursor, sizeof ( contents ) );
384         if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) {
385                 DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor );
386                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
387                 return rc;
388         }
389
390         /* Validity checks */
391         if ( contents.len < sizeof ( *bit_string ) ) {
392                 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
393                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
394                 return -EINVAL_BIT_STRING;
395         }
396         bit_string = contents.data;
397         len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) );
398         unused = bit_string->unused;
399         unused_mask = ( 0xff >> ( 8 - unused ) );
400         last = ( bit_string->data + len - 1 );
401         if ( ( unused >= 8 ) ||
402              ( ( unused > 0 ) && ( len == 0 ) ) ||
403              ( ( *last & unused_mask ) != 0 ) ) {
404                 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
405                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
406                 return -EINVAL_BIT_STRING;
407         }
408
409         /* Populate bit string */
410         bits->data = &bit_string->data;
411         bits->len = len;
412         bits->unused = unused;
413
414         return 0;
415 }
416
417 /**
418  * Parse ASN.1 bit string that must be an integral number of bytes
419  *
420  * @v cursor            ASN.1 cursor
421  * @v bits              Bit string to fill in
422  * @ret rc              Return status code
423  */
424 int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
425                                struct asn1_bit_string *bits ) {
426         int rc;
427
428         /* Parse bit string */
429         if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
430                 return rc;
431
432         /* Check that there are no unused bits at end of string */
433         if ( bits->unused ) {
434                 DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
435                        cursor );
436                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
437                 return -EINVAL_BIT_STRING;
438         }
439
440         return 0;
441 }
442
443 /**
444  * Compare two ASN.1 objects
445  *
446  * @v cursor1           ASN.1 object cursor
447  * @v cursor2           ASN.1 object cursor
448  * @ret difference      Difference as returned by memcmp()
449  *
450  * Note that invalid and empty cursors will compare as equal with each
451  * other.
452  */
453 int asn1_compare ( const struct asn1_cursor *cursor1,
454                    const struct asn1_cursor *cursor2 ) {
455         int difference;
456
457         difference = ( cursor2->len - cursor1->len );
458         return ( difference ? difference :
459                  memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
460 }
461
462 /**
463  * Identify ASN.1 algorithm by OID
464  *
465  * @v cursor            ASN.1 object cursor
466
467  * @ret algorithm       Algorithm, or NULL
468  */
469 static struct asn1_algorithm *
470 asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
471         struct asn1_algorithm *algorithm;
472
473         for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
474                 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
475                         return algorithm;
476         }
477
478         return NULL;
479 }
480
481 /**
482  * Parse ASN.1 OID-identified algorithm
483  *
484  * @v cursor            ASN.1 object cursor
485  * @ret algorithm       Algorithm
486  * @ret rc              Return status code
487  */
488 int asn1_algorithm ( const struct asn1_cursor *cursor,
489                      struct asn1_algorithm **algorithm ) {
490         struct asn1_cursor contents;
491         int rc;
492
493         /* Enter signatureAlgorithm */
494         memcpy ( &contents, cursor, sizeof ( contents ) );
495         asn1_enter ( &contents, ASN1_SEQUENCE );
496
497         /* Enter algorithm */
498         if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
499                 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
500                        cursor );
501                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
502                 return -EINVAL_ASN1_ALGORITHM;
503         }
504
505         /* Identify algorithm */
506         *algorithm = asn1_find_algorithm ( &contents );
507         if ( ! *algorithm ) {
508                 DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
509                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
510                 return -ENOTSUP_ALGORITHM;
511         }
512
513         return 0;
514 }
515
516 /**
517  * Parse ASN.1 OID-identified public-key algorithm
518  *
519  * @v cursor            ASN.1 object cursor
520  * @ret algorithm       Algorithm
521  * @ret rc              Return status code
522  */
523 int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
524                             struct asn1_algorithm **algorithm ) {
525         int rc;
526
527         /* Parse algorithm */
528         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
529                 return rc;
530
531         /* Check algorithm has a public key */
532         if ( ! (*algorithm)->pubkey ) {
533                 DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
534                        "algorithm:\n", cursor, (*algorithm)->name );
535                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
536                 return -ENOTTY_ALGORITHM;
537         }
538
539         return 0;
540 }
541
542 /**
543  * Parse ASN.1 OID-identified digest algorithm
544  *
545  * @v cursor            ASN.1 object cursor
546  * @ret algorithm       Algorithm
547  * @ret rc              Return status code
548  */
549 int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
550                             struct asn1_algorithm **algorithm ) {
551         int rc;
552
553         /* Parse algorithm */
554         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
555                 return rc;
556
557         /* Check algorithm has a digest */
558         if ( ! (*algorithm)->digest ) {
559                 DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
560                        "algorithm:\n", cursor, (*algorithm)->name );
561                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
562                 return -ENOTTY_ALGORITHM;
563         }
564
565         return 0;
566 }
567
568 /**
569  * Parse ASN.1 OID-identified signature algorithm
570  *
571  * @v cursor            ASN.1 object cursor
572  * @ret algorithm       Algorithm
573  * @ret rc              Return status code
574  */
575 int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
576                                struct asn1_algorithm **algorithm ) {
577         int rc;
578
579         /* Parse algorithm */
580         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
581                 return rc;
582
583         /* Check algorithm has a public key */
584         if ( ! (*algorithm)->pubkey ) {
585                 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
586                        "algorithm:\n", cursor, (*algorithm)->name );
587                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
588                 return -ENOTTY_ALGORITHM;
589         }
590
591         /* Check algorithm has a digest */
592         if ( ! (*algorithm)->digest ) {
593                 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
594                        "algorithm:\n", cursor, (*algorithm)->name );
595                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
596                 return -ENOTTY_ALGORITHM;
597         }
598
599         return 0;
600 }
601
602 /**
603  * Parse ASN.1 GeneralizedTime
604  *
605  * @v cursor            ASN.1 cursor
606  * @v time              Time to fill in
607  * @ret rc              Return status code
608  *
609  * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
610  * formats for UTCTime and GeneralizedTime, and mandates the
611  * interpretation of centuryless year values.
612  */
613 int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
614         struct asn1_cursor contents;
615         unsigned int have_century;
616         unsigned int type;
617         union {
618                 struct {
619                         uint8_t century;
620                         uint8_t year;
621                         uint8_t month;
622                         uint8_t day;
623                         uint8_t hour;
624                         uint8_t minute;
625                         uint8_t second;
626                 } __attribute__ (( packed )) named;
627                 uint8_t raw[7];
628         } pairs;
629         struct tm tm;
630         const uint8_t *data;
631         size_t remaining;
632         unsigned int tens;
633         unsigned int units;
634         unsigned int i;
635         int rc;
636
637         /* Determine time format utcTime/generalizedTime */
638         memcpy ( &contents, cursor, sizeof ( contents ) );
639         type = asn1_type ( &contents );
640         switch ( type ) {
641         case ASN1_UTC_TIME:
642                 have_century = 0;
643                 break;
644         case ASN1_GENERALIZED_TIME:
645                 have_century = 1;
646                 break;
647         default:
648                 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
649                        cursor, type );
650                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
651                 return -EINVAL_ASN1_TIME;
652         }
653
654         /* Enter utcTime/generalizedTime */
655         if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
656                 DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
657                        ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
658                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
659                 return rc;
660         }
661
662         /* Parse digit string a pair at a time */
663         memset ( &pairs, 0, sizeof ( pairs ) );
664         data = contents.data;
665         remaining = contents.len;
666         for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
667                 if ( remaining < 2 ) {
668                         /* Some certificates violate the X.509 RFC by
669                          * omitting the "seconds" value.
670                          */
671                         if ( i == ( sizeof ( pairs.raw ) - 1 ) )
672                                 break;
673                         DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
674                         DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
675                         return -EINVAL_ASN1_TIME;
676                 }
677                 tens = data[0];
678                 units = data[1];
679                 if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
680                         DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
681                         DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
682                         return -EINVAL_ASN1_TIME;
683                 }
684                 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
685                 data += 2;
686                 remaining -= 2;
687         }
688
689         /* Determine century if applicable */
690         if ( ! have_century )
691                 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
692
693         /* Check for trailing "Z" */
694         if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
695                 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
696                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
697                 return -EINVAL_ASN1_TIME;
698         }
699
700         /* Fill in time */
701         tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
702                        pairs.named.year );
703         tm.tm_mon = ( pairs.named.month - 1 );
704         tm.tm_mday = pairs.named.day;
705         tm.tm_hour = pairs.named.hour;
706         tm.tm_min = pairs.named.minute;
707         tm.tm_sec = pairs.named.second;
708
709         /* Convert to seconds since the Epoch */
710         *time = mktime ( &tm );
711
712         return 0;
713 }
714
715 /**
716  * Construct ASN.1 header
717  *
718  * @v header            ASN.1 builder header
719  * @v type              Type
720  * @v len               Content length
721  * @ret header_len      Header length
722  */
723 static size_t asn1_header ( struct asn1_builder_header *header,
724                             unsigned int type, size_t len ) {
725         unsigned int header_len = 2;
726         unsigned int len_len = 0;
727         size_t temp;
728
729         /* Construct header */
730         header->type = type;
731         if ( len < 0x80 ) {
732                 header->length[0] = len;
733         } else {
734                 for ( temp = len ; temp ; temp >>= 8 )
735                         len_len++;
736                 header->length[0] = ( 0x80 | len_len );
737                 header_len += len_len;
738                 for ( temp = len ; temp ; temp >>= 8 )
739                         header->length[len_len--] = ( temp & 0xff );
740         }
741
742         return header_len;
743 }
744
745 /**
746  * Grow ASN.1 builder
747  *
748  * @v builder           ASN.1 builder
749  * @v extra             Extra space to prepend
750  * @ret rc              Return status code
751  */
752 static int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
753         size_t new_len;
754         void *new;
755
756         /* As with the ASN1 parsing functions, make errors permanent */
757         if ( builder->len && ! builder->data )
758                 return -ENOMEM;
759
760         /* Reallocate data buffer */
761         new_len = ( builder->len + extra );
762         new = realloc ( builder->data, new_len );
763         if ( ! new ) {
764                 free ( builder->data );
765                 builder->data = NULL;
766                 return -ENOMEM;
767         }
768         builder->data = new;
769
770         /* Move existing data to end of buffer */
771         memmove ( ( builder->data + extra ), builder->data, builder->len );
772         builder->len = new_len;
773
774         return 0;
775 }
776
777 /**
778  * Prepend raw data to ASN.1 builder
779  *
780  * @v builder           ASN.1 builder
781  * @v data              Data to prepend
782  * @v len               Length of data to prepend
783  * @ret rc              Return status code
784  */
785 int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
786                        size_t len ) {
787         int rc;
788
789         /* Grow buffer */
790         if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
791                 return rc;
792
793         /* Populate data buffer */
794         memcpy ( builder->data, data, len );
795
796         return 0;
797 }
798
799 /**
800  * Prepend data to ASN.1 builder
801  *
802  * @v builder           ASN.1 builder
803  * @v type              Type
804  * @v data              Data to prepend
805  * @v len               Length of data to prepend
806  * @ret rc              Return status code
807  */
808 int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
809                    const void *data, size_t len ) {
810         struct asn1_builder_header header;
811         size_t header_len;
812         int rc;
813
814         /* Construct header */
815         header_len = asn1_header ( &header, type, len );
816
817         /* Grow buffer */
818         if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
819                 return rc;
820
821         /* Populate data buffer */
822         memcpy ( builder->data, &header, header_len );
823         memcpy ( ( builder->data + header_len ), data, len );
824
825         return 0;
826 }
827
828 /**
829  * Wrap ASN.1 builder
830  *
831  * @v builder           ASN.1 builder
832  * @v type              Type
833  * @ret rc              Return status code
834  */
835 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
836         struct asn1_builder_header header;
837         size_t header_len;
838         int rc;
839
840         /* Construct header */
841         header_len = asn1_header ( &header, type, builder->len );
842
843         /* Grow buffer */
844         if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
845                 return rc;
846
847         /* Populate data buffer */
848         memcpy ( builder->data, &header, header_len );
849
850         return 0;
851 }