• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/wpa_supplicant/src/tls/
1/*
2 * ASN.1 DER parsing
3 * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18
19#ifdef CONFIG_INTERNAL_X509
20
21#include "asn1.h"
22
23int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
24{
25	const u8 *pos, *end;
26	u8 tmp;
27
28	os_memset(hdr, 0, sizeof(*hdr));
29	pos = buf;
30	end = buf + len;
31
32	hdr->identifier = *pos++;
33	hdr->class = hdr->identifier >> 6;
34	hdr->constructed = !!(hdr->identifier & (1 << 5));
35
36	if ((hdr->identifier & 0x1f) == 0x1f) {
37		hdr->tag = 0;
38		do {
39			if (pos >= end) {
40				wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
41					   "underflow");
42				return -1;
43			}
44			tmp = *pos++;
45			wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
46				   "0x%02x", tmp);
47			hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
48		} while (tmp & 0x80);
49	} else
50		hdr->tag = hdr->identifier & 0x1f;
51
52	tmp = *pos++;
53	if (tmp & 0x80) {
54		if (tmp == 0xff) {
55			wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
56				   "value 0xff used");
57			return -1;
58		}
59		tmp &= 0x7f; /* number of subsequent octets */
60		hdr->length = 0;
61		if (tmp > 4) {
62			wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
63			return -1;
64		}
65		while (tmp--) {
66			if (pos >= end) {
67				wpa_printf(MSG_DEBUG, "ASN.1: Length "
68					   "underflow");
69				return -1;
70			}
71			hdr->length = (hdr->length << 8) | *pos++;
72		}
73	} else {
74		/* Short form - length 0..127 in one octet */
75		hdr->length = tmp;
76	}
77
78	if (end < pos || hdr->length > (unsigned int) (end - pos)) {
79		wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
80		return -1;
81	}
82
83	hdr->payload = pos;
84	return 0;
85}
86
87
88int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
89		 const u8 **next)
90{
91	struct asn1_hdr hdr;
92	const u8 *pos, *end;
93	unsigned long val;
94	u8 tmp;
95
96	os_memset(oid, 0, sizeof(*oid));
97
98	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
99		return -1;
100
101	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
102		wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
103			   "tag 0x%x", hdr.class, hdr.tag);
104		return -1;
105	}
106
107	pos = hdr.payload;
108	end = hdr.payload + hdr.length;
109	*next = end;
110
111	while (pos < end) {
112		val = 0;
113
114		do {
115			if (pos >= end)
116				return -1;
117			tmp = *pos++;
118			val = (val << 7) | (tmp & 0x7f);
119		} while (tmp & 0x80);
120
121		if (oid->len >= ASN1_MAX_OID_LEN) {
122			wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
123			return -1;
124		}
125		if (oid->len == 0) {
126			/*
127			 * The first octet encodes the first two object
128			 * identifier components in (X*40) + Y formula.
129			 * X = 0..2.
130			 */
131			oid->oid[0] = val / 40;
132			if (oid->oid[0] > 2)
133				oid->oid[0] = 2;
134			oid->oid[1] = val - oid->oid[0] * 40;
135			oid->len = 2;
136		} else
137			oid->oid[oid->len++] = val;
138	}
139
140	return 0;
141}
142
143
144void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len)
145{
146	char *pos = buf;
147	size_t i;
148	int ret;
149
150	if (len == 0)
151		return;
152
153	buf[0] = '\0';
154
155	for (i = 0; i < oid->len; i++) {
156		ret = os_snprintf(pos, buf + len - pos,
157				  "%s%lu",
158				  i == 0 ? "" : ".", oid->oid[i]);
159		if (ret < 0 || ret >= buf + len - pos)
160			break;
161		pos += ret;
162	}
163	buf[len - 1] = '\0';
164}
165
166
167static u8 rotate_bits(u8 octet)
168{
169	int i;
170	u8 res;
171
172	res = 0;
173	for (i = 0; i < 8; i++) {
174		res <<= 1;
175		if (octet & 1)
176			res |= 1;
177		octet >>= 1;
178	}
179
180	return res;
181}
182
183
184unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
185{
186	unsigned long val = 0;
187	const u8 *pos = buf;
188
189	/* BER requires that unused bits are zero, so we can ignore the number
190	 * of unused bits */
191	pos++;
192
193	if (len >= 2)
194		val |= rotate_bits(*pos++);
195	if (len >= 3)
196		val |= ((unsigned long) rotate_bits(*pos++)) << 8;
197	if (len >= 4)
198		val |= ((unsigned long) rotate_bits(*pos++)) << 16;
199	if (len >= 5)
200		val |= ((unsigned long) rotate_bits(*pos++)) << 24;
201	if (len >= 6)
202		wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
203			   "(BIT STRING length %lu)",
204			   __func__, (unsigned long) len);
205
206	return val;
207}
208
209#endif /* CONFIG_INTERNAL_X509 */
210