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  * Parse ASN.1 GeneralizedTime
594  *
595  * @v cursor ASN.1 cursor
596  * @v time Time to fill in
597  * @ret rc Return status code
598  *
599  * RFC 5280 section 4.1.2.5 places several restrictions on the allowed
600  * formats for UTCTime and GeneralizedTime, and mandates the
601  * interpretation of centuryless year values.
602  */
603 int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) {
604  struct asn1_cursor contents;
605  unsigned int have_century;
606  unsigned int type;
607  union {
608  struct {
609  uint8_t century;
610  uint8_t year;
611  uint8_t month;
612  uint8_t day;
613  uint8_t hour;
614  uint8_t minute;
615  uint8_t second;
616  } __attribute__ (( packed )) named;
617  uint8_t raw[7];
618  } pairs;
619  struct tm tm;
620  const uint8_t *data;
621  size_t remaining;
622  unsigned int tens;
623  unsigned int units;
624  unsigned int i;
625  int rc;
626 
627  /* Determine time format utcTime/generalizedTime */
628  memcpy ( &contents, cursor, sizeof ( contents ) );
629  type = asn1_type ( &contents );
630  switch ( type ) {
631  case ASN1_UTC_TIME:
632  have_century = 0;
633  break;
635  have_century = 1;
636  break;
637  default:
638  DBGC ( cursor, "ASN1 %p invalid time type %02x\n",
639  cursor, type );
640  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
641  return -EINVAL_ASN1_TIME;
642  }
643 
644  /* Enter utcTime/generalizedTime */
645  if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) {
646  DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor,
647  ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) );
648  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
649  return rc;
650  }
651 
652  /* Parse digit string a pair at a time */
653  memset ( &pairs, 0, sizeof ( pairs ) );
654  data = contents.data;
655  remaining = contents.len;
656  for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) {
657  if ( remaining < 2 ) {
658  /* Some certificates violate the X.509 RFC by
659  * omitting the "seconds" value.
660  */
661  if ( i == ( sizeof ( pairs.raw ) - 1 ) )
662  break;
663  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
664  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
665  return -EINVAL_ASN1_TIME;
666  }
667  tens = data[0];
668  units = data[1];
669  if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) {
670  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
671  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
672  return -EINVAL_ASN1_TIME;
673  }
674  pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) );
675  data += 2;
676  remaining -= 2;
677  }
678 
679  /* Determine century if applicable */
680  if ( ! have_century )
681  pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 );
682 
683  /* Check for trailing "Z" */
684  if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) {
685  DBGC ( cursor, "ASN1 %p invalid time:\n", cursor );
686  DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
687  return -EINVAL_ASN1_TIME;
688  }
689 
690  /* Fill in time */
691  tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) +
692  pairs.named.year );
693  tm.tm_mon = ( pairs.named.month - 1 );
694  tm.tm_mday = pairs.named.day;
695  tm.tm_hour = pairs.named.hour;
696  tm.tm_min = pairs.named.minute;
697  tm.tm_sec = pairs.named.second;
698 
699  /* Convert to seconds since the Epoch */
700  *time = mktime ( &tm );
701 
702  return 0;
703 }
704 
705 /**
706  * Construct ASN.1 header
707  *
708  * @v header ASN.1 builder header
709  * @v type Type
710  * @v len Content length
711  * @ret header_len Header length
712  */
713 static size_t asn1_header ( struct asn1_builder_header *header,
714  unsigned int type, size_t len ) {
715  unsigned int header_len = 2;
716  unsigned int len_len = 0;
717  size_t temp;
718 
719  /* Construct header */
720  header->type = type;
721  if ( len < 0x80 ) {
722  header->length[0] = len;
723  } else {
724  for ( temp = len ; temp ; temp >>= 8 )
725  len_len++;
726  header->length[0] = ( 0x80 | len_len );
727  header_len += len_len;
728  for ( temp = len ; temp ; temp >>= 8 )
729  header->length[len_len--] = ( temp & 0xff );
730  }
731 
732  return header_len;
733 }
734 
735 /**
736  * Grow ASN.1 builder
737  *
738  * @v builder ASN.1 builder
739  * @v extra Extra space to prepend
740  * @ret rc Return status code
741  */
742 int asn1_grow ( struct asn1_builder *builder, size_t extra ) {
743  size_t new_len;
744  void *new;
745 
746  /* As with the ASN1 parsing functions, make errors permanent */
747  if ( builder->len && ! builder->data )
748  return -ENOMEM;
749 
750  /* Reallocate data buffer */
751  new_len = ( builder->len + extra );
752  new = realloc ( builder->data, new_len );
753  if ( ! new ) {
754  free ( builder->data );
755  builder->data = NULL;
756  return -ENOMEM;
757  }
758  builder->data = new;
759 
760  /* Move existing data to end of buffer */
761  memmove ( ( builder->data + extra ), builder->data, builder->len );
762  builder->len = new_len;
763 
764  return 0;
765 }
766 
767 /**
768  * Prepend raw data to ASN.1 builder
769  *
770  * @v builder ASN.1 builder
771  * @v data Data to prepend
772  * @v len Length of data to prepend
773  * @ret rc Return status code
774  */
775 int asn1_prepend_raw ( struct asn1_builder *builder, const void *data,
776  size_t len ) {
777  int rc;
778 
779  /* Grow buffer */
780  if ( ( rc = asn1_grow ( builder, len ) ) != 0 )
781  return rc;
782 
783  /* Populate data buffer */
784  memcpy ( builder->data, data, len );
785 
786  return 0;
787 }
788 
789 /**
790  * Prepend data to ASN.1 builder
791  *
792  * @v builder ASN.1 builder
793  * @v type Type
794  * @v data Data to prepend
795  * @v len Length of data to prepend
796  * @ret rc Return status code
797  */
798 int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
799  const void *data, size_t len ) {
801  size_t header_len;
802  int rc;
803 
804  /* Construct header */
805  header_len = asn1_header ( &header, type, len );
806 
807  /* Grow buffer */
808  if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 )
809  return rc;
810 
811  /* Populate data buffer */
812  memcpy ( builder->data, &header, header_len );
813  memcpy ( ( builder->data + header_len ), data, len );
814 
815  return 0;
816 }
817 
818 /**
819  * Wrap ASN.1 builder
820  *
821  * @v builder ASN.1 builder
822  * @v type Type
823  * @ret rc Return status code
824  */
825 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
827  size_t header_len;
828  int rc;
829 
830  /* Construct header */
831  header_len = asn1_header ( &header, type, builder->len );
832 
833  /* Grow buffer */
834  if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 )
835  return rc;
836 
837  /* Populate data buffer */
838  memcpy ( builder->data, &header, header_len );
839 
840  return 0;
841 }
842 
843 /**
844  * Extract ASN.1 object from image
845  *
846  * @v image Image
847  * @v offset Offset within image
848  * @v cursor ASN.1 cursor to fill in
849  * @ret next Offset to next image, or negative error
850  *
851  * The caller is responsible for eventually calling free() on the
852  * allocated ASN.1 cursor.
853  */
854 int image_asn1 ( struct image *image, size_t offset,
855  struct asn1_cursor **cursor ) {
856  int next;
857  int rc;
858 
859  /* Sanity check */
860  assert ( offset <= image->len );
861 
862  /* Check that this image can be used to extract an ASN.1 object */
863  if ( ! ( image->type && image->type->asn1 ) )
864  return -ENOTSUP;
865 
866  /* Try creating ASN.1 cursor */
867  next = image->type->asn1 ( image, offset, cursor );
868  if ( next < 0 ) {
869  rc = next;
870  DBGC ( image, "IMAGE %s could not extract ASN.1 object: %s\n",
871  image->name, strerror ( rc ) );
872  return rc;
873  }
874 
875  return next;
876 }
877 
878 /* Drag in objects via image_asn1() */
880 
881 /* Drag in ASN.1 image formats */
882 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:298
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void * data
Data.
Definition: asn1.h:34
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:603
uint32_t next
Next descriptor address.
Definition: myson.h:18
#define ASN1_BOOLEAN
ASN.1 boolean.
Definition: asn1.h:58
Error codes.
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
uint8_t type
Type.
Definition: ena.h:16
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:775
const void * data
Start of data.
Definition: asn1.h:21
#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:854
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:342
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:97
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:23
static int isdigit(int character)
Check if character is a decimal digit.
Definition: ctype.h:18
#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
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:82
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:742
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:331
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:27
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
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:825
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:713
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:85
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:61
An ASN.1 header.
Definition: asn1.h:47
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition: ieee80211.h:1030
Date and time.
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:73
#define ENXIO
No such device or address.
Definition: errno.h:599
#define ASN1_ALGORITHMS
ASN.1 OID-identified algorithms.
Definition: asn1.h:310
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:798
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
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:79
#define EINVAL_ASN1_BOOLEAN
Definition: asn1.c:56
int tm_hour
Hour [0,23].
Definition: time.h:21
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
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:98
char * name
Name.
Definition: image.h:34
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
size_t len
Length of data.
Definition: asn1.h:36
String functions.
An ASN.1 object cursor.
Definition: asn1.h:19
#define EINVAL_ASN1_EMPTY
Definition: asn1.c:44
#define ASN1_BIT_STRING
ASN.1 bit string.
Definition: asn1.h:64
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:316
void * memset(void *dest, int character, size_t len) __nonnull