1 /* 2 * Copyright (c) 1997 - 2002 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.33 2002/09/03 16:21:49 nectar 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 > 0) { 70 val = (signed char)*p++; 71 while (--len) 72 val = val * 256 + *p++; 73 } 74 *ret = val; 75 if(size) *size = oldlen; 76 return 0; 77 } 78 79 int 80 der_get_length (const unsigned char *p, size_t len, 81 size_t *val, size_t *size) 82 { 83 size_t v; 84 85 if (len <= 0) 86 return ASN1_OVERRUN; 87 --len; 88 v = *p++; 89 if (v < 128) { 90 *val = v; 91 if(size) *size = 1; 92 } else { 93 int e; 94 size_t l; 95 unsigned tmp; 96 97 if(v == 0x80){ 98 *val = ASN1_INDEFINITE; 99 if(size) *size = 1; 100 return 0; 101 } 102 v &= 0x7F; 103 if (len < v) 104 return ASN1_OVERRUN; 105 e = der_get_unsigned (p, v, &tmp, &l); 106 if(e) return e; 107 *val = tmp; 108 if(size) *size = l + 1; 109 } 110 return 0; 111 } 112 113 int 114 der_get_general_string (const unsigned char *p, size_t len, 115 general_string *str, size_t *size) 116 { 117 char *s; 118 119 s = malloc (len + 1); 120 if (s == NULL) 121 return ENOMEM; 122 memcpy (s, p, len); 123 s[len] = '\0'; 124 *str = s; 125 if(size) *size = len; 126 return 0; 127 } 128 129 int 130 der_get_octet_string (const unsigned char *p, size_t len, 131 octet_string *data, size_t *size) 132 { 133 data->length = len; 134 data->data = malloc(len); 135 if (data->data == NULL && data->length != 0) 136 return ENOMEM; 137 memcpy (data->data, p, len); 138 if(size) *size = len; 139 return 0; 140 } 141 142 int 143 der_get_oid (const unsigned char *p, size_t len, 144 oid *data, size_t *size) 145 { 146 int n; 147 size_t oldlen = len; 148 149 if (len < 1) 150 return ASN1_OVERRUN; 151 152 data->components = malloc(len * sizeof(*data->components)); 153 if (data->components == NULL && len != 0) 154 return ENOMEM; 155 data->components[0] = (*p) / 40; 156 data->components[1] = (*p) % 40; 157 --len; 158 ++p; 159 for (n = 2; len > 0; ++n) { 160 unsigned u = 0; 161 162 do { 163 --len; 164 u = u * 128 + (*p++ % 128); 165 } while (len > 0 && p[-1] & 0x80); 166 data->components[n] = u; 167 } 168 if (p[-1] & 0x80) { 169 free_oid (data); 170 return ASN1_OVERRUN; 171 } 172 data->length = n; 173 if (size) 174 *size = oldlen; 175 return 0; 176 } 177 178 int 179 der_get_tag (const unsigned char *p, size_t len, 180 Der_class *class, Der_type *type, 181 int *tag, size_t *size) 182 { 183 if (len < 1) 184 return ASN1_OVERRUN; 185 *class = (Der_class)(((*p) >> 6) & 0x03); 186 *type = (Der_type)(((*p) >> 5) & 0x01); 187 *tag = (*p) & 0x1F; 188 if(size) *size = 1; 189 return 0; 190 } 191 192 int 193 der_match_tag (const unsigned char *p, size_t len, 194 Der_class class, Der_type type, 195 int tag, size_t *size) 196 { 197 size_t l; 198 Der_class thisclass; 199 Der_type thistype; 200 int thistag; 201 int e; 202 203 e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); 204 if (e) return e; 205 if (class != thisclass || type != thistype) 206 return ASN1_BAD_ID; 207 if(tag > thistag) 208 return ASN1_MISPLACED_FIELD; 209 if(tag < thistag) 210 return ASN1_MISSING_FIELD; 211 if(size) *size = l; 212 return 0; 213 } 214 215 int 216 der_match_tag_and_length (const unsigned char *p, size_t len, 217 Der_class class, Der_type type, int tag, 218 size_t *length_ret, size_t *size) 219 { 220 size_t l, ret = 0; 221 int e; 222 223 e = der_match_tag (p, len, class, type, tag, &l); 224 if (e) return e; 225 p += l; 226 len -= l; 227 ret += l; 228 e = der_get_length (p, len, length_ret, &l); 229 if (e) return e; 230 p += l; 231 len -= l; 232 ret += l; 233 if(size) *size = ret; 234 return 0; 235 } 236 237 int 238 decode_integer (const unsigned char *p, size_t len, 239 int *num, size_t *size) 240 { 241 size_t ret = 0; 242 size_t l, reallen; 243 int e; 244 245 e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); 246 if (e) return e; 247 p += l; 248 len -= l; 249 ret += l; 250 e = der_get_length (p, len, &reallen, &l); 251 if (e) return e; 252 p += l; 253 len -= l; 254 ret += l; 255 if (reallen > len) 256 return ASN1_OVERRUN; 257 e = der_get_int (p, reallen, num, &l); 258 if (e) return e; 259 p += l; 260 len -= l; 261 ret += l; 262 if(size) *size = ret; 263 return 0; 264 } 265 266 int 267 decode_unsigned (const unsigned char *p, size_t len, 268 unsigned *num, size_t *size) 269 { 270 size_t ret = 0; 271 size_t l, reallen; 272 int e; 273 274 e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); 275 if (e) return e; 276 p += l; 277 len -= l; 278 ret += l; 279 e = der_get_length (p, len, &reallen, &l); 280 if (e) return e; 281 p += l; 282 len -= l; 283 ret += l; 284 if (reallen > len) 285 return ASN1_OVERRUN; 286 e = der_get_unsigned (p, reallen, num, &l); 287 if (e) return e; 288 p += l; 289 len -= l; 290 ret += l; 291 if(size) *size = ret; 292 return 0; 293 } 294 295 int 296 decode_enumerated (const unsigned char *p, size_t len, 297 unsigned *num, size_t *size) 298 { 299 size_t ret = 0; 300 size_t l, reallen; 301 int e; 302 303 e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l); 304 if (e) return e; 305 p += l; 306 len -= l; 307 ret += l; 308 e = der_get_length (p, len, &reallen, &l); 309 if (e) return e; 310 p += l; 311 len -= l; 312 ret += l; 313 e = der_get_int (p, reallen, num, &l); 314 if (e) return e; 315 p += l; 316 len -= l; 317 ret += l; 318 if(size) *size = ret; 319 return 0; 320 } 321 322 int 323 decode_general_string (const unsigned char *p, size_t len, 324 general_string *str, size_t *size) 325 { 326 size_t ret = 0; 327 size_t l; 328 int e; 329 size_t slen; 330 331 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); 332 if (e) return e; 333 p += l; 334 len -= l; 335 ret += l; 336 337 e = der_get_length (p, len, &slen, &l); 338 if (e) return e; 339 p += l; 340 len -= l; 341 ret += l; 342 if (len < slen) 343 return ASN1_OVERRUN; 344 345 e = der_get_general_string (p, slen, str, &l); 346 if (e) return e; 347 p += l; 348 len -= l; 349 ret += l; 350 if(size) *size = ret; 351 return 0; 352 } 353 354 int 355 decode_octet_string (const unsigned char *p, size_t len, 356 octet_string *k, size_t *size) 357 { 358 size_t ret = 0; 359 size_t l; 360 int e; 361 size_t slen; 362 363 e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); 364 if (e) return e; 365 p += l; 366 len -= l; 367 ret += l; 368 369 e = der_get_length (p, len, &slen, &l); 370 if (e) return e; 371 p += l; 372 len -= l; 373 ret += l; 374 if (len < slen) 375 return ASN1_OVERRUN; 376 377 e = der_get_octet_string (p, slen, k, &l); 378 if (e) return e; 379 p += l; 380 len -= l; 381 ret += l; 382 if(size) *size = ret; 383 return 0; 384 } 385 386 int 387 decode_oid (const unsigned char *p, size_t len, 388 oid *k, size_t *size) 389 { 390 size_t ret = 0; 391 size_t l; 392 int e; 393 size_t slen; 394 395 e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l); 396 if (e) return e; 397 p += l; 398 len -= l; 399 ret += l; 400 401 e = der_get_length (p, len, &slen, &l); 402 if (e) return e; 403 p += l; 404 len -= l; 405 ret += l; 406 if (len < slen) 407 return ASN1_OVERRUN; 408 409 e = der_get_oid (p, slen, k, &l); 410 if (e) return e; 411 p += l; 412 len -= l; 413 ret += l; 414 if(size) *size = ret; 415 return 0; 416 } 417 418 static void 419 generalizedtime2time (const char *s, time_t *t) 420 { 421 struct tm tm; 422 423 memset(&tm, 0, sizeof(tm)); 424 sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 425 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 426 &tm.tm_min, &tm.tm_sec); 427 tm.tm_year -= 1900; 428 tm.tm_mon -= 1; 429 *t = timegm (&tm); 430 } 431 432 int 433 decode_generalized_time (const unsigned char *p, size_t len, 434 time_t *t, size_t *size) 435 { 436 octet_string k; 437 char *times; 438 size_t ret = 0; 439 size_t l; 440 int e; 441 size_t slen; 442 443 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); 444 if (e) return e; 445 p += l; 446 len -= l; 447 ret += l; 448 449 e = der_get_length (p, len, &slen, &l); 450 if (e) return e; 451 p += l; 452 len -= l; 453 ret += l; 454 if (len < slen) 455 return ASN1_OVERRUN; 456 e = der_get_octet_string (p, slen, &k, &l); 457 if (e) return e; 458 p += l; 459 len -= l; 460 ret += l; 461 times = realloc(k.data, k.length + 1); 462 if (times == NULL){ 463 free(k.data); 464 return ENOMEM; 465 } 466 times[k.length] = 0; 467 generalizedtime2time (times, t); 468 free (times); 469 if(size) *size = ret; 470 return 0; 471 } 472 473 474 int 475 fix_dce(size_t reallen, size_t *len) 476 { 477 if(reallen == ASN1_INDEFINITE) 478 return 1; 479 if(*len < reallen) 480 return -1; 481 *len = reallen; 482 return 0; 483 } 484