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