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
36 RCSID("$Id$");
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 int
der_put_unsigned(unsigned char * p,size_t len,const unsigned * v,size_t * size)47 der_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
78 int
der_put_unsigned64(unsigned char * p,size_t len,const uint64_t * v,size_t * size)79 der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
80 {
81 unsigned char *base = p;
82 uint64_t val = *v;
83
84 if (val) {
85 while (len > 0 && val) {
86 *p-- = val % 256;
87 val /= 256;
88 --len;
89 }
90 if (val != 0)
91 return ASN1_OVERFLOW;
92 else {
93 if(p[1] >= 128) {
94 if(len < 1)
95 return ASN1_OVERFLOW;
96 *p-- = 0;
97 }
98 *size = base - p;
99 return 0;
100 }
101 } else if (len < 1)
102 return ASN1_OVERFLOW;
103 else {
104 *p = 0;
105 *size = 1;
106 return 0;
107 }
108 }
109
110 int
der_put_integer(unsigned char * p,size_t len,const int * v,size_t * size)111 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
112 {
113 unsigned char *base = p;
114 int val = *v;
115
116 if(val >= 0) {
117 do {
118 if(len < 1)
119 return ASN1_OVERFLOW;
120 *p-- = val % 256;
121 len--;
122 val /= 256;
123 } while(val);
124 if(p[1] >= 128) {
125 if(len < 1)
126 return ASN1_OVERFLOW;
127 *p-- = 0;
128 len--;
129 }
130 } else {
131 val = ~val;
132 do {
133 if(len < 1)
134 return ASN1_OVERFLOW;
135 *p-- = ~(val % 256);
136 len--;
137 val /= 256;
138 } while(val);
139 if(p[1] < 128) {
140 if(len < 1)
141 return ASN1_OVERFLOW;
142 *p-- = 0xff;
143 len--;
144 }
145 }
146 *size = base - p;
147 return 0;
148 }
149
150 int
der_put_integer64(unsigned char * p,size_t len,const int64_t * v,size_t * size)151 der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
152 {
153 unsigned char *base = p;
154 int64_t val = *v;
155
156 if(val >= 0) {
157 do {
158 if(len < 1)
159 return ASN1_OVERFLOW;
160 *p-- = val % 256;
161 len--;
162 val /= 256;
163 } while(val);
164 if(p[1] >= 128) {
165 if(len < 1)
166 return ASN1_OVERFLOW;
167 *p-- = 0;
168 len--;
169 }
170 } else {
171 val = ~val;
172 do {
173 if(len < 1)
174 return ASN1_OVERFLOW;
175 *p-- = ~(val % 256);
176 len--;
177 val /= 256;
178 } while(val);
179 if(p[1] < 128) {
180 if(len < 1)
181 return ASN1_OVERFLOW;
182 *p-- = 0xff;
183 len--;
184 }
185 }
186 *size = base - p;
187 return 0;
188 }
189
190
191 int
der_put_length(unsigned char * p,size_t len,size_t val,size_t * size)192 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
193 {
194 if (len < 1)
195 return ASN1_OVERFLOW;
196
197 if (val < 128) {
198 *p = val;
199 *size = 1;
200 } else {
201 size_t l = 0;
202
203 while(val > 0) {
204 if(len < 2)
205 return ASN1_OVERFLOW;
206 *p-- = val % 256;
207 val /= 256;
208 len--;
209 l++;
210 }
211 *p = 0x80 | l;
212 if(size)
213 *size = l + 1;
214 }
215 return 0;
216 }
217
218 int
der_put_boolean(unsigned char * p,size_t len,const int * data,size_t * size)219 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
220 {
221 if(len < 1)
222 return ASN1_OVERFLOW;
223 if(*data != 0)
224 *p = 0xff;
225 else
226 *p = 0;
227 *size = 1;
228 return 0;
229 }
230
231 int
der_put_general_string(unsigned char * p,size_t len,const heim_general_string * str,size_t * size)232 der_put_general_string (unsigned char *p, size_t len,
233 const heim_general_string *str, size_t *size)
234 {
235 size_t slen = strlen(*str);
236
237 if (len < slen)
238 return ASN1_OVERFLOW;
239 p -= slen;
240 memcpy (p+1, *str, slen);
241 *size = slen;
242 return 0;
243 }
244
245 int
der_put_utf8string(unsigned char * p,size_t len,const heim_utf8_string * str,size_t * size)246 der_put_utf8string (unsigned char *p, size_t len,
247 const heim_utf8_string *str, size_t *size)
248 {
249 return der_put_general_string(p, len, str, size);
250 }
251
252 int
der_put_printable_string(unsigned char * p,size_t len,const heim_printable_string * str,size_t * size)253 der_put_printable_string (unsigned char *p, size_t len,
254 const heim_printable_string *str, size_t *size)
255 {
256 return der_put_octet_string(p, len, str, size);
257 }
258
259 int
der_put_ia5_string(unsigned char * p,size_t len,const heim_ia5_string * str,size_t * size)260 der_put_ia5_string (unsigned char *p, size_t len,
261 const heim_ia5_string *str, size_t *size)
262 {
263 return der_put_octet_string(p, len, str, size);
264 }
265
266 int
der_put_bmp_string(unsigned char * p,size_t len,const heim_bmp_string * data,size_t * size)267 der_put_bmp_string (unsigned char *p, size_t len,
268 const heim_bmp_string *data, size_t *size)
269 {
270 size_t i;
271 if (len / 2 < data->length)
272 return ASN1_OVERFLOW;
273 p -= data->length * 2;
274 for (i = 0; i < data->length; i++) {
275 p[1] = (data->data[i] >> 8) & 0xff;
276 p[2] = data->data[i] & 0xff;
277 p += 2;
278 }
279 if (size) *size = data->length * 2;
280 return 0;
281 }
282
283 int
der_put_universal_string(unsigned char * p,size_t len,const heim_universal_string * data,size_t * size)284 der_put_universal_string (unsigned char *p, size_t len,
285 const heim_universal_string *data, size_t *size)
286 {
287 size_t i;
288 if (len / 4 < data->length)
289 return ASN1_OVERFLOW;
290 p -= data->length * 4;
291 for (i = 0; i < data->length; i++) {
292 p[1] = (data->data[i] >> 24) & 0xff;
293 p[2] = (data->data[i] >> 16) & 0xff;
294 p[3] = (data->data[i] >> 8) & 0xff;
295 p[4] = data->data[i] & 0xff;
296 p += 4;
297 }
298 if (size) *size = data->length * 4;
299 return 0;
300 }
301
302 int
der_put_visible_string(unsigned char * p,size_t len,const heim_visible_string * str,size_t * size)303 der_put_visible_string (unsigned char *p, size_t len,
304 const heim_visible_string *str, size_t *size)
305 {
306 return der_put_general_string(p, len, str, size);
307 }
308
309 int
der_put_octet_string(unsigned char * p,size_t len,const heim_octet_string * data,size_t * size)310 der_put_octet_string (unsigned char *p, size_t len,
311 const heim_octet_string *data, size_t *size)
312 {
313 if (len < data->length)
314 return ASN1_OVERFLOW;
315 p -= data->length;
316 memcpy (p+1, data->data, data->length);
317 *size = data->length;
318 return 0;
319 }
320
321 int
der_put_heim_integer(unsigned char * p,size_t len,const heim_integer * data,size_t * size)322 der_put_heim_integer (unsigned char *p, size_t len,
323 const heim_integer *data, size_t *size)
324 {
325 unsigned char *buf = data->data;
326 int hibitset = 0;
327
328 if (data->length == 0) {
329 if (len < 1)
330 return ASN1_OVERFLOW;
331 *p-- = 0;
332 if (size)
333 *size = 1;
334 return 0;
335 }
336 if (len < data->length)
337 return ASN1_OVERFLOW;
338
339 len -= data->length;
340
341 if (data->negative) {
342 int i, carry;
343 for (i = data->length - 1, carry = 1; i >= 0; i--) {
344 *p = buf[i] ^ 0xff;
345 if (carry)
346 carry = !++*p;
347 p--;
348 }
349 if (p[1] < 128) {
350 if (len < 1)
351 return ASN1_OVERFLOW;
352 *p-- = 0xff;
353 len--;
354 hibitset = 1;
355 }
356 } else {
357 p -= data->length;
358 memcpy(p + 1, buf, data->length);
359
360 if (p[1] >= 128) {
361 if (len < 1)
362 return ASN1_OVERFLOW;
363 p[0] = 0;
364 len--;
365 hibitset = 1;
366 }
367 }
368 if (size)
369 *size = data->length + hibitset;
370 return 0;
371 }
372
373 int
der_put_generalized_time(unsigned char * p,size_t len,const time_t * data,size_t * size)374 der_put_generalized_time (unsigned char *p, size_t len,
375 const time_t *data, size_t *size)
376 {
377 heim_octet_string k;
378 size_t l;
379 int e;
380
381 e = _heim_time2generalizedtime (*data, &k, 1);
382 if (e)
383 return e;
384 e = der_put_octet_string(p, len, &k, &l);
385 free(k.data);
386 if(e)
387 return e;
388 if(size)
389 *size = l;
390 return 0;
391 }
392
393 int
der_put_utctime(unsigned char * p,size_t len,const time_t * data,size_t * size)394 der_put_utctime (unsigned char *p, size_t len,
395 const time_t *data, size_t *size)
396 {
397 heim_octet_string k;
398 size_t l;
399 int e;
400
401 e = _heim_time2generalizedtime (*data, &k, 0);
402 if (e)
403 return e;
404 e = der_put_octet_string(p, len, &k, &l);
405 free(k.data);
406 if(e)
407 return e;
408 if(size)
409 *size = l;
410 return 0;
411 }
412
413 int
der_put_oid(unsigned char * p,size_t len,const heim_oid * data,size_t * size)414 der_put_oid (unsigned char *p, size_t len,
415 const heim_oid *data, size_t *size)
416 {
417 unsigned char *base = p;
418 int n;
419
420 for (n = data->length - 1; n >= 2; --n) {
421 unsigned u = data->components[n];
422
423 if (len < 1)
424 return ASN1_OVERFLOW;
425 *p-- = u % 128;
426 u /= 128;
427 --len;
428 while (u > 0) {
429 if (len < 1)
430 return ASN1_OVERFLOW;
431 *p-- = 128 + u % 128;
432 u /= 128;
433 --len;
434 }
435 }
436 if (len < 1)
437 return ASN1_OVERFLOW;
438 *p-- = 40 * data->components[0] + data->components[1];
439 *size = base - p;
440 return 0;
441 }
442
443 int
der_put_tag(unsigned char * p,size_t len,Der_class class,Der_type type,unsigned int tag,size_t * size)444 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
445 unsigned int tag, size_t *size)
446 {
447 if (tag <= 30) {
448 if (len < 1)
449 return ASN1_OVERFLOW;
450 *p = MAKE_TAG(class, type, tag);
451 *size = 1;
452 } else {
453 size_t ret = 0;
454 unsigned int continuation = 0;
455
456 do {
457 if (len < 1)
458 return ASN1_OVERFLOW;
459 *p-- = tag % 128 | continuation;
460 len--;
461 ret++;
462 tag /= 128;
463 continuation = 0x80;
464 } while(tag > 0);
465 if (len < 1)
466 return ASN1_OVERFLOW;
467 *p-- = MAKE_TAG(class, type, 0x1f);
468 ret++;
469 *size = ret;
470 }
471 return 0;
472 }
473
474 int
der_put_length_and_tag(unsigned char * p,size_t len,size_t len_val,Der_class class,Der_type type,unsigned int tag,size_t * size)475 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
476 Der_class class, Der_type type,
477 unsigned int tag, size_t *size)
478 {
479 size_t ret = 0;
480 size_t l;
481 int e;
482
483 e = der_put_length (p, len, len_val, &l);
484 if(e)
485 return e;
486 p -= l;
487 len -= l;
488 ret += l;
489 e = der_put_tag (p, len, class, type, tag, &l);
490 if(e)
491 return e;
492
493 ret += l;
494 *size = ret;
495 return 0;
496 }
497
498 int
_heim_time2generalizedtime(time_t t,heim_octet_string * s,int gtimep)499 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
500 {
501 struct tm tm;
502 const size_t len = gtimep ? 15 : 13;
503
504 s->data = malloc(len + 1);
505 if (s->data == NULL)
506 return ENOMEM;
507 s->length = len;
508 if (_der_gmtime(t, &tm) == NULL)
509 return ASN1_BAD_TIMEFORMAT;
510 if (gtimep)
511 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
512 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
513 tm.tm_hour, tm.tm_min, tm.tm_sec);
514 else
515 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
516 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
517 tm.tm_hour, tm.tm_min, tm.tm_sec);
518
519 return 0;
520 }
521
522 int
der_put_bit_string(unsigned char * p,size_t len,const heim_bit_string * data,size_t * size)523 der_put_bit_string (unsigned char *p, size_t len,
524 const heim_bit_string *data, size_t *size)
525 {
526 size_t data_size = (data->length + 7) / 8;
527 if (len < data_size + 1)
528 return ASN1_OVERFLOW;
529 p -= data_size + 1;
530
531 memcpy (p+2, data->data, data_size);
532 if (data->length && (data->length % 8) != 0)
533 p[1] = 8 - (data->length % 8);
534 else
535 p[1] = 0;
536 *size = data_size + 1;
537 return 0;
538 }
539
540 int
_heim_der_set_sort(const void * a1,const void * a2)541 _heim_der_set_sort(const void *a1, const void *a2)
542 {
543 const struct heim_octet_string *s1 = a1, *s2 = a2;
544 int ret;
545
546 ret = memcmp(s1->data, s2->data,
547 s1->length < s2->length ? s1->length : s2->length);
548 if(ret)
549 return ret;
550 return s1->length - s2->length;
551 }
552