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 ENOTSUP_HIGH \
155 __einfo_error ( EINFO_ENOTSUP_HIGH )
156#define EINFO_ENOTSUP_HIGH \
157 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported high tag number" )
158#define ENOTTY_ALGORITHM \
159 __einfo_error ( EINFO_ENOTTY_ALGORITHM )
160#define EINFO_ENOTTY_ALGORITHM \
161 __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" )
162
163/**
164 * Start parsing ASN.1 object
165 *
166 * @v cursor ASN.1 object cursor
167 * @v type Expected type, or ASN1_ANY
168 * @ret len Length of object body, or negative error
169 *
170 * The object cursor will be updated to point to the start of the
171 * object body (i.e. the first byte following the length byte(s)), and
172 * the length of the object body (i.e. the number of bytes until the
173 * following object tag, if any) is returned.
174 *
175 * If the expected type is not found, the object cursor will not be
176 * modified. If any other error occurs, the object cursor will be
177 * invalidated.
178 */
179static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
180 unsigned int len_len;
181 unsigned int len;
182 uint8_t high_byte;
183
184 /* Sanity check */
185 if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
186 if ( cursor->len )
187 DBGC ( cursor, "ASN1 %p too short\n", cursor );
188 asn1_invalidate_cursor ( cursor );
189 return -EINVAL_ASN1_EMPTY;
190 }
191
192 /* Refuse to handle multi-byte tags */
193 if ( ( asn1_type ( cursor ) & ASN1_HIGH ) == ASN1_HIGH ) {
194 DBGC ( cursor, "ASN1 %p has unsupported high tag number\n",
195 cursor );
196 asn1_invalidate_cursor ( cursor );
197 return -ENOTSUP_HIGH;
198 }
199
200 /* Check the tag byte */
201 if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
202 DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
203 cursor, type, *( ( uint8_t * ) cursor->data ) );
204 return -ENXIO;
205 }
206 cursor->data++;
207 cursor->len--;
208
209 /* Extract length of the length field and sanity check */
210 len_len = *( ( uint8_t * ) cursor->data );
211 if ( len_len & 0x80 ) {
212 len_len = ( len_len & 0x7f );
213 cursor->data++;
214 cursor->len--;
215 } else {
216 len_len = 1;
217 }
218 if ( ( len_len == 0 ) || ( cursor->len < len_len ) ) {
219 DBGC ( cursor, "ASN1 %p bad length field length %d (min 0, "
220 "max %zd)\n", cursor, len_len, cursor->len );
221 asn1_invalidate_cursor ( cursor );
222 return -EINVAL_ASN1_LEN_LEN;
223 }
224
225 /* Extract the length and sanity check */
226 for ( len = 0 ; len_len ; len_len-- ) {
227 high_byte = ( len >> ( 8 * ( sizeof ( len ) - 1 ) ) );
228 if ( high_byte ) {
229 DBGC ( cursor, "ASN1 %p unrepresentable length\n",
230 cursor );
231 asn1_invalidate_cursor ( cursor );
232 return -EINVAL_ASN1_LEN;
233 }
234 len <<= 8;
235 len |= *( ( uint8_t * ) cursor->data );
236 cursor->data++;
237 cursor->len--;
238 }
239 if ( ( cursor->len < len ) || ( ( ( int ) len ) < 0 ) ) {
240 DBGC ( cursor, "ASN1 %p bad length %d (min 0, max %zd)\n",
241 cursor, len, cursor->len );
242 asn1_invalidate_cursor ( cursor );
243 return -EINVAL_ASN1_LEN;
244 }
245
246 return len;
247}
248
249/**
250 * Enter ASN.1 object
251 *
252 * @v cursor ASN.1 object cursor
253 * @v type Expected type, or ASN1_ANY
254 * @ret rc Return status code
255 *
256 * The object cursor will be updated to point to the body of the
257 * current ASN.1 object.
258 *
259 * If any error occurs, the object cursor will be invalidated.
260 */
261int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
262 int len;
263
264 /* Parse current object */
265 len = asn1_start ( cursor, type );
266 if ( len < 0 ) {
267 asn1_invalidate_cursor ( cursor );
268 return len;
269 }
270
271 /* Update cursor */
272 if ( ( ( size_t ) len ) <= cursor->len )
273 cursor->len = len;
274
275 DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
276 cursor, type, len );
277 return 0;
278}
279
280/**
281 * Skip ASN.1 object if present
282 *
283 * @v cursor ASN.1 object cursor
284 * @v type Expected type, or ASN1_ANY
285 * @ret rc Return status code
286 *
287 * The object cursor will be updated to point to the next ASN.1
288 * object.
289 *
290 * If the expected type is not found, the object cursor will not be
291 * modified. If any other error occurs, the object cursor will be
292 * invalidated.
293 */
294int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
295 int len;
296
297 /* Parse current object */
298 len = asn1_start ( cursor, type );
299 if ( len < 0 )
300 return len;
301
302 /* Update cursor */
303 cursor->data += len;
304 cursor->len -= len;
305
306 DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
307 cursor, type, len );
308 return 0;
309}
310
311/**
312 * Skip ASN.1 object
313 *
314 * @v cursor ASN.1 object cursor
315 * @v type Expected type, or ASN1_ANY
316 * @ret rc Return status code
317 *
318 * The object cursor will be updated to point to the next ASN.1
319 * object.
320 *
321 * If any error occurs, the object cursor will be invalidated.
322 */
323int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
324 int rc;
325
326 if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
327 asn1_invalidate_cursor ( cursor );
328 return rc;
329 }
330
331 return 0;
332}
333
334/**
335 * Shrink ASN.1 cursor to fit object
336 *
337 * @v cursor ASN.1 object cursor
338 * @v type Expected type, or ASN1_ANY
339 * @ret rc Return status code
340 *
341 * The object cursor will be shrunk to contain only the current ASN.1
342 * object.
343 *
344 * If any error occurs, the object cursor will be invalidated.
345 */
346int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
347 struct asn1_cursor temp;
348 const void *end;
349 int len;
350
351 /* Find end of object */
352 memcpy ( &temp, cursor, sizeof ( temp ) );
353 len = asn1_start ( &temp, type );
354 if ( len < 0 ) {
355 asn1_invalidate_cursor ( cursor );
356 return len;
357 }
358 end = ( temp.data + len );
359
360 /* Shrink original cursor to contain only its first object */
361 cursor->len = ( end - cursor->data );
362
363 return 0;
364}
365
366/**
367 * Enter ASN.1 object of any type
368 *
369 * @v cursor ASN.1 object cursor
370 * @ret rc Return status code
371 */
372int asn1_enter_any ( struct asn1_cursor *cursor ) {
373 return asn1_enter ( cursor, ASN1_ANY );
374}
375
376/**
377 * Skip ASN.1 object of any type
378 *
379 * @v cursor ASN.1 object cursor
380 * @ret rc Return status code
381 */
382int asn1_skip_any ( struct asn1_cursor *cursor ) {
383 return asn1_skip ( cursor, ASN1_ANY );
384}
385
386/**
387 * Shrink ASN.1 object of any type
388 *
389 * @v cursor ASN.1 object cursor
390 * @ret rc Return status code
391 */
392int asn1_shrink_any ( struct asn1_cursor *cursor ) {
393 return asn1_shrink ( cursor, ASN1_ANY );
394}
395
396/**
397 * Enter ASN.1 bit string
398 *
399 * @v cursor ASN.1 cursor
400 * @v unused Unused bits to fill in (or NULL to require all used)
401 * @ret rc Return status code
402 */
403int asn1_enter_bits ( struct asn1_cursor *cursor, unsigned int *unused ) {
404 const struct {
406 uint8_t data[0];
407 } __attribute__ (( packed )) *bit_string;
408 const uint8_t *last;
409 unsigned int unused_bits;
410 int rc;
411
412 /* Enter bit string */
413 if ( ( rc = asn1_enter ( cursor, ASN1_BIT_STRING ) ) != 0 )
414 return rc;
415
416 /* Check that bit string header exists */
417 if ( cursor->len < sizeof ( *bit_string ) ) {
418 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
419 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
420 asn1_invalidate_cursor ( cursor );
421 return -EINVAL_BIT_STRING;
422 }
423 bit_string = cursor->data;
424 last = ( cursor->data + cursor->len - 1 );
425 cursor->data = &bit_string->data;
426 cursor->len -= offsetof ( typeof ( *bit_string ), data );
427 unused_bits = bit_string->unused;
428
429 /* Check validity of unused bits */
430 if ( ( unused_bits >= 8 ) ||
431 ( ( unused_bits > 0 ) && ( cursor->len == 0 ) ) ||
432 ( ( *last & ( 0xffU >> ( 8 - unused_bits ) ) ) != 0 ) ) {
433 DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
434 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
435 asn1_invalidate_cursor ( cursor );
436 return -EINVAL_BIT_STRING;
437 }
438
439 /* Record or check number of unused bits, as applicable */
440 if ( unused ) {
441 *unused = unused_bits;
442 } else if ( unused_bits ) {
443 DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
444 cursor );
445 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
446 asn1_invalidate_cursor ( cursor );
447 return -EINVAL_BIT_STRING;
448 }
449
450 return 0;
451}
452
453/**
454 * Enter ASN.1 unsigned integer
455 *
456 * @v cursor ASN.1 object cursor
457 * @ret rc Return status code
458 */
459int asn1_enter_unsigned ( struct asn1_cursor *cursor ) {
460 uint8_t msb;
461 int rc;
462
463 /* Enter integer */
464 if ( ( rc = asn1_enter ( cursor, ASN1_INTEGER ) ) != 0 )
465 return rc;
466
467 /* Reject empty integers */
468 if ( ! cursor->len ) {
469 DBGC ( cursor, "ASN1 %p empty unsigned integer\n", cursor );
470 /* Cursor is already invalid */
471 return -EINVAL;
472 }
473
474 /* Reject negative values */
475 msb = *( ( uint8_t * ) cursor->data );
476 if ( msb & 0x80 ) {
477 DBGC ( cursor, "ASN1 %p negative unsigned integer:\n",
478 cursor );
479 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
480 asn1_invalidate_cursor ( cursor );
481 return -EINVAL;
482 }
483
484 /* Skip any initial positive sign byte(s) */
485 while ( ( cursor->len > 1 ) && ( msb == 0x00 ) ) {
486 cursor->data++;
487 cursor->len--;
488 msb = *( ( uint8_t * ) cursor->data );
489 }
490
491 return 0;
492}
493
494/**
495 * Parse value of ASN.1 boolean
496 *
497 * @v cursor ASN.1 object cursor
498 * @ret value Value, or negative error
499 */
500int asn1_boolean ( const struct asn1_cursor *cursor ) {
501 struct asn1_cursor contents;
502 const struct {
504 } __attribute__ (( packed )) *boolean;
505
506 /* Enter boolean */
507 memcpy ( &contents, cursor, sizeof ( contents ) );
508 asn1_enter ( &contents, ASN1_BOOLEAN );
509 if ( contents.len != sizeof ( *boolean ) )
510 return -EINVAL_ASN1_BOOLEAN;
511
512 /* Extract value */
513 boolean = contents.data;
514 return boolean->value;
515}
516
517/**
518 * Parse value of ASN.1 integer
519 *
520 * @v cursor ASN.1 object cursor
521 * @v value Value to fill in
522 * @ret rc Return status code
523 */
524int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
525 struct asn1_cursor contents;
526 uint8_t high_byte;
527 int rc;
528
529 /* Enter integer */
530 memcpy ( &contents, cursor, sizeof ( contents ) );
531 if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
532 return rc;
533 if ( contents.len < 1 )
534 return -EINVAL_ASN1_INTEGER;
535
536 /* Initialise value according to sign byte */
537 *value = *( ( int8_t * ) contents.data );
538 contents.data++;
539 contents.len--;
540
541 /* Process value */
542 while ( contents.len ) {
543 high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
544 if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
545 DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
546 return -EINVAL_ASN1_INTEGER;
547 }
548 *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
549 contents.data++;
550 contents.len--;
551 }
552
553 return 0;
554}
555
556/**
557 * Compare two ASN.1 objects
558 *
559 * @v cursor1 ASN.1 object cursor
560 * @v cursor2 ASN.1 object cursor
561 * @ret difference Difference as returned by memcmp()
562 *
563 * Note that invalid and empty cursors will compare as equal with each
564 * other.
565 */
566int asn1_compare ( const struct asn1_cursor *cursor1,
567 const struct asn1_cursor *cursor2 ) {
568 int difference;
569
570 difference = ( cursor2->len - cursor1->len );
571 return ( difference ? difference :
572 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
573}
574
575/**
576 * Identify ASN.1 algorithm by OID
577 *
578 * @v cursor ASN.1 object cursor
579
580 * @ret algorithm Algorithm, or NULL
581 */
582static struct asn1_algorithm *
583asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
585
587 if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
588 return algorithm;
589 }
590
591 return NULL;
592}
593
594/**
595 * Parse ASN.1 OID-identified algorithm
596 *
597 * @v cursor ASN.1 object cursor
598 * @ret algorithm Algorithm
599 * @ret params Algorithm parameters, or NULL
600 * @ret rc Return status code
601 */
602int asn1_algorithm ( const struct asn1_cursor *cursor,
603 struct asn1_algorithm **algorithm,
604 struct asn1_cursor *params ) {
605 struct asn1_cursor contents;
606 int rc;
607
608 /* Enter algorithm */
609 memcpy ( &contents, cursor, sizeof ( contents ) );
610 asn1_enter ( &contents, ASN1_SEQUENCE );
611
612 /* Get raw parameters, if applicable */
613 if ( params ) {
614 memcpy ( params, &contents, sizeof ( *params ) );
615 asn1_skip_any ( params );
616 }
617
618 /* Enter algorithm identifier */
619 if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
620 DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
621 cursor );
622 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
623 return -EINVAL_ASN1_ALGORITHM;
624 }
625
626 /* Identify algorithm */
627 *algorithm = asn1_find_algorithm ( &contents );
628 if ( ! *algorithm ) {
629 DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
630 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
631 return -ENOTSUP_ALGORITHM;
632 }
633
634 /* Parse parameters, if applicable */
635 if ( params && (*algorithm)->parse &&
636 ( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
637 DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
638 cursor, (*algorithm)->name, strerror ( rc ) );
639 return rc;
640 }
641
642 return 0;
643}
644
645/**
646 * Parse ASN.1 OID-identified public-key algorithm
647 *
648 * @v cursor ASN.1 object cursor
649 * @ret algorithm Algorithm
650 * @ret rc Return status code
651 */
652int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
653 struct asn1_algorithm **algorithm ) {
654 int rc;
655
656 /* Parse algorithm */
657 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
658 return rc;
659
660 /* Check algorithm has a public key */
661 if ( ! (*algorithm)->pubkey ) {
662 DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
663 "algorithm:\n", cursor, (*algorithm)->name );
664 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
665 return -ENOTTY_ALGORITHM;
666 }
667
668 return 0;
669}
670
671/**
672 * Parse ASN.1 OID-identified digest algorithm
673 *
674 * @v cursor ASN.1 object cursor
675 * @ret algorithm Algorithm
676 * @ret rc Return status code
677 */
678int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
679 struct asn1_algorithm **algorithm ) {
680 int rc;
681
682 /* Parse algorithm */
683 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
684 return rc;
685
686 /* Check algorithm has a digest */
687 if ( ! (*algorithm)->digest ) {
688 DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
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 * Parse ASN.1 OID-identified cipher algorithm
699 *
700 * @v cursor ASN.1 object cursor
701 * @ret algorithm Algorithm
702 * @ret params Algorithm parameters, or NULL
703 * @ret rc Return status code
704 */
705int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
706 struct asn1_algorithm **algorithm,
707 struct asn1_cursor *params ) {
708 int rc;
709
710 /* Parse algorithm */
711 if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
712 return rc;
713
714 /* Check algorithm has a cipher */
715 if ( ! (*algorithm)->cipher ) {
716 DBGC ( cursor, "ASN1 %p algorithm %s is not a cipher "
717 "algorithm:\n", cursor, (*algorithm)->name );
718 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
719 return -ENOTTY_ALGORITHM;
720 }
721
722 return 0;
723}
724
725/**
726 * Parse ASN.1 OID-identified signature algorithm
727 *
728 * @v cursor ASN.1 object cursor
729 * @ret algorithm Algorithm
730 * @ret rc Return status code
731 */
732int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
733 struct asn1_algorithm **algorithm ) {
734 int rc;
735
736 /* Parse algorithm */
737 if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
738 return rc;
739
740 /* Check algorithm has a public key */
741 if ( ! (*algorithm)->pubkey ) {
742 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
743 "algorithm:\n", cursor, (*algorithm)->name );
744 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
745 return -ENOTTY_ALGORITHM;
746 }
747
748 /* Check algorithm has a digest */
749 if ( ! (*algorithm)->digest ) {
750 DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
751 "algorithm:\n", cursor, (*algorithm)->name );
752 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
753 return -ENOTTY_ALGORITHM;
754 }
755
756 return 0;
757}
758
759/**
760 * Parse ASN.1 OID-identified elliptic curve algorithm
761 *
762 * @v cursor ASN.1 object cursor
763 * @v wrapper Optional wrapper algorithm, or NULL
764 * @ret algorithm Algorithm
765 * @ret rc Return status code
766 */
767int asn1_curve_algorithm ( const struct asn1_cursor *cursor,
768 struct asn1_algorithm *wrapper,
769 struct asn1_algorithm **algorithm ) {
770 struct asn1_cursor curve;
771
772 /* Elliptic curves are identified as either:
773 *
774 * - a wrapper algorithm "id-ecPublicKey" with the actual
775 * curve specified in the algorithm parameters, or
776 *
777 * - a standalone object identifier for the curve
778 */
779 if ( ( wrapper == NULL ) ||
780 ( asn1_check_algorithm ( cursor, wrapper, &curve ) != 0 ) ) {
781 memcpy ( &curve, cursor, sizeof ( curve ) );
782 }
783
784 /* Identify curve */
785 asn1_enter ( &curve, ASN1_OID );
786 *algorithm = asn1_find_algorithm ( &curve );
787 if ( ! *algorithm ) {
788 DBGC ( cursor, "ASN1 %p unrecognised EC algorithm:\n",
789 cursor );
790 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
791 return -ENOTSUP_ALGORITHM;
792 }
793
794 /* Check algorithm has an elliptic curve */
795 if ( ! (*algorithm)->curve ) {
796 DBGC ( cursor, "ASN1 %p algorithm %s is not an elliptic curve "
797 "algorithm:\n", cursor, (*algorithm)->name );
798 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
799 return -ENOTTY_ALGORITHM;
800 }
801
802 return 0;
803}
804
805/**
806 * Check ASN.1 OID-identified algorithm
807 *
808 * @v cursor ASN.1 object cursor
809 * @v expected Expected algorithm
810 * @ret params Algorithm parameters, or NULL
811 * @ret rc Return status code
812 */
813int asn1_check_algorithm ( const struct asn1_cursor *cursor,
814 struct asn1_algorithm *expected,
815 struct asn1_cursor *params ) {
816 struct asn1_algorithm *actual;
817 int rc;
818
819 /* Parse algorithm */
820 if ( ( rc = asn1_algorithm ( cursor, &actual, params ) ) != 0 )
821 return rc;
822
823 /* Check algorithm matches */
824 if ( actual != expected ) {
825 DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
826 cursor, actual->name, expected->name );
827 return -ENOTTY_ALGORITHM;
828 }
829
830 return 0;
831}
832
833/**
834 * Parse ASN.1 CBC cipher parameters
835 *
836 * @v algorithm Algorithm
837 * @v param Parameters to parse
838 * @ret rc Return status code
839 */
841 struct asn1_cursor *params ) {
842 struct cipher_algorithm *cipher = algorithm->cipher;
843
844 /* Sanity check */
845 assert ( cipher != NULL );
846
847 /* Enter parameters */
848 asn1_enter ( params, ASN1_OCTET_STRING );
849
850 /* Check length */
851 if ( params->len != cipher->blocksize )
852 return -EINVAL;
853
854 return 0;
855}
856
857/**
858 * Parse ASN.1 GCM cipher parameters
859 *
860 * @v algorithm Algorithm
861 * @v param Parameters to parse
862 * @ret rc Return status code
863 */
865 struct asn1_cursor *params ) {
866
867 /* Enter parameters */
868 asn1_enter ( params, ASN1_SEQUENCE );
869
870 /* Enter nonce */
871 return asn1_enter ( params, ASN1_OCTET_STRING );
872}
873
874/**
875 * Parse ASN.1 GeneralizedTime
876 *
877 * @v cursor ASN.1 cursor
878 * @v time Time to fill in
879 * @ret rc Return status code
880 *
881 * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
882 * formats for UTCTime and GeneralizedTime, and mandates the
883 * interpretation of centuryless year values.
884 */
885int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
886 struct asn1_cursor contents;
887 unsigned int have_century;
888 unsigned int type;
889 union {
890 struct {
894 uint8_t day;
895 uint8_t hour;
896 uint8_t minute;
897 uint8_t second;
898 } __attribute__ (( packed )) named;
899 uint8_t raw[7];
900 } pairs;
901 struct tm tm;
902 const uint8_t *data;
903 size_t remaining;
904 unsigned int tens;
905 unsigned int units;
906 unsigned int i;
907 int rc;
908
909 /* Determine time format utcTime/generalizedTime */
910 memcpy ( &contents, cursor, sizeof ( contents ) );
911 type = asn1_type ( &contents );
912 switch ( type ) {
913 case ASN1_UTC_TIME:
914 have_century = 0;
915 break;
917 have_century = 1;
918 break;
919 default:
920 DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
921 cursor, type );
922 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
923 return -EINVAL_ASN1_TIME;
924 }
925
926 /* Enter utcTime/generalizedTime */
927 if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
928 DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
929 ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
930 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
931 return rc;
932 }
933
934 /* Parse digit string a pair at a time */
935 memset ( &pairs, 0, sizeof ( pairs ) );
936 data = contents.data;
937 remaining = contents.len;
938 for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
939 if ( remaining < 2 ) {
940 /* Some certificates violate the X.509 RFC by
941 * omitting the "seconds" value.
942 */
943 if ( i == ( sizeof ( pairs.raw ) - 1 ) )
944 break;
945 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
946 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
947 return -EINVAL_ASN1_TIME;
948 }
949 tens = data[0];
950 units = data[1];
951 if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
952 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
953 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
954 return -EINVAL_ASN1_TIME;
955 }
956 pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
957 data += 2;
958 remaining -= 2;
959 }
960
961 /* Determine century if applicable */
962 if ( ! have_century )
963 pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
964
965 /* Check for trailing "Z" */
966 if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
967 DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
968 DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
969 return -EINVAL_ASN1_TIME;
970 }
971
972 /* Fill in time */
973 tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
974 pairs.named.year );
975 tm.tm_mon = ( pairs.named.month - 1 );
976 tm.tm_mday = pairs.named.day;
977 tm.tm_hour = pairs.named.hour;
978 tm.tm_min = pairs.named.minute;
979 tm.tm_sec = pairs.named.second;
980
981 /* Convert to seconds since the Epoch */
982 *time = mktime ( &tm );
983
984 return 0;
985}
986
987/**
988 * Construct ASN.1 header
989 *
990 * @v header ASN.1 builder header
991 * @v type Type
992 * @v len Content length
993 * @ret header_len Header length
994 */
995static size_t asn1_header ( struct asn1_builder_header *header,
996 unsigned int type, size_t len ) {
997 unsigned int header_len = 2;
998 unsigned int len_len = 0;
999 size_t temp;
1000
1001 /* Construct header */
1002 header->type = type;
1003 if ( len < 0x80 ) {
1004 header->length[0] = len;
1005 } else {
1006 for ( temp = len ; temp ; temp >>= 8 )
1007 len_len++;
1008 header->length[0] = ( 0x80 | len_len );
1009 header_len += len_len;
1010 for ( temp = len ; temp ; temp >>= 8 )
1011 header->length[len_len--] = ( temp & 0xff );
1012 }
1013
1014 return header_len;
1015}
1016
1017/**
1018 * Calculate ASN.1 header length
1019 *
1020 * @v len Content length
1021 * @ret header_len Header length
1022 */
1023size_t asn1_header_len ( size_t len ) {
1025
1026 return asn1_header ( &header, ASN1_ANY, len );
1027}
1028
1029/**
1030 * Grow ASN.1 builder
1031 *
1032 * @v builder ASN.1 builder
1033 * @v extra Extra space to prepend
1034 * @ret rc Return status code
1035 */
1036int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
1037 size_t new_len;
1038 void *new;
1039
1040 /* As with the ASN1 parsing functions, make errors permanent */
1041 if ( builder->len && ! builder->data )
1042 return -ENOMEM;
1043
1044 /* Reallocate data buffer */
1045 new_len = ( builder->len + extra );
1046 new = realloc ( builder->data, new_len );
1047 if ( ! new ) {
1048 zfree ( builder->data );
1049 builder->data = NULL;
1050 return -ENOMEM;
1051 }
1052 builder->data = new;
1053
1054 /* Move existing data to end of buffer */
1055 memmove ( ( builder->data + extra ), builder->data, builder->len );
1056 builder->len = new_len;
1057
1058 return 0;
1059}
1060
1061/**
1062 * Prepend raw data to ASN.1 builder
1063 *
1064 * @v builder ASN.1 builder
1065 * @v data Data to prepend
1066 * @v len Length of data to prepend
1067 * @ret rc Return status code
1068 */
1069int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
1070 size_t len ) {
1071 int rc;
1072
1073 /* Grow buffer */
1074 if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
1075 return rc;
1076
1077 /* Populate data buffer */
1078 memcpy ( builder->data, data, len );
1079
1080 return 0;
1081}
1082
1083/**
1084 * Prepend data to ASN.1 builder
1085 *
1086 * @v builder ASN.1 builder
1087 * @v type Type
1088 * @v data Data to prepend
1089 * @v len Length of data to prepend
1090 * @ret rc Return status code
1091 */
1092int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
1093 const void *data, size_t len ) {
1095 size_t header_len;
1096 int rc;
1097
1098 /* Construct header */
1099 header_len = asn1_header ( &header, type, len );
1100
1101 /* Grow buffer */
1102 if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
1103 return rc;
1104
1105 /* Populate data buffer */
1106 memcpy ( builder->data, &header, header_len );
1107 memcpy ( ( builder->data + header_len ), data, len );
1108
1109 return 0;
1110}
1111
1112/**
1113 * Wrap ASN.1 builder
1114 *
1115 * @v builder ASN.1 builder
1116 * @v type Type
1117 * @ret rc Return status code
1118 */
1119int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
1121 size_t header_len;
1122 int rc;
1123
1124 /* Construct header */
1125 header_len = asn1_header ( &header, type, builder->len );
1126
1127 /* Grow buffer */
1128 if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
1129 return rc;
1130
1131 /* Populate data buffer */
1132 memcpy ( builder->data, &header, header_len );
1133
1134 return 0;
1135}
1136
1137/**
1138 * Extract ASN.1 object from image
1139 *
1140 * @v image Image
1141 * @v offset Offset within image
1142 * @v cursor ASN.1 cursor to fill in
1143 * @ret next Offset to next image, or negative error
1144 *
1145 * The caller is responsible for eventually calling free() on the
1146 * allocated ASN.1 cursor.
1147 */
1148int image_asn1 ( struct image *image, size_t offset,
1149 struct asn1_cursor **cursor ) {
1150 int next;
1151 int rc;
1152
1153 /* Sanity check */
1155
1156 /* Check that this image can be used to extract an ASN.1 object */
1157 if ( ! ( image->type && image->type->asn1 ) )
1158 return -ENOTSUP;
1159
1160 /* Try creating ASN.1 cursor */
1161 next = image->type->asn1 ( image, offset, cursor );
1162 if ( next < 0 ) {
1163 rc = next;
1164 DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
1165 image->name, strerror ( rc ) );
1166 return rc;
1167 }
1168
1169 return next;
1170}
1171
1172/* Drag in objects via image_asn1() */
1174
1175/* Drag in ASN.1 image formats */
1176REQUIRE_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:705
#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:1092
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:1069
int asn1_enter_unsigned(struct asn1_cursor *cursor)
Enter ASN.1 unsigned integer.
Definition asn1.c:459
#define EINVAL_ASN1_BOOLEAN
Definition asn1.c:130
#define EINVAL_ASN1_INTEGER
Definition asn1.c:134
#define ENOTSUP_HIGH
Definition asn1.c:154
#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:382
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:813
int asn1_generalized_time(const struct asn1_cursor *cursor, time_t *time)
Parse ASN.1 GeneralizedTime.
Definition asn1.c:885
int asn1_boolean(const struct asn1_cursor *cursor)
Parse value of ASN.1 boolean.
Definition asn1.c:500
int asn1_digest_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified digest algorithm.
Definition asn1.c:678
#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:995
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:767
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:1036
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:261
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:372
int image_asn1(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition asn1.c:1148
size_t asn1_header_len(size_t len)
Calculate ASN.1 header length.
Definition asn1.c:1023
#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:840
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:323
int asn1_pubkey_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified public-key algorithm.
Definition asn1.c:652
#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:403
static struct asn1_algorithm * asn1_find_algorithm(const struct asn1_cursor *cursor)
Identify ASN.1 algorithm by OID.
Definition asn1.c:583
static int asn1_start(struct asn1_cursor *cursor, unsigned int type)
Start parsing ASN.1 object.
Definition asn1.c:179
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:392
#define ENOTTY_ALGORITHM
Definition asn1.c:158
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:602
#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:524
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:566
int asn1_signature_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified signature algorithm.
Definition asn1.c:732
int asn1_parse_gcm(struct asn1_algorithm *algorithm __unused, struct asn1_cursor *params)
Parse ASN.1 GCM cipher parameters.
Definition asn1.c:864
#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:1119
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:346
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:294
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_HIGH
ASN.1 high tag number.
Definition asn1.h:90
#define ASN1_ANY
ASN.1 "any tag" magic value.
Definition asn1.h:105
#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:494
#define ASN1_ALGORITHMS
ASN.1 OID-identified algorithms.
Definition asn1.h:454
#define ASN1_BOOLEAN
ASN.1 boolean.
Definition asn1.h:60
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:93
#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:505
#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:429
const char * name
Name.
Definition asn1.h:431
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