1b528cefcSMark Murray /* 2c19800e8SDoug Rabson * 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 36c19800e8SDoug Rabson RCSID("$Id: der_get.c 21369 2007-06-27 10:14:39Z lha $"); 37b528cefcSMark Murray 38b528cefcSMark Murray #include <version.h> 39b528cefcSMark Murray 40b528cefcSMark Murray /* 41b528cefcSMark Murray * All decoding functions take a pointer `p' to first position in 42b528cefcSMark Murray * which to read, from the left, `len' which means the maximum number 43b528cefcSMark Murray * of characters we are able to read, `ret' were the value will be 44b528cefcSMark Murray * returned and `size' where the number of used bytes is stored. 45b528cefcSMark Murray * Either 0 or an error code is returned. 46b528cefcSMark Murray */ 47b528cefcSMark Murray 48c19800e8SDoug Rabson int 49b528cefcSMark Murray der_get_unsigned (const unsigned char *p, size_t len, 50b528cefcSMark Murray unsigned *ret, size_t *size) 51b528cefcSMark Murray { 52b528cefcSMark Murray unsigned val = 0; 53b528cefcSMark Murray size_t oldlen = len; 54b528cefcSMark Murray 55c19800e8SDoug Rabson if (len == sizeof(unsigned) + 1 && p[0] == 0) 56c19800e8SDoug Rabson ; 57c19800e8SDoug Rabson else if (len > sizeof(unsigned)) 58c19800e8SDoug Rabson return ASN1_OVERRUN; 59c19800e8SDoug Rabson 60b528cefcSMark Murray while (len--) 61b528cefcSMark Murray val = val * 256 + *p++; 62b528cefcSMark Murray *ret = val; 63b528cefcSMark Murray if(size) *size = oldlen; 64b528cefcSMark Murray return 0; 65b528cefcSMark Murray } 66b528cefcSMark Murray 67b528cefcSMark Murray int 68c19800e8SDoug Rabson der_get_integer (const unsigned char *p, size_t len, 69b528cefcSMark Murray int *ret, size_t *size) 70b528cefcSMark Murray { 71b528cefcSMark Murray int val = 0; 72b528cefcSMark Murray size_t oldlen = len; 73b528cefcSMark Murray 74c19800e8SDoug Rabson if (len > sizeof(int)) 75c19800e8SDoug Rabson return ASN1_OVERRUN; 76c19800e8SDoug Rabson 778373020dSJacques Vidrine if (len > 0) { 78b528cefcSMark Murray val = (signed char)*p++; 798373020dSJacques Vidrine while (--len) 80b528cefcSMark Murray val = val * 256 + *p++; 818373020dSJacques Vidrine } 82b528cefcSMark Murray *ret = val; 83b528cefcSMark Murray if(size) *size = oldlen; 84b528cefcSMark Murray return 0; 85b528cefcSMark Murray } 86b528cefcSMark Murray 87b528cefcSMark Murray int 88b528cefcSMark Murray der_get_length (const unsigned char *p, size_t len, 89b528cefcSMark Murray size_t *val, size_t *size) 90b528cefcSMark Murray { 91b528cefcSMark Murray size_t v; 92b528cefcSMark Murray 93b528cefcSMark Murray if (len <= 0) 94b528cefcSMark Murray return ASN1_OVERRUN; 95b528cefcSMark Murray --len; 96b528cefcSMark Murray v = *p++; 97b528cefcSMark Murray if (v < 128) { 98b528cefcSMark Murray *val = v; 99b528cefcSMark Murray if(size) *size = 1; 100b528cefcSMark Murray } else { 101b528cefcSMark Murray int e; 102b528cefcSMark Murray size_t l; 103b528cefcSMark Murray unsigned tmp; 104b528cefcSMark Murray 105b528cefcSMark Murray if(v == 0x80){ 106b528cefcSMark Murray *val = ASN1_INDEFINITE; 107b528cefcSMark Murray if(size) *size = 1; 108b528cefcSMark Murray return 0; 109b528cefcSMark Murray } 110b528cefcSMark Murray v &= 0x7F; 111b528cefcSMark Murray if (len < v) 112b528cefcSMark Murray return ASN1_OVERRUN; 113b528cefcSMark Murray e = der_get_unsigned (p, v, &tmp, &l); 114b528cefcSMark Murray if(e) return e; 115b528cefcSMark Murray *val = tmp; 116b528cefcSMark Murray if(size) *size = l + 1; 117b528cefcSMark Murray } 118b528cefcSMark Murray return 0; 119b528cefcSMark Murray } 120b528cefcSMark Murray 121b528cefcSMark Murray int 122c19800e8SDoug Rabson der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) 123b528cefcSMark Murray { 124c19800e8SDoug Rabson if(len < 1) 125c19800e8SDoug Rabson return ASN1_OVERRUN; 126c19800e8SDoug Rabson if(*p != 0) 127c19800e8SDoug Rabson *data = 1; 128c19800e8SDoug Rabson else 129c19800e8SDoug Rabson *data = 0; 130c19800e8SDoug Rabson *size = 1; 131c19800e8SDoug Rabson return 0; 132c19800e8SDoug Rabson } 133c19800e8SDoug Rabson 134c19800e8SDoug Rabson int 135c19800e8SDoug Rabson der_get_general_string (const unsigned char *p, size_t len, 136c19800e8SDoug Rabson heim_general_string *str, size_t *size) 137c19800e8SDoug Rabson { 138c19800e8SDoug Rabson const unsigned char *p1; 139b528cefcSMark Murray char *s; 140b528cefcSMark Murray 141c19800e8SDoug Rabson p1 = memchr(p, 0, len); 142c19800e8SDoug Rabson if (p1 != NULL) { 143c19800e8SDoug Rabson /* 144c19800e8SDoug Rabson * Allow trailing NULs. We allow this since MIT Kerberos sends 145c19800e8SDoug Rabson * an strings in the NEED_PREAUTH case that includes a 146c19800e8SDoug Rabson * trailing NUL. 147c19800e8SDoug Rabson */ 148c19800e8SDoug Rabson while (p1 - p < len && *p1 == '\0') 149c19800e8SDoug Rabson p1++; 150c19800e8SDoug Rabson if (p1 - p != len) 151c19800e8SDoug Rabson return ASN1_BAD_CHARACTER; 152c19800e8SDoug Rabson } 153c19800e8SDoug Rabson if (len > len + 1) 154c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 155c19800e8SDoug Rabson 156b528cefcSMark Murray s = malloc (len + 1); 157b528cefcSMark Murray if (s == NULL) 158b528cefcSMark Murray return ENOMEM; 159b528cefcSMark Murray memcpy (s, p, len); 160b528cefcSMark Murray s[len] = '\0'; 161b528cefcSMark Murray *str = s; 162b528cefcSMark Murray if(size) *size = len; 163b528cefcSMark Murray return 0; 164b528cefcSMark Murray } 165b528cefcSMark Murray 166b528cefcSMark Murray int 167c19800e8SDoug Rabson der_get_utf8string (const unsigned char *p, size_t len, 168c19800e8SDoug Rabson heim_utf8_string *str, size_t *size) 169c19800e8SDoug Rabson { 170c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 171c19800e8SDoug Rabson } 172c19800e8SDoug Rabson 173c19800e8SDoug Rabson int 174c19800e8SDoug Rabson der_get_printable_string (const unsigned char *p, size_t len, 175c19800e8SDoug Rabson heim_printable_string *str, size_t *size) 176c19800e8SDoug Rabson { 177c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 178c19800e8SDoug Rabson } 179c19800e8SDoug Rabson 180c19800e8SDoug Rabson int 181c19800e8SDoug Rabson der_get_ia5_string (const unsigned char *p, size_t len, 182c19800e8SDoug Rabson heim_ia5_string *str, size_t *size) 183c19800e8SDoug Rabson { 184c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 185c19800e8SDoug Rabson } 186c19800e8SDoug Rabson 187c19800e8SDoug Rabson int 188c19800e8SDoug Rabson der_get_bmp_string (const unsigned char *p, size_t len, 189c19800e8SDoug Rabson heim_bmp_string *data, size_t *size) 190c19800e8SDoug Rabson { 191c19800e8SDoug Rabson size_t i; 192c19800e8SDoug Rabson 193c19800e8SDoug Rabson if (len & 1) 194c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 195c19800e8SDoug Rabson data->length = len / 2; 196c19800e8SDoug Rabson if (data->length > UINT_MAX/sizeof(data->data[0])) 197c19800e8SDoug Rabson return ERANGE; 198c19800e8SDoug Rabson data->data = malloc(data->length * sizeof(data->data[0])); 199c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) 200c19800e8SDoug Rabson return ENOMEM; 201c19800e8SDoug Rabson 202c19800e8SDoug Rabson for (i = 0; i < data->length; i++) { 203c19800e8SDoug Rabson data->data[i] = (p[0] << 8) | p[1]; 204c19800e8SDoug Rabson p += 2; 205c19800e8SDoug Rabson } 206c19800e8SDoug Rabson if (size) *size = len; 207c19800e8SDoug Rabson 208c19800e8SDoug Rabson return 0; 209c19800e8SDoug Rabson } 210c19800e8SDoug Rabson 211c19800e8SDoug Rabson int 212c19800e8SDoug Rabson der_get_universal_string (const unsigned char *p, size_t len, 213c19800e8SDoug Rabson heim_universal_string *data, size_t *size) 214c19800e8SDoug Rabson { 215c19800e8SDoug Rabson size_t i; 216c19800e8SDoug Rabson 217c19800e8SDoug Rabson if (len & 3) 218c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 219c19800e8SDoug Rabson data->length = len / 4; 220c19800e8SDoug Rabson if (data->length > UINT_MAX/sizeof(data->data[0])) 221c19800e8SDoug Rabson return ERANGE; 222c19800e8SDoug Rabson data->data = malloc(data->length * sizeof(data->data[0])); 223c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) 224c19800e8SDoug Rabson return ENOMEM; 225c19800e8SDoug Rabson 226c19800e8SDoug Rabson for (i = 0; i < data->length; i++) { 227c19800e8SDoug Rabson data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 228c19800e8SDoug Rabson p += 4; 229c19800e8SDoug Rabson } 230c19800e8SDoug Rabson if (size) *size = len; 231c19800e8SDoug Rabson return 0; 232c19800e8SDoug Rabson } 233c19800e8SDoug Rabson 234c19800e8SDoug Rabson int 235c19800e8SDoug Rabson der_get_visible_string (const unsigned char *p, size_t len, 236c19800e8SDoug Rabson heim_visible_string *str, size_t *size) 237c19800e8SDoug Rabson { 238c19800e8SDoug Rabson return der_get_general_string(p, len, str, size); 239c19800e8SDoug Rabson } 240c19800e8SDoug Rabson 241c19800e8SDoug Rabson int 242b528cefcSMark Murray der_get_octet_string (const unsigned char *p, size_t len, 243c19800e8SDoug Rabson heim_octet_string *data, size_t *size) 244b528cefcSMark Murray { 245b528cefcSMark Murray data->length = len; 246b528cefcSMark Murray data->data = malloc(len); 247b528cefcSMark Murray if (data->data == NULL && data->length != 0) 248b528cefcSMark Murray return ENOMEM; 249b528cefcSMark Murray memcpy (data->data, p, len); 250b528cefcSMark Murray if(size) *size = len; 251b528cefcSMark Murray return 0; 252b528cefcSMark Murray } 253b528cefcSMark Murray 254b528cefcSMark Murray int 255c19800e8SDoug Rabson der_get_heim_integer (const unsigned char *p, size_t len, 256c19800e8SDoug Rabson heim_integer *data, size_t *size) 2574137ff4cSJacques Vidrine { 258c19800e8SDoug Rabson data->length = 0; 259c19800e8SDoug Rabson data->negative = 0; 260c19800e8SDoug Rabson data->data = NULL; 261c19800e8SDoug Rabson 262c19800e8SDoug Rabson if (len == 0) { 263c19800e8SDoug Rabson if (size) 264c19800e8SDoug Rabson *size = 0; 265c19800e8SDoug Rabson return 0; 266c19800e8SDoug Rabson } 267c19800e8SDoug Rabson if (p[0] & 0x80) { 268c19800e8SDoug Rabson unsigned char *q; 269c19800e8SDoug Rabson int carry = 1; 270c19800e8SDoug Rabson data->negative = 1; 271c19800e8SDoug Rabson 272c19800e8SDoug Rabson data->length = len; 273c19800e8SDoug Rabson 274c19800e8SDoug Rabson if (p[0] == 0xff) { 275c19800e8SDoug Rabson p++; 276c19800e8SDoug Rabson data->length--; 277c19800e8SDoug Rabson } 278c19800e8SDoug Rabson data->data = malloc(data->length); 279c19800e8SDoug Rabson if (data->data == NULL) { 280c19800e8SDoug Rabson data->length = 0; 281c19800e8SDoug Rabson if (size) 282c19800e8SDoug Rabson *size = 0; 283c19800e8SDoug Rabson return ENOMEM; 284c19800e8SDoug Rabson } 285c19800e8SDoug Rabson q = &((unsigned char*)data->data)[data->length - 1]; 286c19800e8SDoug Rabson p += data->length - 1; 287c19800e8SDoug Rabson while (q >= (unsigned char*)data->data) { 288c19800e8SDoug Rabson *q = *p ^ 0xff; 289c19800e8SDoug Rabson if (carry) 290c19800e8SDoug Rabson carry = !++*q; 291c19800e8SDoug Rabson p--; 292c19800e8SDoug Rabson q--; 293c19800e8SDoug Rabson } 294c19800e8SDoug Rabson } else { 295c19800e8SDoug Rabson data->negative = 0; 296c19800e8SDoug Rabson data->length = len; 297c19800e8SDoug Rabson 298c19800e8SDoug Rabson if (p[0] == 0) { 299c19800e8SDoug Rabson p++; 300c19800e8SDoug Rabson data->length--; 301c19800e8SDoug Rabson } 302c19800e8SDoug Rabson data->data = malloc(data->length); 303c19800e8SDoug Rabson if (data->data == NULL && data->length != 0) { 304c19800e8SDoug Rabson data->length = 0; 305c19800e8SDoug Rabson if (size) 306c19800e8SDoug Rabson *size = 0; 307c19800e8SDoug Rabson return ENOMEM; 308c19800e8SDoug Rabson } 309c19800e8SDoug Rabson memcpy(data->data, p, data->length); 310c19800e8SDoug Rabson } 311c19800e8SDoug Rabson if (size) 312c19800e8SDoug Rabson *size = len; 313c19800e8SDoug Rabson return 0; 314c19800e8SDoug Rabson } 315c19800e8SDoug Rabson 316c19800e8SDoug Rabson static int 317c19800e8SDoug Rabson generalizedtime2time (const char *s, time_t *t) 318c19800e8SDoug Rabson { 319c19800e8SDoug Rabson struct tm tm; 320c19800e8SDoug Rabson 321c19800e8SDoug Rabson memset(&tm, 0, sizeof(tm)); 322c19800e8SDoug Rabson if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 323c19800e8SDoug Rabson &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 324c19800e8SDoug Rabson &tm.tm_min, &tm.tm_sec) != 6) { 325c19800e8SDoug Rabson if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ", 326c19800e8SDoug Rabson &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 327c19800e8SDoug Rabson &tm.tm_min, &tm.tm_sec) != 6) 328c19800e8SDoug Rabson return ASN1_BAD_TIMEFORMAT; 329c19800e8SDoug Rabson if (tm.tm_year < 50) 330c19800e8SDoug Rabson tm.tm_year += 2000; 331c19800e8SDoug Rabson else 332c19800e8SDoug Rabson tm.tm_year += 1900; 333c19800e8SDoug Rabson } 334c19800e8SDoug Rabson tm.tm_year -= 1900; 335c19800e8SDoug Rabson tm.tm_mon -= 1; 336c19800e8SDoug Rabson *t = _der_timegm (&tm); 337c19800e8SDoug Rabson return 0; 338c19800e8SDoug Rabson } 339c19800e8SDoug Rabson 340c19800e8SDoug Rabson static int 341c19800e8SDoug Rabson der_get_time (const unsigned char *p, size_t len, 342c19800e8SDoug Rabson time_t *data, size_t *size) 343c19800e8SDoug Rabson { 344c19800e8SDoug Rabson char *times; 345c19800e8SDoug Rabson int e; 346c19800e8SDoug Rabson 347c19800e8SDoug Rabson if (len > len + 1 || len == 0) 348c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 349c19800e8SDoug Rabson 350c19800e8SDoug Rabson times = malloc(len + 1); 351c19800e8SDoug Rabson if (times == NULL) 352c19800e8SDoug Rabson return ENOMEM; 353c19800e8SDoug Rabson memcpy(times, p, len); 354c19800e8SDoug Rabson times[len] = '\0'; 355c19800e8SDoug Rabson e = generalizedtime2time(times, data); 356c19800e8SDoug Rabson free (times); 357c19800e8SDoug Rabson if(size) *size = len; 358c19800e8SDoug Rabson return e; 359c19800e8SDoug Rabson } 360c19800e8SDoug Rabson 361c19800e8SDoug Rabson int 362c19800e8SDoug Rabson der_get_generalized_time (const unsigned char *p, size_t len, 363c19800e8SDoug Rabson time_t *data, size_t *size) 364c19800e8SDoug Rabson { 365c19800e8SDoug Rabson return der_get_time(p, len, data, size); 366c19800e8SDoug Rabson } 367c19800e8SDoug Rabson 368c19800e8SDoug Rabson int 369c19800e8SDoug Rabson der_get_utctime (const unsigned char *p, size_t len, 370c19800e8SDoug Rabson time_t *data, size_t *size) 371c19800e8SDoug Rabson { 372c19800e8SDoug Rabson return der_get_time(p, len, data, size); 373c19800e8SDoug Rabson } 374c19800e8SDoug Rabson 375c19800e8SDoug Rabson int 376c19800e8SDoug Rabson der_get_oid (const unsigned char *p, size_t len, 377c19800e8SDoug Rabson heim_oid *data, size_t *size) 378c19800e8SDoug Rabson { 379c19800e8SDoug Rabson size_t n; 3804137ff4cSJacques Vidrine size_t oldlen = len; 3814137ff4cSJacques Vidrine 3824137ff4cSJacques Vidrine if (len < 1) 3834137ff4cSJacques Vidrine return ASN1_OVERRUN; 3844137ff4cSJacques Vidrine 385c19800e8SDoug Rabson if (len > len + 1) 386c19800e8SDoug Rabson return ASN1_BAD_LENGTH; 387c19800e8SDoug Rabson 388c19800e8SDoug Rabson if (len + 1 > UINT_MAX/sizeof(data->components[0])) 389c19800e8SDoug Rabson return ERANGE; 390c19800e8SDoug Rabson 391c19800e8SDoug Rabson data->components = malloc((len + 1) * sizeof(data->components[0])); 392c19800e8SDoug Rabson if (data->components == NULL) 3934137ff4cSJacques Vidrine return ENOMEM; 3944137ff4cSJacques Vidrine data->components[0] = (*p) / 40; 3954137ff4cSJacques Vidrine data->components[1] = (*p) % 40; 3964137ff4cSJacques Vidrine --len; 3974137ff4cSJacques Vidrine ++p; 3984137ff4cSJacques Vidrine for (n = 2; len > 0; ++n) { 399c19800e8SDoug Rabson unsigned u = 0, u1; 4004137ff4cSJacques Vidrine 4014137ff4cSJacques Vidrine do { 4024137ff4cSJacques Vidrine --len; 403c19800e8SDoug Rabson u1 = u * 128 + (*p++ % 128); 404c19800e8SDoug Rabson /* check that we don't overflow the element */ 405c19800e8SDoug Rabson if (u1 < u) { 406c19800e8SDoug Rabson der_free_oid(data); 407c19800e8SDoug Rabson return ASN1_OVERRUN; 408c19800e8SDoug Rabson } 409c19800e8SDoug Rabson u = u1; 4104137ff4cSJacques Vidrine } while (len > 0 && p[-1] & 0x80); 4114137ff4cSJacques Vidrine data->components[n] = u; 4124137ff4cSJacques Vidrine } 413c19800e8SDoug Rabson if (n > 2 && p[-1] & 0x80) { 414c19800e8SDoug Rabson der_free_oid (data); 4154137ff4cSJacques Vidrine return ASN1_OVERRUN; 4164137ff4cSJacques Vidrine } 4174137ff4cSJacques Vidrine data->length = n; 4184137ff4cSJacques Vidrine if (size) 4194137ff4cSJacques Vidrine *size = oldlen; 4204137ff4cSJacques Vidrine return 0; 4214137ff4cSJacques Vidrine } 4224137ff4cSJacques Vidrine 4234137ff4cSJacques Vidrine int 424b528cefcSMark Murray der_get_tag (const unsigned char *p, size_t len, 425b528cefcSMark Murray Der_class *class, Der_type *type, 426c19800e8SDoug Rabson unsigned int *tag, size_t *size) 427b528cefcSMark Murray { 428c19800e8SDoug Rabson size_t ret = 0; 429b528cefcSMark Murray if (len < 1) 430b528cefcSMark Murray return ASN1_OVERRUN; 431b528cefcSMark Murray *class = (Der_class)(((*p) >> 6) & 0x03); 432b528cefcSMark Murray *type = (Der_type)(((*p) >> 5) & 0x01); 433c19800e8SDoug Rabson *tag = (*p) & 0x1f; 434c19800e8SDoug Rabson p++; len--; ret++; 435c19800e8SDoug Rabson if(*tag == 0x1f) { 436c19800e8SDoug Rabson unsigned int continuation; 437c19800e8SDoug Rabson unsigned int tag1; 438c19800e8SDoug Rabson *tag = 0; 439c19800e8SDoug Rabson do { 440c19800e8SDoug Rabson if(len < 1) 441c19800e8SDoug Rabson return ASN1_OVERRUN; 442c19800e8SDoug Rabson continuation = *p & 128; 443c19800e8SDoug Rabson tag1 = *tag * 128 + (*p % 128); 444c19800e8SDoug Rabson /* check that we don't overflow the tag */ 445c19800e8SDoug Rabson if (tag1 < *tag) 446c19800e8SDoug Rabson return ASN1_OVERFLOW; 447c19800e8SDoug Rabson *tag = tag1; 448c19800e8SDoug Rabson p++; len--; ret++; 449c19800e8SDoug Rabson } while(continuation); 450c19800e8SDoug Rabson } 451c19800e8SDoug Rabson if(size) *size = ret; 452b528cefcSMark Murray return 0; 453b528cefcSMark Murray } 454b528cefcSMark Murray 455b528cefcSMark Murray int 456b528cefcSMark Murray der_match_tag (const unsigned char *p, size_t len, 457b528cefcSMark Murray Der_class class, Der_type type, 458c19800e8SDoug Rabson unsigned int tag, size_t *size) 459b528cefcSMark Murray { 460b528cefcSMark Murray size_t l; 461b528cefcSMark Murray Der_class thisclass; 462b528cefcSMark Murray Der_type thistype; 463c19800e8SDoug Rabson unsigned int thistag; 464b528cefcSMark Murray int e; 465b528cefcSMark Murray 466b528cefcSMark Murray e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); 467b528cefcSMark Murray if (e) return e; 468b528cefcSMark Murray if (class != thisclass || type != thistype) 469b528cefcSMark Murray return ASN1_BAD_ID; 470b528cefcSMark Murray if(tag > thistag) 471b528cefcSMark Murray return ASN1_MISPLACED_FIELD; 472b528cefcSMark Murray if(tag < thistag) 473b528cefcSMark Murray return ASN1_MISSING_FIELD; 474b528cefcSMark Murray if(size) *size = l; 475b528cefcSMark Murray return 0; 476b528cefcSMark Murray } 477b528cefcSMark Murray 478b528cefcSMark Murray int 479b528cefcSMark Murray der_match_tag_and_length (const unsigned char *p, size_t len, 480c19800e8SDoug Rabson Der_class class, Der_type type, unsigned int tag, 481b528cefcSMark Murray size_t *length_ret, size_t *size) 482b528cefcSMark Murray { 483b528cefcSMark Murray size_t l, ret = 0; 484b528cefcSMark Murray int e; 485b528cefcSMark Murray 486b528cefcSMark Murray e = der_match_tag (p, len, class, type, tag, &l); 487b528cefcSMark Murray if (e) return e; 488b528cefcSMark Murray p += l; 489b528cefcSMark Murray len -= l; 490b528cefcSMark Murray ret += l; 491b528cefcSMark Murray e = der_get_length (p, len, length_ret, &l); 492b528cefcSMark Murray if (e) return e; 493b528cefcSMark Murray p += l; 494b528cefcSMark Murray len -= l; 495b528cefcSMark Murray ret += l; 496b528cefcSMark Murray if(size) *size = ret; 497b528cefcSMark Murray return 0; 498b528cefcSMark Murray } 499b528cefcSMark Murray 500c19800e8SDoug Rabson /* 501c19800e8SDoug Rabson * Old versions of DCE was based on a very early beta of the MIT code, 502c19800e8SDoug Rabson * which used MAVROS for ASN.1 encoding. MAVROS had the interesting 503c19800e8SDoug Rabson * feature that it encoded data in the forward direction, which has 504c19800e8SDoug Rabson * it's problems, since you have no idea how long the data will be 505c19800e8SDoug Rabson * until after you're done. MAVROS solved this by reserving one byte 506c19800e8SDoug Rabson * for length, and later, if the actual length was longer, it reverted 507c19800e8SDoug Rabson * to indefinite, BER style, lengths. The version of MAVROS used by 508c19800e8SDoug Rabson * the DCE people could apparently generate correct X.509 DER encodings, and 509c19800e8SDoug Rabson * did this by making space for the length after encoding, but 510c19800e8SDoug Rabson * unfortunately this feature wasn't used with Kerberos. 511c19800e8SDoug Rabson */ 512b528cefcSMark Murray 513b528cefcSMark Murray int 514c19800e8SDoug Rabson _heim_fix_dce(size_t reallen, size_t *len) 515b528cefcSMark Murray { 516b528cefcSMark Murray if(reallen == ASN1_INDEFINITE) 517b528cefcSMark Murray return 1; 518b528cefcSMark Murray if(*len < reallen) 519b528cefcSMark Murray return -1; 520b528cefcSMark Murray *len = reallen; 521b528cefcSMark Murray return 0; 522b528cefcSMark Murray } 523c19800e8SDoug Rabson 524c19800e8SDoug Rabson int 525c19800e8SDoug Rabson der_get_bit_string (const unsigned char *p, size_t len, 526c19800e8SDoug Rabson heim_bit_string *data, size_t *size) 527c19800e8SDoug Rabson { 528c19800e8SDoug Rabson if (len < 1) 529c19800e8SDoug Rabson return ASN1_OVERRUN; 530c19800e8SDoug Rabson if (p[0] > 7) 531c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 532c19800e8SDoug Rabson if (len - 1 == 0 && p[0] != 0) 533c19800e8SDoug Rabson return ASN1_BAD_FORMAT; 534c19800e8SDoug Rabson /* check if any of the three upper bits are set 535c19800e8SDoug Rabson * any of them will cause a interger overrun */ 536c19800e8SDoug Rabson if ((len - 1) >> (sizeof(len) * 8 - 3)) 537c19800e8SDoug Rabson return ASN1_OVERRUN; 538c19800e8SDoug Rabson data->length = (len - 1) * 8; 539c19800e8SDoug Rabson data->data = malloc(len - 1); 540c19800e8SDoug Rabson if (data->data == NULL && (len - 1) != 0) 541c19800e8SDoug Rabson return ENOMEM; 542c19800e8SDoug Rabson memcpy (data->data, p + 1, len - 1); 543c19800e8SDoug Rabson data->length -= p[0]; 544c19800e8SDoug Rabson if(size) *size = len; 545c19800e8SDoug Rabson return 0; 546c19800e8SDoug Rabson } 547