Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/asn1/der_put.c
34879 views
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
553