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  */
asn1_start(struct asn1_cursor * cursor,unsigned int type,size_t extra)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  */
asn1_enter(struct asn1_cursor * cursor,unsigned int type)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  */
asn1_skip_if_exists(struct asn1_cursor * cursor,unsigned int type)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  */
asn1_skip(struct asn1_cursor * cursor,unsigned int type)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  */
asn1_shrink(struct asn1_cursor * cursor,unsigned int type)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  */
asn1_enter_any(struct asn1_cursor * cursor)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  */
asn1_skip_any(struct asn1_cursor * cursor)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  */
asn1_shrink_any(struct asn1_cursor * cursor)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  */
asn1_boolean(const struct asn1_cursor * cursor)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  */
asn1_integer(const struct asn1_cursor * cursor,int * value)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  */
asn1_bit_string(const struct asn1_cursor * cursor,struct asn1_bit_string * bits)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  */
asn1_integral_bit_string(const struct asn1_cursor * cursor,struct asn1_bit_string * bits)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  */
asn1_compare(const struct asn1_cursor * cursor1,const struct asn1_cursor * cursor2)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 *
asn1_find_algorithm(const struct asn1_cursor * cursor)460 asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
461 	struct asn1_algorithm *algorithm;
462 
463 	for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
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  */
asn1_algorithm(const struct asn1_cursor * cursor,struct asn1_algorithm ** algorithm)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  */
asn1_pubkey_algorithm(const struct asn1_cursor * cursor,struct asn1_algorithm ** algorithm)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  */
asn1_digest_algorithm(const struct asn1_cursor * cursor,struct asn1_algorithm ** algorithm)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  */
asn1_signature_algorithm(const struct asn1_cursor * cursor,struct asn1_algorithm ** algorithm)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  */
asn1_generalized_time(const struct asn1_cursor * cursor,time_t * time)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;
634 	case ASN1_GENERALIZED_TIME:
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  */
asn1_header(struct asn1_builder_header * header,unsigned int type,size_t len)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  */
asn1_grow(struct asn1_builder * builder,size_t extra)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  */
asn1_prepend_raw(struct asn1_builder * builder,const void * data,size_t len)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  */
asn1_prepend(struct asn1_builder * builder,unsigned int type,const void * data,size_t len)798 int asn1_prepend ( struct asn1_builder *builder, unsigned int type,
799 		   const void *data, size_t len ) {
800 	struct asn1_builder_header header;
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  */
asn1_wrap(struct asn1_builder * builder,unsigned int type)825 int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) {
826 	struct asn1_builder_header header;
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  */
image_asn1(struct image * image,size_t offset,struct asn1_cursor ** cursor)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() */
879 REQUIRING_SYMBOL ( image_asn1 );
880 
881 /* Drag in ASN.1 image formats */
882 REQUIRE_OBJECT ( config_asn1 );
883