1 /* 2 * Copyright (c) 1997 - 2001 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 36 RCSID("$Id: der_put.c,v 1.28 2003/04/17 07:12:24 lha 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 46 static int 47 der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) 48 { 49 unsigned char *base = p; 50 51 if (val) { 52 while (len > 0 && val) { 53 *p-- = val % 256; 54 val /= 256; 55 --len; 56 } 57 if (val != 0) 58 return ASN1_OVERFLOW; 59 else { 60 *size = base - p; 61 return 0; 62 } 63 } else if (len < 1) 64 return ASN1_OVERFLOW; 65 else { 66 *p = 0; 67 *size = 1; 68 return 0; 69 } 70 } 71 72 int 73 der_put_int (unsigned char *p, size_t len, int val, size_t *size) 74 { 75 unsigned char *base = p; 76 77 if(val >= 0) { 78 do { 79 if(len < 1) 80 return ASN1_OVERFLOW; 81 *p-- = val % 256; 82 len--; 83 val /= 256; 84 } while(val); 85 if(p[1] >= 128) { 86 if(len < 1) 87 return ASN1_OVERFLOW; 88 *p-- = 0; 89 len--; 90 } 91 } else { 92 val = ~val; 93 do { 94 if(len < 1) 95 return ASN1_OVERFLOW; 96 *p-- = ~(val % 256); 97 len--; 98 val /= 256; 99 } while(val); 100 if(p[1] < 128) { 101 if(len < 1) 102 return ASN1_OVERFLOW; 103 *p-- = 0xff; 104 len--; 105 } 106 } 107 *size = base - p; 108 return 0; 109 } 110 111 112 int 113 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) 114 { 115 if (len < 1) 116 return ASN1_OVERFLOW; 117 if (val < 128) { 118 *p = val; 119 *size = 1; 120 return 0; 121 } else { 122 size_t l; 123 int e; 124 125 e = der_put_unsigned (p, len - 1, val, &l); 126 if (e) 127 return e; 128 p -= l; 129 *p = 0x80 | l; 130 *size = l + 1; 131 return 0; 132 } 133 } 134 135 int 136 der_put_general_string (unsigned char *p, size_t len, 137 const general_string *str, size_t *size) 138 { 139 size_t slen = strlen(*str); 140 141 if (len < slen) 142 return ASN1_OVERFLOW; 143 p -= slen; 144 len -= slen; 145 memcpy (p+1, *str, slen); 146 *size = slen; 147 return 0; 148 } 149 150 int 151 der_put_octet_string (unsigned char *p, size_t len, 152 const octet_string *data, size_t *size) 153 { 154 if (len < data->length) 155 return ASN1_OVERFLOW; 156 p -= data->length; 157 len -= data->length; 158 memcpy (p+1, data->data, data->length); 159 *size = data->length; 160 return 0; 161 } 162 163 int 164 der_put_oid (unsigned char *p, size_t len, 165 const oid *data, size_t *size) 166 { 167 unsigned char *base = p; 168 int n; 169 170 for (n = data->length - 1; n >= 2; --n) { 171 unsigned u = data->components[n]; 172 173 if (len < 1) 174 return ASN1_OVERFLOW; 175 *p-- = u % 128; 176 u /= 128; 177 --len; 178 while (u > 0) { 179 if (len < 1) 180 return ASN1_OVERFLOW; 181 *p-- = 128 + u % 128; 182 u /= 128; 183 --len; 184 } 185 } 186 if (len < 1) 187 return ASN1_OVERFLOW; 188 *p-- = 40 * data->components[0] + data->components[1]; 189 *size = base - p; 190 return 0; 191 } 192 193 int 194 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, 195 int tag, size_t *size) 196 { 197 if (len < 1) 198 return ASN1_OVERFLOW; 199 *p = (class << 6) | (type << 5) | tag; /* XXX */ 200 *size = 1; 201 return 0; 202 } 203 204 int 205 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, 206 Der_class class, Der_type type, int tag, size_t *size) 207 { 208 size_t ret = 0; 209 size_t l; 210 int e; 211 212 e = der_put_length (p, len, len_val, &l); 213 if(e) 214 return e; 215 p -= l; 216 len -= l; 217 ret += l; 218 e = der_put_tag (p, len, class, type, tag, &l); 219 if(e) 220 return e; 221 p -= l; 222 len -= l; 223 ret += l; 224 *size = ret; 225 return 0; 226 } 227 228 int 229 encode_integer (unsigned char *p, size_t len, const int *data, size_t *size) 230 { 231 int num = *data; 232 size_t ret = 0; 233 size_t l; 234 int e; 235 236 e = der_put_int (p, len, num, &l); 237 if(e) 238 return e; 239 p -= l; 240 len -= l; 241 ret += l; 242 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); 243 if (e) 244 return e; 245 p -= l; 246 len -= l; 247 ret += l; 248 *size = ret; 249 return 0; 250 } 251 252 int 253 encode_unsigned (unsigned char *p, size_t len, const unsigned *data, 254 size_t *size) 255 { 256 unsigned num = *data; 257 size_t ret = 0; 258 size_t l; 259 int e; 260 261 e = der_put_unsigned (p, len, num, &l); 262 if(e) 263 return e; 264 p -= l; 265 len -= l; 266 ret += l; 267 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); 268 if (e) 269 return e; 270 p -= l; 271 len -= l; 272 ret += l; 273 *size = ret; 274 return 0; 275 } 276 277 int 278 encode_enumerated (unsigned char *p, size_t len, const unsigned *data, 279 size_t *size) 280 { 281 unsigned num = *data; 282 size_t ret = 0; 283 size_t l; 284 int e; 285 286 e = der_put_int (p, len, num, &l); 287 if(e) 288 return e; 289 p -= l; 290 len -= l; 291 ret += l; 292 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Enumerated, &l); 293 if (e) 294 return e; 295 p -= l; 296 len -= l; 297 ret += l; 298 *size = ret; 299 return 0; 300 } 301 302 int 303 encode_general_string (unsigned char *p, size_t len, 304 const general_string *data, size_t *size) 305 { 306 size_t ret = 0; 307 size_t l; 308 int e; 309 310 e = der_put_general_string (p, len, data, &l); 311 if (e) 312 return e; 313 p -= l; 314 len -= l; 315 ret += l; 316 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l); 317 if (e) 318 return e; 319 p -= l; 320 len -= l; 321 ret += l; 322 *size = ret; 323 return 0; 324 } 325 326 int 327 encode_octet_string (unsigned char *p, size_t len, 328 const octet_string *k, size_t *size) 329 { 330 size_t ret = 0; 331 size_t l; 332 int e; 333 334 e = der_put_octet_string (p, len, k, &l); 335 if (e) 336 return e; 337 p -= l; 338 len -= l; 339 ret += l; 340 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l); 341 if (e) 342 return e; 343 p -= l; 344 len -= l; 345 ret += l; 346 *size = ret; 347 return 0; 348 } 349 350 int 351 encode_oid(unsigned char *p, size_t len, 352 const oid *k, size_t *size) 353 { 354 size_t ret = 0; 355 size_t l; 356 int e; 357 358 e = der_put_oid (p, len, k, &l); 359 if (e) 360 return e; 361 p -= l; 362 len -= l; 363 ret += l; 364 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OID, &l); 365 if (e) 366 return e; 367 p -= l; 368 len -= l; 369 ret += l; 370 *size = ret; 371 return 0; 372 } 373 374 int 375 time2generalizedtime (time_t t, octet_string *s) 376 { 377 struct tm *tm; 378 size_t len; 379 380 len = 15; 381 382 s->data = malloc(len + 1); 383 if (s->data == NULL) 384 return ENOMEM; 385 s->length = len; 386 tm = gmtime (&t); 387 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 388 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 389 tm->tm_hour, tm->tm_min, tm->tm_sec); 390 return 0; 391 } 392 393 int 394 encode_generalized_time (unsigned char *p, size_t len, 395 const time_t *t, size_t *size) 396 { 397 size_t ret = 0; 398 size_t l; 399 octet_string k; 400 int e; 401 402 e = time2generalizedtime (*t, &k); 403 if (e) 404 return e; 405 e = der_put_octet_string (p, len, &k, &l); 406 free (k.data); 407 if (e) 408 return e; 409 p -= l; 410 len -= l; 411 ret += l; 412 e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, 413 UT_GeneralizedTime, &l); 414 if (e) 415 return e; 416 p -= l; 417 len -= l; 418 ret += l; 419 *size = ret; 420 return 0; 421 } 422