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