00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "asn1.h"
00019
00020 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
00021 {
00022 const u8 *pos, *end;
00023 u8 tmp;
00024
00025 os_memset(hdr, 0, sizeof(*hdr));
00026 pos = buf;
00027 end = buf + len;
00028
00029 hdr->identifier = *pos++;
00030 hdr->class = hdr->identifier >> 6;
00031 hdr->constructed = !!(hdr->identifier & (1 << 5));
00032
00033 if ((hdr->identifier & 0x1f) == 0x1f) {
00034 hdr->tag = 0;
00035 do {
00036 if (pos >= end) {
00037 wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
00038 "underflow");
00039 return -1;
00040 }
00041 tmp = *pos++;
00042 wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
00043 "0x%02x", tmp);
00044 hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
00045 } while (tmp & 0x80);
00046 } else
00047 hdr->tag = hdr->identifier & 0x1f;
00048
00049 tmp = *pos++;
00050 if (tmp & 0x80) {
00051 if (tmp == 0xff) {
00052 wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
00053 "value 0xff used");
00054 return -1;
00055 }
00056 tmp &= 0x7f;
00057 hdr->length = 0;
00058 if (tmp > 4) {
00059 wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
00060 return -1;
00061 }
00062 while (tmp--) {
00063 if (pos >= end) {
00064 wpa_printf(MSG_DEBUG, "ASN.1: Length "
00065 "underflow");
00066 return -1;
00067 }
00068 hdr->length = (hdr->length << 8) | *pos++;
00069 }
00070 } else {
00071
00072 hdr->length = tmp;
00073 }
00074
00075 if (end < pos || hdr->length > (unsigned int) (end - pos)) {
00076 wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
00077 return -1;
00078 }
00079
00080 hdr->payload = pos;
00081 return 0;
00082 }
00083
00084
00085 int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid)
00086 {
00087 const u8 *pos, *end;
00088 unsigned long val;
00089 u8 tmp;
00090
00091 os_memset(oid, 0, sizeof(*oid));
00092
00093 pos = buf;
00094 end = buf + len;
00095
00096 while (pos < end) {
00097 val = 0;
00098
00099 do {
00100 if (pos >= end)
00101 return -1;
00102 tmp = *pos++;
00103 val = (val << 7) | (tmp & 0x7f);
00104 } while (tmp & 0x80);
00105
00106 if (oid->len >= ASN1_MAX_OID_LEN) {
00107 wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
00108 return -1;
00109 }
00110 if (oid->len == 0) {
00111
00112
00113
00114
00115
00116 oid->oid[0] = val / 40;
00117 if (oid->oid[0] > 2)
00118 oid->oid[0] = 2;
00119 oid->oid[1] = val - oid->oid[0] * 40;
00120 oid->len = 2;
00121 } else
00122 oid->oid[oid->len++] = val;
00123 }
00124
00125 return 0;
00126 }
00127
00128
00129 int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
00130 const u8 **next)
00131 {
00132 struct asn1_hdr hdr;
00133
00134 if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
00135 return -1;
00136
00137 if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
00138 wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
00139 "tag 0x%x", hdr.class, hdr.tag);
00140 return -1;
00141 }
00142
00143 *next = hdr.payload + hdr.length;
00144
00145 return asn1_parse_oid(hdr.payload, hdr.length, oid);
00146 }
00147
00148
00149 void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len)
00150 {
00151 char *pos = buf;
00152 size_t i;
00153 int ret;
00154
00155 if (len == 0)
00156 return;
00157
00158 buf[0] = '\0';
00159
00160 for (i = 0; i < oid->len; i++) {
00161 ret = os_snprintf(pos, buf + len - pos,
00162 "%s%lu",
00163 i == 0 ? "" : ".", oid->oid[i]);
00164 if (ret < 0 || ret >= buf + len - pos)
00165 break;
00166 pos += ret;
00167 }
00168 buf[len - 1] = '\0';
00169 }
00170
00171
00172 static u8 rotate_bits(u8 octet)
00173 {
00174 int i;
00175 u8 res;
00176
00177 res = 0;
00178 for (i = 0; i < 8; i++) {
00179 res <<= 1;
00180 if (octet & 1)
00181 res |= 1;
00182 octet >>= 1;
00183 }
00184
00185 return res;
00186 }
00187
00188
00189 unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
00190 {
00191 unsigned long val = 0;
00192 const u8 *pos = buf;
00193
00194
00195
00196 pos++;
00197
00198 if (len >= 2)
00199 val |= rotate_bits(*pos++);
00200 if (len >= 3)
00201 val |= ((unsigned long) rotate_bits(*pos++)) << 8;
00202 if (len >= 4)
00203 val |= ((unsigned long) rotate_bits(*pos++)) << 16;
00204 if (len >= 5)
00205 val |= ((unsigned long) rotate_bits(*pos++)) << 24;
00206 if (len >= 6)
00207 wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
00208 "(BIT STRING length %lu)",
00209 __func__, (unsigned long) len);
00210
00211 return val;
00212 }