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  * Parse value of ASN.1 boolean
377  *
378  * @v cursor ASN.1 object cursor
379  * @ret value Value, or negative error
380  */
381 int asn1_boolean ( const struct asn1_cursor *cursor ) {
382  struct asn1_cursor contents;
383  const struct {
384  uint8_t value;
385  } __attribute__ (( packed )) *boolean;
386 
387  /* Enter boolean */
388  memcpy ( &contents, cursor, sizeof ( contents ) );
389  asn1_enter ( &contents, ASN1_BOOLEAN );
390  if ( contents.len != sizeof ( *boolean ) )
391  return -EINVAL_ASN1_BOOLEAN;
392 
393  /* Extract value */
394  boolean = contents.data;
395  return boolean->value;
396 }
397 
398 /**
399  * Parse value of ASN.1 integer
400  *
401  * @v cursor ASN.1 object cursor
402  * @v value Value to fill in
403  * @ret rc Return status code
404  */
405 int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
406  struct asn1_cursor contents;
407  uint8_t high_byte;
408  int rc;
409 
410  /* Enter integer */
411  memcpy ( &contents, cursor, sizeof ( contents ) );
412  if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
413  return rc;
414  if ( contents.len < 1 )
415  return -EINVAL_ASN1_INTEGER;
416 
417  /* Initialise value according to sign byte */
418  *value = *( ( int8_t * ) contents.data );
419  contents.data++;
420  contents.len--;
421 
422  /* Process value */
423  while ( contents.len ) {
424  high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
425  if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
426  DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
427  return -EINVAL_ASN1_INTEGER;
428  }
429  *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
430  contents.data++;
431  contents.len--;
432  }
433 
434  return 0;
435 }
436 
437 /**
438  * Compare two ASN.1 objects
439  *
440  * @v cursor1 ASN.1 object cursor
441  * @v cursor2 ASN.1 object cursor
442  * @ret difference Difference as returned by memcmp()
443  *
444  * Note that invalid and empty cursors will compare as equal with each
445  * other.
446  */
447 int asn1_compare ( const struct asn1_cursor *cursor1,
448  const struct asn1_cursor *cursor2 ) {
449  int difference;
450 
451  difference = ( cursor2->len - cursor1->len );
452  return ( difference ? difference :
453  memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
454 }
455 
456 /**
457  * Identify ASN.1 algorithm by OID
458  *
459  * @v cursor ASN.1 object cursor
460 
461  * @ret algorithm Algorithm, or NULL
462  */
463 static struct asn1_algorithm *
464 asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
465  struct asn1_algorithm *algorithm;
466 
468  if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
469  return algorithm;
470  }
471 
472  return NULL;
473 }
474 
475 /**
476  * Parse ASN.1 OID-identified algorithm
477  *
478  * @v cursor ASN.1 object cursor
479  * @ret algorithm Algorithm
480  * @ret params Algorithm parameters, or NULL
481  * @ret rc Return status code
482  */
483 int asn1_algorithm ( const struct asn1_cursor *cursor,
484  struct asn1_algorithm **algorithm,
485  struct asn1_cursor *params ) {
486  struct asn1_cursor contents;
487  int rc;
488 
489  /* Enter algorithm */
490  memcpy ( &contents, cursor, sizeof ( contents ) );
491  asn1_enter ( &contents, ASN1_SEQUENCE );
492 
493  /* Get raw parameters, if applicable */
494  if ( params ) {
495  memcpy ( params, &contents, sizeof ( *params ) );
496  asn1_skip_any ( params );
497  }
498 
499  /* Enter algorithm identifier */
500  if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
501  DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
502  cursor );
503  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
504  return -EINVAL_ASN1_ALGORITHM;
505  }
506 
507  /* Identify algorithm */
508  *algorithm = asn1_find_algorithm ( &contents );
509  if ( ! *algorithm ) {
510  DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
511  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
512  return -ENOTSUP_ALGORITHM;
513  }
514 
515  /* Parse parameters, if applicable */
516  if ( params && (*algorithm)->parse &&
517  ( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
518  DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
519  cursor, (*algorithm)->name, strerror ( rc ) );
520  return rc;
521  }
522 
523  return 0;
524 }
525 
526 /**
527  * Parse ASN.1 OID-identified public-key algorithm
528  *
529  * @v cursor ASN.1 object cursor
530  * @ret algorithm Algorithm
531  * @ret rc Return status code
532  */
533 int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
534  struct asn1_algorithm **algorithm ) {
535  int rc;
536 
537  /* Parse algorithm */
538  if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
539  return rc;
540 
541  /* Check algorithm has a public key */
542  if ( ! (*algorithm)->pubkey ) {
543  DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key "
544  "algorithm:\n", cursor, (*algorithm)->name );
545  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
546  return -ENOTTY_ALGORITHM;
547  }
548 
549  return 0;
550 }
551 
552 /**
553  * Parse ASN.1 OID-identified digest algorithm
554  *
555  * @v cursor ASN.1 object cursor
556  * @ret algorithm Algorithm
557  * @ret rc Return status code
558  */
559 int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
560  struct asn1_algorithm **algorithm ) {
561  int rc;
562 
563  /* Parse algorithm */
564  if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
565  return rc;
566 
567  /* Check algorithm has a digest */
568  if ( ! (*algorithm)->digest ) {
569  DBGC ( cursor, "ASN1 %p algorithm %s is not a digest "
570  "algorithm:\n", cursor, (*algorithm)->name );
571  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
572  return -ENOTTY_ALGORITHM;
573  }
574 
575  return 0;
576 }
577 
578 /**
579  * Parse ASN.1 OID-identified cipher algorithm
580  *
581  * @v cursor ASN.1 object cursor
582  * @ret algorithm Algorithm
583  * @ret params Algorithm parameters, or NULL
584  * @ret rc Return status code
585  */
586 int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
587  struct asn1_algorithm **algorithm,
588  struct asn1_cursor *params ) {
589  int rc;
590 
591  /* Parse algorithm */
592  if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
593  return rc;
594 
595  /* Check algorithm has a cipher */
596  if ( ! (*algorithm)->cipher ) {
597  DBGC ( cursor, "ASN1 %p algorithm %s is not a cipher "
598  "algorithm:\n", cursor, (*algorithm)->name );
599  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
600  return -ENOTTY_ALGORITHM;
601  }
602 
603  return 0;
604 }
605 
606 /**
607  * Parse ASN.1 OID-identified signature algorithm
608  *
609  * @v cursor ASN.1 object cursor
610  * @ret algorithm Algorithm
611  * @ret rc Return status code
612  */
613 int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
614  struct asn1_algorithm **algorithm ) {
615  int rc;
616 
617  /* Parse algorithm */
618  if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
619  return rc;
620 
621  /* Check algorithm has a public key */
622  if ( ! (*algorithm)->pubkey ) {
623  DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
624  "algorithm:\n", cursor, (*algorithm)->name );
625  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
626  return -ENOTTY_ALGORITHM;
627  }
628 
629  /* Check algorithm has a digest */
630  if ( ! (*algorithm)->digest ) {
631  DBGC ( cursor, "ASN1 %p algorithm %s is not a signature "
632  "algorithm:\n", cursor, (*algorithm)->name );
633  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
634  return -ENOTTY_ALGORITHM;
635  }
636 
637  return 0;
638 }
639 
640 /**
641  * Parse ASN.1 OID-identified elliptic curve algorithm
642  *
643  * @v cursor ASN.1 object cursor
644  * @ret algorithm Algorithm
645  * @ret rc Return status code
646  */
647 int asn1_curve_algorithm ( const struct asn1_cursor *cursor,
648  struct asn1_algorithm **algorithm ) {
649  struct asn1_cursor curve;
650 
651  /* Elliptic curves are identified as either:
652  *
653  * - the algorithm "id-ecPublicKey" with the actual curve
654  * specified in the algorithm parameters, or
655  *
656  * - a standalone object identifier for the curve
657  */
658  if ( asn1_check_algorithm ( cursor, &ecpubkey_algorithm,
659  &curve ) != 0 ) {
660  memcpy ( &curve, cursor, sizeof ( curve ) );
661  }
662 
663  /* Identify curve */
664  asn1_enter ( &curve, ASN1_OID );
665  *algorithm = asn1_find_algorithm ( &curve );
666  if ( ! *algorithm ) {
667  DBGC ( cursor, "ASN1 %p unrecognised EC algorithm:\n",
668  cursor );
669  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
670  return -ENOTSUP_ALGORITHM;
671  }
672 
673  /* Check algorithm has an elliptic curve */
674  if ( ! (*algorithm)->curve ) {
675  DBGC ( cursor, "ASN1 %p algorithm %s is not an elliptic curve "
676  "algorithm:\n", cursor, (*algorithm)->name );
677  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
678  return -ENOTTY_ALGORITHM;
679  }
680 
681  return 0;
682 }
683 
684 /**
685  * Check ASN.1 OID-identified algorithm
686  *
687  * @v cursor ASN.1 object cursor
688  * @v expected Expected algorithm
689  * @ret params Algorithm parameters, or NULL
690  * @ret rc Return status code
691  */
692 int asn1_check_algorithm ( const struct asn1_cursor *cursor,
693  struct asn1_algorithm *expected,
694  struct asn1_cursor *params ) {
695  struct asn1_algorithm *actual;
696  int rc;
697 
698  /* Parse algorithm */
699  if ( ( rc = asn1_algorithm ( cursor, &actual, params ) ) != 0 )
700  return rc;
701 
702  /* Check algorithm matches */
703  if ( actual != expected ) {
704  DBGC ( cursor, "ASN1 %p algorithm %s does not match %s\n",
705  cursor, actual->name, expected->name );
706  return -ENOTTY_ALGORITHM;
707  }
708 
709  return 0;
710 }
711 
712 /**
713  * Parse ASN.1 CBC cipher parameters
714  *
715  * @v algorithm Algorithm
716  * @v param Parameters to parse
717  * @ret rc Return status code
718  */
720  struct asn1_cursor *params ) {
721  struct cipher_algorithm *cipher = algorithm->cipher;
722 
723  /* Sanity check */
724  assert ( cipher != NULL );
725 
726  /* Enter parameters */
727  asn1_enter ( params, ASN1_OCTET_STRING );
728 
729  /* Check length */
730  if ( params->len != cipher->blocksize )
731  return -EINVAL;
732 
733  return 0;
734 }
735 
736 /**
737  * Parse ASN.1 GCM cipher parameters
738  *
739  * @v algorithm Algorithm
740  * @v param Parameters to parse
741  * @ret rc Return status code
742  */
744  struct asn1_cursor *params ) {
745 
746  /* Enter parameters */
747  asn1_enter ( params, ASN1_SEQUENCE );
748 
749  /* Enter nonce */
750  return asn1_enter ( params, ASN1_OCTET_STRING );
751 }
752 
753 /**
754  * Parse ASN.1 GeneralizedTime
755  *
756  * @v cursor ASN.1 cursor
757  * @v time Time to fill in
758  * @ret rc Return status code
759  *
760  * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
761  * formats for UTCTime and GeneralizedTime, and mandates the
762  * interpretation of centuryless year values.
763  */
764 int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
765  struct asn1_cursor contents;
766  unsigned int have_century;
767  unsigned int type;
768  union {
769  struct {
771  uint8_t year;
772  uint8_t month;
773  uint8_t day;
774  uint8_t hour;
775  uint8_t minute;
776  uint8_t second;
777  } __attribute__ (( packed )) named;
778  uint8_t raw[7];
779  } pairs;
780  struct tm tm;
781  const uint8_t *data;
782  size_t remaining;
783  unsigned int tens;
784  unsigned int units;
785  unsigned int i;
786  int rc;
787 
788  /* Determine time format utcTime/generalizedTime */
789  memcpy ( &contents, cursor, sizeof ( contents ) );
790  type = asn1_type ( &contents );
791  switch ( type ) {
792  case ASN1_UTC_TIME:
793  have_century = 0;
794  break;
796  have_century = 1;
797  break;
798  default:
799  DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
800  cursor, type );
801  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
802  return -EINVAL_ASN1_TIME;
803  }
804 
805  /* Enter utcTime/generalizedTime */
806  if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
807  DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
808  ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
809  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
810  return rc;
811  }
812 
813  /* Parse digit string a pair at a time */
814  memset ( &pairs, 0, sizeof ( pairs ) );
815  data = contents.data;
816  remaining = contents.len;
817  for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
818  if ( remaining < 2 ) {
819  /* Some certificates violate the X.509 RFC by
820  * omitting the "seconds" value.
821  */
822  if ( i == ( sizeof ( pairs.raw ) - 1 ) )
823  break;
824  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
825  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
826  return -EINVAL_ASN1_TIME;
827  }
828  tens = data[0];
829  units = data[1];
830  if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
831  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
832  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
833  return -EINVAL_ASN1_TIME;
834  }
835  pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
836  data += 2;
837  remaining -= 2;
838  }
839 
840  /* Determine century if applicable */
841  if ( ! have_century )
842  pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
843 
844  /* Check for trailing "Z" */
845  if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
846  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
847  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
848  return -EINVAL_ASN1_TIME;
849  }
850 
851  /* Fill in time */
852  tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
853  pairs.named.year );
854  tm.tm_mon = ( pairs.named.month - 1 );
855  tm.tm_mday = pairs.named.day;
856  tm.tm_hour = pairs.named.hour;
857  tm.tm_min = pairs.named.minute;
858  tm.tm_sec = pairs.named.second;
859 
860  /* Convert to seconds since the Epoch */
861  *time = mktime ( &tm );
862 
863  return 0;
864 }
865 
866 /**
867  * Construct ASN.1 header
868  *
869  * @v header ASN.1 builder header
870  * @v type Type
871  * @v len Content length
872  * @ret header_len Header length
873  */
874 static size_t asn1_header ( struct asn1_builder_header *header,
875  unsigned int type, size_t len ) {
876  unsigned int header_len = 2;
877  unsigned int len_len = 0;
878  size_t temp;
879 
880  /* Construct header */
881  header->type = type;
882  if ( len < 0x80 ) {
883  header->length[0] = len;
884  } else {
885  for ( temp = len ; temp ; temp >>= 8 )
886  len_len++;
887  header->length[0] = ( 0x80 | len_len );
888  header_len += len_len;
889  for ( temp = len ; temp ; temp >>= 8 )
890  header->length[len_len--] = ( temp & 0xff );
891  }
892 
893  return header_len;
894 }
895 
896 /**
897  * Grow ASN.1 builder
898  *
899  * @v builder ASN.1 builder
900  * @v extra Extra space to prepend
901  * @ret rc Return status code
902  */
903 int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
904  size_t new_len;
905  void *new;
906 
907  /* As with the ASN1 parsing functions, make errors permanent */
908  if ( builder->len && ! builder->data )
909  return -ENOMEM;
910 
911  /* Reallocate data buffer */
912  new_len = ( builder->len + extra );
913  new = realloc ( builder->data, new_len );
914  if ( ! new ) {
915  free ( builder->data );
916  builder->data = NULL;
917  return -ENOMEM;
918  }
919  builder->data = new;
920 
921  /* Move existing data to end of buffer */
922  memmove ( ( builder->data + extra ), builder->data, builder->len );
923  builder->len = new_len;
924 
925  return 0;
926 }
927 
928 /**
929  * Prepend raw data to ASN.1 builder
930  *
931  * @v builder ASN.1 builder
932  * @v data Data to prepend
933  * @v len Length of data to prepend
934  * @ret rc Return status code
935  */
936 int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
937  size_t len ) {
938  int rc;
939 
940  /* Grow buffer */
941  if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
942  return rc;
943 
944  /* Populate data buffer */
945  memcpy ( builder->data, data, len );
946 
947  return 0;
948 }
949 
950 /**
951  * Prepend data to ASN.1 builder
952  *
953  * @v builder ASN.1 builder
954  * @v type Type
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 ( struct asn1_builder *builder, unsigned int type,
960  const void *data, size_t len ) {
962  size_t header_len;
963  int rc;
964 
965  /* Construct header */
966  header_len = asn1_header ( &header, type, len );
967 
968  /* Grow buffer */
969  if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
970  return rc;
971 
972  /* Populate data buffer */
973  memcpy ( builder->data, &header, header_len );
974  memcpy ( ( builder->data + header_len ), data, len );
975 
976  return 0;
977 }
978 
979 /**
980  * Wrap ASN.1 builder
981  *
982  * @v builder ASN.1 builder
983  * @v type Type
984  * @ret rc Return status code
985  */
986 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
988  size_t header_len;
989  int rc;
990 
991  /* Construct header */
992  header_len = asn1_header ( &header, type, builder->len );
993 
994  /* Grow buffer */
995  if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
996  return rc;
997 
998  /* Populate data buffer */
999  memcpy ( builder->data, &header, header_len );
1000 
1001  return 0;
1002 }
1003 
1004 /**
1005  * Extract ASN.1 object from image
1006  *
1007  * @v image Image
1008  * @v offset Offset within image
1009  * @v cursor ASN.1 cursor to fill in
1010  * @ret next Offset to next image, or negative error
1011  *
1012  * The caller is responsible for eventually calling free() on the
1013  * allocated ASN.1 cursor.
1014  */
1015 int image_asn1 ( struct image *image, size_t offset,
1016  struct asn1_cursor **cursor ) {
1017  int next;
1018  int rc;
1019 
1020  /* Sanity check */
1021  assert ( offset <= image->len );
1022 
1023  /* Check that this image can be used to extract an ASN.1 object */
1024  if ( ! ( image->type && image->type->asn1 ) )
1025  return -ENOTSUP;
1026 
1027  /* Try creating ASN.1 cursor */
1028  next = image->type->asn1 ( image, offset, cursor );
1029  if ( next < 0 ) {
1030  rc = next;
1031  DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
1032  image->name, strerror ( rc ) );
1033  return rc;
1034  }
1035 
1036  return next;
1037 }
1038 
1039 /* Drag in objects via image_asn1() */
1041 
1042 /* Drag in ASN.1 image formats */
1043 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
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:647
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:483
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition: asn1.c:447
#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:764
#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:936
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:559
#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:1015
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:613
#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:381
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:903
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:533
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:743
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition: asn1.c:986
static size_t asn1_header(struct asn1_builder_header *header, unsigned int type, size_t len)
Construct ASN.1 header.
Definition: asn1.c:874
#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:464
#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:586
#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:405
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:959
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:692
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:719
#define ASN1_BIT_STRING
ASN.1 bit string.
Definition: asn1.h:65
void * memset(void *dest, int character, size_t len) __nonnull