3 * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
14 struct asn1_oid asn1_sha1_oid = {
15 .oid = { 1, 3, 14, 3, 2, 26 },
19 struct asn1_oid asn1_sha256_oid = {
20 .oid = { 2, 16, 840, 1, 101, 3, 4, 2, 1 },
25 static int asn1_valid_der_boolean(struct asn1_hdr *hdr)
27 /* Enforce DER requirements for a single way of encoding a BOOLEAN */
28 if (hdr->length != 1) {
29 wpa_printf(MSG_DEBUG, "ASN.1: Unexpected BOOLEAN length (%u)",
34 if (hdr->payload[0] != 0 && hdr->payload[0] != 0xff) {
36 "ASN.1: Invalid BOOLEAN value 0x%x (DER requires 0 or 0xff)",
45 static int asn1_valid_der(struct asn1_hdr *hdr)
47 if (hdr->class != ASN1_CLASS_UNIVERSAL)
49 if (hdr->tag == ASN1_TAG_BOOLEAN && !asn1_valid_der_boolean(hdr))
55 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
60 os_memset(hdr, 0, sizeof(*hdr));
65 wpa_printf(MSG_DEBUG, "ASN.1: No room for Identifier");
68 hdr->identifier = *pos++;
69 hdr->class = hdr->identifier >> 6;
70 hdr->constructed = !!(hdr->identifier & (1 << 5));
72 if ((hdr->identifier & 0x1f) == 0x1f) {
76 wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
81 wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
83 hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
86 hdr->tag = hdr->identifier & 0x1f;
89 wpa_printf(MSG_DEBUG, "ASN.1: No room for Length");
95 wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
99 tmp &= 0x7f; /* number of subsequent octets */
102 wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
107 wpa_printf(MSG_DEBUG, "ASN.1: Length "
111 hdr->length = (hdr->length << 8) | *pos++;
114 /* Short form - length 0..127 in one octet */
118 if (end < pos || hdr->length > (unsigned int) (end - pos)) {
119 wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
125 return asn1_valid_der(hdr) ? 0 : -1;
129 int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid)
135 os_memset(oid, 0, sizeof(*oid));
147 val = (val << 7) | (tmp & 0x7f);
148 } while (tmp & 0x80);
150 if (oid->len >= ASN1_MAX_OID_LEN) {
151 wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
156 * The first octet encodes the first two object
157 * identifier components in (X*40) + Y formula.
160 oid->oid[0] = val / 40;
163 oid->oid[1] = val - oid->oid[0] * 40;
166 oid->oid[oid->len++] = val;
173 int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
178 if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
181 if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
182 wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
183 "tag 0x%x", hdr.class, hdr.tag);
187 *next = hdr.payload + hdr.length;
189 return asn1_parse_oid(hdr.payload, hdr.length, oid);
193 void asn1_oid_to_str(const struct asn1_oid *oid, char *buf, size_t len)
204 for (i = 0; i < oid->len; i++) {
205 ret = os_snprintf(pos, buf + len - pos,
207 i == 0 ? "" : ".", oid->oid[i]);
208 if (os_snprintf_error(buf + len - pos, ret))
216 static u8 rotate_bits(u8 octet)
222 for (i = 0; i < 8; i++) {
233 unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
235 unsigned long val = 0;
238 /* BER requires that unused bits are zero, so we can ignore the number
243 val |= rotate_bits(*pos++);
245 val |= ((unsigned long) rotate_bits(*pos++)) << 8;
247 val |= ((unsigned long) rotate_bits(*pos++)) << 16;
249 val |= ((unsigned long) rotate_bits(*pos++)) << 24;
251 wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
252 "(BIT STRING length %lu)",
253 __func__, (unsigned long) len);
259 int asn1_oid_equal(const struct asn1_oid *a, const struct asn1_oid *b)
263 if (a->len != b->len)
266 for (i = 0; i < a->len; i++) {
267 if (a->oid[i] != b->oid[i])