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: der_put.c,v 1.1.1.1 2011/06/10 09:34:42 andrew Exp $"); 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_general_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_general_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 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 301int 302der_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 321int 322der_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 341int 342der_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 371int 372der_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 402int 403der_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 426int 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 tm = gmtime (&t); 437 if (gtimep) 438 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 439 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 440 tm->tm_hour, tm->tm_min, tm->tm_sec); 441 else 442 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", 443 tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 444 tm->tm_hour, tm->tm_min, tm->tm_sec); 445 446 return 0; 447} 448 449int 450der_put_bit_string (unsigned char *p, size_t len, 451 const heim_bit_string *data, size_t *size) 452{ 453 size_t data_size = (data->length + 7) / 8; 454 if (len < data_size + 1) 455 return ASN1_OVERFLOW; 456 p -= data_size + 1; 457 458 memcpy (p+2, data->data, data_size); 459 if (data->length && (data->length % 8) != 0) 460 p[1] = 8 - (data->length % 8); 461 else 462 p[1] = 0; 463 *size = data_size + 1; 464 return 0; 465} 466 467int 468_heim_der_set_sort(const void *a1, const void *a2) 469{ 470 const struct heim_octet_string *s1 = a1, *s2 = a2; 471 int ret; 472 473 ret = memcmp(s1->data, s2->data, 474 s1->length < s2->length ? s1->length : s2->length); 475 if(ret) 476 return ret; 477 return s1->length - s2->length; 478} 479