Browse Source

[crypto] Add 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
f229162749
2 changed files with 151 additions and 18 deletions
  1. 57
    5
      src/crypto/asn1.c
  2. 94
    13
      src/include/ipxe/asn1.h

+ 57
- 5
src/crypto/asn1.c View File

20
 
20
 
21
 #include <stdint.h>
21
 #include <stdint.h>
22
 #include <stddef.h>
22
 #include <stddef.h>
23
+#include <string.h>
23
 #include <errno.h>
24
 #include <errno.h>
24
 #include <ipxe/asn1.h>
25
 #include <ipxe/asn1.h>
25
 
26
 
43
 #define EINFO_EINVAL_ASN1_LEN \
44
 #define EINFO_EINVAL_ASN1_LEN \
44
 	__einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
45
 	__einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
45
 
46
 
47
+/**
48
+ * Invalidate ASN.1 object cursor
49
+ *
50
+ * @v cursor		ASN.1 object cursor
51
+ */
52
+void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
53
+	static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
54
+
55
+	cursor->data = asn1_invalid_object;
56
+	cursor->len = 0;
57
+}
58
+
46
 /**
59
 /**
47
  * Start parsing ASN.1 object
60
  * Start parsing ASN.1 object
48
  *
61
  *
49
  * @v cursor		ASN.1 object cursor
62
  * @v cursor		ASN.1 object cursor
50
- * @v type		Expected type
63
+ * @v type		Expected type, or ASN1_ANY
51
  * @ret len		Length of object body, or negative error
64
  * @ret len		Length of object body, or negative error
52
  *
65
  *
53
  * The object cursor will be updated to point to the start of the
66
  * The object cursor will be updated to point to the start of the
67
 	}
80
 	}
68
 
81
 
69
 	/* Check the tag byte */
82
 	/* Check the tag byte */
70
-	if ( *( ( uint8_t * ) cursor->data ) != type ) {
83
+	if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
71
 		DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
84
 		DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
72
 		       cursor, type, *( ( uint8_t * ) cursor->data ) );
85
 		       cursor, type, *( ( uint8_t * ) cursor->data ) );
73
 		return -ENXIO;
86
 		return -ENXIO;
110
  * Enter ASN.1 object
123
  * Enter ASN.1 object
111
  *
124
  *
112
  * @v cursor		ASN.1 object cursor
125
  * @v cursor		ASN.1 object cursor
113
- * @v type		Expected type
126
+ * @v type		Expected type, or ASN1_ANY
114
  * @ret rc		Return status code
127
  * @ret rc		Return status code
115
  *
128
  *
116
  * The object cursor will be updated to point to the body of the
129
  * The object cursor will be updated to point to the body of the
137
  * Skip ASN.1 object if present
150
  * Skip ASN.1 object if present
138
  *
151
  *
139
  * @v cursor		ASN.1 object cursor
152
  * @v cursor		ASN.1 object cursor
140
- * @v type		Expected type
153
+ * @v type		Expected type, or ASN1_ANY
141
  * @ret rc		Return status code
154
  * @ret rc		Return status code
142
  *
155
  *
143
  * The object cursor will be updated to point to the next ASN.1
156
  * The object cursor will be updated to point to the next ASN.1
168
  * Skip ASN.1 object
181
  * Skip ASN.1 object
169
  *
182
  *
170
  * @v cursor		ASN.1 object cursor
183
  * @v cursor		ASN.1 object cursor
171
- * @v type		Expected type
184
+ * @v type		Expected type, or ASN1_ANY
172
  * @ret rc		Return status code
185
  * @ret rc		Return status code
173
  *
186
  *
174
  * The object cursor will be updated to point to the next ASN.1
187
  * The object cursor will be updated to point to the next ASN.1
185
 
198
 
186
 	return 0;
199
 	return 0;
187
 }
200
 }
201
+
202
+/**
203
+ * Enter ASN.1 object of any type
204
+ *
205
+ * @v cursor		ASN.1 object cursor
206
+ * @ret rc		Return status code
207
+ */
208
+int asn1_enter_any ( struct asn1_cursor *cursor ) {
209
+	return asn1_enter ( cursor, ASN1_ANY );
210
+}
211
+
212
+/**
213
+ * Skip ASN.1 object of any type
214
+ *
215
+ * @v cursor		ASN.1 object cursor
216
+ * @ret rc		Return status code
217
+ */
218
+int asn1_skip_any ( struct asn1_cursor *cursor ) {
219
+	return asn1_skip ( cursor, ASN1_ANY );
220
+}
221
+
222
+/**
223
+ * Compare two ASN.1 objects
224
+ *
225
+ * @v cursor1		ASN.1 object cursor
226
+ * @v cursor2		ASN.1 object cursor
227
+ * @ret difference	Difference as returned by memcmp()
228
+ *
229
+ * Note that invalid and empty cursors will compare as equal with each
230
+ * other.
231
+ */
232
+int asn1_compare ( const struct asn1_cursor *cursor1,
233
+		   const struct asn1_cursor *cursor2 ) {
234
+	int difference;
235
+
236
+	difference = ( cursor2->len - cursor1->len );
237
+	return ( difference ? difference :
238
+		 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
239
+}

+ 94
- 13
src/include/ipxe/asn1.h View File

9
 
9
 
10
 FILE_LICENCE ( GPL2_OR_LATER );
10
 FILE_LICENCE ( GPL2_OR_LATER );
11
 
11
 
12
+/** An ASN.1 object cursor */
13
+struct asn1_cursor {
14
+	/** Start of data */
15
+	const void *data;
16
+	/** Length of data */
17
+	size_t len;
18
+};
19
+
20
+/** ASN.1 end */
21
+#define ASN1_END 0x00
22
+
23
+/** ASN.1 integer */
12
 #define ASN1_INTEGER 0x02
24
 #define ASN1_INTEGER 0x02
25
+
26
+/** ASN.1 bit string */
13
 #define ASN1_BIT_STRING 0x03
27
 #define ASN1_BIT_STRING 0x03
28
+
29
+/** ASN.1 octet string */
14
 #define ASN1_OCTET_STRING 0x04
30
 #define ASN1_OCTET_STRING 0x04
31
+
32
+/** ASN.1 null */
15
 #define ASN1_NULL 0x05
33
 #define ASN1_NULL 0x05
34
+
35
+/** ASN.1 object identifier */
16
 #define ASN1_OID 0x06
36
 #define ASN1_OID 0x06
37
+
38
+/** ASN.1 UTC time */
39
+#define ASN1_UTC_TIME 0x17
40
+
41
+/** ASN.1 generalized time */
42
+#define ASN1_GENERALIZED_TIME 0x18
43
+
44
+/** ASN.1 sequence */
17
 #define ASN1_SEQUENCE 0x30
45
 #define ASN1_SEQUENCE 0x30
18
-#define ASN1_IP_ADDRESS 0x40
46
+
47
+/** ASN.1 set */
48
+#define ASN1_SET 0x31
49
+
50
+/** ASN.1 explicit tag */
19
 #define ASN1_EXPLICIT_TAG 0xa0
51
 #define ASN1_EXPLICIT_TAG 0xa0
20
 
52
 
21
-/**
22
- * A DER-encoded ASN.1 object cursor
53
+/** ASN.1 "any tag" magic value */
54
+#define ASN1_ANY -1U
55
+
56
+/** Initial OID byte */
57
+#define ASN1_OID_INITIAL( first, second ) ( ( (first) * 40 ) + (second) )
58
+
59
+/** Single-byte OID value
60
+ *
61
+ * Valid for values up to 127
23
  */
62
  */
24
-struct asn1_cursor {
25
-	/** Start of data */
26
-	const void *data;
27
-	/** Length of data */
28
-	size_t len;
29
-};
63
+#define ASN1_OID_SINGLE( value ) ( (value) & 0x7f )
64
+
65
+/** Double-byte OID value
66
+ *
67
+ * Valid for values up to 16383
68
+ */
69
+#define ASN1_OID_DOUBLE( value ) \
70
+	( 0x80 | ( ( (value) >> 7 ) & 0x7f ) ), ASN1_OID_SINGLE ( (value) )
71
+
72
+/** Double-byte OID value
73
+ *
74
+ * Valid for values up to 2097151
75
+ */
76
+#define ASN1_OID_TRIPLE( value ) \
77
+	( 0x80 | ( ( (value) >> 14 ) & 0x7f ) ), ASN1_OID_DOUBLE ( (value) )
78
+
79
+/** ASN.1 OID for iso(1) member-body(2) */
80
+#define ASN1_OID_ISO_MEMBERBODY ASN1_OID_INITIAL ( 1, 2 )
81
+
82
+/** ASN.1 OID for joint-iso-itu-t(2) ds(5) */
83
+#define ASN1_OID_DIRECTORY_SERVICES ASN1_OID_INITIAL ( 2, 5 )
84
+
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
+
92
+/** Define an ASN.1 cursor containing an OID */
93
+#define ASN1_OID_CURSOR( oid_value ) {			\
94
+		.data = oid_value,			\
95
+		.len = sizeof ( oid_value ),		\
96
+	}
97
+
98
+/** An ASN.1 bit string */
99
+struct asn1_bit_string {
100
+	/** Number of unused bits */
101
+	uint8_t unused;
102
+	/** Data */
103
+	uint8_t data[0];
104
+} __attribute__ (( packed ));
30
 
105
 
31
 /**
106
 /**
32
- * Invalidate ASN.1 object cursor
107
+ * Extract ASN.1 type
33
  *
108
  *
34
  * @v cursor		ASN.1 object cursor
109
  * @v cursor		ASN.1 object cursor
110
+ * @ret type		Type
35
  */
111
  */
36
-static inline __attribute__ (( always_inline )) void
37
-asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
38
-	cursor->len = 0;
112
+static inline __attribute__ (( always_inline )) unsigned int
113
+asn1_type ( const struct asn1_cursor *cursor ) {
114
+	return ( *( ( const uint8_t * ) cursor->data ) );
39
 }
115
 }
40
 
116
 
117
+extern void asn1_invalidate_cursor ( struct asn1_cursor *cursor );
41
 extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
118
 extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
42
 extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
119
 extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
43
 				 unsigned int type );
120
 				 unsigned int type );
44
 extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
121
 extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
122
+extern int asn1_enter_any ( struct asn1_cursor *cursor );
123
+extern int asn1_skip_any ( struct asn1_cursor *cursor );
124
+extern int asn1_compare ( const struct asn1_cursor *cursor1,
125
+			  const struct asn1_cursor *cursor2 );
45
 
126
 
46
 #endif /* _IPXE_ASN1_H */
127
 #endif /* _IPXE_ASN1_H */

Loading…
Cancel
Save