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