1/* $NetBSD$ */ 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$"); 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_integer (unsigned char *p, size_t len, const int *v, size_t *size) 82{ 83 unsigned char *base = p; 84 int val = *v; 85 86 if(val >= 0) { 87 do { 88 if(len < 1) 89 return ASN1_OVERFLOW; 90 *p-- = val % 256; 91 len--; 92 val /= 256; 93 } while(val); 94 if(p[1] >= 128) { 95 if(len < 1) 96 return ASN1_OVERFLOW; 97 *p-- = 0; 98 len--; 99 } 100 } else { 101 val = ~val; 102 do { 103 if(len < 1) 104 return ASN1_OVERFLOW; 105 *p-- = ~(val % 256); 106 len--; 107 val /= 256; 108 } while(val); 109 if(p[1] < 128) { 110 if(len < 1) 111 return ASN1_OVERFLOW; 112 *p-- = 0xff; 113 len--; 114 } 115 } 116 *size = base - p; 117 return 0; 118} 119 120 121int 122der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) 123{ 124 if (len < 1) 125 return ASN1_OVERFLOW; 126 127 if (val < 128) { 128 *p = val; 129 *size = 1; 130 } else { 131 size_t l = 0; 132 133 while(val > 0) { 134 if(len < 2) 135 return ASN1_OVERFLOW; 136 *p-- = val % 256; 137 val /= 256; 138 len--; 139 l++; 140 } 141 *p = 0x80 | l; 142 if(size) 143 *size = l + 1; 144 } 145 return 0; 146} 147 148int 149der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) 150{ 151 if(len < 1) 152 return ASN1_OVERFLOW; 153 if(*data != 0) 154 *p = 0xff; 155 else 156 *p = 0; 157 *size = 1; 158 return 0; 159} 160 161int 162der_put_general_string (unsigned char *p, size_t len, 163 const heim_general_string *str, size_t *size) 164{ 165 size_t slen = strlen(*str); 166 167 if (len < slen) 168 return ASN1_OVERFLOW; 169 p -= slen; 170 memcpy (p+1, *str, slen); 171 *size = slen; 172 return 0; 173} 174 175int 176der_put_utf8string (unsigned char *p, size_t len, 177 const heim_utf8_string *str, size_t *size) 178{ 179 return der_put_general_string(p, len, str, size); 180} 181 182int 183der_put_printable_string (unsigned char *p, size_t len, 184 const heim_printable_string *str, size_t *size) 185{ 186 return der_put_octet_string(p, len, str, size); 187} 188 189int 190der_put_ia5_string (unsigned char *p, size_t len, 191 const heim_ia5_string *str, size_t *size) 192{ 193 return der_put_octet_string(p, len, str, size); 194} 195 196int 197der_put_bmp_string (unsigned char *p, size_t len, 198 const heim_bmp_string *data, size_t *size) 199{ 200 size_t i; 201 if (len / 2 < data->length) 202 return ASN1_OVERFLOW; 203 p -= data->length * 2; 204 for (i = 0; i < data->length; i++) { 205 p[1] = (data->data[i] >> 8) & 0xff; 206 p[2] = data->data[i] & 0xff; 207 p += 2; 208 } 209 if (size) *size = data->length * 2; 210 return 0; 211} 212 213int 214der_put_universal_string (unsigned char *p, size_t len, 215 const heim_universal_string *data, size_t *size) 216{ 217 size_t i; 218 if (len / 4 < data->length) 219 return ASN1_OVERFLOW; 220 p -= data->length * 4; 221 for (i = 0; i < data->length; i++) { 222 p[1] = (data->data[i] >> 24) & 0xff; 223 p[2] = (data->data[i] >> 16) & 0xff; 224 p[3] = (data->data[i] >> 8) & 0xff; 225 p[4] = data->data[i] & 0xff; 226 p += 4; 227 } 228 if (size) *size = data->length * 4; 229 return 0; 230} 231 232int 233der_put_visible_string (unsigned char *p, size_t len, 234 const heim_visible_string *str, size_t *size) 235{ 236 return der_put_general_string(p, len, str, size); 237} 238 239int 240der_put_octet_string (unsigned char *p, size_t len, 241 const heim_octet_string *data, size_t *size) 242{ 243 if (len < data->length) 244 return ASN1_OVERFLOW; 245 p -= data->length; 246 memcpy (p+1, data->data, data->length); 247 *size = data->length; 248 return 0; 249} 250 251int 252der_put_heim_integer (unsigned char *p, size_t len, 253 const heim_integer *data, size_t *size) 254{ 255 unsigned char *buf = data->data; 256 int hibitset = 0; 257 258 if (data->length == 0) { 259 if (len < 1) 260 return ASN1_OVERFLOW; 261 *p-- = 0; 262 if (size) 263 *size = 1; 264 return 0; 265 } 266 if (len < data->length) 267 return ASN1_OVERFLOW; 268 269 len -= data->length; 270 271 if (data->negative) { 272 int i, carry; 273 for (i = data->length - 1, carry = 1; i >= 0; i--) { 274 *p = buf[i] ^ 0xff; 275 if (carry) 276 carry = !++*p; 277 p--; 278 } 279 if (p[1] < 128) { 280 if (len < 1) 281 return ASN1_OVERFLOW; 282 *p-- = 0xff; 283 len--; 284 hibitset = 1; 285 } 286 } else { 287 p -= data->length; 288 memcpy(p + 1, buf, data->length); 289 290 if (p[1] >= 128) { 291 if (len < 1) 292 return ASN1_OVERFLOW; 293 p[0] = 0; 294 len--; 295 hibitset = 1; 296 } 297 } 298 if (size) 299 *size = data->length + hibitset; 300 return 0; 301} 302 303int 304der_put_generalized_time (unsigned char *p, size_t len, 305 const time_t *data, size_t *size) 306{ 307 heim_octet_string k; 308 size_t l; 309 int e; 310 311 e = _heim_time2generalizedtime (*data, &k, 1); 312 if (e) 313 return e; 314 e = der_put_octet_string(p, len, &k, &l); 315 free(k.data); 316 if(e) 317 return e; 318 if(size) 319 *size = l; 320 return 0; 321} 322 323int 324der_put_utctime (unsigned char *p, size_t len, 325 const time_t *data, size_t *size) 326{ 327 heim_octet_string k; 328 size_t l; 329 int e; 330 331 e = _heim_time2generalizedtime (*data, &k, 0); 332 if (e) 333 return e; 334 e = der_put_octet_string(p, len, &k, &l); 335 free(k.data); 336 if(e) 337 return e; 338 if(size) 339 *size = l; 340 return 0; 341} 342 343int 344der_put_oid (unsigned char *p, size_t len, 345 const heim_oid *data, size_t *size) 346{ 347 unsigned char *base = p; 348 int n; 349 350 for (n = data->length - 1; n >= 2; --n) { 351 unsigned u = data->components[n]; 352 353 if (len < 1) 354 return ASN1_OVERFLOW; 355 *p-- = u % 128; 356 u /= 128; 357 --len; 358 while (u > 0) { 359 if (len < 1) 360 return ASN1_OVERFLOW; 361 *p-- = 128 + u % 128; 362 u /= 128; 363 --len; 364 } 365 } 366 if (len < 1) 367 return ASN1_OVERFLOW; 368 *p-- = 40 * data->components[0] + data->components[1]; 369 *size = base - p; 370 return 0; 371} 372 373int 374der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 375 unsigned int tag, size_t *size) 376{ 377 if (tag <= 30) { 378 if (len < 1) 379 return ASN1_OVERFLOW; 380 *p = MAKE_TAG(class, type, tag); 381 *size = 1; 382 } else { 383 size_t ret = 0; 384 unsigned int continuation = 0; 385 386 do { 387 if (len < 1) 388 return ASN1_OVERFLOW; 389 *p-- = tag % 128 | continuation; 390 len--; 391 ret++; 392 tag /= 128; 393 continuation = 0x80; 394 } while(tag > 0); 395 if (len < 1) 396 return ASN1_OVERFLOW; 397 *p-- = MAKE_TAG(class, type, 0x1f); 398 ret++; 399 *size = ret; 400 } 401 return 0; 402} 403 404int 405der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 406 Der_class class, Der_type type, 407 unsigned int tag, size_t *size) 408{ 409 size_t ret = 0; 410 size_t l; 411 int e; 412 413 e = der_put_length (p, len, len_val, &l); 414 if(e) 415 return e; 416 p -= l; 417 len -= l; 418 ret += l; 419 e = der_put_tag (p, len, class, type, tag, &l); 420 if(e) 421 return e; 422 423 ret += l; 424 *size = ret; 425 return 0; 426} 427 428int 429_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) 430{ 431 struct tm tm; 432 const size_t len = gtimep ? 15 : 13; 433 434 s->data = malloc(len + 1); 435 if (s->data == NULL) 436 return ENOMEM; 437 s->length = len; 438 _der_gmtime(t, &tm); 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 struct 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 s1->length - s2->length; 480} 481