iPXE
asn1.c
Go to the documentation of this file.
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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stdint.h>
28#include <stddef.h>
29#include <stdlib.h>
30#include <string.h>
31#include <ctype.h>
32#include <errno.h>
33#include <time.h>
34#include <ipxe/tables.h>
35#include <ipxe/image.h>
36#include <ipxe/crypto.h>
37#include <ipxe/asn1.h>
38
39/** @file
40 *
41 * ASN.1 encoding
42 *
43 */
44
45/* Disambiguate the various error causes */
46#define EINVAL_ASN1_EMPTY \
47 __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
48#define EINFO_EINVAL_ASN1_EMPTY \
49 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
50#define EINVAL_ASN1_LEN_LEN \
51 __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
52#define EINFO_EINVAL_ASN1_LEN_LEN \
53 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
54#define EINVAL_ASN1_LEN \
55 __einfo_error ( EINFO_EINVAL_ASN1_LEN )
56#define EINFO_EINVAL_ASN1_LEN \
57 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
58#define EINVAL_ASN1_BOOLEAN \
59 __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
60#define EINFO_EINVAL_ASN1_BOOLEAN \
61 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
62#define EINVAL_ASN1_INTEGER \
63 __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
64#define EINFO_EINVAL_ASN1_INTEGER \
65 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
66#define EINVAL_ASN1_TIME \
67 __einfo_error ( EINFO_EINVAL_ASN1_TIME )
68#define EINFO_EINVAL_ASN1_TIME \
69 __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" )
70#define EINVAL_ASN1_ALGORITHM \
71 __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
72#define EINFO_EINVAL_ASN1_ALGORITHM \
73 __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
74#define EINVAL_BIT_STRING \
75 __einfo_error ( EINFO_EINVAL_BIT_STRING )
76#define EINFO_EINVAL_BIT_STRING \
77 __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
78#define ENOTSUP_ALGORITHM \
79 __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
80#define EINFO_ENOTSUP_ALGORITHM \
81 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
82#define ENOTTY_ALGORITHM \
83 __einfo_error ( EINFO_ENOTTY_ALGORITHM )
84#define EINFO_ENOTTY_ALGORITHM \
85 __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )
86
87/**
88 * Start parsing ASN.1 object
89 *
90 * @v cursor ASN.1 object cursor
91 * @v type Expected type, or ASN1_ANY
92 * @ret len Length of object body, or negative error
93 *
94 * The object cursor will be updated to point to the start of the
95 * object body (i.e. the first byte following the length byte(s)), and
96 * the length of the object body (i.e. the number of bytes until the
97 * following object tag, if any) is returned.
98 *
99 * If the expected type is not found, the object cursor will not be
100 * modified. If any other error occurs, the object cursor will be
101 * invalidated.
102 */
103static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
104 unsigned int len_len;
105 unsigned int len;
106
107 /* Sanity check */
108 if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
109 if ( cursor->len )
110 DBGC ( cursor, "ASN1 %p too short\n", cursor );
111 asn1_invalidate_cursor ( 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 asn1_invalidate_cursor ( cursor );
137 return -EINVAL_ASN1_LEN_LEN;
138 }
139
140 /* Extract the length and sanity check */
141 for ( len = 0 ; len_len ; len_len-- ) {
142 len <<= 8;
143 len |= *( ( uint8_t * ) cursor->data );
144 cursor->data++;
145 cursor->len--;
146 }
147 if ( cursor->len < len ) {
148 DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
149 cursor, len, cursor->len );
150 asn1_invalidate_cursor ( cursor );
151 return -EINVAL_ASN1_LEN;
152 }
153
154 return len;
155}
156
157/**
158 * Enter ASN.1 object
159 *
160 * @v cursor ASN.1 object cursor
161 * @v type Expected type, or ASN1_ANY
162 * @ret rc Return status code
163 *
164 * The object cursor will be updated to point to the body of the
165 * current ASN.1 object.
166 *
167 * If any error occurs, the object cursor will be invalidated.
168 */
169int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
170 int len;
171
172 /* Parse current object */
173 len = asn1_start ( cursor, type );
174 if ( len < 0 ) {
175 asn1_invalidate_cursor ( cursor );
176 return len;
177 }
178
179 /* Update cursor */
180 if ( ( ( size_t ) len ) <= cursor->len )
181 cursor->len = len;
182
183 DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
184 cursor, type, len );
185 return 0;
186}
187
188/**
189 * Skip ASN.1 object if present
190 *
191 * @v cursor ASN.1 object cursor
192 * @v type Expected type, or ASN1_ANY
193 * @ret rc Return status code
194 *
195 * The object cursor will be updated to point to the next ASN.1
196 * object.
197 *
198 * If the expected type is not found, the object cursor will not be
199 * modified. If any other error occurs, the object cursor will be
200 * invalidated.
201 */
202int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
203 int len;
204
205 /* Parse current object */
206 len = asn1_start ( cursor, type );
207 if ( len < 0 )
208 return len;
209
210 /* Update cursor */
211 cursor->data += len;
212 cursor->len -= len;
213
214 DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
215 cursor, type, len );
216 return 0;
217}
218
219/**
220 * Skip ASN.1 object
221 *
222 * @v cursor ASN.1 object cursor
223 * @v type Expected type, or ASN1_ANY
224 * @ret rc Return status code
225 *
226 * The object cursor will be updated to point to the next ASN.1
227 * object.
228 *
229 * If any error occurs, the object cursor will be invalidated.
230 */
231int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
232 int rc;
233
234 if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
235 asn1_invalidate_cursor ( cursor );
236 return rc;
237 }
238
239 return 0;
240}
241
242/**
243 * Shrink ASN.1 cursor to fit object
244 *
245 * @v cursor ASN.1 object cursor
246 * @v type Expected type, or ASN1_ANY
247 * @ret rc Return status code
248 *
249 * The object cursor will be shrunk to contain only the current ASN.1
250 * object.
251 *
252 * If any error occurs, the object cursor will be invalidated.
253 */
254int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
255 struct asn1_cursor temp;
256 const void *end;
257 int len;
258
259 /* Find end of object */
260 memcpy ( &temp, cursor, sizeof ( temp ) );
261 len = asn1_start ( &temp, type );
262 if ( len < 0 ) {
263 asn1_invalidate_cursor ( cursor );
264 return len;
265 }
266 end = ( temp.data + len );
267
268 /* Shrink original cursor to contain only its first object */
269 cursor->len = ( end - cursor->data );
270
271 return 0;
272}
273
274/**
275 * Enter ASN.1 object of any type
276 *
277 * @v cursor ASN.1 object cursor
278 * @ret rc Return status code
279 */
280int asn1_enter_any ( struct asn1_cursor *cursor ) {
281 return asn1_enter ( cursor, ASN1_ANY );
282}
283
284/**
285 * Skip ASN.1 object of any type
286 *
287 * @v cursor ASN.1 object cursor
288 * @ret rc Return status code
289 */
290int asn1_skip_any ( struct asn1_cursor *cursor ) {
291 return asn1_skip ( cursor, ASN1_ANY );
292}
293
294/**
295 * Shrink ASN.1 object of any type
296 *
297 * @v cursor ASN.1 object cursor
298 * @ret rc Return status code
299 */
300int asn1_shrink_any ( struct asn1_cursor *cursor ) {
301 return asn1_shrink ( cursor, ASN1_ANY );
302}
303
304/**
305 * Enter ASN.1 bit string
306 *
307 * @v cursor ASN.1 cursor
308 * @v unused Unused bits to fill in (or NULL to require all used)
309 * @ret rc Return status code
310 */
311int asn1_enter_bits ( struct asn1_cursor *cursor, unsigned int *unused ) {
312 const struct {
314 uint8_t data[0];
315 } __attribute__ (( packed )) *bit_string;
316 const uint8_t *last;
317 unsigned int unused_bits;
318 uint8_t unused_mask;
319 int rc;
320
321 /* Enter bit string */
322 if ( ( rc = asn1_enter ( cursor, ASN1_BIT_STRING ) ) != 0 )
323 return rc;
324
325 /* Check that bit string header exists */
326 if ( cursor->len < sizeof ( *bit_string ) ) {
327 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
328 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
329 asn1_invalidate_cursor ( cursor );
330 return -EINVAL_BIT_STRING;
331 }
332 bit_string = cursor->data;
333 cursor->data = &bit_string->data;
334 cursor->len -= offsetof ( typeof ( *bit_string ), data );
335 unused_bits = bit_string->unused;
336
337 /* Check validity of unused bits */
338 unused_mask = ( 0xff >> ( 8 - unused_bits ) );
339 last = ( cursor->data + cursor->len - 1 );
340 if ( ( unused_bits >= 8 ) ||
341 ( ( unused_bits > 0 ) && ( cursor->len == 0 ) ) ||
342 ( ( *last & unused_mask ) != 0 ) ) {
343 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
344 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
345 asn1_invalidate_cursor ( cursor );
346 return -EINVAL_BIT_STRING;
347 }
348
349 /* Record or check number of unused bits, as applicable */
350 if ( unused ) {
351 *unused = unused_bits;
352 } else if ( unused_bits ) {
353 DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
354 cursor );
355 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
356 asn1_invalidate_cursor ( cursor );
357 return -EINVAL_BIT_STRING;
358 }
359
360 return 0;
361}
362
363/**
364 * Enter ASN.1 unsigned integer
365 *
366 * @v cursor ASN.1 object cursor
367 * @ret rc Return status code
368 */
369int asn1_enter_unsigned ( struct asn1_cursor *cursor ) {
370 int rc;
371
372 /* Enter integer */
373 if ( ( rc = asn1_enter ( cursor, ASN1_INTEGER ) ) != 0 )
374 return rc;
375
376 /* Skip initial positive sign byte if applicable */
377 if ( ( cursor->len > 1 ) &&
378 ( *( ( uint8_t * ) cursor->data ) == 0x00 ) ) {
379 cursor->data++;
380 cursor->len--;
381 }
382
383 return 0;
384}
385
386/**
387 * Parse value of ASN.1 boolean
388 *
389 * @v cursor ASN.1 object cursor
390 * @ret value Value, or negative error
391 */
392int asn1_boolean ( const struct asn1_cursor *cursor ) {
393 struct asn1_cursor contents;
394 const struct {
396 } __attribute__ (( packed )) *boolean;
397
398 /* Enter boolean */
399 memcpy ( &contents, cursor, sizeof ( contents ) );
400 asn1_enter ( &contents, ASN1_BOOLEAN );
401 if ( contents.len != sizeof ( *boolean ) )
402 return -EINVAL_ASN1_BOOLEAN;
403
404 /* Extract value */
405 boolean = contents.data;
406 return boolean->value;
407}
408
409/**
410 * Parse value of ASN.1 integer
411 *
412 * @v cursor ASN.1 object cursor
413 * @v value Value to fill in
414 * @ret rc Return status code
415 */
416int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
417 struct asn1_cursor contents;
418 uint8_t high_byte;
419 int rc;
420
421 /* Enter integer */
422 memcpy ( &contents, cursor, sizeof ( contents ) );
423 if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
424 return rc;
425 if ( contents.len < 1 )
426 return -EINVAL_ASN1_INTEGER;
427
428 /* Initialise value according to sign byte */
429 *value = *( ( int8_t * ) contents.data );
430 contents.data++;
431 contents.len--;
432
433 /* Process value */
434 while ( contents.len ) {
435 high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
436 if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
437 DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
438 return -EINVAL_ASN1_INTEGER;
439 }
440 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
441 contents.data++;
442 contents.len--;
443 }
444
445 return 0;
446}
447
448/**
449 * Compare two ASN.1 objects
450 *
451 * @v cursor1 ASN.1 object cursor
452 * @v cursor2 ASN.1 object cursor
453 * @ret difference Difference as returned by memcmp()
454 *
455 * Note that invalid and empty cursors will compare as equal with each
456 * other.
457 */
458int asn1_compare ( const struct asn1_cursor *cursor1,
459 const struct asn1_cursor *cursor2 ) {
460 int difference;
461
462 difference = ( cursor2->len - cursor1->len );
463 return ( difference ? difference :
464 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
465}
466
467/**
468 * Identify ASN.1 algorithm by OID
469 *
470 * @v cursor ASN.1 object cursor
471
472 * @ret algorithm Algorithm, or NULL
473 */
474static struct asn1_algorithm *
475asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
477
479 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
480 return algorithm;
481 }
482
483 return NULL;
484}
485
486/**
487 * Parse ASN.1 OID-identified algorithm
488 *
489 * @v cursor ASN.1 object cursor
490 * @ret algorithm Algorithm
491 * @ret params Algorithm parameters, or NULL
492 * @ret rc Return status code
493 */
494int asn1_algorithm ( const struct asn1_cursor *cursor,
495 struct asn1_algorithm **algorithm,
496 struct asn1_cursor *params ) {
497 struct asn1_cursor contents;
498 int rc;
499
500 /* Enter algorithm */
501 memcpy ( &contents, cursor, sizeof ( contents ) );
502 asn1_enter ( &contents, ASN1_SEQUENCE );
503
504 /* Get raw parameters, if applicable */
505 if ( params ) {
506 memcpy ( params, &contents, sizeof ( *params ) );
507 asn1_skip_any ( params );
508 }
509
510 /* Enter algorithm identifier */
511 if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
512 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
513 cursor );
514 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
515 return -EINVAL_ASN1_ALGORITHM;
516 }
517
518 /* Identify algorithm */
519 *algorithm = asn1_find_algorithm ( &contents );
520 if ( ! *algorithm ) {
521 DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
522 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
523 return -ENOTSUP_ALGORITHM;
524 }
525
526 /* Parse parameters, if applicable */
527 if ( params && (*algorithm)->parse &&
528 ( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
529 DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
530 cursor, (*algorithm)->name, strerror ( rc ) );
531 return rc;
532 }
533
534 return 0;
535}
536
537/**
538 * Parse ASN.1 OID-identified public-key algorithm
539 *
540 * @v cursor ASN.1 object cursor
541 * @ret algorithm Algorithm
542 * @ret rc Return status code
543 */
544int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
545 struct asn1_algorithm **algorithm ) {
546 int rc;
547
548 /* Parse algorithm */
549 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
550 return rc;
551
552 /* Check algorithm has a public key */
553 if ( ! (*algorithm)->pubkey ) {
554 DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
555 "algorithm:\n", cursor, (*algorithm)->name );
556 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
557 return -ENOTTY_ALGORITHM;
558 }
559
560 return 0;
561}
562
563/**
564 * Parse ASN.1 OID-identified digest algorithm
565 *
566 * @v cursor ASN.1 object cursor
567 * @ret algorithm Algorithm
568 * @ret rc Return status code
569 */
570int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
571 struct asn1_algorithm **algorithm ) {
572 int rc;
573
574 /* Parse algorithm */
575 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
576 return rc;
577
578 /* Check algorithm has a digest */
579 if ( ! (*algorithm)->digest ) {
580 DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
581 "algorithm:\n", cursor, (*algorithm)->name );
582 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
583 return -ENOTTY_ALGORITHM;
584 }
585
586 return 0;
587}
588
589/**
590 * Parse ASN.1 OID-identified cipher algorithm
591 *
592 * @v cursor ASN.1 object cursor
593 * @ret algorithm Algorithm
594 * @ret params Algorithm parameters, or NULL
595 * @ret rc Return status code
596 */
597int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
598 struct asn1_algorithm **algorithm,
599 struct asn1_cursor *params ) {
600 int rc;
601
602 /* Parse algorithm */
603 if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
604 return rc;
605
606 /* Check algorithm has a cipher */
607 if ( ! (*algorithm)->cipher ) {
608 DBGC ( cursor, "ASN1 %p algorithm %s is not a cipher "
609 "algorithm:\n", cursor, (*algorithm)->name );
610 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
611 return -ENOTTY_ALGORITHM;
612 }
613
614 return 0;
615}
616
617/**
618 * Parse ASN.1 OID-identified signature algorithm
619 *
620 * @v cursor ASN.1 object cursor
621 * @ret algorithm Algorithm
622 * @ret rc Return status code
623 */
624int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
625 struct asn1_algorithm **algorithm ) {
626 int rc;
627
628 /* Parse algorithm */
629 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
630 return rc;
631
632 /* Check algorithm has a public key */
633 if ( ! (*algorithm)->pubkey ) {
634 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
635 "algorithm:\n", cursor, (*algorithm)->name );
636 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
637 return -ENOTTY_ALGORITHM;
638 }
639
640 /* Check algorithm has a digest */
641 if ( ! (*algorithm)->digest ) {
642 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
643 "algorithm:\n", cursor, (*algorithm)->name );
644 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
645 return -ENOTTY_ALGORITHM;
646 }
647
648 return 0;
649}
650
651/**
652 * Parse ASN.1 OID-identified elliptic curve algorithm
653 *
654 * @v cursor ASN.1 object cursor
655 * @v wrapper Optional wrapper algorithm, or NULL
656 * @ret algorithm Algorithm
657 * @ret rc Return status code
658 */
659int asn1_curve_algorithm ( const struct asn1_cursor *cursor,
660 struct asn1_algorithm *wrapper,
661 struct asn1_algorithm **algorithm ) {
662 struct asn1_cursor curve;
663
664 /* Elliptic curves are identified as either:
665 *
666 * - a wrapper algorithm "id-ecPublicKey" with the actual
667 * curve specified in the algorithm parameters, or
668 *
669 * - a standalone object identifier for the curve
670 */
671 if ( ( wrapper == NULL ) ||
672 ( asn1_check_algorithm ( cursor, wrapper, &curve ) != 0 ) ) {
673 memcpy ( &curve, cursor, sizeof ( curve ) );
674 }
675
676 /* Identify curve */
677 asn1_enter ( &curve, ASN1_OID );
678 *algorithm = asn1_find_algorithm ( &curve );
679 if ( ! *algorithm ) {
680 DBGC ( cursor, "ASN1 %p unrecognised EC algorithm:\n",
681 cursor );
682 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
683 return -ENOTSUP_ALGORITHM;
684 }
685
686 /* Check algorithm has an elliptic curve */
687 if ( ! (*algorithm)->curve ) {
688 DBGC ( cursor, "ASN1 %p algorithm %s is not an elliptic curve "
689 "algorithm:\n", cursor, (*algorithm)->name );
690 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
691 return -ENOTTY_ALGORITHM;
692 }
693
694 return 0;
695}
696
697/**
698 * Check ASN.1 OID-identified algorithm
699 *
700 * @v cursor ASN.1 object cursor
701 * @v expected Expected algorithm
702 * @ret params Algorithm parameters, or NULL
703 * @ret rc Return status code
704 */
705int asn1_check_algorithm ( const struct asn1_cursor *cursor,
706 struct asn1_algorithm *expected,
707 struct asn1_cursor *params ) {
708 struct asn1_algorithm *actual;
709 int rc;
710
711 /* Parse algorithm */
712 if ( ( rc = asn1_algorithm ( cursor, &actual, params ) ) != 0 )
713 return rc;
714
715 /* Check algorithm matches */
716 if ( actual != expected ) {
717 DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
718 cursor, actual->name, expected->name );
719 return -ENOTTY_ALGORITHM;
720 }
721
722 return 0;
723}
724
725/**
726 * Parse ASN.1 CBC cipher parameters
727 *
728 * @v algorithm Algorithm
729 * @v param Parameters to parse
730 * @ret rc Return status code
731 */
733 struct asn1_cursor *params ) {
734 struct cipher_algorithm *cipher = algorithm->cipher;
735
736 /* Sanity check */
737 assert ( cipher != NULL );
738
739 /* Enter parameters */
740 asn1_enter ( params, ASN1_OCTET_STRING );
741
742 /* Check length */
743 if ( params->len != cipher->blocksize )
744 return -EINVAL;
745
746 return 0;
747}
748
749/**
750 * Parse ASN.1 GCM cipher parameters
751 *
752 * @v algorithm Algorithm
753 * @v param Parameters to parse
754 * @ret rc Return status code
755 */
757 struct asn1_cursor *params ) {
758
759 /* Enter parameters */
760 asn1_enter ( params, ASN1_SEQUENCE );
761
762 /* Enter nonce */
763 return asn1_enter ( params, ASN1_OCTET_STRING );
764}
765
766/**
767 * Parse ASN.1 GeneralizedTime
768 *
769 * @v cursor ASN.1 cursor
770 * @v time Time to fill in
771 * @ret rc Return status code
772 *
773 * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
774 * formats for UTCTime and GeneralizedTime, and mandates the
775 * interpretation of centuryless year values.
776 */
777int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
778 struct asn1_cursor contents;
779 unsigned int have_century;
780 unsigned int type;
781 union {
782 struct {
786 uint8_t day;
787 uint8_t hour;
788 uint8_t minute;
789 uint8_t second;
790 } __attribute__ (( packed )) named;
791 uint8_t raw[7];
792 } pairs;
793 struct tm tm;
794 const uint8_t *data;
795 size_t remaining;
796 unsigned int tens;
797 unsigned int units;
798 unsigned int i;
799 int rc;
800
801 /* Determine time format utcTime/generalizedTime */
802 memcpy ( &contents, cursor, sizeof ( contents ) );
803 type = asn1_type ( &contents );
804 switch ( type ) {
805 case ASN1_UTC_TIME:
806 have_century = 0;
807 break;
809 have_century = 1;
810 break;
811 default:
812 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
813 cursor, type );
814 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
815 return -EINVAL_ASN1_TIME;
816 }
817
818 /* Enter utcTime/generalizedTime */
819 if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
820 DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
821 ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
822 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
823 return rc;
824 }
825
826 /* Parse digit string a pair at a time */
827 memset ( &pairs, 0, sizeof ( pairs ) );
828 data = contents.data;
829 remaining = contents.len;
830 for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
831 if ( remaining < 2 ) {
832 /* Some certificates violate the X.509 RFC by
833 * omitting the "seconds" value.
834 */
835 if ( i == ( sizeof ( pairs.raw ) - 1 ) )
836 break;
837 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
838 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
839 return -EINVAL_ASN1_TIME;
840 }
841 tens = data[0];
842 units = data[1];
843 if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
844 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
845 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
846 return -EINVAL_ASN1_TIME;
847 }
848 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
849 data += 2;
850 remaining -= 2;
851 }
852
853 /* Determine century if applicable */
854 if ( ! have_century )
855 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
856
857 /* Check for trailing "Z" */
858 if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
859 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
860 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
861 return -EINVAL_ASN1_TIME;
862 }
863
864 /* Fill in time */
865 tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
866 pairs.named.year );
867 tm.tm_mon = ( pairs.named.month - 1 );
868 tm.tm_mday = pairs.named.day;
869 tm.tm_hour = pairs.named.hour;
870 tm.tm_min = pairs.named.minute;
871 tm.tm_sec = pairs.named.second;
872
873 /* Convert to seconds since the Epoch */
874 *time = mktime ( &tm );
875
876 return 0;
877}
878
879/**
880 * Construct ASN.1 header
881 *
882 * @v header ASN.1 builder header
883 * @v type Type
884 * @v len Content length
885 * @ret header_len Header length
886 */
887static size_t asn1_header ( struct asn1_builder_header *header,
888 unsigned int type, size_t len ) {
889 unsigned int header_len = 2;
890 unsigned int len_len = 0;
891 size_t temp;
892
893 /* Construct header */
894 header->type = type;
895 if ( len < 0x80 ) {
896 header->length[0] = len;
897 } else {
898 for ( temp = len ; temp ; temp >>= 8 )
899 len_len++;
900 header->length[0] = ( 0x80 | len_len );
901 header_len += len_len;
902 for ( temp = len ; temp ; temp >>= 8 )
903 header->length[len_len--] = ( temp & 0xff );
904 }
905
906 return header_len;
907}
908
909/**
910 * Grow ASN.1 builder
911 *
912 * @v builder ASN.1 builder
913 * @v extra Extra space to prepend
914 * @ret rc Return status code
915 */
916int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
917 size_t new_len;
918 void *new;
919
920 /* As with the ASN1 parsing functions, make errors permanent */
921 if ( builder->len && ! builder->data )
922 return -ENOMEM;
923
924 /* Reallocate data buffer */
925 new_len = ( builder->len + extra );
926 new = realloc ( builder->data, new_len );
927 if ( ! new ) {
928 free ( builder->data );
929 builder->data = NULL;
930 return -ENOMEM;
931 }
932 builder->data = new;
933
934 /* Move existing data to end of buffer */
935 memmove ( ( builder->data + extra ), builder->data, builder->len );
936 builder->len = new_len;
937
938 return 0;
939}
940
941/**
942 * Prepend raw data to ASN.1 builder
943 *
944 * @v builder ASN.1 builder
945 * @v data Data to prepend
946 * @v len Length of data to prepend
947 * @ret rc Return status code
948 */
949int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
950 size_t len ) {
951 int rc;
952
953 /* Grow buffer */
954 if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
955 return rc;
956
957 /* Populate data buffer */
958 memcpy ( builder->data, data, len );
959
960 return 0;
961}
962
963/**
964 * Prepend data to ASN.1 builder
965 *
966 * @v builder ASN.1 builder
967 * @v type Type
968 * @v data Data to prepend
969 * @v len Length of data to prepend
970 * @ret rc Return status code
971 */
972int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
973 const void *data, size_t len ) {
975 size_t header_len;
976 int rc;
977
978 /* Construct header */
979 header_len = asn1_header ( &header, type, len );
980
981 /* Grow buffer */
982 if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
983 return rc;
984
985 /* Populate data buffer */
986 memcpy ( builder->data, &header, header_len );
987 memcpy ( ( builder->data + header_len ), data, len );
988
989 return 0;
990}
991
992/**
993 * Wrap ASN.1 builder
994 *
995 * @v builder ASN.1 builder
996 * @v type Type
997 * @ret rc Return status code
998 */
999int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
1001 size_t header_len;
1002 int rc;
1003
1004 /* Construct header */
1005 header_len = asn1_header ( &header, type, builder->len );
1006
1007 /* Grow buffer */
1008 if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
1009 return rc;
1010
1011 /* Populate data buffer */
1012 memcpy ( builder->data, &header, header_len );
1013
1014 return 0;
1015}
1016
1017/**
1018 * Extract ASN.1 object from image
1019 *
1020 * @v image Image
1021 * @v offset Offset within image
1022 * @v cursor ASN.1 cursor to fill in
1023 * @ret next Offset to next image, or negative error
1024 *
1025 * The caller is responsible for eventually calling free() on the
1026 * allocated ASN.1 cursor.
1027 */
1028int image_asn1 ( struct image *image, size_t offset,
1029 struct asn1_cursor **cursor ) {
1030 int next;
1031 int rc;
1032
1033 /* Sanity check */
1035
1036 /* Check that this image can be used to extract an ASN.1 object */
1037 if ( ! ( image->type && image->type->asn1 ) )
1038 return -ENOTSUP;
1039
1040 /* Try creating ASN.1 cursor */
1041 next = image->type->asn1 ( image, offset, cursor );
1042 if ( next < 0 ) {
1043 rc = next;
1044 DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
1045 image->name, strerror ( rc ) );
1046 return rc;
1047 }
1048
1049 return next;
1050}
1051
1052/* Drag in objects via image_asn1() */
1054
1055/* Drag in ASN.1 image formats */
1056REQUIRE_OBJECT ( config_asn1 );
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__be32 raw[7]
Definition CIB_PRM.h:0
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
signed char int8_t
Definition stdint.h:15
int asn1_cipher_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
Parse ASN.1 OID-identified cipher algorithm.
Definition asn1.c:597
#define EINVAL_ASN1_LEN_LEN
Definition asn1.c:50
int asn1_prepend(struct asn1_builder *builder, unsigned int type, const void *data, size_t len)
Prepend data to ASN.1 builder.
Definition asn1.c:972
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:949
int asn1_enter_unsigned(struct asn1_cursor *cursor)
Enter ASN.1 unsigned integer.
Definition asn1.c:369
#define EINVAL_ASN1_BOOLEAN
Definition asn1.c:58
#define EINVAL_ASN1_INTEGER
Definition asn1.c:62
#define EINVAL_BIT_STRING
Definition asn1.c:74
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:290
int asn1_check_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm *expected, struct asn1_cursor *params)
Check ASN.1 OID-identified algorithm.
Definition asn1.c:705
int asn1_generalized_time(const struct asn1_cursor *cursor, time_t *time)
Parse ASN.1 GeneralizedTime.
Definition asn1.c:777
int asn1_boolean(const struct asn1_cursor *cursor)
Parse value of ASN.1 boolean.
Definition asn1.c:392
int asn1_digest_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified digest algorithm.
Definition asn1.c:570
#define EINVAL_ASN1_EMPTY
Definition asn1.c:46
static size_t asn1_header(struct asn1_builder_header *header, unsigned int type, size_t len)
Construct ASN.1 header.
Definition asn1.c:887
int asn1_curve_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm *wrapper, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified elliptic curve algorithm.
Definition asn1.c:659
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:916
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:169
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:280
int image_asn1(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition asn1.c:1028
#define ENOTSUP_ALGORITHM
Definition asn1.c:78
int asn1_parse_cbc(struct asn1_algorithm *algorithm, struct asn1_cursor *params)
Parse ASN.1 CBC cipher parameters.
Definition asn1.c:732
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:231
int asn1_pubkey_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified public-key algorithm.
Definition asn1.c:544
#define EINVAL_ASN1_ALGORITHM
Definition asn1.c:70
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:311
static struct asn1_algorithm * asn1_find_algorithm(const struct asn1_cursor *cursor)
Identify ASN.1 algorithm by OID.
Definition asn1.c:475
static int asn1_start(struct asn1_cursor *cursor, unsigned int type)
Start parsing ASN.1 object.
Definition asn1.c:103
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:300
#define ENOTTY_ALGORITHM
Definition asn1.c:82
int asn1_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
Parse ASN.1 OID-identified algorithm.
Definition asn1.c:494
#define EINVAL_ASN1_TIME
Definition asn1.c:66
int asn1_integer(const struct asn1_cursor *cursor, int *value)
Parse value of ASN.1 integer.
Definition asn1.c:416
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:458
int asn1_signature_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified signature algorithm.
Definition asn1.c:624
int asn1_parse_gcm(struct asn1_algorithm *algorithm __unused, struct asn1_cursor *params)
Parse ASN.1 GCM cipher parameters.
Definition asn1.c:756
#define EINVAL_ASN1_LEN
Definition asn1.c:54
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition asn1.c:999
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:254
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:202
ASN.1 encoding.
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_BIT_STRING
ASN.1 bit string.
Definition asn1.h:66
#define ASN1_ANY
ASN.1 "any tag" magic value.
Definition asn1.h:102
#define ASN1_OID
ASN.1 object identifier.
Definition asn1.h:75
static void asn1_invalidate_cursor(struct asn1_cursor *cursor)
Invalidate ASN.1 object cursor.
Definition asn1.h:468
#define ASN1_ALGORITHMS
ASN.1 OID-identified algorithms.
Definition asn1.h:433
#define ASN1_BOOLEAN
ASN.1 boolean.
Definition asn1.h:60
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90
#define ASN1_UTC_TIME
ASN.1 UTC time.
Definition asn1.h:84
#define ASN1_GENERALIZED_TIME
ASN.1 generalized time.
Definition asn1.h:87
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
static unsigned int asn1_type(const struct asn1_cursor *cursor)
Extract ASN.1 type.
Definition asn1.h:479
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
Character types.
static int isdigit(int character)
Check if character is a decimal digit.
Definition ctype.h:30
uint32_t next
Next descriptor address.
Definition dwmac.h:11
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
struct ena_llq_option header
Header locations.
Definition ena.h:5
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:202
#define ENXIO
No such device or address.
Definition errno.h:600
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition ieee80211.h:1
Executable images.
#define __attribute__(x)
Definition compiler.h:10
Cryptographic API.
uint8_t extra
Signature extra byte.
Definition smbios.h:6
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void * memmove(void *dest, const void *src, size_t len) __nonnull
int64_t time_t
Seconds since the Epoch.
Definition time.h:19
Date and time.
uint8_t unused
Unused.
Definition librm.h:5
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition malloc.c:607
uint32_t end
Ending offset.
Definition netvsc.h:7
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ASN.1 OID-identified algorithm.
Definition asn1.h:408
const char * name
Name.
Definition asn1.h:410
An ASN.1 header.
Definition asn1.h:49
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A cipher algorithm.
Definition crypto.h:51
size_t blocksize
Block size.
Definition crypto.h:61
int(* asn1)(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition image.h:133
An executable image.
Definition image.h:24
struct image_type * type
Image type, if known.
Definition image.h:59
char * name
Name.
Definition image.h:38
Broken-down time.
Definition time.h:16
int tm_mon
Month of year [0,11].
Definition time.h:26
int tm_year
Years since 1900.
Definition time.h:28
int tm_hour
Hour [0,23].
Definition time.h:22
int tm_sec
Seconds [0,60].
Definition time.h:18
int tm_mday
Day of month [1,31].
Definition time.h:24
int tm_min
Minutes [0,59].
Definition time.h:20
Linker tables.
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
time_t mktime(struct tm *tm)
Calculate seconds since the Epoch.
Definition time.c:118
uint8_t month
Month (BCD)
Definition ucode.h:7
uint8_t day
Day (BCD)
Definition ucode.h:5
uint8_t year
Year (BCD)
Definition ucode.h:1
uint8_t century
Century (BCD)
Definition ucode.h:3