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