Add qemu 2.4.0
[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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdint.h>
23 #include <stddef.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <time.h>
29 #include <ipxe/tables.h>
30 #include <ipxe/asn1.h>
31
32 /** @file
33  *
34  * ASN.1 encoding
35  *
36  */
37
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" )
79
80 /**
81  * Invalidate ASN.1 object cursor
82  *
83  * @v cursor            ASN.1 object cursor
84  */
85 void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
86         static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
87
88         cursor->data = asn1_invalid_object;
89         cursor->len = 0;
90 }
91
92 /**
93  * Start parsing ASN.1 object
94  *
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
98  *
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.
103  */
104 static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
105         unsigned int len_len;
106         unsigned int len;
107
108         /* Sanity check */
109         if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
110                 if ( cursor->len )
111                         DBGC ( cursor, "ASN1 %p too short\n", cursor );
112                 return -EINVAL_ASN1_EMPTY;
113         }
114
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 ) );
119                 return -ENXIO;
120         }
121         cursor->data++;
122         cursor->len--;
123
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 );
128                 cursor->data++;
129                 cursor->len--;
130         } else {
131                 len_len = 1;
132         }
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;
137         }
138
139         /* Extract the length and sanity check */
140         for ( len = 0 ; len_len ; len_len-- ) {
141                 len <<= 8;
142                 len |= *( ( uint8_t * ) cursor->data );
143                 cursor->data++;
144                 cursor->len--;
145         }
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;
150         }
151
152         return len;
153 }
154
155 /**
156  * Enter ASN.1 object
157  *
158  * @v cursor            ASN.1 object cursor
159  * @v type              Expected type, or ASN1_ANY
160  * @ret rc              Return status code
161  *
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
164  * be invalidated.
165  */
166 int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
167         int len;
168
169         len = asn1_start ( cursor, type );
170         if ( len < 0 ) {
171                 asn1_invalidate_cursor ( cursor );
172                 return len;
173         }
174
175         cursor->len = len;
176         DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
177                cursor, type, len );
178
179         return 0;
180 }
181
182 /**
183  * Skip ASN.1 object if present
184  *
185  * @v cursor            ASN.1 object cursor
186  * @v type              Expected type, or ASN1_ANY
187  * @ret rc              Return status code
188  *
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
191  * modified.
192  */
193 int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
194         int len;
195
196         len = asn1_start ( cursor, type );
197         if ( len < 0 )
198                 return len;
199
200         cursor->data += len;
201         cursor->len -= len;
202         DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
203                cursor, type, len );
204
205         if ( ! cursor->len ) {
206                 DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
207                 return -ENOENT;
208         }
209
210         return 0;
211 }
212
213 /**
214  * Skip ASN.1 object
215  *
216  * @v cursor            ASN.1 object cursor
217  * @v type              Expected type, or ASN1_ANY
218  * @ret rc              Return status code
219  *
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
222  * invalidated.
223  */
224 int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
225         int rc;
226
227         if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
228                 asn1_invalidate_cursor ( cursor );
229                 return rc;
230         }
231
232         return 0;
233 }
234
235 /**
236  * Shrink ASN.1 cursor to fit object
237  *
238  * @v cursor            ASN.1 object cursor
239  * @v type              Expected type, or ASN1_ANY
240  * @ret rc              Return status code
241  *
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
244  * invalidated.
245  */
246 int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
247         struct asn1_cursor temp;
248         const void *end;
249         int len;
250
251         /* Find end of object */
252         memcpy ( &temp, cursor, sizeof ( temp ) );
253         len = asn1_start ( &temp, type );
254         if ( len < 0 ) {
255                 asn1_invalidate_cursor ( cursor );
256                 return len;
257         }
258         end = ( temp.data + len );
259
260         /* Shrink original cursor to contain only its first object */
261         cursor->len = ( end - cursor->data );
262
263         return 0;
264 }
265
266 /**
267  * Enter ASN.1 object of any type
268  *
269  * @v cursor            ASN.1 object cursor
270  * @ret rc              Return status code
271  */
272 int asn1_enter_any ( struct asn1_cursor *cursor ) {
273         return asn1_enter ( cursor, ASN1_ANY );
274 }
275
276 /**
277  * Skip ASN.1 object of any type
278  *
279  * @v cursor            ASN.1 object cursor
280  * @ret rc              Return status code
281  */
282 int asn1_skip_any ( struct asn1_cursor *cursor ) {
283         return asn1_skip ( cursor, ASN1_ANY );
284 }
285
286 /**
287  * Shrink ASN.1 object of any type
288  *
289  * @v cursor            ASN.1 object cursor
290  * @ret rc              Return status code
291  */
292 int asn1_shrink_any ( struct asn1_cursor *cursor ) {
293         return asn1_shrink ( cursor, ASN1_ANY );
294 }
295
296 /**
297  * Parse value of ASN.1 boolean
298  *
299  * @v cursor            ASN.1 object cursor
300  * @ret value           Value, or negative error
301  */
302 int asn1_boolean ( const struct asn1_cursor *cursor ) {
303         struct asn1_cursor contents;
304         const struct {
305                 uint8_t value;
306         } __attribute__ (( packed )) *boolean;
307
308         /* Enter boolean */
309         memcpy ( &contents, cursor, sizeof ( contents ) );
310         asn1_enter ( &contents, ASN1_BOOLEAN );
311         if ( contents.len != sizeof ( *boolean ) )
312                 return -EINVAL_ASN1_BOOLEAN;
313
314         /* Extract value */
315         boolean = contents.data;
316         return boolean->value;
317 }
318
319 /**
320  * Parse value of ASN.1 integer
321  *
322  * @v cursor            ASN.1 object cursor
323  * @v value             Value to fill in
324  * @ret rc              Return status code
325  */
326 int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
327         struct asn1_cursor contents;
328         uint8_t high_byte;
329         int rc;
330
331         /* Enter integer */
332         memcpy ( &contents, cursor, sizeof ( contents ) );
333         if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
334                 return rc;
335         if ( contents.len < 1 )
336                 return -EINVAL_ASN1_INTEGER;
337
338         /* Initialise value according to sign byte */
339         *value = *( ( int8_t * ) contents.data );
340         contents.data++;
341         contents.len--;
342
343         /* Process value */
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;
349                 }
350                 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
351                 contents.data++;
352                 contents.len--;
353         }
354
355         return 0;
356 }
357
358 /**
359  * Parse ASN.1 bit string
360  *
361  * @v cursor            ASN.1 cursor
362  * @v bits              Bit string to fill in
363  * @ret rc              Return status code
364  */
365 int asn1_bit_string ( const struct asn1_cursor *cursor,
366                       struct asn1_bit_string *bits ) {
367         struct asn1_cursor contents;
368         const struct {
369                 uint8_t unused;
370                 uint8_t data[0];
371         } __attribute__ (( packed )) *bit_string;
372         size_t len;
373         unsigned int unused;
374         uint8_t unused_mask;
375         const uint8_t *last;
376         int rc;
377
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 );
383                 return rc;
384         }
385
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;
391         }
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;
403         }
404
405         /* Populate bit string */
406         bits->data = &bit_string->data;
407         bits->len = len;
408         bits->unused = unused;
409
410         return 0;
411 }
412
413 /**
414  * Parse ASN.1 bit string that must be an integral number of bytes
415  *
416  * @v cursor            ASN.1 cursor
417  * @v bits              Bit string to fill in
418  * @ret rc              Return status code
419  */
420 int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
421                                struct asn1_bit_string *bits ) {
422         int rc;
423
424         /* Parse bit string */
425         if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
426                 return rc;
427
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",
431                        cursor );
432                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
433                 return -EINVAL_BIT_STRING;
434         }
435
436         return 0;
437 }
438
439 /**
440  * Compare two ASN.1 objects
441  *
442  * @v cursor1           ASN.1 object cursor
443  * @v cursor2           ASN.1 object cursor
444  * @ret difference      Difference as returned by memcmp()
445  *
446  * Note that invalid and empty cursors will compare as equal with each
447  * other.
448  */
449 int asn1_compare ( const struct asn1_cursor *cursor1,
450                    const struct asn1_cursor *cursor2 ) {
451         int difference;
452
453         difference = ( cursor2->len - cursor1->len );
454         return ( difference ? difference :
455                  memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
456 }
457
458 /**
459  * Identify ASN.1 algorithm by OID
460  *
461  * @v cursor            ASN.1 object cursor
462
463  * @ret algorithm       Algorithm, or NULL
464  */
465 static struct asn1_algorithm *
466 asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
467         struct asn1_algorithm *algorithm;
468
469         for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
470                 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
471                         return algorithm;
472         }
473
474         return NULL;
475 }
476
477 /**
478  * Parse ASN.1 OID-identified algorithm
479  *
480  * @v cursor            ASN.1 object cursor
481  * @ret algorithm       Algorithm
482  * @ret rc              Return status code
483  */
484 int asn1_algorithm ( const struct asn1_cursor *cursor,
485                      struct asn1_algorithm **algorithm ) {
486         struct asn1_cursor contents;
487         int rc;
488
489         /* Enter signatureAlgorithm */
490         memcpy ( &contents, cursor, sizeof ( contents ) );
491         asn1_enter ( &contents, ASN1_SEQUENCE );
492
493         /* Enter algorithm */
494         if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
495                 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
496                        cursor );
497                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
498                 return -EINVAL_ASN1_ALGORITHM;
499         }
500
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;
507         }
508
509         return 0;
510 }
511
512 /**
513  * Parse ASN.1 OID-identified public-key algorithm
514  *
515  * @v cursor            ASN.1 object cursor
516  * @ret algorithm       Algorithm
517  * @ret rc              Return status code
518  */
519 int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
520                             struct asn1_algorithm **algorithm ) {
521         int rc;
522
523         /* Parse algorithm */
524         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
525                 return rc;
526
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;
533         }
534
535         return 0;
536 }
537
538 /**
539  * Parse ASN.1 OID-identified digest algorithm
540  *
541  * @v cursor            ASN.1 object cursor
542  * @ret algorithm       Algorithm
543  * @ret rc              Return status code
544  */
545 int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
546                             struct asn1_algorithm **algorithm ) {
547         int rc;
548
549         /* Parse algorithm */
550         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
551                 return rc;
552
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;
559         }
560
561         return 0;
562 }
563
564 /**
565  * Parse ASN.1 OID-identified signature algorithm
566  *
567  * @v cursor            ASN.1 object cursor
568  * @ret algorithm       Algorithm
569  * @ret rc              Return status code
570  */
571 int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
572                                struct asn1_algorithm **algorithm ) {
573         int rc;
574
575         /* Parse algorithm */
576         if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
577                 return rc;
578
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;
585         }
586
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;
593         }
594
595         return 0;
596 }
597
598 /**
599  * Parse ASN.1 GeneralizedTime
600  *
601  * @v cursor            ASN.1 cursor
602  * @v time              Time to fill in
603  * @ret rc              Return status code
604  *
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.
608  */
609 int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
610         struct asn1_cursor contents;
611         unsigned int have_century;
612         unsigned int type;
613         union {
614                 struct {
615                         uint8_t century;
616                         uint8_t year;
617                         uint8_t month;
618                         uint8_t day;
619                         uint8_t hour;
620                         uint8_t minute;
621                         uint8_t second;
622                 } __attribute__ (( packed )) named;
623                 uint8_t raw[7];
624         } pairs;
625         struct tm tm;
626         const uint8_t *data;
627         size_t remaining;
628         unsigned int tens;
629         unsigned int units;
630         unsigned int i;
631         int rc;
632
633         /* Determine time format utcTime/generalizedTime */
634         memcpy ( &contents, cursor, sizeof ( contents ) );
635         type = asn1_type ( &contents );
636         switch ( type ) {
637         case ASN1_UTC_TIME:
638                 have_century = 0;
639                 break;
640         case ASN1_GENERALIZED_TIME:
641                 have_century = 1;
642                 break;
643         default:
644                 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
645                        cursor, type );
646                 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
647                 return -EINVAL_ASN1_TIME;
648         }
649
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 );
655                 return rc;
656         }
657
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.
666                          */
667                         if ( i == ( sizeof ( pairs.raw ) - 1 ) )
668                                 break;
669                         DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
670                         DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
671                         return -EINVAL_ASN1_TIME;
672                 }
673                 tens = data[0];
674                 units = data[1];
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;
679                 }
680                 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
681                 data += 2;
682                 remaining -= 2;
683         }
684
685         /* Determine century if applicable */
686         if ( ! have_century )
687                 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
688
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;
694         }
695
696         /* Fill in time */
697         tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
698                        pairs.named.year );
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;
704
705         /* Convert to seconds since the Epoch */
706         *time = mktime ( &tm );
707
708         return 0;
709 }
710
711 /**
712  * Construct ASN.1 header
713  *
714  * @v header            ASN.1 builder header
715  * @v type              Type
716  * @v len               Content length
717  * @ret header_len      Header length
718  */
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;
723         size_t temp;
724
725         /* Construct header */
726         header->type = type;
727         if ( len < 0x80 ) {
728                 header->length[0] = len;
729         } else {
730                 for ( temp = len ; temp ; temp >>= 8 )
731                         len_len++;
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 );
736         }
737
738         return header_len;
739 }
740
741 /**
742  * Grow ASN.1 builder
743  *
744  * @v builder           ASN.1 builder
745  * @v extra             Extra space to prepend
746  * @ret rc              Return status code
747  */
748 static int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
749         size_t new_len;
750         void *new;
751
752         /* As with the ASN1 parsing functions, make errors permanent */
753         if ( builder->len && ! builder->data )
754                 return -ENOMEM;
755
756         /* Reallocate data buffer */
757         new_len = ( builder->len + extra );
758         new = realloc ( builder->data, new_len );
759         if ( ! new ) {
760                 free ( builder->data );
761                 builder->data = NULL;
762                 return -ENOMEM;
763         }
764         builder->data = new;
765
766         /* Move existing data to end of buffer */
767         memmove ( ( builder->data + extra ), builder->data, builder->len );
768         builder->len = new_len;
769
770         return 0;
771 }
772
773 /**
774  * Prepend raw data to ASN.1 builder
775  *
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
780  */
781 int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
782                        size_t len ) {
783         int rc;
784
785         /* Grow buffer */
786         if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
787                 return rc;
788
789         /* Populate data buffer */
790         memcpy ( builder->data, data, len );
791
792         return 0;
793 }
794
795 /**
796  * Prepend data to ASN.1 builder
797  *
798  * @v builder           ASN.1 builder
799  * @v type              Type
800  * @v data              Data to prepend
801  * @v len               Length of data to prepend
802  * @ret rc              Return status code
803  */
804 int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
805                    const void *data, size_t len ) {
806         struct asn1_builder_header header;
807         size_t header_len;
808         int rc;
809
810         /* Construct header */
811         header_len = asn1_header ( &header, type, len );
812
813         /* Grow buffer */
814         if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
815                 return rc;
816
817         /* Populate data buffer */
818         memcpy ( builder->data, &header, header_len );
819         memcpy ( ( builder->data + header_len ), data, len );
820
821         return 0;
822 }
823
824 /**
825  * Wrap ASN.1 builder
826  *
827  * @v builder           ASN.1 builder
828  * @v type              Type
829  * @ret rc              Return status code
830  */
831 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
832         struct asn1_builder_header header;
833         size_t header_len;
834         int rc;
835
836         /* Construct header */
837         header_len = asn1_header ( &header, type, builder->len );
838
839         /* Grow buffer */
840         if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
841                 return rc;
842
843         /* Populate data buffer */
844         memcpy ( builder->data, &header, header_len );
845
846         return 0;
847 }