1b528cefcSMark Murray /* 2ae771770SStanislav Sedov * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "der_locl.h" 35b528cefcSMark Murray 36b528cefcSMark Murray /* 37b528cefcSMark Murray * All decoding functions take a pointer `p' to first position in 38b528cefcSMark Murray * which to read, from the left, `len' which means the maximum number 39b528cefcSMark Murray * of characters we are able to read, `ret' were the value will be 40b528cefcSMark Murray * returned and `size' where the number of used bytes is stored. 41b528cefcSMark Murray * Either 0 or an error code is returned. 42b528cefcSMark Murray */ 43b528cefcSMark Murray 44c19800e8SDoug Rabson int 45b528cefcSMark Murray der_get_unsigned (const unsigned char *p, size_t len, 46b528cefcSMark Murray unsigned *ret, size_t *size) 47b528cefcSMark Murray { 48b528cefcSMark Murray unsigned val = 0; 49b528cefcSMark Murray size_t oldlen = len; 50b528cefcSMark Murray 51*1b748759SDimitry Andric if (len == sizeof(val) + 1 && p[0] == 0) 52c19800e8SDoug Rabson ; 53*1b748759SDimitry Andric else if (len > sizeof(val)) 54*1b748759SDimitry Andric return ASN1_OVERRUN; 55*1b748759SDimitry Andric 56*1b748759SDimitry Andric while (len--) 57*1b748759SDimitry Andric val = val * 256 + *p++; 58*1b748759SDimitry Andric *ret = val; 59*1b748759SDimitry Andric if(size) *size = oldlen; 60*1b748759SDimitry Andric return 0; 61*1b748759SDimitry Andric } 62*1b748759SDimitry Andric 63*1b748759SDimitry Andric int 64*1b748759SDimitry Andric der_get_unsigned64 (const unsigned char *p, size_t len, 65*1b748759SDimitry Andric uint64_t *ret, size_t *size) 66*1b748759SDimitry Andric { 67*1b748759SDimitry Andric uint64_t val = 0; 68*1b748759SDimitry Andric size_t oldlen = len; 69*1b748759SDimitry Andric 70*1b748759SDimitry Andric if (len == sizeof(val) + 1 && p[0] == 0) 71*1b748759SDimitry Andric ; 72*1b748759SDimitry Andric else if (len > sizeof(val)) 73c19800e8SDoug Rabson return ASN1_OVERRUN; 74c19800e8SDoug Rabson 75b528cefcSMark Murray while (len--) 76b528cefcSMark Murray val = val * 256 + *p++; 77b528cefcSMark Murray *ret = val; 78b528cefcSMark Murray if(size) *size = oldlen; 79b528cefcSMark Murray return 0; 80b528cefcSMark Murray } 81b528cefcSMark Murray 82b528cefcSMark Murray int 83c19800e8SDoug Rabson der_get_integer (const unsigned char *p, size_t len, 84b528cefcSMark Murray int *ret, size_t *size) 85b528cefcSMark Murray { 86b528cefcSMark Murray int val = 0; 87b528cefcSMark Murray size_t oldlen = len; 88b528cefcSMark Murray 89*1b748759SDimitry Andric if (len > sizeof(val)) 90*1b748759SDimitry Andric return ASN1_OVERRUN; 91*1b748759SDimitry Andric 92*1b748759SDimitry Andric if (len > 0) { 93*1b748759SDimitry Andric val = (signed char)*p++; 94*1b748759SDimitry Andric while (--len) 95*1b748759SDimitry Andric val = val * 256 + *p++; 96*1b748759SDimitry Andric } 97*1b748759SDimitry Andric *ret = val; 98*1b748759SDimitry Andric if(size) *size = oldlen; 99*1b748759SDimitry Andric return 0; 100*1b748759SDimitry Andric } 101*1b748759SDimitry Andric 102*1b748759SDimitry Andric int 103*1b748759SDimitry Andric der_get_integer64 (const unsigned char *p, size_t len, 104*1b748759SDimitry Andric int64_t *ret, size_t *size) 105*1b748759SDimitry Andric { 106*1b748759SDimitry Andric int64_t val = 0; 107*1b748759SDimitry Andric size_t oldlen = len; 108*1b748759SDimitry Andric 109*1b748759SDimitry Andric if (len > sizeof(val)) 110c19800e8SDoug Rabson return ASN1_OVERRUN; 111c19800e8SDoug Rabson 1128373020dSJacques Vidrine if (len > 0) { 113b528cefcSMark Murray val = (signed char)*p++; 1148373020dSJacques Vidrine while (--len) 115b528cefcSMark Murray val = val * 256 + *p++; 1168373020dSJacques Vidrine } 117b528cefcSMark Murray *ret = val; 118b528cefcSMark Murray if(size) *size = oldlen; 119b528cefcSMark Murray return 0; 120b528cefcSMark Murray } 121b528cefcSMark Murray 122b528cefcSMark Murray int 123b528cefcSMark Murray der_get_length (const unsigned char *p, size_t len, 124b528cefcSMark Murray size_t *val, size_t *size) 125b528cefcSMark Murray { 126b528cefcSMark Murray size_t v; 127b528cefcSMark Murray 128b528cefcSMark Murray if (len <= 0) 129b528cefcSMark Murray return ASN1_OVERRUN; 130b528cefcSMark Murray --len; 131b528cefcSMark Murray v = *p++; 132b528cefcSMark Murray if (v < 128) { 133b528cefcSMark Murray *val = v; 134b528cefcSMark Murray if(size) *size = 1; 135b528cefcSMark Murray } else { 136b528cefcSMark Murray int e; 137b528cefcSMark Murray size_t l; 138b528cefcSMark Murray unsigned tmp; 139b528cefcSMark Murray 140b528cefcSMark Murray if(v == 0x80){ 141b528cefcSMark Murray *val = ASN1_INDEFINITE; 142b528cefcSMark Murray if(size) *size = 1; 143b528cefcSMark Murray return 0; 144b528cefcSMark Murray } 145b528cefcSMark Murray v &= 0x7F; 146b528cefcSMark Murray if (len < v) 147b528cefcSMark Murray return ASN1_OVERRUN; 148b528cefcSMark Murray e = der_get_unsigned (p, v, &tmp, &l); 149b528cefcSMark Murray if(e) return e; 150b528cefcSMark Murray *val = tmp; 151b528cefcSMark Murray if(size) *size = l + 1; 152b528cefcSMark Murray } 153b528cefcSMark Murray return 0; 154b528cefcSMark Murray } 155b528cefcSMark Murray 156b528cefcSMark Murray int 157c19800e8SDoug Rabson der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) 158b528cefcSMark Murray { 159c19800e8SDoug Rabson if(len < 1) 160c19800e8SDoug Rabson return ASN1_OVERRUN; 161c19800e8SDoug Rabson if(*p != 0) 162c19800e8SDoug Rabson *data = 1; 163c19800e8SDoug Rabson else 164c19800e8SDoug Rabson *data = 0; 165c19800e8SDoug Rabson *size = 1; 166c19800e8SDoug Rabson return 0; 167c19800e8SDoug Rabson } 168c19800e8SDoug Rabson 169c19800e8SDoug Rabson int 170c19800e8SDoug Rabson der_get_general_string (const unsigned char *p, size_t len, 171c19800e8SDoug Rabson heim_general_string *str, size_t *size) 172c19800e8SDoug Rabson { 173c19800e8SDoug Rabson const unsigned char *p1; 174b528cefcSMark Murray char *s; 175b528cefcSMark Murray 176c19800e8SDoug Rabson p1 = memchr(p, 0, len); 177c19800e8SDoug Rabson if (p1 != NULL) { 178c19800e8SDoug Rabson /* 179c19800e8SDoug Rabson * Allow trailing NULs. We allow this since MIT Kerberos sends 180c19800e8SDoug Rabson * an strings in the NEED_PREAUTH case that includes a 181c19800e8SDoug Rabson * trailing NUL. 182c19800e8SDoug Rabson */ 183ae771770SStanislav Sedov while ((size_t)(p1 - p) < len && *p1 == '\0') 184c19800e8SDoug Rabson p1++; 185ae771770SStanislav Sedov if ((size_t)(p1 - p) != len) 186c19800e8SDoug Rabson return ASN1_BAD_CHARACTER; 187c19800e8SDoug Rabson } 188c19800e8SDoug Rabson if (len > len + 1) 189c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 190c19800e8SDoug Rabson 191b528cefcSMark Murray s = malloc (len + 1); 192b528cefcSMark Murray if (s == NULL) 193b528cefcSMark Murray return ENOMEM; 194b528cefcSMark Murray memcpy (s, p, len); 195b528cefcSMark Murray s[len] = '\0'; 196b528cefcSMark Murray *str = s; 197b528cefcSMark Murray if(size) *size = len; 198b528cefcSMark Murray return 0; 199b528cefcSMark Murray } 200b528cefcSMark Murray 201b528cefcSMark Murray int 202c19800e8SDoug Rabson der_get_utf8string (const unsigned char *p, size_t len, 203c19800e8SDoug Rabson heim_utf8_string *str, size_t *size) 204c19800e8SDoug Rabson { 205c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 206c19800e8SDoug Rabson } 207c19800e8SDoug Rabson 208c19800e8SDoug Rabson int 209c19800e8SDoug Rabson der_get_printable_string(const unsigned char *p, size_t len, 210c19800e8SDoug Rabson heim_printable_string *str, size_t *size) 211c19800e8SDoug Rabson { 212ae771770SStanislav Sedov str->length = len; 213ae771770SStanislav Sedov str->data = malloc(len + 1); 214ae771770SStanislav Sedov if (str->data == NULL) 215ae771770SStanislav Sedov return ENOMEM; 216ae771770SStanislav Sedov memcpy(str->data, p, len); 217ae771770SStanislav Sedov ((char *)str->data)[len] = '\0'; 218ae771770SStanislav Sedov if(size) *size = len; 219ae771770SStanislav Sedov return 0; 220c19800e8SDoug Rabson } 221c19800e8SDoug Rabson 222c19800e8SDoug Rabson int 223c19800e8SDoug Rabson der_get_ia5_string(const unsigned char *p, size_t len, 224c19800e8SDoug Rabson heim_ia5_string *str, size_t *size) 225c19800e8SDoug Rabson { 226ae771770SStanislav Sedov return der_get_printable_string(p, len, str, size); 227c19800e8SDoug Rabson } 228c19800e8SDoug Rabson 229c19800e8SDoug Rabson int 230c19800e8SDoug Rabson der_get_bmp_string (const unsigned char *p, size_t len, 231c19800e8SDoug Rabson heim_bmp_string *data, size_t *size) 232c19800e8SDoug Rabson { 233c19800e8SDoug Rabson size_t i; 234c19800e8SDoug Rabson 235c19800e8SDoug Rabson if (len & 1) 236c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 237c19800e8SDoug Rabson data->length = len / 2; 238c19800e8SDoug Rabson if (data->length > UINT_MAX/sizeof(data->data[0])) 239c19800e8SDoug Rabson return ERANGE; 240c19800e8SDoug Rabson data->data = malloc(data->length * sizeof(data->data[0])); 241c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) 242c19800e8SDoug Rabson return ENOMEM; 243c19800e8SDoug Rabson 244c19800e8SDoug Rabson for (i = 0; i < data->length; i++) { 245c19800e8SDoug Rabson data->data[i] = (p[0] << 8) | p[1]; 246c19800e8SDoug Rabson p += 2; 247ae771770SStanislav Sedov /* check for NUL in the middle of the string */ 248ae771770SStanislav Sedov if (data->data[i] == 0 && i != (data->length - 1)) { 249ae771770SStanislav Sedov free(data->data); 250ae771770SStanislav Sedov data->data = NULL; 251ae771770SStanislav Sedov data->length = 0; 252ae771770SStanislav Sedov return ASN1_BAD_CHARACTER; 253ae771770SStanislav Sedov } 254c19800e8SDoug Rabson } 255c19800e8SDoug Rabson if (size) *size = len; 256c19800e8SDoug Rabson 257c19800e8SDoug Rabson return 0; 258c19800e8SDoug Rabson } 259c19800e8SDoug Rabson 260c19800e8SDoug Rabson int 261c19800e8SDoug Rabson der_get_universal_string (const unsigned char *p, size_t len, 262c19800e8SDoug Rabson heim_universal_string *data, size_t *size) 263c19800e8SDoug Rabson { 264c19800e8SDoug Rabson size_t i; 265c19800e8SDoug Rabson 266c19800e8SDoug Rabson if (len & 3) 267c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 268c19800e8SDoug Rabson data->length = len / 4; 269c19800e8SDoug Rabson if (data->length > UINT_MAX/sizeof(data->data[0])) 270c19800e8SDoug Rabson return ERANGE; 271c19800e8SDoug Rabson data->data = malloc(data->length * sizeof(data->data[0])); 272c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) 273c19800e8SDoug Rabson return ENOMEM; 274c19800e8SDoug Rabson 275c19800e8SDoug Rabson for (i = 0; i < data->length; i++) { 276c19800e8SDoug Rabson data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 277c19800e8SDoug Rabson p += 4; 278ae771770SStanislav Sedov /* check for NUL in the middle of the string */ 279ae771770SStanislav Sedov if (data->data[i] == 0 && i != (data->length - 1)) { 280ae771770SStanislav Sedov free(data->data); 281ae771770SStanislav Sedov data->data = NULL; 282ae771770SStanislav Sedov data->length = 0; 283ae771770SStanislav Sedov return ASN1_BAD_CHARACTER; 284ae771770SStanislav Sedov } 285c19800e8SDoug Rabson } 286c19800e8SDoug Rabson if (size) *size = len; 287c19800e8SDoug Rabson return 0; 288c19800e8SDoug Rabson } 289c19800e8SDoug Rabson 290c19800e8SDoug Rabson int 291c19800e8SDoug Rabson der_get_visible_string (const unsigned char *p, size_t len, 292c19800e8SDoug Rabson heim_visible_string *str, size_t *size) 293c19800e8SDoug Rabson { 294c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 295c19800e8SDoug Rabson } 296c19800e8SDoug Rabson 297c19800e8SDoug Rabson int 298b528cefcSMark Murray der_get_octet_string (const unsigned char *p, size_t len, 299c19800e8SDoug Rabson heim_octet_string *data, size_t *size) 300b528cefcSMark Murray { 301b528cefcSMark Murray data->length = len; 302b528cefcSMark Murray data->data = malloc(len); 303b528cefcSMark Murray if (data->data == NULL && data->length != 0) 304b528cefcSMark Murray return ENOMEM; 305b528cefcSMark Murray memcpy (data->data, p, len); 306b528cefcSMark Murray if(size) *size = len; 307b528cefcSMark Murray return 0; 308b528cefcSMark Murray } 309b528cefcSMark Murray 310b528cefcSMark Murray int 311ae771770SStanislav Sedov der_get_octet_string_ber (const unsigned char *p, size_t len, 312ae771770SStanislav Sedov heim_octet_string *data, size_t *size) 313ae771770SStanislav Sedov { 314ae771770SStanislav Sedov int e; 315ae771770SStanislav Sedov Der_type type; 316ae771770SStanislav Sedov Der_class class; 317ae771770SStanislav Sedov unsigned int tag, depth = 0; 318ae771770SStanislav Sedov size_t l, datalen, oldlen = len; 319ae771770SStanislav Sedov 320ae771770SStanislav Sedov data->length = 0; 321ae771770SStanislav Sedov data->data = NULL; 322ae771770SStanislav Sedov 323ae771770SStanislav Sedov while (len) { 324ae771770SStanislav Sedov e = der_get_tag (p, len, &class, &type, &tag, &l); 325ae771770SStanislav Sedov if (e) goto out; 326ae771770SStanislav Sedov if (class != ASN1_C_UNIV) { 327ae771770SStanislav Sedov e = ASN1_BAD_ID; 328ae771770SStanislav Sedov goto out; 329ae771770SStanislav Sedov } 330ae771770SStanislav Sedov if (type == PRIM && tag == UT_EndOfContent) { 331ae771770SStanislav Sedov if (depth == 0) 332ae771770SStanislav Sedov break; 333ae771770SStanislav Sedov depth--; 334ae771770SStanislav Sedov } 335ae771770SStanislav Sedov if (tag != UT_OctetString) { 336ae771770SStanislav Sedov e = ASN1_BAD_ID; 337ae771770SStanislav Sedov goto out; 338ae771770SStanislav Sedov } 339ae771770SStanislav Sedov 340ae771770SStanislav Sedov p += l; 341ae771770SStanislav Sedov len -= l; 342ae771770SStanislav Sedov e = der_get_length (p, len, &datalen, &l); 343ae771770SStanislav Sedov if (e) goto out; 344ae771770SStanislav Sedov p += l; 345ae771770SStanislav Sedov len -= l; 346ae771770SStanislav Sedov 347ae771770SStanislav Sedov if (datalen > len) 348ae771770SStanislav Sedov return ASN1_OVERRUN; 349ae771770SStanislav Sedov 350ae771770SStanislav Sedov if (type == PRIM) { 351ae771770SStanislav Sedov void *ptr; 352ae771770SStanislav Sedov 353ae771770SStanislav Sedov ptr = realloc(data->data, data->length + datalen); 354ae771770SStanislav Sedov if (ptr == NULL) { 355ae771770SStanislav Sedov e = ENOMEM; 356ae771770SStanislav Sedov goto out; 357ae771770SStanislav Sedov } 358ae771770SStanislav Sedov data->data = ptr; 359ae771770SStanislav Sedov memcpy(((unsigned char *)data->data) + data->length, p, datalen); 360ae771770SStanislav Sedov data->length += datalen; 361ae771770SStanislav Sedov } else 362ae771770SStanislav Sedov depth++; 363ae771770SStanislav Sedov 364ae771770SStanislav Sedov p += datalen; 365ae771770SStanislav Sedov len -= datalen; 366ae771770SStanislav Sedov } 367ae771770SStanislav Sedov if (depth != 0) 368ae771770SStanislav Sedov return ASN1_INDEF_OVERRUN; 369ae771770SStanislav Sedov if(size) *size = oldlen - len; 370ae771770SStanislav Sedov return 0; 371ae771770SStanislav Sedov out: 372ae771770SStanislav Sedov free(data->data); 373ae771770SStanislav Sedov data->data = NULL; 374ae771770SStanislav Sedov data->length = 0; 375ae771770SStanislav Sedov return e; 376ae771770SStanislav Sedov } 377ae771770SStanislav Sedov 378ae771770SStanislav Sedov 379ae771770SStanislav Sedov int 380c19800e8SDoug Rabson der_get_heim_integer (const unsigned char *p, size_t len, 381c19800e8SDoug Rabson heim_integer *data, size_t *size) 3824137ff4cSJacques Vidrine { 383c19800e8SDoug Rabson data->length = 0; 384c19800e8SDoug Rabson data->negative = 0; 385c19800e8SDoug Rabson data->data = NULL; 386c19800e8SDoug Rabson 387c19800e8SDoug Rabson if (len == 0) { 388c19800e8SDoug Rabson if (size) 389c19800e8SDoug Rabson *size = 0; 390c19800e8SDoug Rabson return 0; 391c19800e8SDoug Rabson } 392c19800e8SDoug Rabson if (p[0] & 0x80) { 393c19800e8SDoug Rabson unsigned char *q; 394c19800e8SDoug Rabson int carry = 1; 395c19800e8SDoug Rabson data->negative = 1; 396c19800e8SDoug Rabson 397c19800e8SDoug Rabson data->length = len; 398c19800e8SDoug Rabson 399c19800e8SDoug Rabson if (p[0] == 0xff) { 400c19800e8SDoug Rabson p++; 401c19800e8SDoug Rabson data->length--; 402c19800e8SDoug Rabson } 403c19800e8SDoug Rabson data->data = malloc(data->length); 404c19800e8SDoug Rabson if (data->data == NULL) { 405c19800e8SDoug Rabson data->length = 0; 406c19800e8SDoug Rabson if (size) 407c19800e8SDoug Rabson *size = 0; 408c19800e8SDoug Rabson return ENOMEM; 409c19800e8SDoug Rabson } 410c19800e8SDoug Rabson q = &((unsigned char*)data->data)[data->length - 1]; 411c19800e8SDoug Rabson p += data->length - 1; 412c19800e8SDoug Rabson while (q >= (unsigned char*)data->data) { 413c19800e8SDoug Rabson *q = *p ^ 0xff; 414c19800e8SDoug Rabson if (carry) 415c19800e8SDoug Rabson carry = !++*q; 416c19800e8SDoug Rabson p--; 417c19800e8SDoug Rabson q--; 418c19800e8SDoug Rabson } 419c19800e8SDoug Rabson } else { 420c19800e8SDoug Rabson data->negative = 0; 421c19800e8SDoug Rabson data->length = len; 422c19800e8SDoug Rabson 423c19800e8SDoug Rabson if (p[0] == 0) { 424c19800e8SDoug Rabson p++; 425c19800e8SDoug Rabson data->length--; 426c19800e8SDoug Rabson } 427c19800e8SDoug Rabson data->data = malloc(data->length); 428c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) { 429c19800e8SDoug Rabson data->length = 0; 430c19800e8SDoug Rabson if (size) 431c19800e8SDoug Rabson *size = 0; 432c19800e8SDoug Rabson return ENOMEM; 433c19800e8SDoug Rabson } 434c19800e8SDoug Rabson memcpy(data->data, p, data->length); 435c19800e8SDoug Rabson } 436c19800e8SDoug Rabson if (size) 437c19800e8SDoug Rabson *size = len; 438c19800e8SDoug Rabson return 0; 439c19800e8SDoug Rabson } 440c19800e8SDoug Rabson 441c19800e8SDoug Rabson static int 442c19800e8SDoug Rabson generalizedtime2time (const char *s, time_t *t) 443c19800e8SDoug Rabson { 444c19800e8SDoug Rabson struct tm tm; 445c19800e8SDoug Rabson 446c19800e8SDoug Rabson memset(&tm, 0, sizeof(tm)); 447c19800e8SDoug Rabson if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 448c19800e8SDoug Rabson &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 449c19800e8SDoug Rabson &tm.tm_min, &tm.tm_sec) != 6) { 450c19800e8SDoug Rabson if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ", 451c19800e8SDoug Rabson &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 452c19800e8SDoug Rabson &tm.tm_min, &tm.tm_sec) != 6) 453c19800e8SDoug Rabson return ASN1_BAD_TIMEFORMAT; 454c19800e8SDoug Rabson if (tm.tm_year < 50) 455c19800e8SDoug Rabson tm.tm_year += 2000; 456c19800e8SDoug Rabson else 457c19800e8SDoug Rabson tm.tm_year += 1900; 458c19800e8SDoug Rabson } 459c19800e8SDoug Rabson tm.tm_year -= 1900; 460c19800e8SDoug Rabson tm.tm_mon -= 1; 461c19800e8SDoug Rabson *t = _der_timegm (&tm); 462c19800e8SDoug Rabson return 0; 463c19800e8SDoug Rabson } 464c19800e8SDoug Rabson 465c19800e8SDoug Rabson static int 466c19800e8SDoug Rabson der_get_time (const unsigned char *p, size_t len, 467c19800e8SDoug Rabson time_t *data, size_t *size) 468c19800e8SDoug Rabson { 469c19800e8SDoug Rabson char *times; 470c19800e8SDoug Rabson int e; 471c19800e8SDoug Rabson 472c19800e8SDoug Rabson if (len > len + 1 || len == 0) 473c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 474c19800e8SDoug Rabson 475c19800e8SDoug Rabson times = malloc(len + 1); 476c19800e8SDoug Rabson if (times == NULL) 477c19800e8SDoug Rabson return ENOMEM; 478c19800e8SDoug Rabson memcpy(times, p, len); 479c19800e8SDoug Rabson times[len] = '\0'; 480c19800e8SDoug Rabson e = generalizedtime2time(times, data); 481c19800e8SDoug Rabson free (times); 482c19800e8SDoug Rabson if(size) *size = len; 483c19800e8SDoug Rabson return e; 484c19800e8SDoug Rabson } 485c19800e8SDoug Rabson 486c19800e8SDoug Rabson int 487c19800e8SDoug Rabson der_get_generalized_time (const unsigned char *p, size_t len, 488c19800e8SDoug Rabson time_t *data, size_t *size) 489c19800e8SDoug Rabson { 490c19800e8SDoug Rabson return der_get_time(p, len, data, size); 491c19800e8SDoug Rabson } 492c19800e8SDoug Rabson 493c19800e8SDoug Rabson int 494c19800e8SDoug Rabson der_get_utctime (const unsigned char *p, size_t len, 495c19800e8SDoug Rabson time_t *data, size_t *size) 496c19800e8SDoug Rabson { 497c19800e8SDoug Rabson return der_get_time(p, len, data, size); 498c19800e8SDoug Rabson } 499c19800e8SDoug Rabson 500c19800e8SDoug Rabson int 501c19800e8SDoug Rabson der_get_oid (const unsigned char *p, size_t len, 502c19800e8SDoug Rabson heim_oid *data, size_t *size) 503c19800e8SDoug Rabson { 504c19800e8SDoug Rabson size_t n; 5054137ff4cSJacques Vidrine size_t oldlen = len; 5064137ff4cSJacques Vidrine 5074137ff4cSJacques Vidrine if (len < 1) 5084137ff4cSJacques Vidrine return ASN1_OVERRUN; 5094137ff4cSJacques Vidrine 510c19800e8SDoug Rabson if (len > len + 1) 511c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 512c19800e8SDoug Rabson 513c19800e8SDoug Rabson if (len + 1 > UINT_MAX/sizeof(data->components[0])) 514c19800e8SDoug Rabson return ERANGE; 515c19800e8SDoug Rabson 516c19800e8SDoug Rabson data->components = malloc((len + 1) * sizeof(data->components[0])); 517c19800e8SDoug Rabson if (data->components == NULL) 5184137ff4cSJacques Vidrine return ENOMEM; 5194137ff4cSJacques Vidrine data->components[0] = (*p) / 40; 5204137ff4cSJacques Vidrine data->components[1] = (*p) % 40; 5214137ff4cSJacques Vidrine --len; 5224137ff4cSJacques Vidrine ++p; 5234137ff4cSJacques Vidrine for (n = 2; len > 0; ++n) { 524c19800e8SDoug Rabson unsigned u = 0, u1; 5254137ff4cSJacques Vidrine 5264137ff4cSJacques Vidrine do { 5274137ff4cSJacques Vidrine --len; 528c19800e8SDoug Rabson u1 = u * 128 + (*p++ % 128); 529c19800e8SDoug Rabson /* check that we don't overflow the element */ 530c19800e8SDoug Rabson if (u1 < u) { 531c19800e8SDoug Rabson der_free_oid(data); 532c19800e8SDoug Rabson return ASN1_OVERRUN; 533c19800e8SDoug Rabson } 534c19800e8SDoug Rabson u = u1; 5354137ff4cSJacques Vidrine } while (len > 0 && p[-1] & 0x80); 5364137ff4cSJacques Vidrine data->components[n] = u; 5374137ff4cSJacques Vidrine } 538c19800e8SDoug Rabson if (n > 2 && p[-1] & 0x80) { 539c19800e8SDoug Rabson der_free_oid (data); 5404137ff4cSJacques Vidrine return ASN1_OVERRUN; 5414137ff4cSJacques Vidrine } 5424137ff4cSJacques Vidrine data->length = n; 5434137ff4cSJacques Vidrine if (size) 5444137ff4cSJacques Vidrine *size = oldlen; 5454137ff4cSJacques Vidrine return 0; 5464137ff4cSJacques Vidrine } 5474137ff4cSJacques Vidrine 5484137ff4cSJacques Vidrine int 549b528cefcSMark Murray der_get_tag (const unsigned char *p, size_t len, 550b528cefcSMark Murray Der_class *class, Der_type *type, 551c19800e8SDoug Rabson unsigned int *tag, size_t *size) 552b528cefcSMark Murray { 553c19800e8SDoug Rabson size_t ret = 0; 554b528cefcSMark Murray if (len < 1) 555b528cefcSMark Murray return ASN1_OVERRUN; 556b528cefcSMark Murray *class = (Der_class)(((*p) >> 6) & 0x03); 557b528cefcSMark Murray *type = (Der_type)(((*p) >> 5) & 0x01); 558c19800e8SDoug Rabson *tag = (*p) & 0x1f; 559c19800e8SDoug Rabson p++; len--; ret++; 560c19800e8SDoug Rabson if(*tag == 0x1f) { 561c19800e8SDoug Rabson unsigned int continuation; 562c19800e8SDoug Rabson unsigned int tag1; 563c19800e8SDoug Rabson *tag = 0; 564c19800e8SDoug Rabson do { 565c19800e8SDoug Rabson if(len < 1) 566c19800e8SDoug Rabson return ASN1_OVERRUN; 567c19800e8SDoug Rabson continuation = *p & 128; 568c19800e8SDoug Rabson tag1 = *tag * 128 + (*p % 128); 569c19800e8SDoug Rabson /* check that we don't overflow the tag */ 570c19800e8SDoug Rabson if (tag1 < *tag) 571c19800e8SDoug Rabson return ASN1_OVERFLOW; 572c19800e8SDoug Rabson *tag = tag1; 573c19800e8SDoug Rabson p++; len--; ret++; 574c19800e8SDoug Rabson } while(continuation); 575c19800e8SDoug Rabson } 576c19800e8SDoug Rabson if(size) *size = ret; 577b528cefcSMark Murray return 0; 578b528cefcSMark Murray } 579b528cefcSMark Murray 580b528cefcSMark Murray int 581b528cefcSMark Murray der_match_tag (const unsigned char *p, size_t len, 582b528cefcSMark Murray Der_class class, Der_type type, 583c19800e8SDoug Rabson unsigned int tag, size_t *size) 584b528cefcSMark Murray { 585ae771770SStanislav Sedov Der_type thistype; 586ae771770SStanislav Sedov int e; 587ae771770SStanislav Sedov 588ae771770SStanislav Sedov e = der_match_tag2(p, len, class, &thistype, tag, size); 589ae771770SStanislav Sedov if (e) return e; 590ae771770SStanislav Sedov if (thistype != type) return ASN1_BAD_ID; 591ae771770SStanislav Sedov return 0; 592ae771770SStanislav Sedov } 593ae771770SStanislav Sedov 594ae771770SStanislav Sedov int 595ae771770SStanislav Sedov der_match_tag2 (const unsigned char *p, size_t len, 596ae771770SStanislav Sedov Der_class class, Der_type *type, 597ae771770SStanislav Sedov unsigned int tag, size_t *size) 598ae771770SStanislav Sedov { 599b528cefcSMark Murray size_t l; 600b528cefcSMark Murray Der_class thisclass; 601c19800e8SDoug Rabson unsigned int thistag; 602b528cefcSMark Murray int e; 603b528cefcSMark Murray 604ae771770SStanislav Sedov e = der_get_tag (p, len, &thisclass, type, &thistag, &l); 605b528cefcSMark Murray if (e) return e; 606ae771770SStanislav Sedov if (class != thisclass) 607b528cefcSMark Murray return ASN1_BAD_ID; 608b528cefcSMark Murray if(tag > thistag) 609b528cefcSMark Murray return ASN1_MISPLACED_FIELD; 610b528cefcSMark Murray if(tag < thistag) 611b528cefcSMark Murray return ASN1_MISSING_FIELD; 612b528cefcSMark Murray if(size) *size = l; 613b528cefcSMark Murray return 0; 614b528cefcSMark Murray } 615b528cefcSMark Murray 616b528cefcSMark Murray int 617b528cefcSMark Murray der_match_tag_and_length (const unsigned char *p, size_t len, 618ae771770SStanislav Sedov Der_class class, Der_type *type, unsigned int tag, 619b528cefcSMark Murray size_t *length_ret, size_t *size) 620b528cefcSMark Murray { 621b528cefcSMark Murray size_t l, ret = 0; 622b528cefcSMark Murray int e; 623b528cefcSMark Murray 624ae771770SStanislav Sedov e = der_match_tag2 (p, len, class, type, tag, &l); 625b528cefcSMark Murray if (e) return e; 626b528cefcSMark Murray p += l; 627b528cefcSMark Murray len -= l; 628b528cefcSMark Murray ret += l; 629b528cefcSMark Murray e = der_get_length (p, len, length_ret, &l); 630b528cefcSMark Murray if (e) return e; 631ae771770SStanislav Sedov if(size) *size = ret + l; 632b528cefcSMark Murray return 0; 633b528cefcSMark Murray } 634b528cefcSMark Murray 635ae771770SStanislav Sedov 636ae771770SStanislav Sedov 637c19800e8SDoug Rabson /* 638c19800e8SDoug Rabson * Old versions of DCE was based on a very early beta of the MIT code, 639c19800e8SDoug Rabson * which used MAVROS for ASN.1 encoding. MAVROS had the interesting 640c19800e8SDoug Rabson * feature that it encoded data in the forward direction, which has 641c19800e8SDoug Rabson * it's problems, since you have no idea how long the data will be 642c19800e8SDoug Rabson * until after you're done. MAVROS solved this by reserving one byte 643c19800e8SDoug Rabson * for length, and later, if the actual length was longer, it reverted 644c19800e8SDoug Rabson * to indefinite, BER style, lengths. The version of MAVROS used by 645c19800e8SDoug Rabson * the DCE people could apparently generate correct X.509 DER encodings, and 646c19800e8SDoug Rabson * did this by making space for the length after encoding, but 647c19800e8SDoug Rabson * unfortunately this feature wasn't used with Kerberos. 648c19800e8SDoug Rabson */ 649b528cefcSMark Murray 650b528cefcSMark Murray int 651c19800e8SDoug Rabson _heim_fix_dce(size_t reallen, size_t *len) 652b528cefcSMark Murray { 653b528cefcSMark Murray if(reallen == ASN1_INDEFINITE) 654b528cefcSMark Murray return 1; 655b528cefcSMark Murray if(*len < reallen) 656b528cefcSMark Murray return -1; 657b528cefcSMark Murray *len = reallen; 658b528cefcSMark Murray return 0; 659b528cefcSMark Murray } 660c19800e8SDoug Rabson 661c19800e8SDoug Rabson int 662c19800e8SDoug Rabson der_get_bit_string (const unsigned char *p, size_t len, 663c19800e8SDoug Rabson heim_bit_string *data, size_t *size) 664c19800e8SDoug Rabson { 665c19800e8SDoug Rabson if (len < 1) 666c19800e8SDoug Rabson return ASN1_OVERRUN; 667c19800e8SDoug Rabson if (p[0] > 7) 668c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 669c19800e8SDoug Rabson if (len - 1 == 0 && p[0] != 0) 670c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 671c19800e8SDoug Rabson /* check if any of the three upper bits are set 672c19800e8SDoug Rabson * any of them will cause a interger overrun */ 673c19800e8SDoug Rabson if ((len - 1) >> (sizeof(len) * 8 - 3)) 674c19800e8SDoug Rabson return ASN1_OVERRUN; 675c19800e8SDoug Rabson data->length = (len - 1) * 8; 676c19800e8SDoug Rabson data->data = malloc(len - 1); 677c19800e8SDoug Rabson if (data->data == NULL && (len - 1) != 0) 678c19800e8SDoug Rabson return ENOMEM; 679ae771770SStanislav Sedov /* copy data is there is data to copy */ 680ae771770SStanislav Sedov if (len - 1 != 0) { 681c19800e8SDoug Rabson memcpy (data->data, p + 1, len - 1); 682c19800e8SDoug Rabson data->length -= p[0]; 683ae771770SStanislav Sedov } 684c19800e8SDoug Rabson if(size) *size = len; 685c19800e8SDoug Rabson return 0; 686c19800e8SDoug Rabson } 687