1 /* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "der_locl.h" 35 36 RCSID("$Id: der_get.c,v 1.31 2001/09/28 22:53:24 assar Exp $"); 37 38 #include <version.h> 39 40 /* 41 * All decoding functions take a pointer `p' to first position in 42 * which to read, from the left, `len' which means the maximum number 43 * of characters we are able to read, `ret' were the value will be 44 * returned and `size' where the number of used bytes is stored. 45 * Either 0 or an error code is returned. 46 */ 47 48 static int 49 der_get_unsigned (const unsigned char *p, size_t len, 50 unsigned *ret, size_t *size) 51 { 52 unsigned val = 0; 53 size_t oldlen = len; 54 55 while (len--) 56 val = val * 256 + *p++; 57 *ret = val; 58 if(size) *size = oldlen; 59 return 0; 60 } 61 62 int 63 der_get_int (const unsigned char *p, size_t len, 64 int *ret, size_t *size) 65 { 66 int val = 0; 67 size_t oldlen = len; 68 69 if (len--) 70 val = (signed char)*p++; 71 while (len--) 72 val = val * 256 + *p++; 73 *ret = val; 74 if(size) *size = oldlen; 75 return 0; 76 } 77 78 int 79 der_get_length (const unsigned char *p, size_t len, 80 size_t *val, size_t *size) 81 { 82 size_t v; 83 84 if (len <= 0) 85 return ASN1_OVERRUN; 86 --len; 87 v = *p++; 88 if (v < 128) { 89 *val = v; 90 if(size) *size = 1; 91 } else { 92 int e; 93 size_t l; 94 unsigned tmp; 95 96 if(v == 0x80){ 97 *val = ASN1_INDEFINITE; 98 if(size) *size = 1; 99 return 0; 100 } 101 v &= 0x7F; 102 if (len < v) 103 return ASN1_OVERRUN; 104 e = der_get_unsigned (p, v, &tmp, &l); 105 if(e) return e; 106 *val = tmp; 107 if(size) *size = l + 1; 108 } 109 return 0; 110 } 111 112 int 113 der_get_general_string (const unsigned char *p, size_t len, 114 general_string *str, size_t *size) 115 { 116 char *s; 117 118 s = malloc (len + 1); 119 if (s == NULL) 120 return ENOMEM; 121 memcpy (s, p, len); 122 s[len] = '\0'; 123 *str = s; 124 if(size) *size = len; 125 return 0; 126 } 127 128 int 129 der_get_octet_string (const unsigned char *p, size_t len, 130 octet_string *data, size_t *size) 131 { 132 data->length = len; 133 data->data = malloc(len); 134 if (data->data == NULL && data->length != 0) 135 return ENOMEM; 136 memcpy (data->data, p, len); 137 if(size) *size = len; 138 return 0; 139 } 140 141 int 142 der_get_oid (const unsigned char *p, size_t len, 143 oid *data, size_t *size) 144 { 145 int n; 146 size_t oldlen = len; 147 148 if (len < 1) 149 return ASN1_OVERRUN; 150 151 data->components = malloc(len * sizeof(*data->components)); 152 if (data->components == NULL && len != 0) 153 return ENOMEM; 154 data->components[0] = (*p) / 40; 155 data->components[1] = (*p) % 40; 156 --len; 157 ++p; 158 for (n = 2; len > 0; ++n) { 159 unsigned u = 0; 160 161 do { 162 --len; 163 u = u * 128 + (*p++ % 128); 164 } while (len > 0 && p[-1] & 0x80); 165 data->components[n] = u; 166 } 167 if (p[-1] & 0x80) { 168 free_oid (data); 169 return ASN1_OVERRUN; 170 } 171 data->length = n; 172 if (size) 173 *size = oldlen; 174 return 0; 175 } 176 177 int 178 der_get_tag (const unsigned char *p, size_t len, 179 Der_class *class, Der_type *type, 180 int *tag, size_t *size) 181 { 182 if (len < 1) 183 return ASN1_OVERRUN; 184 *class = (Der_class)(((*p) >> 6) & 0x03); 185 *type = (Der_type)(((*p) >> 5) & 0x01); 186 *tag = (*p) & 0x1F; 187 if(size) *size = 1; 188 return 0; 189 } 190 191 int 192 der_match_tag (const unsigned char *p, size_t len, 193 Der_class class, Der_type type, 194 int tag, size_t *size) 195 { 196 size_t l; 197 Der_class thisclass; 198 Der_type thistype; 199 int thistag; 200 int e; 201 202 e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); 203 if (e) return e; 204 if (class != thisclass || type != thistype) 205 return ASN1_BAD_ID; 206 if(tag > thistag) 207 return ASN1_MISPLACED_FIELD; 208 if(tag < thistag) 209 return ASN1_MISSING_FIELD; 210 if(size) *size = l; 211 return 0; 212 } 213 214 int 215 der_match_tag_and_length (const unsigned char *p, size_t len, 216 Der_class class, Der_type type, int tag, 217 size_t *length_ret, size_t *size) 218 { 219 size_t l, ret = 0; 220 int e; 221 222 e = der_match_tag (p, len, class, type, tag, &l); 223 if (e) return e; 224 p += l; 225 len -= l; 226 ret += l; 227 e = der_get_length (p, len, length_ret, &l); 228 if (e) return e; 229 p += l; 230 len -= l; 231 ret += l; 232 if(size) *size = ret; 233 return 0; 234 } 235 236 int 237 decode_integer (const unsigned char *p, size_t len, 238 int *num, size_t *size) 239 { 240 size_t ret = 0; 241 size_t l, reallen; 242 int e; 243 244 e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); 245 if (e) return e; 246 p += l; 247 len -= l; 248 ret += l; 249 e = der_get_length (p, len, &reallen, &l); 250 if (e) return e; 251 p += l; 252 len -= l; 253 ret += l; 254 e = der_get_int (p, reallen, num, &l); 255 if (e) return e; 256 p += l; 257 len -= l; 258 ret += l; 259 if(size) *size = ret; 260 return 0; 261 } 262 263 int 264 decode_unsigned (const unsigned char *p, size_t len, 265 unsigned *num, size_t *size) 266 { 267 size_t ret = 0; 268 size_t l, reallen; 269 int e; 270 271 e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); 272 if (e) return e; 273 p += l; 274 len -= l; 275 ret += l; 276 e = der_get_length (p, len, &reallen, &l); 277 if (e) return e; 278 p += l; 279 len -= l; 280 ret += l; 281 e = der_get_unsigned (p, reallen, num, &l); 282 if (e) return e; 283 p += l; 284 len -= l; 285 ret += l; 286 if(size) *size = ret; 287 return 0; 288 } 289 290 int 291 decode_enumerated (const unsigned char *p, size_t len, 292 unsigned *num, size_t *size) 293 { 294 size_t ret = 0; 295 size_t l, reallen; 296 int e; 297 298 e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l); 299 if (e) return e; 300 p += l; 301 len -= l; 302 ret += l; 303 e = der_get_length (p, len, &reallen, &l); 304 if (e) return e; 305 p += l; 306 len -= l; 307 ret += l; 308 e = der_get_int (p, reallen, num, &l); 309 if (e) return e; 310 p += l; 311 len -= l; 312 ret += l; 313 if(size) *size = ret; 314 return 0; 315 } 316 317 int 318 decode_general_string (const unsigned char *p, size_t len, 319 general_string *str, size_t *size) 320 { 321 size_t ret = 0; 322 size_t l; 323 int e; 324 size_t slen; 325 326 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); 327 if (e) return e; 328 p += l; 329 len -= l; 330 ret += l; 331 332 e = der_get_length (p, len, &slen, &l); 333 if (e) return e; 334 p += l; 335 len -= l; 336 ret += l; 337 if (len < slen) 338 return ASN1_OVERRUN; 339 340 e = der_get_general_string (p, slen, str, &l); 341 if (e) return e; 342 p += l; 343 len -= l; 344 ret += l; 345 if(size) *size = ret; 346 return 0; 347 } 348 349 int 350 decode_octet_string (const unsigned char *p, size_t len, 351 octet_string *k, size_t *size) 352 { 353 size_t ret = 0; 354 size_t l; 355 int e; 356 size_t slen; 357 358 e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); 359 if (e) return e; 360 p += l; 361 len -= l; 362 ret += l; 363 364 e = der_get_length (p, len, &slen, &l); 365 if (e) return e; 366 p += l; 367 len -= l; 368 ret += l; 369 if (len < slen) 370 return ASN1_OVERRUN; 371 372 e = der_get_octet_string (p, slen, k, &l); 373 if (e) return e; 374 p += l; 375 len -= l; 376 ret += l; 377 if(size) *size = ret; 378 return 0; 379 } 380 381 int 382 decode_oid (const unsigned char *p, size_t len, 383 oid *k, size_t *size) 384 { 385 size_t ret = 0; 386 size_t l; 387 int e; 388 size_t slen; 389 390 e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l); 391 if (e) return e; 392 p += l; 393 len -= l; 394 ret += l; 395 396 e = der_get_length (p, len, &slen, &l); 397 if (e) return e; 398 p += l; 399 len -= l; 400 ret += l; 401 if (len < slen) 402 return ASN1_OVERRUN; 403 404 e = der_get_oid (p, slen, k, &l); 405 if (e) return e; 406 p += l; 407 len -= l; 408 ret += l; 409 if(size) *size = ret; 410 return 0; 411 } 412 413 static void 414 generalizedtime2time (const char *s, time_t *t) 415 { 416 struct tm tm; 417 418 memset(&tm, 0, sizeof(tm)); 419 sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 420 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 421 &tm.tm_min, &tm.tm_sec); 422 tm.tm_year -= 1900; 423 tm.tm_mon -= 1; 424 *t = timegm (&tm); 425 } 426 427 int 428 decode_generalized_time (const unsigned char *p, size_t len, 429 time_t *t, size_t *size) 430 { 431 octet_string k; 432 char *times; 433 size_t ret = 0; 434 size_t l; 435 int e; 436 size_t slen; 437 438 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); 439 if (e) return e; 440 p += l; 441 len -= l; 442 ret += l; 443 444 e = der_get_length (p, len, &slen, &l); 445 if (e) return e; 446 p += l; 447 len -= l; 448 ret += l; 449 if (len < slen) 450 return ASN1_OVERRUN; 451 e = der_get_octet_string (p, slen, &k, &l); 452 if (e) return e; 453 p += l; 454 len -= l; 455 ret += l; 456 times = realloc(k.data, k.length + 1); 457 if (times == NULL){ 458 free(k.data); 459 return ENOMEM; 460 } 461 times[k.length] = 0; 462 generalizedtime2time (times, t); 463 free (times); 464 if(size) *size = ret; 465 return 0; 466 } 467 468 469 int 470 fix_dce(size_t reallen, size_t *len) 471 { 472 if(reallen == ASN1_INDEFINITE) 473 return 1; 474 if(*len < reallen) 475 return -1; 476 *len = reallen; 477 return 0; 478 } 479