Browse Source

[crypto] Add more ASN.1 functions for X.509 certificate parsing

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
e20550fddf
3 changed files with 125 additions and 9 deletions
  1. 105
    1
      src/crypto/asn1.c
  2. 1
    1
      src/crypto/x509.c
  3. 19
    7
      src/include/ipxe/asn1.h

+ 105
- 1
src/crypto/asn1.c View File

@@ -43,6 +43,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
43 43
 	__einfo_error ( EINFO_EINVAL_ASN1_LEN )
44 44
 #define EINFO_EINVAL_ASN1_LEN \
45 45
 	__einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
46
+#define EINVAL_ASN1_BOOLEAN \
47
+	__einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
48
+#define EINFO_EINVAL_ASN1_BOOLEAN \
49
+	__einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
50
+#define EINVAL_ASN1_INTEGER \
51
+	__einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
52
+#define EINFO_EINVAL_ASN1_INTEGER \
53
+	__einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
46 54
 
47 55
 /**
48 56
  * Invalidate ASN.1 object cursor
@@ -191,7 +199,7 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
191 199
 int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
192 200
 	int rc;
193 201
 
194
-	if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) {
202
+	if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
195 203
 		asn1_invalidate_cursor ( cursor );
196 204
 		return rc;
197 205
 	}
@@ -199,6 +207,32 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
199 207
 	return 0;
200 208
 }
201 209
 
210
+/**
211
+ * Shrink ASN.1 cursor to fit object
212
+ *
213
+ * @v cursor		ASN.1 object cursor
214
+ * @v type		Expected type, or ASN1_ANY
215
+ * @ret rc		Return status code
216
+ *
217
+ * The object cursor will be shrunk to contain only the current ASN.1
218
+ * object.  If any error occurs, the object cursor will be
219
+ * invalidated.
220
+ */
221
+int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
222
+	struct asn1_cursor next;
223
+	int rc;
224
+
225
+	/* Skip to next object */
226
+	memcpy ( &next, cursor, sizeof ( next ) );
227
+	if ( ( rc = asn1_skip ( &next, type ) ) != 0 )
228
+		return rc;
229
+
230
+	/* Shrink original cursor to contain only its first object */
231
+	cursor->len = ( next.data - cursor->data );
232
+
233
+	return 0;
234
+}
235
+
202 236
 /**
203 237
  * Enter ASN.1 object of any type
204 238
  *
@@ -219,6 +253,76 @@ int asn1_skip_any ( struct asn1_cursor *cursor ) {
219 253
 	return asn1_skip ( cursor, ASN1_ANY );
220 254
 }
221 255
 
256
+/**
257
+ * Shrink ASN.1 object of any type
258
+ *
259
+ * @v cursor		ASN.1 object cursor
260
+ * @ret rc		Return status code
261
+ */
262
+int asn1_shrink_any ( struct asn1_cursor *cursor ) {
263
+	return asn1_shrink ( cursor, ASN1_ANY );
264
+}
265
+
266
+/**
267
+ * Parse value of ASN.1 boolean
268
+ *
269
+ * @v cursor		ASN.1 object cursor
270
+ * @ret value		Value, or negative error
271
+ */
272
+int asn1_boolean ( const struct asn1_cursor *cursor ) {
273
+	struct asn1_cursor contents;
274
+	const struct asn1_boolean *boolean;
275
+
276
+	/* Enter boolean */
277
+	memcpy ( &contents, cursor, sizeof ( contents ) );
278
+	asn1_enter ( &contents, ASN1_BOOLEAN );
279
+	if ( contents.len != sizeof ( *boolean ) )
280
+		return -EINVAL_ASN1_BOOLEAN;
281
+
282
+	/* Extract value */
283
+	boolean = contents.data;
284
+	return boolean->value;
285
+}
286
+
287
+/**
288
+ * Parse value of ASN.1 integer
289
+ *
290
+ * @v cursor		ASN.1 object cursor
291
+ * @v value		Value to fill in
292
+ * @ret rc		Return status code
293
+ */
294
+int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
295
+	struct asn1_cursor contents;
296
+	uint8_t high_byte;
297
+	int rc;
298
+
299
+	/* Enter integer */
300
+	memcpy ( &contents, cursor, sizeof ( contents ) );
301
+	if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
302
+		return rc;
303
+	if ( contents.len < 1 )
304
+		return -EINVAL_ASN1_INTEGER;
305
+
306
+	/* Initialise value according to sign byte */
307
+	*value = *( ( int8_t * ) contents.data );
308
+	contents.data++;
309
+	contents.len--;
310
+
311
+	/* Process value */
312
+	while ( contents.len ) {
313
+		high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
314
+		if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
315
+			DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
316
+			return -EINVAL_ASN1_INTEGER;
317
+		}
318
+		*value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
319
+		contents.data++;
320
+		contents.len--;
321
+	}
322
+
323
+	return 0;
324
+}
325
+
222 326
 /**
223 327
  * Compare two ASN.1 objects
224 328
  *

+ 1
- 1
src/crypto/x509.c View File

@@ -55,7 +55,7 @@ static int x509_public_key ( const struct asn1_cursor *certificate,
55 55
 	memcpy ( &cursor, certificate, sizeof ( cursor ) );
56 56
 	rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
57 57
 	       asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
58
-	       asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
58
+	       asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG(0) ),/*version*/
59 59
 	       asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
60 60
 	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
61 61
 	       asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */

+ 19
- 7
src/include/ipxe/asn1.h View File

@@ -20,6 +20,9 @@ struct asn1_cursor {
20 20
 /** ASN.1 end */
21 21
 #define ASN1_END 0x00
22 22
 
23
+/** ASN.1 boolean */
24
+#define ASN1_BOOLEAN 0x01
25
+
23 26
 /** ASN.1 integer */
24 27
 #define ASN1_INTEGER 0x02
25 28
 
@@ -48,7 +51,7 @@ struct asn1_cursor {
48 51
 #define ASN1_SET 0x31
49 52
 
50 53
 /** ASN.1 explicit tag */
51
-#define ASN1_EXPLICIT_TAG 0xa0
54
+#define ASN1_EXPLICIT_TAG( number) ( 0xa0 | (number) )
52 55
 
53 56
 /** ASN.1 "any tag" magic value */
54 57
 #define ASN1_ANY -1U
@@ -79,15 +82,14 @@ struct asn1_cursor {
79 82
 /** ASN.1 OID for iso(1) member-body(2) */
80 83
 #define ASN1_OID_ISO_MEMBERBODY ASN1_OID_INITIAL ( 1, 2 )
81 84
 
85
+/** ASN.1 OID for iso(1) identified-organization(3) */
86
+#define ASN1_OID_IDENTIFIED_ORGANIZATION ASN1_OID_INITIAL ( 1, 3 )
87
+
82 88
 /** ASN.1 OID for joint-iso-itu-t(2) ds(5) */
83 89
 #define ASN1_OID_DIRECTORY_SERVICES ASN1_OID_INITIAL ( 2, 5 )
84 90
 
85
-/** ASN.1 OID for joint-iso-itu-t(2) ds(5) attributeType(4) */
86
-#define ASN1_OID_ATTRIBUTE_TYPE \
87
-	ASN1_OID_DIRECTORY_SERVICES, ASN1_OID_SINGLE ( 4 )
88
-
89
-/** ASN.1 OID for joint-iso-itu-t(2) ds(5) attributeType(4) commonName(3) */
90
-#define ASN1_OID_COMMON_NAME ASN1_OID_ATTRIBUTE_TYPE, ASN1_OID_SINGLE ( 3 )
91
+/** ASN.1 OID for joint-iso-itu-t(2) country(16) */
92
+#define ASN1_OID_COUNTRY ASN1_OID_INITIAL ( 2, 16 )
91 93
 
92 94
 /** Define an ASN.1 cursor containing an OID */
93 95
 #define ASN1_OID_CURSOR( oid_value ) {			\
@@ -95,6 +97,12 @@ struct asn1_cursor {
95 97
 		.len = sizeof ( oid_value ),		\
96 98
 	}
97 99
 
100
+/** An ASN.1 boolean */
101
+struct asn1_boolean {
102
+	/** Value */
103
+	uint8_t value;
104
+} __attribute__ (( packed ));
105
+
98 106
 /** An ASN.1 bit string */
99 107
 struct asn1_bit_string {
100 108
 	/** Number of unused bits */
@@ -119,8 +127,12 @@ extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
119 127
 extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
120 128
 				 unsigned int type );
121 129
 extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
130
+extern int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type );
122 131
 extern int asn1_enter_any ( struct asn1_cursor *cursor );
123 132
 extern int asn1_skip_any ( struct asn1_cursor *cursor );
133
+extern int asn1_shrink_any ( struct asn1_cursor *cursor );
134
+extern int asn1_boolean ( const struct asn1_cursor *cursor );
135
+extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
124 136
 extern int asn1_compare ( const struct asn1_cursor *cursor1,
125 137
 			  const struct asn1_cursor *cursor2 );
126 138
 

Loading…
Cancel
Save