1/* $NetBSD: der_put.c,v 1.3 2023/06/19 21:41:42 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.3 2023/06/19 21:41:42 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 48int 49der_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 80int 81der_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 112int 113der_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 152int 153der_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 193int 194der_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 220int 221der_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 233int 234der_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 247int 248der_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 254int 255der_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 261int 262der_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 268int 269der_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 285int 286der_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 304int 305der_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 311int 312der_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 if (data->length) 319 memcpy(p+1, data->data, data->length); 320 *size = data->length; 321 return 0; 322} 323 324int 325der_put_heim_integer (unsigned char *p, size_t len, 326 const heim_integer *data, size_t *size) 327{ 328 unsigned char *buf = data->data; 329 int hibitset = 0; 330 331 if (data->length == 0) { 332 if (len < 1) 333 return ASN1_OVERFLOW; 334 *p-- = 0; 335 if (size) 336 *size = 1; 337 return 0; 338 } 339 if (len < data->length) 340 return ASN1_OVERFLOW; 341 342 len -= data->length; 343 344 if (data->negative) { 345 ssize_t i; 346 int carry; 347 348 /* 349 * We represent the parsed integer as a positive value with a 350 * negativity flag. But we need to put it on the wire as the shortest 351 * twos-complement byte sequence possible. So we're going to negate 352 * the number as go. 353 */ 354 if (data->length == 1 && *(unsigned char *)data->data == 1) { 355 *(p--) = 0xff; 356 } else { 357 for (i = data->length - 1, carry = 1; i >= 0; i--) { 358 *p = buf[i] ^ 0xff; 359 if (carry) 360 carry = !++*p; 361 p--; 362 } 363 if (p[1] < 128) { 364 if (len < 1) 365 return ASN1_OVERFLOW; 366 *p-- = 0xff; 367 len--; 368 hibitset = 1; 369 } 370 } 371 } else { 372 p -= data->length; 373 memcpy(p + 1, buf, data->length); 374 375 if (p[1] >= 128) { 376 if (len < 1) 377 return ASN1_OVERFLOW; 378 p[0] = 0; 379 len--; 380 hibitset = 1; 381 } 382 } 383 if (size) 384 *size = data->length + hibitset; 385 return 0; 386} 387 388int 389der_put_generalized_time (unsigned char *p, size_t len, 390 const time_t *data, size_t *size) 391{ 392 heim_octet_string k; 393 size_t l; 394 int e; 395 396 e = _heim_time2generalizedtime (*data, &k, 1); 397 if (e) 398 return e; 399 e = der_put_octet_string(p, len, &k, &l); 400 free(k.data); 401 if(e) 402 return e; 403 if(size) 404 *size = l; 405 return 0; 406} 407 408int 409der_put_utctime (unsigned char *p, size_t len, 410 const time_t *data, size_t *size) 411{ 412 heim_octet_string k; 413 size_t l; 414 int e; 415 416 e = _heim_time2generalizedtime (*data, &k, 0); 417 if (e) 418 return e; 419 e = der_put_octet_string(p, len, &k, &l); 420 free(k.data); 421 if(e) 422 return e; 423 if(size) 424 *size = l; 425 return 0; 426} 427 428int 429der_put_oid (unsigned char *p, size_t len, 430 const heim_oid *data, size_t *size) 431{ 432 unsigned char *base = p; 433 size_t n; 434 435 for (n = data->length - 1; n >= 2; --n) { 436 unsigned u = data->components[n]; 437 438 if (len < 1) 439 return ASN1_OVERFLOW; 440 *p-- = u % 128; 441 u /= 128; 442 --len; 443 while (u > 0) { 444 if (len < 1) 445 return ASN1_OVERFLOW; 446 *p-- = 128 + u % 128; 447 u /= 128; 448 --len; 449 } 450 } 451 if (len < 1) 452 return ASN1_OVERFLOW; 453 *p-- = 40 * data->components[0] + data->components[1]; 454 *size = base - p; 455 return 0; 456} 457 458int 459der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 460 unsigned int tag, size_t *size) 461{ 462 if (tag <= 30) { 463 if (len < 1) 464 return ASN1_OVERFLOW; 465 *p = MAKE_TAG(class, type, tag); 466 *size = 1; 467 } else { 468 size_t ret = 0; 469 unsigned int continuation = 0; 470 471 do { 472 if (len < 1) 473 return ASN1_OVERFLOW; 474 *p-- = tag % 128 | continuation; 475 len--; 476 ret++; 477 tag /= 128; 478 continuation = 0x80; 479 } while(tag > 0); 480 if (len < 1) 481 return ASN1_OVERFLOW; 482 *p-- = MAKE_TAG(class, type, 0x1f); 483 ret++; 484 *size = ret; 485 } 486 return 0; 487} 488 489int 490der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 491 Der_class class, Der_type type, 492 unsigned int tag, size_t *size) 493{ 494 size_t ret = 0; 495 size_t l; 496 int e; 497 498 e = der_put_length (p, len, len_val, &l); 499 if(e) 500 return e; 501 p -= l; 502 len -= l; 503 ret += l; 504 e = der_put_tag (p, len, class, type, tag, &l); 505 if(e) 506 return e; 507 508 ret += l; 509 *size = ret; 510 return 0; 511} 512 513int 514_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) 515{ 516 struct tm tm; 517 const size_t len = gtimep ? 15 : 13; 518 519 s->data = NULL; 520 s->length = 0; 521 if (_der_gmtime(t, &tm) == NULL) 522 return ASN1_BAD_TIMEFORMAT; 523 s->data = malloc(len + 1); 524 if (s->data == NULL) 525 return ENOMEM; 526 s->length = len; 527 if (gtimep) 528 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 529 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 530 tm.tm_hour, tm.tm_min, tm.tm_sec); 531 else 532 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", 533 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, 534 tm.tm_hour, tm.tm_min, tm.tm_sec); 535 536 return 0; 537} 538 539int 540der_put_bit_string (unsigned char *p, size_t len, 541 const heim_bit_string *data, size_t *size) 542{ 543 size_t data_size = (data->length + 7) / 8; 544 if (len < data_size + 1) 545 return ASN1_OVERFLOW; 546 p -= data_size + 1; 547 548 memcpy (p+2, data->data, data_size); 549 if (data->length && (data->length % 8) != 0) 550 p[1] = 8 - (data->length % 8); 551 else 552 p[1] = 0; 553 *size = data_size + 1; 554 return 0; 555} 556 557int 558_heim_der_set_sort(const void *a1, const void *a2) 559{ 560 const heim_octet_string *s1 = a1, *s2 = a2; 561 int ret; 562 563 ret = memcmp(s1->data, s2->data, 564 s1->length < s2->length ? s1->length : s2->length); 565 if(ret) 566 return ret; 567 return (int)(s1->length - s2->length); 568} 569