Browse Source

Trivial ASN.1 decoding functions.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
95206577a7
2 changed files with 191 additions and 0 deletions
  1. 159
    0
      src/crypto/asn1.c
  2. 32
    0
      src/include/gpxe/asn1.h

+ 159
- 0
src/crypto/asn1.c View 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <stddef.h>
21
+#include <errno.h>
22
+#include <gpxe/asn1.h>
23
+
24
+/** @file
25
+ *
26
+ * ASN.1 encoding
27
+ *
28
+ */
29
+
30
+/**
31
+ * Start parsing ASN.1 object
32
+ *
33
+ * @v cursor		ASN.1 object cursor
34
+ * @v type		Expected type
35
+ * @ret len		Length of object body, or -1 on error
36
+ *
37
+ * The object cursor will be updated to point to the start of the
38
+ * object body (i.e. the first byte following the length byte(s)), and
39
+ * the length of the object body (i.e. the number of bytes until the
40
+ * following object tag, if any) is returned.
41
+ *
42
+ * If any error occurs (i.e. if the object is not of the expected
43
+ * type, or if we overflow beyond the end of the ASN.1 object), then
44
+ * the cursor will be invalidated and a negative value will be
45
+ * returned.
46
+ */
47
+static int asn1_start_object ( struct asn1_cursor *cursor,
48
+			       unsigned int type ) {
49
+	unsigned int len_len;
50
+	unsigned int len;
51
+
52
+	/* Sanity check */
53
+	if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
54
+		if ( cursor->len )
55
+			DBGC ( cursor, "ASN1 %p too short\n", cursor );
56
+		goto notfound;
57
+	}
58
+
59
+	/* Check the tag byte */
60
+	if ( cursor->data[0] != type ) {
61
+		DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
62
+		       cursor, type, cursor->data[0] );
63
+		goto notfound;
64
+	}
65
+	cursor->data++;
66
+	cursor->len--;
67
+
68
+	/* Extract length of the length field and sanity check */
69
+	len_len = cursor->data[0];
70
+	if ( len_len & 0x80 ) {
71
+		len_len = ( len_len & 0x7f );
72
+		cursor->data++;
73
+		cursor->len--;
74
+	} else {
75
+		len_len = 1;
76
+	}
77
+	if ( cursor->len < len_len ) {
78
+		DBGC ( cursor, "ASN1 %p bad length field length %d (max %d)\n",
79
+		       cursor, len_len, cursor->len );
80
+		goto notfound;
81
+	}
82
+
83
+	/* Extract the length and sanity check */
84
+	for ( len = 0 ; len_len ; len_len-- ) {
85
+		len <<= 8;
86
+		len |= cursor->data[0];
87
+		cursor->data++;
88
+		cursor->len--;
89
+	}
90
+	if ( cursor->len < len ) {
91
+		DBGC ( cursor, "ASN1 %p bad length %d (max %d)\n",
92
+		       cursor, len, cursor->len );
93
+		goto notfound;
94
+	}
95
+
96
+	return len;
97
+
98
+ notfound:
99
+	cursor->data = NULL;
100
+	cursor->len = 0;
101
+	return -1;
102
+}
103
+
104
+/**
105
+ * Enter ASN.1 object
106
+ *
107
+ * @v cursor		ASN.1 object cursor
108
+ * @v type		Expected type
109
+ * @ret rc		Return status code
110
+ *
111
+ * The object cursor will be updated to point to the body of the
112
+ * current ASN.1 object.  If any error occurs, the object cursor will
113
+ * be invalidated.
114
+ */
115
+int asn1_enter_object ( struct asn1_cursor *cursor, unsigned int type ) {
116
+	int len;
117
+
118
+	len = asn1_start_object ( cursor, type );
119
+	if ( len < 0 )
120
+		return -ENOENT;
121
+
122
+	cursor->len = len;
123
+	DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
124
+	       cursor, type, len );
125
+
126
+	return 0;
127
+}
128
+
129
+/**
130
+ * Skip ASN.1 object
131
+ *
132
+ * @v cursor		ASN.1 object cursor
133
+ * @v type		Expected type
134
+ * @ret rc		Return status code
135
+ *
136
+ * The object cursor will be updated to point to the next ASN.1
137
+ * object.  If any error occurs, the object cursor will be
138
+ * invalidated.
139
+ */
140
+int asn1_skip_object ( struct asn1_cursor *cursor, unsigned int type ) {
141
+	int len;
142
+
143
+	len = asn1_start_object ( cursor, type );
144
+	if ( len < 0 )
145
+		return -ENOENT;
146
+
147
+	cursor->data += len;
148
+	cursor->len -= len;
149
+	DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
150
+	       cursor, type, len );
151
+
152
+	if ( ! cursor->len ) {
153
+		DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
154
+		cursor->data = NULL;
155
+		return -ENOENT;
156
+	}
157
+
158
+	return 0;
159
+}

+ 32
- 0
src/include/gpxe/asn1.h View File

1
+#ifndef _GPXE_ASN1_H
2
+#define _GPXE_ASN1_H
3
+
4
+/** @file
5
+ *
6
+ * ASN.1 encoding
7
+ *
8
+ */
9
+
10
+#define ASN1_INTEGER 0x02
11
+#define ASN1_BIT_STRING 0x03
12
+#define ASN1_OCTET_STRING 0x04
13
+#define ASN1_NULL 0x05
14
+#define ASN1_OID 0x06
15
+#define ASN1_SEQUENCE 0x30
16
+#define ASN1_IP_ADDRESS 0x40
17
+#define ASN1_EXPLICIT_TAG 0xa0
18
+
19
+/**
20
+ * A DER-encoded ASN.1 object cursor
21
+ */
22
+struct asn1_cursor {
23
+	/** Start of data */
24
+	uint8_t *data;
25
+	/** Length of data */
26
+	size_t len;
27
+};
28
+
29
+extern int asn1_enter_object ( struct asn1_cursor *cursor, unsigned int type );
30
+extern int asn1_skip_object ( struct asn1_cursor *cursor, unsigned int type );
31
+
32
+#endif /* _GPXE_ASN1_H */

Loading…
Cancel
Save