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