155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "der_locl.h" 3555682Smarkm 36233294Sstas/* 3755682Smarkm * All decoding functions take a pointer `p' to first position in 3855682Smarkm * which to read, from the left, `len' which means the maximum number 3955682Smarkm * of characters we are able to read, `ret' were the value will be 4055682Smarkm * returned and `size' where the number of used bytes is stored. 4155682Smarkm * Either 0 or an error code is returned. 4255682Smarkm */ 4355682Smarkm 44178825Sdfrint 4555682Smarkmder_get_unsigned (const unsigned char *p, size_t len, 4655682Smarkm unsigned *ret, size_t *size) 4755682Smarkm{ 4855682Smarkm unsigned val = 0; 4955682Smarkm size_t oldlen = len; 5055682Smarkm 51178825Sdfr if (len == sizeof(unsigned) + 1 && p[0] == 0) 52178825Sdfr ; 53178825Sdfr else if (len > sizeof(unsigned)) 54178825Sdfr return ASN1_OVERRUN; 55178825Sdfr 5655682Smarkm while (len--) 5755682Smarkm val = val * 256 + *p++; 5855682Smarkm *ret = val; 5955682Smarkm if(size) *size = oldlen; 6055682Smarkm return 0; 6155682Smarkm} 6255682Smarkm 6355682Smarkmint 64178825Sdfrder_get_integer (const unsigned char *p, size_t len, 65178825Sdfr int *ret, size_t *size) 6655682Smarkm{ 6755682Smarkm int val = 0; 6855682Smarkm size_t oldlen = len; 6955682Smarkm 70178825Sdfr if (len > sizeof(int)) 71178825Sdfr return ASN1_OVERRUN; 72178825Sdfr 73102644Snectar if (len > 0) { 7455682Smarkm val = (signed char)*p++; 75102644Snectar while (--len) 76102644Snectar val = val * 256 + *p++; 77102644Snectar } 7855682Smarkm *ret = val; 7955682Smarkm if(size) *size = oldlen; 8055682Smarkm return 0; 8155682Smarkm} 8255682Smarkm 8355682Smarkmint 8455682Smarkmder_get_length (const unsigned char *p, size_t len, 8555682Smarkm size_t *val, size_t *size) 8655682Smarkm{ 8755682Smarkm size_t v; 8855682Smarkm 8955682Smarkm if (len <= 0) 9055682Smarkm return ASN1_OVERRUN; 9155682Smarkm --len; 9255682Smarkm v = *p++; 9355682Smarkm if (v < 128) { 9455682Smarkm *val = v; 9555682Smarkm if(size) *size = 1; 9655682Smarkm } else { 9755682Smarkm int e; 9855682Smarkm size_t l; 9955682Smarkm unsigned tmp; 10055682Smarkm 10155682Smarkm if(v == 0x80){ 10255682Smarkm *val = ASN1_INDEFINITE; 10355682Smarkm if(size) *size = 1; 10455682Smarkm return 0; 10555682Smarkm } 10655682Smarkm v &= 0x7F; 10755682Smarkm if (len < v) 10855682Smarkm return ASN1_OVERRUN; 10955682Smarkm e = der_get_unsigned (p, v, &tmp, &l); 11055682Smarkm if(e) return e; 11155682Smarkm *val = tmp; 11255682Smarkm if(size) *size = l + 1; 11355682Smarkm } 11455682Smarkm return 0; 11555682Smarkm} 11655682Smarkm 11755682Smarkmint 118178825Sdfrder_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) 119178825Sdfr{ 120178825Sdfr if(len < 1) 121178825Sdfr return ASN1_OVERRUN; 122178825Sdfr if(*p != 0) 123178825Sdfr *data = 1; 124178825Sdfr else 125178825Sdfr *data = 0; 126178825Sdfr *size = 1; 127178825Sdfr return 0; 128178825Sdfr} 129178825Sdfr 130178825Sdfrint 131233294Sstasder_get_general_string (const unsigned char *p, size_t len, 132178825Sdfr heim_general_string *str, size_t *size) 13355682Smarkm{ 134178825Sdfr const unsigned char *p1; 13555682Smarkm char *s; 13655682Smarkm 137178825Sdfr p1 = memchr(p, 0, len); 138178825Sdfr if (p1 != NULL) { 139233294Sstas /* 140178825Sdfr * Allow trailing NULs. We allow this since MIT Kerberos sends 141178825Sdfr * an strings in the NEED_PREAUTH case that includes a 142178825Sdfr * trailing NUL. 143178825Sdfr */ 144233294Sstas while ((size_t)(p1 - p) < len && *p1 == '\0') 145178825Sdfr p1++; 146233294Sstas if ((size_t)(p1 - p) != len) 147178825Sdfr return ASN1_BAD_CHARACTER; 148178825Sdfr } 149178825Sdfr if (len > len + 1) 150178825Sdfr return ASN1_BAD_LENGTH; 151178825Sdfr 15255682Smarkm s = malloc (len + 1); 15355682Smarkm if (s == NULL) 15455682Smarkm return ENOMEM; 15555682Smarkm memcpy (s, p, len); 15655682Smarkm s[len] = '\0'; 15755682Smarkm *str = s; 15855682Smarkm if(size) *size = len; 15955682Smarkm return 0; 16055682Smarkm} 16155682Smarkm 16255682Smarkmint 163233294Sstasder_get_utf8string (const unsigned char *p, size_t len, 164178825Sdfr heim_utf8_string *str, size_t *size) 165178825Sdfr{ 166178825Sdfr return der_get_general_string(p, len, str, size); 167178825Sdfr} 168178825Sdfr 169178825Sdfrint 170233294Sstasder_get_printable_string(const unsigned char *p, size_t len, 171233294Sstas heim_printable_string *str, size_t *size) 172178825Sdfr{ 173233294Sstas str->length = len; 174233294Sstas str->data = malloc(len + 1); 175233294Sstas if (str->data == NULL) 176233294Sstas return ENOMEM; 177233294Sstas memcpy(str->data, p, len); 178233294Sstas ((char *)str->data)[len] = '\0'; 179233294Sstas if(size) *size = len; 180233294Sstas return 0; 181178825Sdfr} 182178825Sdfr 183178825Sdfrint 184233294Sstasder_get_ia5_string(const unsigned char *p, size_t len, 185233294Sstas heim_ia5_string *str, size_t *size) 186178825Sdfr{ 187233294Sstas return der_get_printable_string(p, len, str, size); 188178825Sdfr} 189178825Sdfr 190178825Sdfrint 191233294Sstasder_get_bmp_string (const unsigned char *p, size_t len, 192178825Sdfr heim_bmp_string *data, size_t *size) 193178825Sdfr{ 194178825Sdfr size_t i; 195178825Sdfr 196178825Sdfr if (len & 1) 197178825Sdfr return ASN1_BAD_FORMAT; 198178825Sdfr data->length = len / 2; 199178825Sdfr if (data->length > UINT_MAX/sizeof(data->data[0])) 200178825Sdfr return ERANGE; 201178825Sdfr data->data = malloc(data->length * sizeof(data->data[0])); 202178825Sdfr if (data->data == NULL && data->length != 0) 203178825Sdfr return ENOMEM; 204178825Sdfr 205178825Sdfr for (i = 0; i < data->length; i++) { 206178825Sdfr data->data[i] = (p[0] << 8) | p[1]; 207178825Sdfr p += 2; 208233294Sstas /* check for NUL in the middle of the string */ 209233294Sstas if (data->data[i] == 0 && i != (data->length - 1)) { 210233294Sstas free(data->data); 211233294Sstas data->data = NULL; 212233294Sstas data->length = 0; 213233294Sstas return ASN1_BAD_CHARACTER; 214233294Sstas } 215178825Sdfr } 216178825Sdfr if (size) *size = len; 217178825Sdfr 218178825Sdfr return 0; 219178825Sdfr} 220178825Sdfr 221178825Sdfrint 222233294Sstasder_get_universal_string (const unsigned char *p, size_t len, 223178825Sdfr heim_universal_string *data, size_t *size) 224178825Sdfr{ 225178825Sdfr size_t i; 226178825Sdfr 227178825Sdfr if (len & 3) 228178825Sdfr return ASN1_BAD_FORMAT; 229178825Sdfr data->length = len / 4; 230178825Sdfr if (data->length > UINT_MAX/sizeof(data->data[0])) 231178825Sdfr return ERANGE; 232178825Sdfr data->data = malloc(data->length * sizeof(data->data[0])); 233178825Sdfr if (data->data == NULL && data->length != 0) 234178825Sdfr return ENOMEM; 235178825Sdfr 236178825Sdfr for (i = 0; i < data->length; i++) { 237178825Sdfr data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 238178825Sdfr p += 4; 239233294Sstas /* check for NUL in the middle of the string */ 240233294Sstas if (data->data[i] == 0 && i != (data->length - 1)) { 241233294Sstas free(data->data); 242233294Sstas data->data = NULL; 243233294Sstas data->length = 0; 244233294Sstas return ASN1_BAD_CHARACTER; 245233294Sstas } 246178825Sdfr } 247178825Sdfr if (size) *size = len; 248178825Sdfr return 0; 249178825Sdfr} 250178825Sdfr 251178825Sdfrint 252233294Sstasder_get_visible_string (const unsigned char *p, size_t len, 253178825Sdfr heim_visible_string *str, size_t *size) 254178825Sdfr{ 255178825Sdfr return der_get_general_string(p, len, str, size); 256178825Sdfr} 257178825Sdfr 258178825Sdfrint 259233294Sstasder_get_octet_string (const unsigned char *p, size_t len, 260178825Sdfr heim_octet_string *data, size_t *size) 26155682Smarkm{ 26255682Smarkm data->length = len; 26355682Smarkm data->data = malloc(len); 26455682Smarkm if (data->data == NULL && data->length != 0) 26555682Smarkm return ENOMEM; 26655682Smarkm memcpy (data->data, p, len); 26755682Smarkm if(size) *size = len; 26855682Smarkm return 0; 26955682Smarkm} 27055682Smarkm 27155682Smarkmint 272233294Sstasder_get_octet_string_ber (const unsigned char *p, size_t len, 273233294Sstas heim_octet_string *data, size_t *size) 274233294Sstas{ 275233294Sstas int e; 276233294Sstas Der_type type; 277233294Sstas Der_class class; 278233294Sstas unsigned int tag, depth = 0; 279233294Sstas size_t l, datalen, oldlen = len; 280233294Sstas 281233294Sstas data->length = 0; 282233294Sstas data->data = NULL; 283233294Sstas 284233294Sstas while (len) { 285233294Sstas e = der_get_tag (p, len, &class, &type, &tag, &l); 286233294Sstas if (e) goto out; 287233294Sstas if (class != ASN1_C_UNIV) { 288233294Sstas e = ASN1_BAD_ID; 289233294Sstas goto out; 290233294Sstas } 291233294Sstas if (type == PRIM && tag == UT_EndOfContent) { 292233294Sstas if (depth == 0) 293233294Sstas break; 294233294Sstas depth--; 295233294Sstas } 296233294Sstas if (tag != UT_OctetString) { 297233294Sstas e = ASN1_BAD_ID; 298233294Sstas goto out; 299233294Sstas } 300233294Sstas 301233294Sstas p += l; 302233294Sstas len -= l; 303233294Sstas e = der_get_length (p, len, &datalen, &l); 304233294Sstas if (e) goto out; 305233294Sstas p += l; 306233294Sstas len -= l; 307233294Sstas 308233294Sstas if (datalen > len) 309233294Sstas return ASN1_OVERRUN; 310233294Sstas 311233294Sstas if (type == PRIM) { 312233294Sstas void *ptr; 313233294Sstas 314233294Sstas ptr = realloc(data->data, data->length + datalen); 315233294Sstas if (ptr == NULL) { 316233294Sstas e = ENOMEM; 317233294Sstas goto out; 318233294Sstas } 319233294Sstas data->data = ptr; 320233294Sstas memcpy(((unsigned char *)data->data) + data->length, p, datalen); 321233294Sstas data->length += datalen; 322233294Sstas } else 323233294Sstas depth++; 324233294Sstas 325233294Sstas p += datalen; 326233294Sstas len -= datalen; 327233294Sstas } 328233294Sstas if (depth != 0) 329233294Sstas return ASN1_INDEF_OVERRUN; 330233294Sstas if(size) *size = oldlen - len; 331233294Sstas return 0; 332233294Sstas out: 333233294Sstas free(data->data); 334233294Sstas data->data = NULL; 335233294Sstas data->length = 0; 336233294Sstas return e; 337233294Sstas} 338233294Sstas 339233294Sstas 340233294Sstasint 341233294Sstasder_get_heim_integer (const unsigned char *p, size_t len, 342178825Sdfr heim_integer *data, size_t *size) 343178825Sdfr{ 344178825Sdfr data->length = 0; 345178825Sdfr data->negative = 0; 346178825Sdfr data->data = NULL; 347178825Sdfr 348178825Sdfr if (len == 0) { 349178825Sdfr if (size) 350178825Sdfr *size = 0; 351178825Sdfr return 0; 352178825Sdfr } 353178825Sdfr if (p[0] & 0x80) { 354178825Sdfr unsigned char *q; 355178825Sdfr int carry = 1; 356178825Sdfr data->negative = 1; 357178825Sdfr 358178825Sdfr data->length = len; 359178825Sdfr 360178825Sdfr if (p[0] == 0xff) { 361178825Sdfr p++; 362178825Sdfr data->length--; 363178825Sdfr } 364178825Sdfr data->data = malloc(data->length); 365178825Sdfr if (data->data == NULL) { 366178825Sdfr data->length = 0; 367178825Sdfr if (size) 368178825Sdfr *size = 0; 369178825Sdfr return ENOMEM; 370178825Sdfr } 371178825Sdfr q = &((unsigned char*)data->data)[data->length - 1]; 372178825Sdfr p += data->length - 1; 373178825Sdfr while (q >= (unsigned char*)data->data) { 374178825Sdfr *q = *p ^ 0xff; 375178825Sdfr if (carry) 376178825Sdfr carry = !++*q; 377178825Sdfr p--; 378178825Sdfr q--; 379178825Sdfr } 380178825Sdfr } else { 381178825Sdfr data->negative = 0; 382178825Sdfr data->length = len; 383178825Sdfr 384178825Sdfr if (p[0] == 0) { 385178825Sdfr p++; 386178825Sdfr data->length--; 387178825Sdfr } 388178825Sdfr data->data = malloc(data->length); 389178825Sdfr if (data->data == NULL && data->length != 0) { 390178825Sdfr data->length = 0; 391178825Sdfr if (size) 392178825Sdfr *size = 0; 393178825Sdfr return ENOMEM; 394178825Sdfr } 395178825Sdfr memcpy(data->data, p, data->length); 396178825Sdfr } 397178825Sdfr if (size) 398178825Sdfr *size = len; 399178825Sdfr return 0; 400178825Sdfr} 401178825Sdfr 402178825Sdfrstatic int 403178825Sdfrgeneralizedtime2time (const char *s, time_t *t) 404178825Sdfr{ 405178825Sdfr struct tm tm; 406178825Sdfr 407178825Sdfr memset(&tm, 0, sizeof(tm)); 408178825Sdfr if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 409178825Sdfr &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 410178825Sdfr &tm.tm_min, &tm.tm_sec) != 6) { 411178825Sdfr if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ", 412178825Sdfr &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 413178825Sdfr &tm.tm_min, &tm.tm_sec) != 6) 414178825Sdfr return ASN1_BAD_TIMEFORMAT; 415178825Sdfr if (tm.tm_year < 50) 416178825Sdfr tm.tm_year += 2000; 417178825Sdfr else 418178825Sdfr tm.tm_year += 1900; 419178825Sdfr } 420178825Sdfr tm.tm_year -= 1900; 421178825Sdfr tm.tm_mon -= 1; 422178825Sdfr *t = _der_timegm (&tm); 423178825Sdfr return 0; 424178825Sdfr} 425178825Sdfr 426178825Sdfrstatic int 427233294Sstasder_get_time (const unsigned char *p, size_t len, 428178825Sdfr time_t *data, size_t *size) 429178825Sdfr{ 430178825Sdfr char *times; 431178825Sdfr int e; 432178825Sdfr 433178825Sdfr if (len > len + 1 || len == 0) 434178825Sdfr return ASN1_BAD_LENGTH; 435178825Sdfr 436178825Sdfr times = malloc(len + 1); 437178825Sdfr if (times == NULL) 438178825Sdfr return ENOMEM; 439178825Sdfr memcpy(times, p, len); 440178825Sdfr times[len] = '\0'; 441178825Sdfr e = generalizedtime2time(times, data); 442178825Sdfr free (times); 443178825Sdfr if(size) *size = len; 444178825Sdfr return e; 445178825Sdfr} 446178825Sdfr 447178825Sdfrint 448233294Sstasder_get_generalized_time (const unsigned char *p, size_t len, 449178825Sdfr time_t *data, size_t *size) 450178825Sdfr{ 451178825Sdfr return der_get_time(p, len, data, size); 452178825Sdfr} 453178825Sdfr 454178825Sdfrint 455233294Sstasder_get_utctime (const unsigned char *p, size_t len, 456178825Sdfr time_t *data, size_t *size) 457178825Sdfr{ 458178825Sdfr return der_get_time(p, len, data, size); 459178825Sdfr} 460178825Sdfr 461178825Sdfrint 46290926Snectarder_get_oid (const unsigned char *p, size_t len, 463178825Sdfr heim_oid *data, size_t *size) 46490926Snectar{ 465178825Sdfr size_t n; 46690926Snectar size_t oldlen = len; 46790926Snectar 46890926Snectar if (len < 1) 46990926Snectar return ASN1_OVERRUN; 47090926Snectar 471178825Sdfr if (len > len + 1) 472178825Sdfr return ASN1_BAD_LENGTH; 473178825Sdfr 474178825Sdfr if (len + 1 > UINT_MAX/sizeof(data->components[0])) 475178825Sdfr return ERANGE; 476178825Sdfr 477178825Sdfr data->components = malloc((len + 1) * sizeof(data->components[0])); 478178825Sdfr if (data->components == NULL) 47990926Snectar return ENOMEM; 48090926Snectar data->components[0] = (*p) / 40; 48190926Snectar data->components[1] = (*p) % 40; 48290926Snectar --len; 48390926Snectar ++p; 48490926Snectar for (n = 2; len > 0; ++n) { 485178825Sdfr unsigned u = 0, u1; 486233294Sstas 48790926Snectar do { 48890926Snectar --len; 489178825Sdfr u1 = u * 128 + (*p++ % 128); 490178825Sdfr /* check that we don't overflow the element */ 491178825Sdfr if (u1 < u) { 492178825Sdfr der_free_oid(data); 493178825Sdfr return ASN1_OVERRUN; 494178825Sdfr } 495178825Sdfr u = u1; 49690926Snectar } while (len > 0 && p[-1] & 0x80); 49790926Snectar data->components[n] = u; 49890926Snectar } 499178825Sdfr if (n > 2 && p[-1] & 0x80) { 500178825Sdfr der_free_oid (data); 50190926Snectar return ASN1_OVERRUN; 50290926Snectar } 50390926Snectar data->length = n; 50490926Snectar if (size) 50590926Snectar *size = oldlen; 50690926Snectar return 0; 50790926Snectar} 50890926Snectar 50990926Snectarint 51055682Smarkmder_get_tag (const unsigned char *p, size_t len, 51155682Smarkm Der_class *class, Der_type *type, 512178825Sdfr unsigned int *tag, size_t *size) 51355682Smarkm{ 514178825Sdfr size_t ret = 0; 51555682Smarkm if (len < 1) 51655682Smarkm return ASN1_OVERRUN; 51755682Smarkm *class = (Der_class)(((*p) >> 6) & 0x03); 51855682Smarkm *type = (Der_type)(((*p) >> 5) & 0x01); 519178825Sdfr *tag = (*p) & 0x1f; 520178825Sdfr p++; len--; ret++; 521178825Sdfr if(*tag == 0x1f) { 522178825Sdfr unsigned int continuation; 523178825Sdfr unsigned int tag1; 524178825Sdfr *tag = 0; 525178825Sdfr do { 526178825Sdfr if(len < 1) 527178825Sdfr return ASN1_OVERRUN; 528178825Sdfr continuation = *p & 128; 529178825Sdfr tag1 = *tag * 128 + (*p % 128); 530178825Sdfr /* check that we don't overflow the tag */ 531178825Sdfr if (tag1 < *tag) 532178825Sdfr return ASN1_OVERFLOW; 533178825Sdfr *tag = tag1; 534178825Sdfr p++; len--; ret++; 535178825Sdfr } while(continuation); 536178825Sdfr } 537178825Sdfr if(size) *size = ret; 53855682Smarkm return 0; 53955682Smarkm} 54055682Smarkm 54155682Smarkmint 54255682Smarkmder_match_tag (const unsigned char *p, size_t len, 54355682Smarkm Der_class class, Der_type type, 544178825Sdfr unsigned int tag, size_t *size) 54555682Smarkm{ 546233294Sstas Der_type thistype; 547233294Sstas int e; 548233294Sstas 549233294Sstas e = der_match_tag2(p, len, class, &thistype, tag, size); 550233294Sstas if (e) return e; 551233294Sstas if (thistype != type) return ASN1_BAD_ID; 552233294Sstas return 0; 553233294Sstas} 554233294Sstas 555233294Sstasint 556233294Sstasder_match_tag2 (const unsigned char *p, size_t len, 557233294Sstas Der_class class, Der_type *type, 558233294Sstas unsigned int tag, size_t *size) 559233294Sstas{ 56055682Smarkm size_t l; 56155682Smarkm Der_class thisclass; 562178825Sdfr unsigned int thistag; 56355682Smarkm int e; 56455682Smarkm 565233294Sstas e = der_get_tag (p, len, &thisclass, type, &thistag, &l); 56655682Smarkm if (e) return e; 567233294Sstas if (class != thisclass) 56855682Smarkm return ASN1_BAD_ID; 56955682Smarkm if(tag > thistag) 57055682Smarkm return ASN1_MISPLACED_FIELD; 57155682Smarkm if(tag < thistag) 57255682Smarkm return ASN1_MISSING_FIELD; 57355682Smarkm if(size) *size = l; 57455682Smarkm return 0; 57555682Smarkm} 57655682Smarkm 57755682Smarkmint 57855682Smarkmder_match_tag_and_length (const unsigned char *p, size_t len, 579233294Sstas Der_class class, Der_type *type, unsigned int tag, 58055682Smarkm size_t *length_ret, size_t *size) 58155682Smarkm{ 58255682Smarkm size_t l, ret = 0; 58355682Smarkm int e; 58455682Smarkm 585233294Sstas e = der_match_tag2 (p, len, class, type, tag, &l); 58655682Smarkm if (e) return e; 58755682Smarkm p += l; 58855682Smarkm len -= l; 58955682Smarkm ret += l; 59055682Smarkm e = der_get_length (p, len, length_ret, &l); 59155682Smarkm if (e) return e; 592233294Sstas if(size) *size = ret + l; 59355682Smarkm return 0; 59455682Smarkm} 59555682Smarkm 596233294Sstas 597233294Sstas 598233294Sstas/* 599178825Sdfr * Old versions of DCE was based on a very early beta of the MIT code, 600178825Sdfr * which used MAVROS for ASN.1 encoding. MAVROS had the interesting 601178825Sdfr * feature that it encoded data in the forward direction, which has 602178825Sdfr * it's problems, since you have no idea how long the data will be 603178825Sdfr * until after you're done. MAVROS solved this by reserving one byte 604178825Sdfr * for length, and later, if the actual length was longer, it reverted 605178825Sdfr * to indefinite, BER style, lengths. The version of MAVROS used by 606178825Sdfr * the DCE people could apparently generate correct X.509 DER encodings, and 607178825Sdfr * did this by making space for the length after encoding, but 608233294Sstas * unfortunately this feature wasn't used with Kerberos. 609178825Sdfr */ 61055682Smarkm 61155682Smarkmint 612178825Sdfr_heim_fix_dce(size_t reallen, size_t *len) 61372445Sassar{ 614178825Sdfr if(reallen == ASN1_INDEFINITE) 615178825Sdfr return 1; 616178825Sdfr if(*len < reallen) 617178825Sdfr return -1; 618178825Sdfr *len = reallen; 61972445Sassar return 0; 62072445Sassar} 62172445Sassar 62272445Sassarint 623233294Sstasder_get_bit_string (const unsigned char *p, size_t len, 624178825Sdfr heim_bit_string *data, size_t *size) 62590926Snectar{ 626178825Sdfr if (len < 1) 62755682Smarkm return ASN1_OVERRUN; 628178825Sdfr if (p[0] > 7) 629178825Sdfr return ASN1_BAD_FORMAT; 630178825Sdfr if (len - 1 == 0 && p[0] != 0) 631178825Sdfr return ASN1_BAD_FORMAT; 632178825Sdfr /* check if any of the three upper bits are set 633178825Sdfr * any of them will cause a interger overrun */ 634178825Sdfr if ((len - 1) >> (sizeof(len) * 8 - 3)) 63555682Smarkm return ASN1_OVERRUN; 636178825Sdfr data->length = (len - 1) * 8; 637178825Sdfr data->data = malloc(len - 1); 638178825Sdfr if (data->data == NULL && (len - 1) != 0) 63955682Smarkm return ENOMEM; 640233294Sstas /* copy data is there is data to copy */ 641233294Sstas if (len - 1 != 0) { 642233294Sstas memcpy (data->data, p + 1, len - 1); 643233294Sstas data->length -= p[0]; 644233294Sstas } 645178825Sdfr if(size) *size = len; 64655682Smarkm return 0; 64755682Smarkm} 648