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.32 2002/08/22 19:11:07 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 > 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 e = der_get_int (p, reallen, num, &l); 256 if (e) return e; 257 p += l; 258 len -= l; 259 ret += l; 260 if(size) *size = ret; 261 return 0; 262 } 263 264 int 265 decode_unsigned (const unsigned char *p, size_t len, 266 unsigned *num, size_t *size) 267 { 268 size_t ret = 0; 269 size_t l, reallen; 270 int e; 271 272 e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); 273 if (e) return e; 274 p += l; 275 len -= l; 276 ret += l; 277 e = der_get_length (p, len, &reallen, &l); 278 if (e) return e; 279 p += l; 280 len -= l; 281 ret += l; 282 e = der_get_unsigned (p, reallen, num, &l); 283 if (e) return e; 284 p += l; 285 len -= l; 286 ret += l; 287 if(size) *size = ret; 288 return 0; 289 } 290 291 int 292 decode_enumerated (const unsigned char *p, size_t len, 293 unsigned *num, size_t *size) 294 { 295 size_t ret = 0; 296 size_t l, reallen; 297 int e; 298 299 e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l); 300 if (e) return e; 301 p += l; 302 len -= l; 303 ret += l; 304 e = der_get_length (p, len, &reallen, &l); 305 if (e) return e; 306 p += l; 307 len -= l; 308 ret += l; 309 e = der_get_int (p, reallen, num, &l); 310 if (e) return e; 311 p += l; 312 len -= l; 313 ret += l; 314 if(size) *size = ret; 315 return 0; 316 } 317 318 int 319 decode_general_string (const unsigned char *p, size_t len, 320 general_string *str, size_t *size) 321 { 322 size_t ret = 0; 323 size_t l; 324 int e; 325 size_t slen; 326 327 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); 328 if (e) return e; 329 p += l; 330 len -= l; 331 ret += l; 332 333 e = der_get_length (p, len, &slen, &l); 334 if (e) return e; 335 p += l; 336 len -= l; 337 ret += l; 338 if (len < slen) 339 return ASN1_OVERRUN; 340 341 e = der_get_general_string (p, slen, str, &l); 342 if (e) return e; 343 p += l; 344 len -= l; 345 ret += l; 346 if(size) *size = ret; 347 return 0; 348 } 349 350 int 351 decode_octet_string (const unsigned char *p, size_t len, 352 octet_string *k, size_t *size) 353 { 354 size_t ret = 0; 355 size_t l; 356 int e; 357 size_t slen; 358 359 e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); 360 if (e) return e; 361 p += l; 362 len -= l; 363 ret += l; 364 365 e = der_get_length (p, len, &slen, &l); 366 if (e) return e; 367 p += l; 368 len -= l; 369 ret += l; 370 if (len < slen) 371 return ASN1_OVERRUN; 372 373 e = der_get_octet_string (p, slen, k, &l); 374 if (e) return e; 375 p += l; 376 len -= l; 377 ret += l; 378 if(size) *size = ret; 379 return 0; 380 } 381 382 int 383 decode_oid (const unsigned char *p, size_t len, 384 oid *k, size_t *size) 385 { 386 size_t ret = 0; 387 size_t l; 388 int e; 389 size_t slen; 390 391 e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l); 392 if (e) return e; 393 p += l; 394 len -= l; 395 ret += l; 396 397 e = der_get_length (p, len, &slen, &l); 398 if (e) return e; 399 p += l; 400 len -= l; 401 ret += l; 402 if (len < slen) 403 return ASN1_OVERRUN; 404 405 e = der_get_oid (p, slen, k, &l); 406 if (e) return e; 407 p += l; 408 len -= l; 409 ret += l; 410 if(size) *size = ret; 411 return 0; 412 } 413 414 static void 415 generalizedtime2time (const char *s, time_t *t) 416 { 417 struct tm tm; 418 419 memset(&tm, 0, sizeof(tm)); 420 sscanf (s, "%04d%02d%02d%02d%02d%02dZ", 421 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 422 &tm.tm_min, &tm.tm_sec); 423 tm.tm_year -= 1900; 424 tm.tm_mon -= 1; 425 *t = timegm (&tm); 426 } 427 428 int 429 decode_generalized_time (const unsigned char *p, size_t len, 430 time_t *t, size_t *size) 431 { 432 octet_string k; 433 char *times; 434 size_t ret = 0; 435 size_t l; 436 int e; 437 size_t slen; 438 439 e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); 440 if (e) return e; 441 p += l; 442 len -= l; 443 ret += l; 444 445 e = der_get_length (p, len, &slen, &l); 446 if (e) return e; 447 p += l; 448 len -= l; 449 ret += l; 450 if (len < slen) 451 return ASN1_OVERRUN; 452 e = der_get_octet_string (p, slen, &k, &l); 453 if (e) return e; 454 p += l; 455 len -= l; 456 ret += l; 457 times = realloc(k.data, k.length + 1); 458 if (times == NULL){ 459 free(k.data); 460 return ENOMEM; 461 } 462 times[k.length] = 0; 463 generalizedtime2time (times, t); 464 free (times); 465 if(size) *size = ret; 466 return 0; 467 } 468 469 470 int 471 fix_dce(size_t reallen, size_t *len) 472 { 473 if(reallen == ASN1_INDEFINITE) 474 return 1; 475 if(*len < reallen) 476 return -1; 477 *len = reallen; 478 return 0; 479 } 480