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