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