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