1 /* $NetBSD: der_put.c,v 1.2 2017/01/28 21:31:45 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "der_locl.h" 37 38 __RCSID("$NetBSD: der_put.c,v 1.2 2017/01/28 21:31:45 christos Exp $"); 39 40 /* 41 * All encoding functions take a pointer `p' to first position in 42 * which to write, from the right, `len' which means the maximum 43 * number of characters we are able to write. The function returns 44 * the number of characters written in `size' (if non-NULL). 45 * The return value is 0 or an error. 46 */ 47 48 int 49 der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size) 50 { 51 unsigned char *base = p; 52 unsigned val = *v; 53 54 if (val) { 55 while (len > 0 && val) { 56 *p-- = val % 256; 57 val /= 256; 58 --len; 59 } 60 if (val != 0) 61 return ASN1_OVERFLOW; 62 else { 63 if(p[1] >= 128) { 64 if(len < 1) 65 return ASN1_OVERFLOW; 66 *p-- = 0; 67 } 68 *size = base - p; 69 return 0; 70 } 71 } else if (len < 1) 72 return ASN1_OVERFLOW; 73 else { 74 *p = 0; 75 *size = 1; 76 return 0; 77 } 78 } 79 80 int 81 der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size) 82 { 83 unsigned char *base = p; 84 uint64_t val = *v; 85 86 if (val) { 87 while (len > 0 && val) { 88 *p-- = val % 256; 89 val /= 256; 90 --len; 91 } 92 if (val != 0) 93 return ASN1_OVERFLOW; 94 else { 95 if(p[1] >= 128) { 96 if(len < 1) 97 return ASN1_OVERFLOW; 98 *p-- = 0; 99 } 100 *size = base - p; 101 return 0; 102 } 103 } else if (len < 1) 104 return ASN1_OVERFLOW; 105 else { 106 *p = 0; 107 *size = 1; 108 return 0; 109 } 110 } 111 112 int 113 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size) 114 { 115 unsigned char *base = p; 116 int val = *v; 117 118 if(val >= 0) { 119 do { 120 if(len < 1) 121 return ASN1_OVERFLOW; 122 *p-- = val % 256; 123 len--; 124 val /= 256; 125 } while(val); 126 if(p[1] >= 128) { 127 if(len < 1) 128 return ASN1_OVERFLOW; 129 *p-- = 0; 130 len--; 131 } 132 } else { 133 val = ~val; 134 do { 135 if(len < 1) 136 return ASN1_OVERFLOW; 137 *p-- = ~(val % 256); 138 len--; 139 val /= 256; 140 } while(val); 141 if(p[1] < 128) { 142 if(len < 1) 143 return ASN1_OVERFLOW; 144 *p-- = 0xff; 145 len--; 146 } 147 } 148 *size = base - p; 149 return 0; 150 } 151 152 int 153 der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size) 154 { 155 unsigned char *base = p; 156 int64_t val = *v; 157 158 if(val >= 0) { 159 do { 160 if(len < 1) 161 return ASN1_OVERFLOW; 162 *p-- = val % 256; 163 len--; 164 val /= 256; 165 } while(val); 166 if(p[1] >= 128) { 167 if(len < 1) 168 return ASN1_OVERFLOW; 169 *p-- = 0; 170 len--; 171 } 172 } else { 173 val = ~val; 174 do { 175 if(len < 1) 176 return ASN1_OVERFLOW; 177 *p-- = ~(val % 256); 178 len--; 179 val /= 256; 180 } while(val); 181 if(p[1] < 128) { 182 if(len < 1) 183 return ASN1_OVERFLOW; 184 *p-- = 0xff; 185 len--; 186 } 187 } 188 *size = base - p; 189 return 0; 190 } 191 192 193 int 194 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) 195 { 196 if (len < 1) 197 return ASN1_OVERFLOW; 198 199 if (val < 128) { 200 *p = val; 201 *size = 1; 202 } else { 203 size_t l = 0; 204 205 while(val > 0) { 206 if(len < 2) 207 return ASN1_OVERFLOW; 208 *p-- = val % 256; 209 val /= 256; 210 len--; 211 l++; 212 } 213 *p = 0x80 | l; 214 if(size) 215 *size = l + 1; 216 } 217 return 0; 218 } 219 220 int 221 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) 222 { 223 if(len < 1) 224 return ASN1_OVERFLOW; 225 if(*data != 0) 226 *p = 0xff; 227 else 228 *p = 0; 229 *size = 1; 230 return 0; 231 } 232 233 int 234 der_put_general_string (unsigned char *p, size_t len, 235 const heim_general_string *str, size_t *size) 236 { 237 size_t slen = strlen(*str); 238 239 if (len < slen) 240 return ASN1_OVERFLOW; 241 p -= slen; 242 memcpy (p+1, *str, slen); 243 *size = slen; 244 return 0; 245 } 246 247 int 248 der_put_utf8string (unsigned char *p, size_t len, 249 const heim_utf8_string *str, size_t *size) 250 { 251 return der_put_general_string(p, len, str, size); 252 } 253 254 int 255 der_put_printable_string (unsigned char *p, size_t len, 256 const heim_printable_string *str, size_t *size) 257 { 258 return der_put_octet_string(p, len, str, size); 259 } 260 261 int 262 der_put_ia5_string (unsigned char *p, size_t len, 263 const heim_ia5_string *str, size_t *size) 264 { 265 return der_put_octet_string(p, len, str, size); 266 } 267 268 int 269 der_put_bmp_string (unsigned char *p, size_t len, 270 const heim_bmp_string *data, size_t *size) 271 { 272 size_t i; 273 if (len / 2 < data->length) 274 return ASN1_OVERFLOW; 275 p -= data->length * 2; 276 for (i = 0; i < data->length; i++) { 277 p[1] = (data->data[i] >> 8) & 0xff; 278 p[2] = data->data[i] & 0xff; 279 p += 2; 280 } 281 if (size) *size = data->length * 2; 282 return 0; 283 } 284 285 int 286 der_put_universal_string (unsigned char *p, size_t len, 287 const heim_universal_string *data, size_t *size) 288 { 289 size_t i; 290 if (len / 4 < data->length) 291 return ASN1_OVERFLOW; 292 p -= data->length * 4; 293 for (i = 0; i < data->length; i++) { 294 p[1] = (data->data[i] >> 24) & 0xff; 295 p[2] = (data->data[i] >> 16) & 0xff; 296 p[3] = (data->data[i] >> 8) & 0xff; 297 p[4] = data->data[i] & 0xff; 298 p += 4; 299 } 300 if (size) *size = data->length * 4; 301 return 0; 302 } 303 304 int 305 der_put_visible_string (unsigned char *p, size_t len, 306 const heim_visible_string *str, size_t *size) 307 { 308 return der_put_general_string(p, len, str, size); 309 } 310 311 int 312 der_put_octet_string (unsigned char *p, size_t len, 313 const heim_octet_string *data, size_t *size) 314 { 315 if (len < data->length) 316 return ASN1_OVERFLOW; 317 p -= data->length; 318 memcpy (p+1, data->data, data->length); 319 *size = data->length; 320 return 0; 321 } 322 323 int 324 der_put_heim_integer (unsigned char *p, size_t len, 325 const heim_integer *data, size_t *size) 326 { 327 unsigned char *buf = data->data; 328 int hibitset = 0; 329 330 if (data->length == 0) { 331 if (len < 1) 332 return ASN1_OVERFLOW; 333 *p-- = 0; 334 if (size) 335 *size = 1; 336 return 0; 337 } 338 if (len < data->length) 339 return ASN1_OVERFLOW; 340 341 len -= data->length; 342 343 if (data->negative) { 344 ssize_t i; 345 int carry; 346 for (i = data->length - 1, carry = 1; i >= 0; i--) { 347 *p = buf[i] ^ 0xff; 348 if (carry) 349 carry = !++*p; 350 p--; 351 } 352 if (p[1] < 128) { 353 if (len < 1) 354 return ASN1_OVERFLOW; 355 *p-- = 0xff; 356 len--; 357 hibitset = 1; 358 } 359 } else { 360 p -= data->length; 361 memcpy(p + 1, buf, data->length); 362 363 if (p[1] >= 128) { 364 if (len < 1) 365 return ASN1_OVERFLOW; 366 p[0] = 0; 367 len--; 368 hibitset = 1; 369 } 370 } 371 if (size) 372 *size = data->length + hibitset; 373 return 0; 374 } 375 376 int 377 der_put_generalized_time (unsigned char *p, size_t len, 378 const time_t *data, size_t *size) 379 { 380 heim_octet_string k; 381 size_t l; 382 int e; 383 384 e = _heim_time2generalizedtime (*data, &k, 1); 385 if (e) 386 return e; 387 e = der_put_octet_string(p, len, &k, &l); 388 free(k.data); 389 if(e) 390 return e; 391 if(size) 392 *size = l; 393 return 0; 394 } 395 396 int 397 der_put_utctime (unsigned char *p, size_t len, 398 const time_t *data, size_t *size) 399 { 400 heim_octet_string k; 401 size_t l; 402 int e; 403 404 e = _heim_time2generalizedtime (*data, &k, 0); 405 if (e) 406 return e; 407 e = der_put_octet_string(p, len, &k, &l); 408 free(k.data); 409 if(e) 410 return e; 411 if(size) 412 *size = l; 413 return 0; 414 } 415 416 int 417 der_put_oid (unsigned char *p, size_t len, 418 const heim_oid *data, size_t *size) 419 { 420 unsigned char *base = p; 421 size_t n; 422 423 for (n = data->length - 1; n >= 2; --n) { 424 unsigned u = data->components[n]; 425 426 if (len < 1) 427 return ASN1_OVERFLOW; 428 *p-- = u % 128; 429 u /= 128; 430 --len; 431 while (u > 0) { 432 if (len < 1) 433 return ASN1_OVERFLOW; 434 *p-- = 128 + u % 128; 435 u /= 128; 436 --len; 437 } 438 } 439 if (len < 1) 440 return ASN1_OVERFLOW; 441 *p-- = 40 * data->components[0] + data->components[1]; 442 *size = base - p; 443 return 0; 444 } 445 446 int 447 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 448 unsigned int tag, size_t *size) 449 { 450 if (tag <= 30) { 451 if (len < 1) 452 return ASN1_OVERFLOW; 453 *p = MAKE_TAG(class, type, tag); 454 *size = 1; 455 } else { 456 size_t ret = 0; 457 unsigned int continuation = 0; 458 459 do { 460 if (len < 1) 461 return ASN1_OVERFLOW; 462 *p-- = tag % 128 | continuation; 463 len--; 464 ret++; 465 tag /= 128; 466 continuation = 0x80; 467 } while(tag > 0); 468 if (len < 1) 469 return ASN1_OVERFLOW; 470 *p-- = MAKE_TAG(class, type, 0x1f); 471 ret++; 472 *size = ret; 473 } 474 return 0; 475 } 476 477 int 478 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 479 Der_class class, Der_type type, 480 unsigned int tag, size_t *size) 481 { 482 size_t ret = 0; 483 size_t l; 484 int e; 485 486 e = der_put_length (p, len, len_val, &l); 487 if(e) 488 return e; 489 p -= l; 490 len -= l; 491 ret += l; 492 e = der_put_tag (p, len, class, type, tag, &l); 493 if(e) 494 return e; 495 496 ret += l; 497 *size = ret; 498 return 0; 499 } 500 501 int 502 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) 503 { 504 struct tm tm; 505 const size_t len = gtimep ? 15 : 13; 506 507 s->data = NULL; 508 s->length = 0; 509 if (_der_gmtime(t, &tm) == NULL) 510 return ASN1_BAD_TIMEFORMAT; 511 s->data = malloc(len + 1); 512 if (s->data == NULL) 513 return ENOMEM; 514 s->length = len; 515 if (gtimep) 516 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 517 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 518 tm.tm_hour, tm.tm_min, tm.tm_sec); 519 else 520 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", 521 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, 522 tm.tm_hour, tm.tm_min, tm.tm_sec); 523 524 return 0; 525 } 526 527 int 528 der_put_bit_string (unsigned char *p, size_t len, 529 const heim_bit_string *data, size_t *size) 530 { 531 size_t data_size = (data->length + 7) / 8; 532 if (len < data_size + 1) 533 return ASN1_OVERFLOW; 534 p -= data_size + 1; 535 536 memcpy (p+2, data->data, data_size); 537 if (data->length && (data->length % 8) != 0) 538 p[1] = 8 - (data->length % 8); 539 else 540 p[1] = 0; 541 *size = data_size + 1; 542 return 0; 543 } 544 545 int 546 _heim_der_set_sort(const void *a1, const void *a2) 547 { 548 const heim_octet_string *s1 = a1, *s2 = a2; 549 int ret; 550 551 ret = memcmp(s1->data, s2->data, 552 s1->length < s2->length ? s1->length : s2->length); 553 if(ret) 554 return ret; 555 return (int)(s1->length - s2->length); 556 } 557