]>
git.ipfire.org Git - thirdparty/hostap.git/blob - src/tls/asn1.c
06bbd6f939c80280ee5ac59f565620a16a72842a
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
])
275 int asn1_get_integer(const u8
*buf
, size_t len
, int *integer
, const u8
**next
)
282 if (asn1_get_next(buf
, len
, &hdr
) < 0 || hdr
.length
== 0)
285 if (hdr
.class != ASN1_CLASS_UNIVERSAL
|| hdr
.tag
!= ASN1_TAG_INTEGER
) {
286 wpa_printf(MSG_DEBUG
,
287 "ASN.1: Expected INTEGER - found class %d tag 0x%x",
292 *next
= hdr
.payload
+ hdr
.length
;
295 if (left
> sizeof(value
)) {
296 wpa_printf(MSG_DEBUG
, "ASN.1: Too large INTEGER (len %u)",