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