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 36RCSID("$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 46int 47der_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 78int 79der_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 119int 120der_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 146int 147der_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 159int 160der_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 173int 174der_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 180int 181der_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 187int 188der_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 194int 195der_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 211int 212der_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 230int 231der_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 237int 238der_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 249int 250der_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 ssize_t i; 271 int carry; 272 for (i = data->length - 1, carry = 1; i >= 0; i--) { 273 *p = buf[i] ^ 0xff; 274 if (carry) 275 carry = !++*p; 276 p--; 277 } 278 if (p[1] < 128) { 279 if (len < 1) 280 return ASN1_OVERFLOW; 281 *p-- = 0xff; 282 len--; 283 hibitset = 1; 284 } 285 } else { 286 p -= data->length; 287 memcpy(p + 1, buf, data->length); 288 289 if (p[1] >= 128) { 290 if (len < 1) 291 return ASN1_OVERFLOW; 292 p[0] = 0; 293 len--; 294 hibitset = 1; 295 } 296 } 297 if (size) 298 *size = data->length + hibitset; 299 return 0; 300} 301 302int 303der_put_generalized_time (unsigned char *p, size_t len, 304 const time_t *data, size_t *size) 305{ 306 heim_octet_string k; 307 size_t l; 308 int e; 309 310 e = _heim_time2generalizedtime (*data, &k, 1); 311 if (e) 312 return e; 313 e = der_put_octet_string(p, len, &k, &l); 314 free(k.data); 315 if(e) 316 return e; 317 if(size) 318 *size = l; 319 return 0; 320} 321 322int 323der_put_utctime (unsigned char *p, size_t len, 324 const time_t *data, size_t *size) 325{ 326 heim_octet_string k; 327 size_t l; 328 int e; 329 330 e = _heim_time2generalizedtime (*data, &k, 0); 331 if (e) 332 return e; 333 e = der_put_octet_string(p, len, &k, &l); 334 free(k.data); 335 if(e) 336 return e; 337 if(size) 338 *size = l; 339 return 0; 340} 341 342int 343der_put_oid (unsigned char *p, size_t len, 344 const heim_oid *data, size_t *size) 345{ 346 unsigned char *base = p; 347 size_t n; 348 349 for (n = data->length - 1; n >= 2; --n) { 350 unsigned u = data->components[n]; 351 352 if (len < 1) 353 return ASN1_OVERFLOW; 354 *p-- = u % 128; 355 u /= 128; 356 --len; 357 while (u > 0) { 358 if (len < 1) 359 return ASN1_OVERFLOW; 360 *p-- = 128 + u % 128; 361 u /= 128; 362 --len; 363 } 364 } 365 if (len < 1) 366 return ASN1_OVERFLOW; 367 *p-- = 40 * data->components[0] + data->components[1]; 368 *size = base - p; 369 return 0; 370} 371 372int 373der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 374 unsigned int tag, size_t *size) 375{ 376 if (tag <= 30) { 377 if (len < 1) 378 return ASN1_OVERFLOW; 379 *p = MAKE_TAG(class, type, tag); 380 *size = 1; 381 } else { 382 size_t ret = 0; 383 unsigned int continuation = 0; 384 385 do { 386 if (len < 1) 387 return ASN1_OVERFLOW; 388 *p-- = tag % 128 | continuation; 389 len--; 390 ret++; 391 tag /= 128; 392 continuation = 0x80; 393 } while(tag > 0); 394 if (len < 1) 395 return ASN1_OVERFLOW; 396 *p-- = MAKE_TAG(class, type, 0x1f); 397 ret++; 398 *size = ret; 399 } 400 return 0; 401} 402 403int 404der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 405 Der_class class, Der_type type, 406 unsigned int tag, size_t *size) 407{ 408 size_t ret = 0; 409 size_t l; 410 int e; 411 412 e = der_put_length (p, len, len_val, &l); 413 if(e) 414 return e; 415 p -= l; 416 len -= l; 417 ret += l; 418 e = der_put_tag (p, len, class, type, tag, &l); 419 if(e) 420 return e; 421 422 ret += l; 423 *size = ret; 424 return 0; 425} 426 427int 428_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) 429{ 430 struct tm tm; 431 const size_t len = gtimep ? 15 : 13; 432 433 s->data = malloc(len + 1); 434 if (s->data == NULL) 435 return ENOMEM; 436 s->length = len; 437 if (_der_gmtime(t, &tm) == NULL) 438 return ASN1_BAD_TIMEFORMAT; 439 if (gtimep) 440 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 441 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 442 tm.tm_hour, tm.tm_min, tm.tm_sec); 443 else 444 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", 445 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, 446 tm.tm_hour, tm.tm_min, tm.tm_sec); 447 448 return 0; 449} 450 451int 452der_put_bit_string (unsigned char *p, size_t len, 453 const heim_bit_string *data, size_t *size) 454{ 455 size_t data_size = (data->length + 7) / 8; 456 if (len < data_size + 1) 457 return ASN1_OVERFLOW; 458 p -= data_size + 1; 459 460 memcpy (p+2, data->data, data_size); 461 if (data->length && (data->length % 8) != 0) 462 p[1] = 8 - (data->length % 8); 463 else 464 p[1] = 0; 465 *size = data_size + 1; 466 return 0; 467} 468 469int 470_heim_der_set_sort(const void *a1, const void *a2) 471{ 472 const heim_octet_string *s1 = a1, *s2 = a2; 473 int ret; 474 475 ret = memcmp(s1->data, s2->data, 476 s1->length < s2->length ? s1->length : s2->length); 477 if(ret) 478 return ret; 479 return (int)(s1->length - s2->length); 480} 481