소스 검색

[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 년 전
부모
커밋
f229162749
2개의 변경된 파일151개의 추가작업 그리고 18개의 파일을 삭제
  1. 57
    5
      src/crypto/asn1.c
  2. 94
    13
      src/include/ipxe/asn1.h

+ 57
- 5
src/crypto/asn1.c 파일 보기

@@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21 21
 #include <stdint.h>
22 22
 #include <stddef.h>
23
+#include <string.h>
23 24
 #include <errno.h>
24 25
 #include <ipxe/asn1.h>
25 26
 
@@ -43,11 +44,23 @@ FILE_LICENCE ( GPL2_OR_LATER );
43 44
 #define EINFO_EINVAL_ASN1_LEN \
44 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 60
  * Start parsing ASN.1 object
48 61
  *
49 62
  * @v cursor		ASN.1 object cursor
50
- * @v type		Expected type
63
+ * @v type		Expected type, or ASN1_ANY
51 64
  * @ret len		Length of object body, or negative error
52 65
  *
53 66
  * The object cursor will be updated to point to the start of the
@@ -67,7 +80,7 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
67 80
 	}
68 81
 
69 82
 	/* Check the tag byte */
70
-	if ( *( ( uint8_t * ) cursor->data ) != type ) {
83
+	if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
71 84
 		DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
72 85
 		       cursor, type, *( ( uint8_t * ) cursor->data ) );
73 86
 		return -ENXIO;
@@ -110,7 +123,7 @@ static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
110 123
  * Enter ASN.1 object
111 124
  *
112 125
  * @v cursor		ASN.1 object cursor
113
- * @v type		Expected type
126
+ * @v type		Expected type, or ASN1_ANY
114 127
  * @ret rc		Return status code
115 128
  *
116 129
  * The object cursor will be updated to point to the body of the
@@ -137,7 +150,7 @@ int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
137 150
  * Skip ASN.1 object if present
138 151
  *
139 152
  * @v cursor		ASN.1 object cursor
140
- * @v type		Expected type
153
+ * @v type		Expected type, or ASN1_ANY
141 154
  * @ret rc		Return status code
142 155
  *
143 156
  * The object cursor will be updated to point to the next ASN.1
@@ -168,7 +181,7 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
168 181
  * Skip ASN.1 object
169 182
  *
170 183
  * @v cursor		ASN.1 object cursor
171
- * @v type		Expected type
184
+ * @v type		Expected type, or ASN1_ANY
172 185
  * @ret rc		Return status code
173 186
  *
174 187
  * The object cursor will be updated to point to the next ASN.1
@@ -185,3 +198,42 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
185 198
 
186 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 파일 보기

@@ -9,38 +9,119 @@
9 9
 
10 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 24
 #define ASN1_INTEGER 0x02
25
+
26
+/** ASN.1 bit string */
13 27
 #define ASN1_BIT_STRING 0x03
28
+
29
+/** ASN.1 octet string */
14 30
 #define ASN1_OCTET_STRING 0x04
31
+
32
+/** ASN.1 null */
15 33
 #define ASN1_NULL 0x05
34
+
35
+/** ASN.1 object identifier */
16 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 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 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 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 118
 extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
42 119
 extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
43 120
 				 unsigned int type );
44 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 127
 #endif /* _IPXE_ASN1_H */

Loading…
취소
저장