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