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