1 /* 2 * Copyright (c) 1997-2005 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$"); 37 38 /* 39 * All encoding functions take a pointer `p' to first position in 40 * which to write, from the right, `len' which means the maximum 41 * number of characters we are able to write. The function returns 42 * the number of characters written in `size' (if non-NULL). 43 * The return value is 0 or an error. 44 */ 45 46 int 47 der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size) 48 { 49 unsigned char *base = p; 50 unsigned val = *v; 51 52 if (val) { 53 while (len > 0 && val) { 54 *p-- = val % 256; 55 val /= 256; 56 --len; 57 } 58 if (val != 0) 59 return ASN1_OVERFLOW; 60 else { 61 if(p[1] >= 128) { 62 if(len < 1) 63 return ASN1_OVERFLOW; 64 *p-- = 0; 65 } 66 *size = base - p; 67 return 0; 68 } 69 } else if (len < 1) 70 return ASN1_OVERFLOW; 71 else { 72 *p = 0; 73 *size = 1; 74 return 0; 75 } 76 } 77 78 int 79 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size) 80 { 81 unsigned char *base = p; 82 int val = *v; 83 84 if(val >= 0) { 85 do { 86 if(len < 1) 87 return ASN1_OVERFLOW; 88 *p-- = val % 256; 89 len--; 90 val /= 256; 91 } while(val); 92 if(p[1] >= 128) { 93 if(len < 1) 94 return ASN1_OVERFLOW; 95 *p-- = 0; 96 len--; 97 } 98 } else { 99 val = ~val; 100 do { 101 if(len < 1) 102 return ASN1_OVERFLOW; 103 *p-- = ~(val % 256); 104 len--; 105 val /= 256; 106 } while(val); 107 if(p[1] < 128) { 108 if(len < 1) 109 return ASN1_OVERFLOW; 110 *p-- = 0xff; 111 len--; 112 } 113 } 114 *size = base - p; 115 return 0; 116 } 117 118 119 int 120 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) 121 { 122 if (len < 1) 123 return ASN1_OVERFLOW; 124 125 if (val < 128) { 126 *p = val; 127 *size = 1; 128 } else { 129 size_t l = 0; 130 131 while(val > 0) { 132 if(len < 2) 133 return ASN1_OVERFLOW; 134 *p-- = val % 256; 135 val /= 256; 136 len--; 137 l++; 138 } 139 *p = 0x80 | l; 140 if(size) 141 *size = l + 1; 142 } 143 return 0; 144 } 145 146 int 147 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) 148 { 149 if(len < 1) 150 return ASN1_OVERFLOW; 151 if(*data != 0) 152 *p = 0xff; 153 else 154 *p = 0; 155 *size = 1; 156 return 0; 157 } 158 159 int 160 der_put_general_string (unsigned char *p, size_t len, 161 const heim_general_string *str, size_t *size) 162 { 163 size_t slen = strlen(*str); 164 165 if (len < slen) 166 return ASN1_OVERFLOW; 167 p -= slen; 168 memcpy (p+1, *str, slen); 169 *size = slen; 170 return 0; 171 } 172 173 int 174 der_put_utf8string (unsigned char *p, size_t len, 175 const heim_utf8_string *str, size_t *size) 176 { 177 return der_put_general_string(p, len, str, size); 178 } 179 180 int 181 der_put_printable_string (unsigned char *p, size_t len, 182 const heim_printable_string *str, size_t *size) 183 { 184 return der_put_octet_string(p, len, str, size); 185 } 186 187 int 188 der_put_ia5_string (unsigned char *p, size_t len, 189 const heim_ia5_string *str, size_t *size) 190 { 191 return der_put_octet_string(p, len, str, size); 192 } 193 194 int 195 der_put_bmp_string (unsigned char *p, size_t len, 196 const heim_bmp_string *data, size_t *size) 197 { 198 size_t i; 199 if (len / 2 < data->length) 200 return ASN1_OVERFLOW; 201 p -= data->length * 2; 202 for (i = 0; i < data->length; i++) { 203 p[1] = (data->data[i] >> 8) & 0xff; 204 p[2] = data->data[i] & 0xff; 205 p += 2; 206 } 207 if (size) *size = data->length * 2; 208 return 0; 209 } 210 211 int 212 der_put_universal_string (unsigned char *p, size_t len, 213 const heim_universal_string *data, size_t *size) 214 { 215 size_t i; 216 if (len / 4 < data->length) 217 return ASN1_OVERFLOW; 218 p -= data->length * 4; 219 for (i = 0; i < data->length; i++) { 220 p[1] = (data->data[i] >> 24) & 0xff; 221 p[2] = (data->data[i] >> 16) & 0xff; 222 p[3] = (data->data[i] >> 8) & 0xff; 223 p[4] = data->data[i] & 0xff; 224 p += 4; 225 } 226 if (size) *size = data->length * 4; 227 return 0; 228 } 229 230 int 231 der_put_visible_string (unsigned char *p, size_t len, 232 const heim_visible_string *str, size_t *size) 233 { 234 return der_put_general_string(p, len, str, size); 235 } 236 237 int 238 der_put_octet_string (unsigned char *p, size_t len, 239 const heim_octet_string *data, size_t *size) 240 { 241 if (len < data->length) 242 return ASN1_OVERFLOW; 243 p -= data->length; 244 memcpy (p+1, data->data, data->length); 245 *size = data->length; 246 return 0; 247 } 248 249 int 250 der_put_heim_integer (unsigned char *p, size_t len, 251 const heim_integer *data, size_t *size) 252 { 253 unsigned char *buf = data->data; 254 int hibitset = 0; 255 256 if (data->length == 0) { 257 if (len < 1) 258 return ASN1_OVERFLOW; 259 *p-- = 0; 260 if (size) 261 *size = 1; 262 return 0; 263 } 264 if (len < data->length) 265 return ASN1_OVERFLOW; 266 267 len -= data->length; 268 269 if (data->negative) { 270 int i, carry; 271 for (i = data->length - 1, carry = 1; i >= 0; i--) { 272 *p = buf[i] ^ 0xff; 273 if (carry) 274 carry = !++*p; 275 p--; 276 } 277 if (p[1] < 128) { 278 if (len < 1) 279 return ASN1_OVERFLOW; 280 *p-- = 0xff; 281 len--; 282 hibitset = 1; 283 } 284 } else { 285 p -= data->length; 286 memcpy(p + 1, buf, data->length); 287 288 if (p[1] >= 128) { 289 if (len < 1) 290 return ASN1_OVERFLOW; 291 p[0] = 0; 292 len--; 293 hibitset = 1; 294 } 295 } 296 if (size) 297 *size = data->length + hibitset; 298 return 0; 299 } 300 301 int 302 der_put_generalized_time (unsigned char *p, size_t len, 303 const time_t *data, size_t *size) 304 { 305 heim_octet_string k; 306 size_t l; 307 int e; 308 309 e = _heim_time2generalizedtime (*data, &k, 1); 310 if (e) 311 return e; 312 e = der_put_octet_string(p, len, &k, &l); 313 free(k.data); 314 if(e) 315 return e; 316 if(size) 317 *size = l; 318 return 0; 319 } 320 321 int 322 der_put_utctime (unsigned char *p, size_t len, 323 const time_t *data, size_t *size) 324 { 325 heim_octet_string k; 326 size_t l; 327 int e; 328 329 e = _heim_time2generalizedtime (*data, &k, 0); 330 if (e) 331 return e; 332 e = der_put_octet_string(p, len, &k, &l); 333 free(k.data); 334 if(e) 335 return e; 336 if(size) 337 *size = l; 338 return 0; 339 } 340 341 int 342 der_put_oid (unsigned char *p, size_t len, 343 const heim_oid *data, size_t *size) 344 { 345 unsigned char *base = p; 346 int n; 347 348 for (n = data->length - 1; n >= 2; --n) { 349 unsigned u = data->components[n]; 350 351 if (len < 1) 352 return ASN1_OVERFLOW; 353 *p-- = u % 128; 354 u /= 128; 355 --len; 356 while (u > 0) { 357 if (len < 1) 358 return ASN1_OVERFLOW; 359 *p-- = 128 + u % 128; 360 u /= 128; 361 --len; 362 } 363 } 364 if (len < 1) 365 return ASN1_OVERFLOW; 366 *p-- = 40 * data->components[0] + data->components[1]; 367 *size = base - p; 368 return 0; 369 } 370 371 int 372 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 373 unsigned int tag, size_t *size) 374 { 375 if (tag <= 30) { 376 if (len < 1) 377 return ASN1_OVERFLOW; 378 *p = MAKE_TAG(class, type, tag); 379 *size = 1; 380 } else { 381 size_t ret = 0; 382 unsigned int continuation = 0; 383 384 do { 385 if (len < 1) 386 return ASN1_OVERFLOW; 387 *p-- = tag % 128 | continuation; 388 len--; 389 ret++; 390 tag /= 128; 391 continuation = 0x80; 392 } while(tag > 0); 393 if (len < 1) 394 return ASN1_OVERFLOW; 395 *p-- = MAKE_TAG(class, type, 0x1f); 396 ret++; 397 *size = ret; 398 } 399 return 0; 400 } 401 402 int 403 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 404 Der_class class, Der_type type, 405 unsigned int tag, size_t *size) 406 { 407 size_t ret = 0; 408 size_t l; 409 int e; 410 411 e = der_put_length (p, len, len_val, &l); 412 if(e) 413 return e; 414 p -= l; 415 len -= l; 416 ret += l; 417 e = der_put_tag (p, len, class, type, tag, &l); 418 if(e) 419 return e; 420 421 ret += l; 422 *size = ret; 423 return 0; 424 } 425 426 int 427 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) 428 { 429 struct tm tm; 430 const size_t len = gtimep ? 15 : 13; 431 432 s->data = malloc(len + 1); 433 if (s->data == NULL) 434 return ENOMEM; 435 s->length = len; 436 if (_der_gmtime(t, &tm) == NULL) 437 return ASN1_BAD_TIMEFORMAT; 438 if (gtimep) 439 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 440 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 441 tm.tm_hour, tm.tm_min, tm.tm_sec); 442 else 443 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", 444 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, 445 tm.tm_hour, tm.tm_min, tm.tm_sec); 446 447 return 0; 448 } 449 450 int 451 der_put_bit_string (unsigned char *p, size_t len, 452 const heim_bit_string *data, size_t *size) 453 { 454 size_t data_size = (data->length + 7) / 8; 455 if (len < data_size + 1) 456 return ASN1_OVERFLOW; 457 p -= data_size + 1; 458 459 memcpy (p+2, data->data, data_size); 460 if (data->length && (data->length % 8) != 0) 461 p[1] = 8 - (data->length % 8); 462 else 463 p[1] = 0; 464 *size = data_size + 1; 465 return 0; 466 } 467 468 int 469 _heim_der_set_sort(const void *a1, const void *a2) 470 { 471 const struct heim_octet_string *s1 = a1, *s2 = a2; 472 int ret; 473 474 ret = memcmp(s1->data, s2->data, 475 s1->length < s2->length ? s1->length : s2->length); 476 if(ret) 477 return ret; 478 return s1->length - s2->length; 479 } 480