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