/src/opensc/src/libopensc/asn1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * asn1.c: ASN.1 decoding functions (DER) |
3 | | * |
4 | | * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi> |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | #include "config.h" |
23 | | #endif |
24 | | |
25 | | #include <assert.h> |
26 | | #include <ctype.h> |
27 | | #include <stddef.h> |
28 | | #include <stdio.h> |
29 | | #include <stdlib.h> |
30 | | #include <string.h> |
31 | | #include <limits.h> |
32 | | |
33 | | #include "internal.h" |
34 | | #include "asn1.h" |
35 | | |
36 | | static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, |
37 | | const u8 *in, size_t len, const u8 **newp, size_t *len_left, |
38 | | int choice, int depth); |
39 | | static int asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1, |
40 | | u8 **ptr, size_t *size, int depth); |
41 | | static int asn1_write_element(sc_context_t *ctx, unsigned int tag, |
42 | | const u8 * data, size_t datalen, u8 ** out, size_t * outlen); |
43 | | |
44 | | static const char *tag2str(unsigned int tag) |
45 | 75.6k | { |
46 | 75.6k | static const char *tags[] = { |
47 | 75.6k | "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ |
48 | 75.6k | "NULL", "OBJECT IDENTIFIER", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ |
49 | 75.6k | "ENUMERATED", "Universal 11", "UTF8String", "Universal 13", /* 10-13 */ |
50 | 75.6k | "Universal 14", "Universal 15", "SEQUENCE", "SET", /* 15-17 */ |
51 | 75.6k | "NumericString", "PrintableString", "T61String", /* 18-20 */ |
52 | 75.6k | "VideotexString", "IA5String", "UTCTIME", "GENERALIZEDTIME", /* 21-24 */ |
53 | 75.6k | "GraphicString", "VisibleString", "GeneralString", /* 25-27 */ |
54 | 75.6k | "UniversalString", "Universal 29", "BMPString" /* 28-30 */ |
55 | 75.6k | }; |
56 | | |
57 | 75.6k | if (tag > 30) |
58 | 5.72k | return "(unknown)"; |
59 | 69.9k | return tags[tag]; |
60 | 75.6k | } |
61 | | |
62 | | int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out, |
63 | | unsigned int *tag_out, size_t *taglen) |
64 | 3.51M | { |
65 | 3.51M | const u8 *p = *buf; |
66 | 3.51M | size_t left = buflen, len; |
67 | 3.51M | unsigned int cla, tag, i; |
68 | | |
69 | 3.51M | *buf = NULL; |
70 | | |
71 | 3.51M | if (left == 0 || !p || buflen == 0) |
72 | 39.4k | return SC_ERROR_INVALID_ASN1_OBJECT; |
73 | 3.47M | if (*p == 0xff || *p == 0) { |
74 | | /* end of data reached */ |
75 | 218k | *taglen = 0; |
76 | 218k | *tag_out = SC_ASN1_TAG_EOC; |
77 | 218k | return SC_SUCCESS; |
78 | 218k | } |
79 | | |
80 | | /* parse tag byte(s) |
81 | | * Resulted tag is presented by integer that has not to be |
82 | | * confused with the 'tag number' part of ASN.1 tag. |
83 | | */ |
84 | 3.25M | cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED); |
85 | 3.25M | tag = *p & SC_ASN1_TAG_PRIMITIVE; |
86 | 3.25M | if (left < 1) |
87 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
88 | 3.25M | p++; |
89 | 3.25M | left--; |
90 | 3.25M | if (tag == SC_ASN1_TAG_PRIMITIVE) { |
91 | | /* high tag number */ |
92 | 80.1k | size_t n = SC_ASN1_TAGNUM_SIZE - 1; |
93 | | /* search the last tag octet */ |
94 | 96.6k | do { |
95 | 96.6k | if (left == 0 || n == 0) |
96 | | /* either an invalid tag or it doesn't fit in |
97 | | * unsigned int */ |
98 | 5.34k | return SC_ERROR_INVALID_ASN1_OBJECT; |
99 | 91.3k | tag <<= 8; |
100 | 91.3k | tag |= *p; |
101 | 91.3k | p++; |
102 | 91.3k | left--; |
103 | 91.3k | n--; |
104 | 91.3k | } while (tag & 0x80); |
105 | 80.1k | } |
106 | | |
107 | | /* parse length byte(s) */ |
108 | 3.25M | if (left == 0) |
109 | 48.2k | return SC_ERROR_INVALID_ASN1_OBJECT; |
110 | 3.20M | len = *p; |
111 | 3.20M | p++; |
112 | 3.20M | left--; |
113 | 3.20M | if (len & 0x80) { |
114 | 1.21M | len &= 0x7f; |
115 | 1.21M | unsigned int a = 0; |
116 | 1.21M | if (len > sizeof a || len > left) |
117 | 84.7k | return SC_ERROR_INVALID_ASN1_OBJECT; |
118 | 1.24M | for (i = 0; i < len; i++) { |
119 | 113k | a <<= 8; |
120 | 113k | a |= *p; |
121 | 113k | p++; |
122 | 113k | left--; |
123 | 113k | } |
124 | 1.13M | len = a; |
125 | 1.13M | } |
126 | | |
127 | 3.11M | *cla_out = cla; |
128 | 3.11M | *tag_out = tag; |
129 | 3.11M | *taglen = len; |
130 | 3.11M | *buf = p; |
131 | | |
132 | 3.11M | if (len > left) |
133 | 195k | return SC_ERROR_ASN1_END_OF_CONTENTS; |
134 | | |
135 | 2.92M | return SC_SUCCESS; |
136 | 3.11M | } |
137 | | |
138 | | void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg, |
139 | | int set_present) |
140 | 2.98M | { |
141 | 2.98M | entry->parm = parm; |
142 | 2.98M | entry->arg = arg; |
143 | 2.98M | if (set_present) |
144 | 549k | entry->flags |= SC_ASN1_PRESENT; |
145 | 2.98M | } |
146 | | |
147 | | void sc_copy_asn1_entry(const struct sc_asn1_entry *src, |
148 | | struct sc_asn1_entry *dest) |
149 | 1.02M | { |
150 | 4.28M | while (src->name != NULL) { |
151 | 3.26M | *dest = *src; |
152 | 3.26M | dest++; |
153 | 3.26M | src++; |
154 | 3.26M | } |
155 | 1.02M | dest->name = NULL; |
156 | 1.02M | } |
157 | | |
158 | | static void print_indent(size_t depth) |
159 | 626k | { |
160 | 2.37M | for (; depth > 0; depth--) { |
161 | 1.75M | putchar(' '); |
162 | 1.75M | } |
163 | 626k | } |
164 | | |
165 | | static void print_hex(const u8 * buf, size_t buflen, size_t depth) |
166 | 23.1k | { |
167 | 23.1k | size_t lines_len = buflen * 5 + 128; |
168 | 23.1k | char *lines = malloc(lines_len); |
169 | 23.1k | char *line = lines; |
170 | | |
171 | 23.1k | if (buf == NULL || buflen == 0 || lines == NULL) { |
172 | 2.75k | free(lines); |
173 | 2.75k | return; |
174 | 2.75k | } |
175 | | |
176 | 20.3k | sc_hex_dump(buf, buflen, lines, lines_len); |
177 | | |
178 | 549k | while (*line != '\0') { |
179 | 529k | char *line_end = strchr(line, '\n'); |
180 | 529k | ptrdiff_t width = line_end - line; |
181 | 529k | if (!line_end || width <= 1) { |
182 | | /* don't print empty lines */ |
183 | 0 | break; |
184 | 0 | } |
185 | 529k | if (buflen > 8) { |
186 | 524k | putchar('\n'); |
187 | 524k | print_indent(depth); |
188 | 524k | } else { |
189 | 4.66k | printf(": "); |
190 | 4.66k | } |
191 | 529k | printf("%.*s", (int) width, line); |
192 | 529k | line = line_end + 1; |
193 | 529k | } |
194 | | |
195 | 20.3k | free(lines); |
196 | 20.3k | } |
197 | | |
198 | | static void print_ascii(const u8 * buf, size_t buflen) |
199 | 47.2k | { |
200 | 2.14M | for (; 0 < buflen; buflen--, buf++) { |
201 | 2.09M | if (isprint(*buf)) |
202 | 1.03M | printf("%c", *buf); |
203 | 1.06M | else |
204 | 1.06M | putchar('.'); |
205 | 2.09M | } |
206 | 47.2k | } |
207 | | |
208 | | static void sc_asn1_print_octet_string(const u8 * buf, size_t buflen, size_t depth) |
209 | 1.08k | { |
210 | 1.08k | print_hex(buf, buflen, depth); |
211 | 1.08k | } |
212 | | |
213 | | static void sc_asn1_print_utf8string(const u8 * buf, size_t buflen) |
214 | 10.3k | { |
215 | | /* FIXME UTF-8 is not ASCII */ |
216 | 10.3k | print_ascii(buf, buflen); |
217 | 10.3k | } |
218 | | |
219 | | static void sc_asn1_print_integer(const u8 * buf, size_t buflen) |
220 | 10.7k | { |
221 | 10.7k | size_t a = 0; |
222 | | |
223 | 10.7k | if (buflen > sizeof(a)) { |
224 | 8.15k | printf("0x%s", sc_dump_hex(buf, buflen)); |
225 | 8.15k | } else { |
226 | 2.62k | size_t i; |
227 | 8.44k | for (i = 0; i < buflen; i++) { |
228 | 5.82k | a <<= 8; |
229 | 5.82k | a |= buf[i]; |
230 | 5.82k | } |
231 | 2.62k | printf("%"SC_FORMAT_LEN_SIZE_T"u", a); |
232 | 2.62k | } |
233 | 10.7k | } |
234 | | |
235 | | static void sc_asn1_print_boolean(const u8 * buf, size_t buflen) |
236 | 7.96k | { |
237 | 7.96k | if (!buflen) |
238 | 731 | return; |
239 | | |
240 | 7.22k | if (buf[0]) |
241 | 6.93k | printf("true"); |
242 | 295 | else |
243 | 295 | printf("false"); |
244 | 7.22k | } |
245 | | |
246 | | static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen, size_t depth) |
247 | 12.1k | { |
248 | 12.1k | #ifndef _WIN32 |
249 | 12.1k | long long a = 0; |
250 | | #else |
251 | | __int64 a = 0; |
252 | | #endif |
253 | 12.1k | int r, i; |
254 | | |
255 | 12.1k | if (buflen > sizeof(a) + 1) { |
256 | 1.19k | print_hex(buf, buflen, depth); |
257 | 10.9k | } else { |
258 | 10.9k | r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 1); |
259 | 10.9k | if (r < 0) { |
260 | 6.45k | printf("decode error, "); |
261 | | /* try again without the strict mode */ |
262 | 6.45k | r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 0); |
263 | 6.45k | if (r < 0) { |
264 | 4.74k | printf("even for lax decoding"); |
265 | 4.74k | return ; |
266 | 4.74k | } |
267 | 6.45k | } |
268 | 96.5k | for (i = r - 1; i >= 0; i--) { |
269 | 90.3k | printf("%c", ((a >> i) & 1) ? '1' : '0'); |
270 | 90.3k | } |
271 | 6.18k | } |
272 | 12.1k | } |
273 | | |
274 | | #ifdef ENABLE_OPENSSL |
275 | | #include <openssl/objects.h> |
276 | | |
277 | | static void openssl_print_object_sn(const char *s) |
278 | 8.32k | { |
279 | 8.32k | ASN1_OBJECT *obj = OBJ_txt2obj(s, 0); |
280 | 8.32k | if (obj) { |
281 | 8.32k | int nid = OBJ_obj2nid(obj); |
282 | 8.32k | if (nid != NID_undef) { |
283 | 939 | printf(", %s", OBJ_nid2sn(nid)); |
284 | 939 | } |
285 | 8.32k | ASN1_OBJECT_free(obj); |
286 | 8.32k | } |
287 | 8.32k | } |
288 | | #else |
289 | | static void openssl_print_object_sn(const char *s) |
290 | | { |
291 | | } |
292 | | #endif |
293 | | |
294 | | static void sc_asn1_print_object_id(const u8 * buf, size_t buflen) |
295 | 12.0k | { |
296 | 12.0k | struct sc_object_id oid; |
297 | 12.0k | const char *sbuf; |
298 | | |
299 | 12.0k | if (sc_asn1_decode_object_id(buf, buflen, &oid)) { |
300 | 3.68k | printf("decode error"); |
301 | 3.68k | return; |
302 | 3.68k | } |
303 | | |
304 | 8.32k | sbuf = sc_dump_oid(&oid); |
305 | 8.32k | printf(" %s", sbuf); |
306 | 8.32k | openssl_print_object_sn(sbuf); |
307 | 8.32k | } |
308 | | |
309 | | static void sc_asn1_print_utctime(const u8 * buf, size_t buflen) |
310 | 11.3k | { |
311 | 11.3k | if (buflen < 8) { |
312 | 3.60k | printf("Error in decoding.\n"); |
313 | 3.60k | return; |
314 | 3.60k | } |
315 | | |
316 | 7.77k | print_ascii(buf, 2); /* YY */ |
317 | 7.77k | putchar('-'); |
318 | 7.77k | print_ascii(buf+2, 2); /* MM */ |
319 | 7.77k | putchar('-'); |
320 | 7.77k | print_ascii(buf+4, 2); /* DD */ |
321 | 7.77k | putchar(' '); |
322 | 7.77k | print_ascii(buf+6, 2); /* hh */ |
323 | 7.77k | buf += 8; |
324 | 7.77k | buflen -= 8; |
325 | 7.77k | if (buflen >= 2 && isdigit(buf[0]) && isdigit(buf[1])) { |
326 | 1.38k | putchar(':'); |
327 | 1.38k | print_ascii(buf, 2); /* mm */ |
328 | 1.38k | buf += 2; |
329 | 1.38k | buflen -= 2; |
330 | 1.38k | } |
331 | 7.77k | if (buflen >= 2 && isdigit(buf[0]) && isdigit(buf[1])) { |
332 | 611 | putchar(':'); |
333 | 611 | print_ascii(buf, 2); /* ss */ |
334 | 611 | buf += 2; |
335 | 611 | buflen -= 2; |
336 | 611 | } |
337 | 7.77k | if (buflen >= 4 && '.' == buf[0]) { |
338 | 450 | print_ascii(buf, 4); /* fff */ |
339 | 450 | buf += 4; |
340 | 450 | buflen -= 4; |
341 | 450 | } |
342 | | |
343 | 7.77k | if (buflen >= 1 && 'Z' == buf[0]) { |
344 | 685 | printf(" UTC"); |
345 | 7.09k | } else if (buflen >= 5 && ('-' == buf[0] || '+' == buf[0])) { |
346 | 1.05k | putchar(' '); |
347 | 1.05k | print_ascii(buf, 3); /* +/-hh */ |
348 | 1.05k | putchar(':'); |
349 | 1.05k | print_ascii(buf+3, 2); /* mm */ |
350 | 1.05k | } |
351 | 7.77k | } |
352 | | |
353 | | static void sc_asn1_print_generalizedtime(const u8 * buf, size_t buflen) |
354 | 1.44k | { |
355 | 1.44k | if (buflen < 8) { |
356 | 228 | printf("Error in decoding.\n"); |
357 | 228 | return; |
358 | 228 | } |
359 | | |
360 | 1.21k | print_ascii(buf, 2); |
361 | 1.21k | sc_asn1_print_utctime(buf + 2, buflen - 2); |
362 | 1.21k | } |
363 | | |
364 | | static void print_tags_recursive(const u8 * buf0, const u8 * buf, |
365 | | size_t buflen, size_t depth) |
366 | 21.8k | { |
367 | 21.8k | int r; |
368 | 21.8k | size_t i; |
369 | 21.8k | size_t bytesleft = buflen; |
370 | 21.8k | const char *classes[4] = { |
371 | 21.8k | "Universal", |
372 | 21.8k | "Application", |
373 | 21.8k | "Context", |
374 | 21.8k | "Private" |
375 | 21.8k | }; |
376 | 21.8k | const u8 *p = buf; |
377 | | |
378 | 123k | while (bytesleft >= 2) { |
379 | 116k | unsigned int cla = 0, tag = 0; |
380 | 116k | size_t hlen; |
381 | 116k | const u8 *tagp = p; |
382 | 116k | size_t len; |
383 | | |
384 | 116k | r = sc_asn1_read_tag(&tagp, bytesleft, &cla, &tag, &len); |
385 | 116k | if (r != SC_SUCCESS || (tagp == NULL && tag != SC_ASN1_TAG_EOC)) { |
386 | 13.4k | printf("Error in decoding.\n"); |
387 | 13.4k | return; |
388 | 13.4k | } |
389 | 103k | hlen = tagp - p; |
390 | 103k | if (cla == 0 && tag == 0) { |
391 | 1.11k | printf("Zero tag, finishing\n"); |
392 | 1.11k | break; |
393 | 1.11k | } |
394 | 101k | print_indent(depth); |
395 | | /* let i be the length of the tag in bytes */ |
396 | 111k | for (i = 1; i < sizeof tag - 1; i++) { |
397 | 108k | if (!(tag >> 8*i)) |
398 | 99.0k | break; |
399 | 108k | } |
400 | 101k | printf("%02X", cla<<(i-1)*8 | tag); |
401 | | |
402 | 101k | if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_UNIVERSAL) { |
403 | 75.6k | printf(" %s", tag2str(tag)); |
404 | 75.6k | } else { |
405 | 26.2k | printf(" %s %-2u", |
406 | 26.2k | classes[cla >> 6], |
407 | 26.2k | i == 1 ? tag & SC_ASN1_TAG_PRIMITIVE : tag & (((unsigned int) ~0) >> (i-1)*8)); |
408 | 26.2k | } |
409 | 101k | if (!((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_UNIVERSAL |
410 | 101k | && tag == SC_ASN1_TAG_NULL && len == 0)) { |
411 | 100k | printf(" (%"SC_FORMAT_LEN_SIZE_T"u byte%s)", |
412 | 100k | len, |
413 | 100k | len != 1 ? "s" : ""); |
414 | 100k | } |
415 | | |
416 | 101k | if (len + hlen > bytesleft) { |
417 | 0 | printf(" Illegal length!\n"); |
418 | 0 | return; |
419 | 0 | } |
420 | 101k | p += hlen + len; |
421 | 101k | bytesleft -= hlen + len; |
422 | | |
423 | 101k | if (cla & SC_ASN1_TAG_CONSTRUCTED) { |
424 | 20.5k | putchar('\n'); |
425 | 20.5k | print_tags_recursive(buf0, tagp, len, depth + 2*i + 1); |
426 | 20.5k | continue; |
427 | 20.5k | } |
428 | | |
429 | 81.3k | switch (tag) { |
430 | 12.1k | case SC_ASN1_TAG_BIT_STRING: |
431 | 12.1k | printf(": "); |
432 | 12.1k | sc_asn1_print_bit_string(tagp, len, depth + 2*i + 1); |
433 | 12.1k | break; |
434 | 1.08k | case SC_ASN1_TAG_OCTET_STRING: |
435 | 1.08k | sc_asn1_print_octet_string(tagp, len, depth + 2*i + 1); |
436 | 1.08k | break; |
437 | 12.0k | case SC_ASN1_TAG_OBJECT: |
438 | 12.0k | printf(": "); |
439 | 12.0k | sc_asn1_print_object_id(tagp, len); |
440 | 12.0k | break; |
441 | 9.24k | case SC_ASN1_TAG_INTEGER: |
442 | 10.7k | case SC_ASN1_TAG_ENUMERATED: |
443 | 10.7k | printf(": "); |
444 | 10.7k | sc_asn1_print_integer(tagp, len); |
445 | 10.7k | break; |
446 | 219 | case SC_ASN1_TAG_IA5STRING: |
447 | 779 | case SC_ASN1_TAG_PRINTABLESTRING: |
448 | 1.04k | case SC_ASN1_TAG_T61STRING: |
449 | 10.3k | case SC_ASN1_TAG_UTF8STRING: |
450 | 10.3k | printf(": "); |
451 | 10.3k | sc_asn1_print_utf8string(tagp, len); |
452 | 10.3k | break; |
453 | 7.96k | case SC_ASN1_TAG_BOOLEAN: |
454 | 7.96k | printf(": "); |
455 | 7.96k | sc_asn1_print_boolean(tagp, len); |
456 | 7.96k | break; |
457 | 1.44k | case SC_ASN1_GENERALIZEDTIME: |
458 | 1.44k | printf(": "); |
459 | 1.44k | sc_asn1_print_generalizedtime(tagp, len); |
460 | 1.44k | break; |
461 | 10.1k | case SC_ASN1_UTCTIME: |
462 | 10.1k | printf(": "); |
463 | 10.1k | sc_asn1_print_utctime(tagp, len); |
464 | 10.1k | break; |
465 | 81.3k | } |
466 | | |
467 | 81.3k | if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_APPLICATION) { |
468 | 15.4k | print_hex(tagp, len, depth + 2*i + 1); |
469 | 15.4k | } |
470 | | |
471 | 81.3k | if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_CONTEXT) { |
472 | 5.41k | print_hex(tagp, len, depth + 2*i + 1); |
473 | 5.41k | } |
474 | | |
475 | 81.3k | putchar('\n'); |
476 | 81.3k | } |
477 | 21.8k | } |
478 | | |
479 | | void sc_asn1_print_tags(const u8 * buf, size_t buflen) |
480 | 1.30k | { |
481 | 1.30k | print_tags_recursive(buf, buf, buflen, 0); |
482 | 1.30k | } |
483 | | |
484 | | const u8 *sc_asn1_find_tag(sc_context_t *ctx, const u8 * buf, |
485 | | size_t buflen, unsigned int tag_in, size_t *taglen_in) |
486 | 244k | { |
487 | 244k | size_t left = buflen, taglen; |
488 | 244k | const u8 *p = buf; |
489 | | |
490 | 244k | *taglen_in = 0; |
491 | 570k | while (left >= 2) { |
492 | 524k | unsigned int cla = 0, tag, mask = 0xff00; |
493 | | |
494 | 524k | buf = p; |
495 | | /* read a tag */ |
496 | 524k | if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS |
497 | 524k | || p == NULL) |
498 | 79.0k | return NULL; |
499 | | |
500 | 445k | left -= (p - buf); |
501 | | /* we need to shift the class byte to the leftmost |
502 | | * byte of the tag */ |
503 | 454k | while ((tag & mask) != 0) { |
504 | 8.39k | cla <<= 8; |
505 | 8.39k | mask <<= 8; |
506 | 8.39k | } |
507 | | /* compare the read tag with the given tag */ |
508 | 445k | if ((tag | cla) == tag_in) { |
509 | | /* we have a match => return length and value part */ |
510 | 120k | if (taglen > left) |
511 | 0 | return NULL; |
512 | 120k | *taglen_in = taglen; |
513 | 120k | return p; |
514 | 120k | } |
515 | | /* otherwise continue reading tags */ |
516 | 325k | left -= taglen; |
517 | 325k | p += taglen; |
518 | 325k | } |
519 | 45.2k | return NULL; |
520 | 244k | } |
521 | | |
522 | | const u8 *sc_asn1_skip_tag(sc_context_t *ctx, const u8 ** buf, size_t *buflen, |
523 | | unsigned int tag_in, size_t *taglen_out) |
524 | 608k | { |
525 | 608k | const u8 *p = *buf; |
526 | 608k | size_t len = *buflen, taglen; |
527 | 608k | unsigned int cla = 0, tag; |
528 | | |
529 | 608k | if (sc_asn1_read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != SC_SUCCESS |
530 | 608k | || p == NULL) |
531 | 164k | return NULL; |
532 | 444k | switch (cla & 0xC0) { |
533 | 238k | case SC_ASN1_TAG_UNIVERSAL: |
534 | 238k | if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_UNI) |
535 | 30.8k | return NULL; |
536 | 207k | break; |
537 | 207k | case SC_ASN1_TAG_APPLICATION: |
538 | 63.3k | if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_APP) |
539 | 19.3k | return NULL; |
540 | 43.9k | break; |
541 | 133k | case SC_ASN1_TAG_CONTEXT: |
542 | 133k | if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_CTX) |
543 | 17.4k | return NULL; |
544 | 115k | break; |
545 | 115k | case SC_ASN1_TAG_PRIVATE: |
546 | 9.10k | if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_PRV) |
547 | 9.10k | return NULL; |
548 | 0 | break; |
549 | 444k | } |
550 | 367k | if (cla & SC_ASN1_TAG_CONSTRUCTED) { |
551 | 195k | if ((tag_in & SC_ASN1_CONS) == 0) |
552 | 17.6k | return NULL; |
553 | 195k | } else |
554 | 172k | if (tag_in & SC_ASN1_CONS) |
555 | 11.5k | return NULL; |
556 | 338k | if ((tag_in & SC_ASN1_TAG_MASK) != tag) |
557 | 99.3k | return NULL; |
558 | 239k | len -= (p - *buf); /* header size */ |
559 | 239k | if (taglen > len) { |
560 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
561 | 0 | "too long ASN.1 object (size %"SC_FORMAT_LEN_SIZE_T"u while only %"SC_FORMAT_LEN_SIZE_T"u available)\n", |
562 | 0 | taglen, len); |
563 | 0 | return NULL; |
564 | 0 | } |
565 | 239k | *buflen -= (p - *buf) + taglen; |
566 | 239k | *buf = p + taglen; /* point to next tag */ |
567 | 239k | *taglen_out = taglen; |
568 | 239k | return p; |
569 | 239k | } |
570 | | |
571 | | const u8 *sc_asn1_verify_tag(sc_context_t *ctx, const u8 * buf, size_t buflen, |
572 | | unsigned int tag_in, size_t *taglen_out) |
573 | 8.02k | { |
574 | 8.02k | return sc_asn1_skip_tag(ctx, &buf, &buflen, tag_in, taglen_out); |
575 | 8.02k | } |
576 | | |
577 | | static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf, |
578 | | size_t outlen, int invert, const int strict) |
579 | 28.3k | { |
580 | 28.3k | const u8 *in = inbuf; |
581 | 28.3k | u8 *out = (u8 *) outbuf; |
582 | 28.3k | int i, count = 0; |
583 | 28.3k | int zero_bits; |
584 | 28.3k | size_t octets_left; |
585 | | |
586 | 28.3k | if (inlen < 1) |
587 | 1.43k | return SC_ERROR_INVALID_ASN1_OBJECT; |
588 | | |
589 | | /* The formatting is only enforced by SHALL keyword so we should accept |
590 | | * by default also non-strict values. */ |
591 | 26.9k | if (strict) { |
592 | | /* 8.6.2.3 If the bitstring is empty, there shall be no |
593 | | * subsequent octets,and the initial octet shall be zero. */ |
594 | 10.2k | if (inlen == 1 && *in != 0) |
595 | 3.05k | return SC_ERROR_INVALID_ASN1_OBJECT; |
596 | | /* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */ |
597 | 7.18k | if ((*in & ~0x07) != 0) |
598 | 1.49k | return SC_ERROR_INVALID_ASN1_OBJECT; |
599 | 7.18k | } |
600 | | |
601 | 22.3k | memset(outbuf, 0, outlen); |
602 | 22.3k | zero_bits = *in & 0x07; |
603 | 22.3k | in++; |
604 | 22.3k | octets_left = inlen - 1; |
605 | 22.3k | if (outlen < octets_left) |
606 | 48 | return SC_ERROR_BUFFER_TOO_SMALL; |
607 | | |
608 | 386k | while (octets_left) { |
609 | | /* 1st octet of input: ABCDEFGH, where A is the MSB */ |
610 | | /* 1st octet of output: HGFEDCBA, where A is the LSB */ |
611 | | /* first bit in bit string is the LSB in first resulting octet */ |
612 | 367k | int bits_to_go; |
613 | | |
614 | 367k | *out = 0; |
615 | 367k | if (octets_left == 1 && zero_bits > 0) { |
616 | 11.8k | bits_to_go = 8 - zero_bits; |
617 | | /* Verify the padding is zero bits */ |
618 | 11.8k | if (*in & (1 << (zero_bits-1))) { |
619 | 2.59k | return SC_ERROR_INVALID_ASN1_OBJECT; |
620 | 2.59k | } |
621 | 11.8k | } else |
622 | 355k | bits_to_go = 8; |
623 | 364k | if (invert) |
624 | 193k | for (i = 0; i < bits_to_go; i++) { |
625 | 169k | *out |= ((*in >> (7 - i)) & 1) << i; |
626 | 169k | } |
627 | 339k | else { |
628 | 339k | *out = *in; |
629 | 339k | } |
630 | 364k | out++; |
631 | 364k | in++; |
632 | 364k | octets_left--; |
633 | 364k | count++; |
634 | 364k | } |
635 | 19.7k | return (count * 8) - zero_bits; |
636 | 22.3k | } |
637 | | |
638 | | int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen, |
639 | | void *outbuf, size_t outlen, const int strict) |
640 | 17.3k | { |
641 | 17.3k | return decode_bit_string(inbuf, inlen, outbuf, outlen, 1, strict); |
642 | 17.3k | } |
643 | | |
644 | | int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen, |
645 | | void *outbuf, size_t outlen, const int strict) |
646 | 0 | { |
647 | 0 | return decode_bit_string(inbuf, inlen, outbuf, outlen, 0, strict); |
648 | 0 | } |
649 | | |
650 | | static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf, |
651 | | size_t *outlen, int invert) |
652 | 18.4k | { |
653 | 18.4k | const u8 *in = inbuf; |
654 | 18.4k | u8 *out; |
655 | 18.4k | size_t bytes, skipped = 0; |
656 | | |
657 | 18.4k | bytes = BYTES4BITS(bits_left) + 1; |
658 | 18.4k | *outbuf = out = malloc(bytes); |
659 | 18.4k | if (out == NULL) |
660 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
661 | 18.4k | *outlen = bytes; |
662 | 18.4k | out += 1; |
663 | 201k | while (bits_left) { |
664 | 183k | size_t i, bits_to_go = 8; |
665 | | |
666 | 183k | *out = 0; |
667 | 183k | if (bits_left < 8) { |
668 | 14.5k | bits_to_go = bits_left; |
669 | 14.5k | skipped = 8 - bits_left; |
670 | 14.5k | } |
671 | 183k | if (invert) { |
672 | 73.5k | for (i = 0; i < bits_to_go; i++) |
673 | 57.1k | *out |= ((*in >> i) & 1) << (7 - i); |
674 | 167k | } else { |
675 | 167k | *out = *in; |
676 | 167k | if (bits_left < 8) |
677 | 0 | return SC_ERROR_NOT_SUPPORTED; /* FIXME */ |
678 | 167k | } |
679 | 183k | bits_left -= bits_to_go; |
680 | 183k | out++, in++; |
681 | 183k | } |
682 | 18.4k | out = *outbuf; |
683 | 18.4k | out[0] = skipped; |
684 | 18.4k | return 0; |
685 | 18.4k | } |
686 | | |
687 | | /* |
688 | | * Bitfields are just bit strings, stored in an unsigned int |
689 | | * (taking endianness into account) |
690 | | */ |
691 | | static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen, const int strict) |
692 | 6.04k | { |
693 | 6.04k | u8 data[sizeof(unsigned int)]; |
694 | 6.04k | unsigned int field = 0; |
695 | 6.04k | int i, n; |
696 | | |
697 | 6.04k | if (outlen != sizeof(data)) |
698 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
699 | | |
700 | 6.04k | n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1, strict); |
701 | 6.04k | if (n < 0) |
702 | 297 | return n; |
703 | | |
704 | 14.8k | for (i = 0; i < n; i += 8) { |
705 | 9.12k | field |= ((unsigned int) data[i/8] << i); |
706 | 9.12k | } |
707 | 5.74k | memcpy(outbuf, &field, outlen); |
708 | 5.74k | return 0; |
709 | 6.04k | } |
710 | | |
711 | | static int encode_bit_field(const u8 *inbuf, size_t inlen, |
712 | | u8 **outbuf, size_t *outlen) |
713 | 15.6k | { |
714 | 15.6k | u8 data[sizeof(unsigned int)]; |
715 | 15.6k | unsigned int field = 0; |
716 | 15.6k | size_t i, bits; |
717 | | |
718 | 15.6k | if (inlen != sizeof(data)) |
719 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
720 | | |
721 | | /* count the bits */ |
722 | 15.6k | memcpy(&field, inbuf, inlen); |
723 | 72.8k | for (bits = 0; field; bits++) |
724 | 57.1k | field >>= 1; |
725 | | |
726 | 15.6k | memcpy(&field, inbuf, inlen); |
727 | 32.0k | for (i = 0; i < bits; i += 8) |
728 | 16.3k | data[i/8] = field >> i; |
729 | | |
730 | 15.6k | return encode_bit_string(data, bits, outbuf, outlen, 1); |
731 | 15.6k | } |
732 | | |
733 | | int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out, int strict) |
734 | 14.0k | { |
735 | 14.0k | int a = 0, is_negative = 0; |
736 | 14.0k | size_t i = 0; |
737 | | |
738 | 14.0k | if (inlen == 0) { |
739 | 78 | return SC_ERROR_INVALID_ASN1_OBJECT; |
740 | 78 | } |
741 | 14.0k | if (inlen > sizeof(int)) { |
742 | 100 | return SC_ERROR_NOT_SUPPORTED; |
743 | 100 | } |
744 | 13.9k | if (inbuf[0] & 0x80) { |
745 | 4.09k | if (strict && inlen > 1 && inbuf[0] == 0xff && (inbuf[1] & 0x80)) { |
746 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
747 | 0 | } |
748 | 4.09k | is_negative = 1; |
749 | 4.09k | a |= 0xff^(*inbuf++); |
750 | 4.09k | i = 1; |
751 | 9.81k | } else { |
752 | 9.81k | if (strict && inlen > 1 && inbuf[0] == 0x00 && (inbuf[1] & 0x80) == 0) { |
753 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
754 | 0 | } |
755 | 9.81k | } |
756 | 31.0k | for (; i < inlen; i++) { |
757 | 17.1k | if (a > (INT_MAX >> 8) || a < (INT_MIN + (1<<8))) { |
758 | 0 | return SC_ERROR_NOT_SUPPORTED; |
759 | 0 | } |
760 | 17.1k | a <<= 8; |
761 | 17.1k | if (is_negative) { |
762 | 4.11k | a |= 0xff^(*inbuf++); |
763 | 13.0k | } else { |
764 | 13.0k | a |= *inbuf++; |
765 | 13.0k | } |
766 | 17.1k | } |
767 | 13.9k | if (is_negative) { |
768 | | /* Calculate Two's complement from previously positive number */ |
769 | 4.09k | a = (-1 * a) - 1; |
770 | 4.09k | } |
771 | 13.9k | *out = a; |
772 | 13.9k | return 0; |
773 | 13.9k | } |
774 | | |
775 | | static int asn1_encode_integer(int in, u8 ** obj, size_t * objsize) |
776 | 36.0k | { |
777 | 36.0k | int i = sizeof(in) * 8, skip_zero, skip_sign; |
778 | 36.0k | u8 *p, b; |
779 | | |
780 | 36.0k | if (in < 0) |
781 | 439 | { |
782 | 439 | skip_sign = 1; |
783 | 439 | skip_zero= 0; |
784 | 439 | } |
785 | 35.6k | else |
786 | 35.6k | { |
787 | 35.6k | skip_sign = 0; |
788 | 35.6k | skip_zero= 1; |
789 | 35.6k | } |
790 | 36.0k | *obj = p = malloc(sizeof(in)+1); |
791 | 36.0k | if (*obj == NULL) |
792 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
793 | 144k | do { |
794 | 144k | i -= 8; |
795 | 144k | b = in >> i; |
796 | 144k | if (skip_sign) |
797 | 1.60k | { |
798 | 1.60k | if (b != 0xff) |
799 | 243 | skip_sign = 0; |
800 | 1.60k | if (b & 0x80) |
801 | 1.59k | { |
802 | 1.59k | *p = b; |
803 | 1.59k | if (0xff == b) |
804 | 1.36k | continue; |
805 | 1.59k | } |
806 | 16 | else |
807 | 16 | { |
808 | 16 | p++; |
809 | 16 | skip_sign = 0; |
810 | 16 | } |
811 | 1.60k | } |
812 | 143k | if (b == 0 && skip_zero) |
813 | 107k | continue; |
814 | 35.8k | if (skip_zero) { |
815 | 25.3k | skip_zero = 0; |
816 | | /* prepend 0x00 if MSb is 1 and integer positive */ |
817 | 25.3k | if ((b & 0x80) != 0 && in > 0) |
818 | 1.68k | *p++ = 0; |
819 | 25.3k | } |
820 | 35.8k | *p++ = b; |
821 | 144k | } while (i > 0); |
822 | 36.0k | if (skip_sign) |
823 | 196 | p++; |
824 | 36.0k | *objsize = p - *obj; |
825 | 36.0k | if (*objsize == 0) { |
826 | 10.2k | *objsize = 1; |
827 | 10.2k | (*obj)[0] = 0; |
828 | 10.2k | } |
829 | 36.0k | return 0; |
830 | 36.0k | } |
831 | | |
832 | | int |
833 | | sc_asn1_decode_object_id(const u8 *inbuf, size_t inlen, struct sc_object_id *id) |
834 | 64.9k | { |
835 | 64.9k | int large_second_octet = 0; |
836 | 64.9k | unsigned int a = 0; |
837 | 64.9k | const u8 *p = inbuf; |
838 | 64.9k | int *octet; |
839 | | |
840 | 64.9k | if (inlen == 0 || inbuf == NULL || id == NULL) |
841 | 4.41k | return SC_ERROR_INVALID_ARGUMENTS; |
842 | | |
843 | 60.5k | sc_init_oid(id); |
844 | 60.5k | octet = id->value; |
845 | | |
846 | | /* The first octet can be 0, 1 or 2 and is derived from the first byte */ |
847 | 60.5k | a = MIN(*p / 40, 2); |
848 | 60.5k | *octet++ = a; |
849 | | |
850 | | /* The second octet fits here if the previous was 0 or 1 and second one is smaller than 40. |
851 | | * for the value 2 we can go up to 47. Otherwise the first bit needs to be set |
852 | | * and we continue reading further */ |
853 | 60.5k | if ((*p & 0x80) == 0) { |
854 | 49.4k | *octet++ = *p - (a * 40); |
855 | 49.4k | inlen--; |
856 | 49.4k | } else { |
857 | 11.0k | large_second_octet = 1; |
858 | 11.0k | } |
859 | | |
860 | 280k | while (inlen) { |
861 | 235k | if (!large_second_octet) |
862 | 224k | p++; |
863 | | /* This signalizes empty most significant bits, which means |
864 | | * the unsigned integer encoding is not minimal */ |
865 | 235k | if (*p == 0x80) { |
866 | 5.04k | sc_init_oid(id); |
867 | 5.04k | return SC_ERROR_INVALID_ASN1_OBJECT; |
868 | 5.04k | } |
869 | | /* Use unsigned type here so we can process the whole INT range. |
870 | | * Values can not be negative */ |
871 | 230k | a = *p & 0x7F; |
872 | 230k | inlen--; |
873 | 319k | while (inlen && *p & 0x80) { |
874 | | /* Limit the OID values to int size and do not overflow */ |
875 | 91.5k | if (a > (UINT_MAX>>7)) { |
876 | 2.20k | sc_init_oid(id); |
877 | 2.20k | return SC_ERROR_NOT_SUPPORTED; |
878 | 2.20k | } |
879 | 89.3k | p++; |
880 | 89.3k | a <<= 7; |
881 | 89.3k | a |= *p & 0x7F; |
882 | 89.3k | inlen--; |
883 | 89.3k | } |
884 | 228k | if (*p & 0x80) { |
885 | | /* We dropped out from previous cycle on the end of |
886 | | * data while still expecting continuation of value */ |
887 | 5.92k | sc_init_oid(id); |
888 | 5.92k | return SC_ERROR_INVALID_ASN1_OBJECT; |
889 | 5.92k | } |
890 | 222k | if (large_second_octet) { |
891 | 5.90k | a -= (2 * 40); |
892 | 5.90k | } |
893 | 222k | if (a > INT_MAX) { |
894 | 928 | sc_init_oid(id); |
895 | 928 | return SC_ERROR_NOT_SUPPORTED; |
896 | 928 | } |
897 | 221k | *octet++ = a; |
898 | 221k | if (octet - id->value >= SC_MAX_OBJECT_ID_OCTETS) { |
899 | 1.48k | sc_init_oid(id); |
900 | 1.48k | return SC_ERROR_INVALID_ASN1_OBJECT; |
901 | 1.48k | } |
902 | 219k | large_second_octet = 0; |
903 | 219k | } |
904 | | |
905 | 44.9k | return 0; |
906 | 60.5k | } |
907 | | |
908 | | int |
909 | | sc_asn1_encode_object_id(u8 **buf, size_t *buflen, const struct sc_object_id *id) |
910 | 50.7k | { |
911 | 50.7k | u8 temp[SC_MAX_OBJECT_ID_OCTETS*5], *p = temp; |
912 | 50.7k | int i; |
913 | | |
914 | 50.7k | if (!buflen || !id) |
915 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
916 | | |
917 | | /* an OID must have at least two components */ |
918 | 50.7k | if (id->value[0] == -1 || id->value[1] == -1) |
919 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
920 | | |
921 | 408k | for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) { |
922 | 408k | unsigned int k, shift; |
923 | | |
924 | 408k | if (id->value[i] == -1) |
925 | 50.6k | break; |
926 | | |
927 | 357k | k = id->value[i]; |
928 | 357k | switch (i) { |
929 | 50.7k | case 0: |
930 | 50.7k | if (k > 2) |
931 | 19 | return SC_ERROR_INVALID_ARGUMENTS; |
932 | 50.7k | *p = k * 40; |
933 | 50.7k | break; |
934 | 50.7k | case 1: |
935 | 50.7k | if (k > 39 && id->value[0] < 2) { |
936 | 12 | return SC_ERROR_INVALID_ARGUMENTS; |
937 | 12 | } |
938 | | /* We can encode larger IDs to multiple bytes |
939 | | * similarly as the following IDs */ |
940 | 50.7k | k += *p; |
941 | | /* fall through */ |
942 | 306k | default: |
943 | 306k | shift = 28; |
944 | 1.46M | while (shift && (k >> shift) == 0) |
945 | 1.15M | shift -= 7; |
946 | 375k | while (shift) { |
947 | 68.2k | *p++ = 0x80 | ((k >> shift) & 0x7f); |
948 | 68.2k | shift -= 7; |
949 | 68.2k | } |
950 | 306k | *p++ = k & 0x7F; |
951 | 306k | break; |
952 | 357k | } |
953 | 357k | } |
954 | | |
955 | 50.7k | *buflen = p - temp; |
956 | | |
957 | 50.7k | if (buf) { |
958 | 50.7k | *buf = malloc(*buflen); |
959 | 50.7k | if (!*buf) |
960 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
961 | 50.7k | memcpy(*buf, temp, *buflen); |
962 | 50.7k | } |
963 | 50.7k | return 0; |
964 | 50.7k | } |
965 | | |
966 | | static int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen, |
967 | | u8 *out, size_t *outlen) |
968 | 5.60k | { |
969 | 5.60k | if (inlen+1 > *outlen) |
970 | 7 | return SC_ERROR_BUFFER_TOO_SMALL; |
971 | 5.59k | *outlen = inlen+1; |
972 | 5.59k | memcpy(out, inbuf, inlen); |
973 | 5.59k | out[inlen] = 0; |
974 | 5.59k | return 0; |
975 | 5.60k | } |
976 | | |
977 | | /* |
978 | | * This assumes the tag is already encoded |
979 | | */ |
980 | | int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr) |
981 | 106k | { |
982 | 106k | size_t c = 0; |
983 | 106k | unsigned int tag_len, ii; |
984 | 106k | u8 *p = out; |
985 | 106k | u8 tag_char[4] = {0, 0, 0, 0}; |
986 | | |
987 | | /* Check tag */ |
988 | 106k | if (tag == 0 || tag > 0xFFFFFFFF) { |
989 | | /* A tag of 0x00 is not valid and at most 4-byte tag names are supported. */ |
990 | 0 | return SC_ERROR_INVALID_DATA; |
991 | 0 | } |
992 | 212k | for (tag_len = 0; tag; tag >>= 8) { |
993 | | /* Note: tag char will be reversed order. */ |
994 | 106k | tag_char[tag_len++] = tag & 0xFF; |
995 | 106k | } |
996 | | |
997 | 106k | if (tag_len > 1) { |
998 | 0 | if ((tag_char[tag_len - 1] & SC_ASN1_TAG_PRIMITIVE) != SC_ASN1_TAG_ESCAPE_MARKER) { |
999 | | /* First byte is not escape marker. */ |
1000 | 0 | return SC_ERROR_INVALID_DATA; |
1001 | 0 | } |
1002 | 0 | for (ii = 1; ii < tag_len - 1; ii++) { |
1003 | 0 | if ((tag_char[ii] & 0x80) != 0x80) { |
1004 | | /* MS bit is not 'one'. */ |
1005 | 0 | return SC_ERROR_INVALID_DATA; |
1006 | 0 | } |
1007 | 0 | } |
1008 | 0 | if ((tag_char[0] & 0x80) != 0x00) { |
1009 | | /* MS bit of the last byte is not 'zero'. */ |
1010 | 0 | return SC_ERROR_INVALID_DATA; |
1011 | 0 | } |
1012 | 0 | } |
1013 | | |
1014 | | /* Calculate the number of additional bytes necessary to encode the length. */ |
1015 | | /* c+1 is the size of the length field. */ |
1016 | 106k | if (datalen > 127) { |
1017 | 919 | c = 1; |
1018 | 1.48k | while (datalen >> (c << 3)) |
1019 | 568 | c++; |
1020 | 919 | } |
1021 | 106k | if (outlen == 0 || out == NULL) { |
1022 | | /* Caller only asks for the length that would be written. */ |
1023 | 5.37k | return (int)(tag_len + (c + 1) + datalen); |
1024 | 5.37k | } |
1025 | | /* We will write the tag, so check the length. */ |
1026 | 100k | if (outlen < tag_len + (c+1) + datalen) |
1027 | 44 | return SC_ERROR_BUFFER_TOO_SMALL; |
1028 | 201k | for (ii=0;ii<tag_len;ii++) |
1029 | 100k | *p++ = tag_char[tag_len - ii - 1]; |
1030 | | |
1031 | 100k | if (c > 0) { |
1032 | 545 | *p++ = 0x80 | c; |
1033 | 1.41k | while (c--) |
1034 | 872 | *p++ = (datalen >> (c << 3)) & 0xFF; |
1035 | 545 | } |
1036 | 100k | else { |
1037 | 100k | *p++ = datalen & 0x7F; |
1038 | 100k | } |
1039 | 100k | if(data && datalen > 0) { |
1040 | 94.5k | memcpy(p, data, datalen); |
1041 | 94.5k | p += datalen; |
1042 | 94.5k | } |
1043 | 100k | if (ptr != NULL) |
1044 | 100k | *ptr = p; |
1045 | 100k | return 0; |
1046 | 100k | } |
1047 | | |
1048 | | int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag, |
1049 | | const u8 * data, size_t datalen, u8 ** out, size_t * outlen) |
1050 | 0 | { |
1051 | 0 | return asn1_write_element(ctx, tag, data, datalen, out, outlen); |
1052 | 0 | } |
1053 | | |
1054 | | static int asn1_write_element(sc_context_t *ctx, unsigned int tag, |
1055 | | const u8 * data, size_t datalen, u8 ** out, size_t * outlen) |
1056 | 391k | { |
1057 | 391k | unsigned char t; |
1058 | 391k | unsigned char *buf, *p; |
1059 | 391k | int c = 0; |
1060 | 391k | unsigned short_tag; |
1061 | 391k | unsigned char tag_char[3] = {0, 0, 0}; |
1062 | 391k | size_t tag_len, ii; |
1063 | | |
1064 | 391k | short_tag = tag & SC_ASN1_TAG_MASK; |
1065 | 776k | for (tag_len = 0; short_tag >> (8 * tag_len); tag_len++) |
1066 | 384k | tag_char[tag_len] = (short_tag >> (8 * tag_len)) & 0xFF; |
1067 | 391k | if (!tag_len) |
1068 | 10.7k | tag_len = 1; |
1069 | | |
1070 | 391k | if (tag_len > 1) { |
1071 | 3.37k | if ((tag_char[tag_len - 1] & SC_ASN1_TAG_PRIMITIVE) != SC_ASN1_TAG_ESCAPE_MARKER) |
1072 | 0 | SC_TEST_RET(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_INVALID_DATA, "First byte of the long tag is not 'escape marker'"); |
1073 | | |
1074 | 3.37k | for (ii = 1; ii < tag_len - 1; ii++) |
1075 | 0 | if (!(tag_char[ii] & 0x80)) |
1076 | 0 | SC_TEST_RET(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_INVALID_DATA, "MS bit expected to be 'one'"); |
1077 | | |
1078 | 3.37k | if (tag_char[0] & 0x80) |
1079 | 0 | SC_TEST_RET(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_INVALID_DATA, "MS bit of the last byte expected to be 'zero'"); |
1080 | 3.37k | } |
1081 | | |
1082 | 391k | t = tag_char[tag_len - 1] & 0x1F; |
1083 | | |
1084 | 391k | switch (tag & SC_ASN1_CLASS_MASK) { |
1085 | 290k | case SC_ASN1_UNI: |
1086 | 290k | break; |
1087 | 63.4k | case SC_ASN1_APP: |
1088 | 63.4k | t |= SC_ASN1_TAG_APPLICATION; |
1089 | 63.4k | break; |
1090 | 37.8k | case SC_ASN1_CTX: |
1091 | 37.8k | t |= SC_ASN1_TAG_CONTEXT; |
1092 | 37.8k | break; |
1093 | 0 | case SC_ASN1_PRV: |
1094 | 0 | t |= SC_ASN1_TAG_PRIVATE; |
1095 | 0 | break; |
1096 | 391k | } |
1097 | 391k | if (tag & SC_ASN1_CONS) |
1098 | 140k | t |= SC_ASN1_TAG_CONSTRUCTED; |
1099 | 391k | if (datalen > 127) { |
1100 | 5.99k | c = 1; |
1101 | 8.05k | while (datalen >> (c << 3)) |
1102 | 2.05k | c++; |
1103 | 5.99k | } |
1104 | | |
1105 | 391k | *outlen = tag_len + 1 + c + datalen; |
1106 | 391k | buf = malloc(*outlen); |
1107 | 391k | if (buf == NULL) |
1108 | 0 | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_OUT_OF_MEMORY); |
1109 | | |
1110 | 391k | *out = p = buf; |
1111 | 391k | *p++ = t; |
1112 | 395k | for (ii=1;ii<tag_len;ii++) |
1113 | 3.37k | *p++ = tag_char[tag_len - ii - 1]; |
1114 | | |
1115 | 391k | if (c) { |
1116 | 5.99k | *p++ = 0x80 | c; |
1117 | 14.0k | while (c--) |
1118 | 8.05k | *p++ = (datalen >> (c << 3)) & 0xFF; |
1119 | 5.99k | } |
1120 | 385k | else { |
1121 | 385k | *p++ = datalen & 0x7F; |
1122 | 385k | } |
1123 | 391k | if (datalen && data) { |
1124 | 388k | memcpy(p, data, datalen); |
1125 | 388k | } |
1126 | | |
1127 | 391k | return SC_SUCCESS; |
1128 | 391k | } |
1129 | | |
1130 | | static const struct sc_asn1_entry c_asn1_path_ext[3] = { |
1131 | | { "aid", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 0x0F, 0, NULL, NULL }, |
1132 | | { "path", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL }, |
1133 | | { NULL, 0, 0, 0, NULL, NULL } |
1134 | | }; |
1135 | | static const struct sc_asn1_entry c_asn1_path[5] = { |
1136 | | { "path", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1137 | | { "index", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
1138 | | { "length", SC_ASN1_INTEGER, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL, NULL }, |
1139 | | /* For some multi-applications PKCS#15 card the ODF records can hold the references to |
1140 | | * the xDF files and objects placed elsewhere then under the application DF of the ODF itself. |
1141 | | * In such a case the 'path' ASN1 data includes also the ID of the target application (AID). |
1142 | | * This path extension do not make a part of PKCS#15 standard. |
1143 | | */ |
1144 | | { "pathExtended", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1145 | | { NULL, 0, 0, 0, NULL, NULL } |
1146 | | }; |
1147 | | |
1148 | | static int asn1_decode_path(sc_context_t *ctx, const u8 *in, size_t len, |
1149 | | sc_path_t *path, int depth) |
1150 | 15.4k | { |
1151 | 15.4k | int idx, count, r; |
1152 | 15.4k | struct sc_asn1_entry asn1_path_ext[3], asn1_path[5]; |
1153 | 15.4k | unsigned char path_value[SC_MAX_PATH_SIZE], aid_value[SC_MAX_AID_SIZE]; |
1154 | 15.4k | size_t path_len = sizeof(path_value), aid_len = sizeof(aid_value); |
1155 | | |
1156 | 15.4k | memset(path, 0, sizeof(struct sc_path)); |
1157 | | |
1158 | 15.4k | sc_copy_asn1_entry(c_asn1_path_ext, asn1_path_ext); |
1159 | 15.4k | sc_copy_asn1_entry(c_asn1_path, asn1_path); |
1160 | | |
1161 | 15.4k | sc_format_asn1_entry(asn1_path_ext + 0, aid_value, &aid_len, 0); |
1162 | 15.4k | sc_format_asn1_entry(asn1_path_ext + 1, path_value, &path_len, 0); |
1163 | | |
1164 | 15.4k | sc_format_asn1_entry(asn1_path + 0, path_value, &path_len, 0); |
1165 | 15.4k | sc_format_asn1_entry(asn1_path + 1, &idx, NULL, 0); |
1166 | 15.4k | sc_format_asn1_entry(asn1_path + 2, &count, NULL, 0); |
1167 | 15.4k | sc_format_asn1_entry(asn1_path + 3, asn1_path_ext, NULL, 0); |
1168 | | |
1169 | 15.4k | r = asn1_decode(ctx, asn1_path, in, len, NULL, NULL, 0, depth + 1); |
1170 | 15.4k | if (r) |
1171 | 168 | return r; |
1172 | | |
1173 | 15.2k | if (asn1_path[3].flags & SC_ASN1_PRESENT) { |
1174 | | /* extended path present: set 'path' and 'aid' */ |
1175 | 0 | memcpy(path->aid.value, aid_value, aid_len); |
1176 | 0 | path->aid.len = aid_len; |
1177 | |
|
1178 | 0 | memcpy(path->value, path_value, path_len); |
1179 | 0 | path->len = path_len; |
1180 | 0 | } |
1181 | 15.2k | else if (asn1_path[0].flags & SC_ASN1_PRESENT) { |
1182 | | /* path present: set 'path' */ |
1183 | 14.6k | memcpy(path->value, path_value, path_len); |
1184 | 14.6k | path->len = path_len; |
1185 | 14.6k | } |
1186 | 643 | else { |
1187 | | /* failed if both 'path' and 'pathExtended' are absent */ |
1188 | 643 | return SC_ERROR_ASN1_OBJECT_NOT_FOUND; |
1189 | 643 | } |
1190 | | |
1191 | 14.6k | if (path->len == 2) |
1192 | 2.25k | path->type = SC_PATH_TYPE_FILE_ID; |
1193 | 12.3k | else if (path->aid.len && path->len > 2) |
1194 | 0 | path->type = SC_PATH_TYPE_FROM_CURRENT; |
1195 | 12.3k | else |
1196 | 12.3k | path->type = SC_PATH_TYPE_PATH; |
1197 | | |
1198 | 14.6k | if ((asn1_path[1].flags & SC_ASN1_PRESENT) && (asn1_path[2].flags & SC_ASN1_PRESENT)) { |
1199 | 176 | path->index = idx; |
1200 | 176 | path->count = count; |
1201 | 176 | } |
1202 | 14.4k | else { |
1203 | 14.4k | path->index = 0; |
1204 | 14.4k | path->count = -1; |
1205 | 14.4k | } |
1206 | | |
1207 | 14.6k | return SC_SUCCESS; |
1208 | 15.2k | } |
1209 | | |
1210 | | static int asn1_encode_path(sc_context_t *ctx, const sc_path_t *path, |
1211 | | u8 **buf, size_t *bufsize, int depth, unsigned int parent_flags) |
1212 | 25.3k | { |
1213 | 25.3k | int r; |
1214 | 25.3k | struct sc_asn1_entry asn1_path[5]; |
1215 | 25.3k | sc_path_t tpath = *path; |
1216 | | |
1217 | 25.3k | sc_copy_asn1_entry(c_asn1_path, asn1_path); |
1218 | 25.3k | sc_format_asn1_entry(asn1_path + 0, (void *) &tpath.value, (void *) &tpath.len, 1); |
1219 | | |
1220 | 25.3k | asn1_path[0].flags |= parent_flags; |
1221 | 25.3k | if (path->count > 0) { |
1222 | 5.29k | sc_format_asn1_entry(asn1_path + 1, (void *) &tpath.index, NULL, 1); |
1223 | 5.29k | sc_format_asn1_entry(asn1_path + 2, (void *) &tpath.count, NULL, 1); |
1224 | 5.29k | } |
1225 | 25.3k | r = asn1_encode(ctx, asn1_path, buf, bufsize, depth + 1); |
1226 | 25.3k | return r; |
1227 | 25.3k | } |
1228 | | |
1229 | | |
1230 | | static const struct sc_asn1_entry c_asn1_se[2] = { |
1231 | | { "seInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
1232 | | { NULL, 0, 0, 0, NULL, NULL } |
1233 | | }; |
1234 | | |
1235 | | static const struct sc_asn1_entry c_asn1_se_info[4] = { |
1236 | | { "se", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, |
1237 | | { "owner",SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL }, |
1238 | | { "aid", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1239 | | { NULL, 0, 0, 0, NULL, NULL } |
1240 | | }; |
1241 | | |
1242 | | static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen, |
1243 | | sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth) |
1244 | 122 | { |
1245 | 122 | struct sc_pkcs15_sec_env_info **ses; |
1246 | 122 | const unsigned char *ptr = obj; |
1247 | 122 | size_t idx, ptrlen = objlen; |
1248 | 122 | int ret; |
1249 | | |
1250 | 122 | LOG_FUNC_CALLED(ctx); |
1251 | | |
1252 | 122 | ses = calloc(SC_MAX_SE_NUM, sizeof(sc_pkcs15_sec_env_info_t *)); |
1253 | 122 | if (ses == NULL) { |
1254 | 0 | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_OUT_OF_MEMORY); |
1255 | 0 | } |
1256 | | |
1257 | 189 | for (idx=0; idx < SC_MAX_SE_NUM && ptrlen; ) { |
1258 | 97 | struct sc_asn1_entry asn1_se[2]; |
1259 | 97 | struct sc_asn1_entry asn1_se_info[4]; |
1260 | 97 | struct sc_pkcs15_sec_env_info si; |
1261 | | |
1262 | 97 | sc_copy_asn1_entry(c_asn1_se, asn1_se); |
1263 | 97 | sc_copy_asn1_entry(c_asn1_se_info, asn1_se_info); |
1264 | | |
1265 | 97 | si.aid.len = sizeof(si.aid.value); |
1266 | 97 | sc_format_asn1_entry(asn1_se_info + 0, &si.se, NULL, 0); |
1267 | 97 | sc_format_asn1_entry(asn1_se_info + 1, &si.owner, NULL, 0); |
1268 | 97 | sc_format_asn1_entry(asn1_se_info + 2, &si.aid.value, &si.aid.len, 0); |
1269 | 97 | sc_format_asn1_entry(asn1_se + 0, asn1_se_info, NULL, 0); |
1270 | | |
1271 | 97 | ret = asn1_decode(ctx, asn1_se, ptr, ptrlen, &ptr, &ptrlen, 0, depth+1); |
1272 | 97 | if (ret != SC_SUCCESS) |
1273 | 30 | goto err; |
1274 | 67 | if (!(asn1_se_info[1].flags & SC_ASN1_PRESENT)) |
1275 | 37 | sc_init_oid(&si.owner); |
1276 | | |
1277 | 67 | ses[idx] = calloc(1, sizeof(sc_pkcs15_sec_env_info_t)); |
1278 | 67 | if (ses[idx] == NULL) { |
1279 | 0 | ret = SC_ERROR_OUT_OF_MEMORY; |
1280 | 0 | goto err; |
1281 | 0 | } |
1282 | | |
1283 | 67 | memcpy(ses[idx], &si, sizeof(struct sc_pkcs15_sec_env_info)); |
1284 | 67 | idx++; |
1285 | 67 | } |
1286 | | |
1287 | 92 | *se = ses; |
1288 | 92 | *num = idx; |
1289 | 92 | ret = SC_SUCCESS; |
1290 | 122 | err: |
1291 | 122 | if (ret != SC_SUCCESS) { |
1292 | 30 | size_t i; |
1293 | 52 | for (i = 0; i < idx; i++) |
1294 | 22 | if (ses[i]) |
1295 | 22 | free(ses[i]); |
1296 | 30 | free(ses); |
1297 | 30 | } |
1298 | | |
1299 | 122 | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, ret); |
1300 | 122 | } |
1301 | | |
1302 | | |
1303 | | static int asn1_encode_se_info(sc_context_t *ctx, |
1304 | | struct sc_pkcs15_sec_env_info **se, size_t se_num, |
1305 | | unsigned char **buf, size_t *bufsize, int depth) |
1306 | 9 | { |
1307 | 9 | unsigned char *ptr = NULL, *out = NULL, *p; |
1308 | 9 | size_t ptrlen = 0, outlen = 0, idx; |
1309 | 9 | int ret; |
1310 | | |
1311 | 41 | for (idx=0; idx < se_num; idx++) { |
1312 | 32 | struct sc_asn1_entry asn1_se[2]; |
1313 | 32 | struct sc_asn1_entry asn1_se_info[4]; |
1314 | | |
1315 | 32 | sc_copy_asn1_entry(c_asn1_se, asn1_se); |
1316 | 32 | sc_copy_asn1_entry(c_asn1_se_info, asn1_se_info); |
1317 | | |
1318 | 32 | sc_format_asn1_entry(asn1_se_info + 0, &se[idx]->se, NULL, 1); |
1319 | 32 | if (sc_valid_oid(&se[idx]->owner)) |
1320 | 13 | sc_format_asn1_entry(asn1_se_info + 1, &se[idx]->owner, NULL, 1); |
1321 | 32 | if (se[idx]->aid.len) |
1322 | 18 | sc_format_asn1_entry(asn1_se_info + 2, &se[idx]->aid.value, &se[idx]->aid.len, 1); |
1323 | 32 | sc_format_asn1_entry(asn1_se + 0, asn1_se_info, NULL, 1); |
1324 | | |
1325 | 32 | ret = sc_asn1_encode(ctx, asn1_se, &ptr, &ptrlen); |
1326 | 32 | if (ret != SC_SUCCESS) |
1327 | 0 | goto err; |
1328 | | |
1329 | 32 | if (!ptrlen) |
1330 | 0 | continue; |
1331 | 32 | p = (unsigned char *) realloc(out, outlen + ptrlen); |
1332 | 32 | if (!p) { |
1333 | 0 | ret = SC_ERROR_OUT_OF_MEMORY; |
1334 | 0 | goto err; |
1335 | 0 | } |
1336 | 32 | out = p; |
1337 | 32 | memcpy(out + outlen, ptr, ptrlen); |
1338 | 32 | outlen += ptrlen; |
1339 | 32 | free(ptr); |
1340 | 32 | ptr = NULL; |
1341 | 32 | ptrlen = 0; |
1342 | 32 | } |
1343 | | |
1344 | 9 | *buf = out; |
1345 | 9 | *bufsize = outlen; |
1346 | 9 | ret = SC_SUCCESS; |
1347 | 9 | err: |
1348 | 9 | if (ret != SC_SUCCESS && out != NULL) |
1349 | 0 | free(out); |
1350 | 9 | return ret; |
1351 | 9 | } |
1352 | | |
1353 | | /* TODO: According to specification type of 'SecurityCondition' is 'CHOICE'. |
1354 | | * Do it at least for SC_ASN1_PKCS15_ID(authId), SC_ASN1_STRUCT(authReference) and NULL(always). */ |
1355 | | static const struct sc_asn1_entry c_asn1_access_control_rule[3] = { |
1356 | | { "accessMode", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1357 | | { "securityCondition", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1358 | | { NULL, 0, 0, 0, NULL, NULL } |
1359 | | }; |
1360 | | |
1361 | | /* |
1362 | | * in src/libopensc/pkcs15.h SC_PKCS15_MAX_ACCESS_RULES defined as 8 |
1363 | | */ |
1364 | | static const struct sc_asn1_entry c_asn1_access_control_rules[SC_PKCS15_MAX_ACCESS_RULES + 1] = { |
1365 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1366 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1367 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1368 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1369 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1370 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1371 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1372 | | { "accessControlRule", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1373 | | { NULL, 0, 0, 0, NULL, NULL } |
1374 | | }; |
1375 | | |
1376 | | static const struct sc_asn1_entry c_asn1_com_obj_attr[6] = { |
1377 | | { "label", SC_ASN1_UTF8STRING, SC_ASN1_TAG_UTF8STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1378 | | { "flags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1379 | | { "authId", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
1380 | | { "userConsent", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
1381 | | { "accessControlRules", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1382 | | { NULL, 0, 0, 0, NULL, NULL } |
1383 | | }; |
1384 | | |
1385 | | static const struct sc_asn1_entry c_asn1_p15_obj[5] = { |
1386 | | { "commonObjectAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
1387 | | { "classAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
1388 | | { "subClassAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
1389 | | { "typeAttributes", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, NULL, NULL }, |
1390 | | { NULL, 0, 0, 0, NULL, NULL } |
1391 | | }; |
1392 | | |
1393 | | static int asn1_decode_p15_object(sc_context_t *ctx, const u8 *in, |
1394 | | size_t len, struct sc_asn1_pkcs15_object *obj, |
1395 | | int depth) |
1396 | 4.32k | { |
1397 | 4.32k | struct sc_pkcs15_object *p15_obj = obj->p15_obj; |
1398 | 4.32k | struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5]; |
1399 | 4.32k | struct sc_asn1_entry asn1_ac_rules[SC_PKCS15_MAX_ACCESS_RULES + 1], asn1_ac_rule[SC_PKCS15_MAX_ACCESS_RULES][3]; |
1400 | 4.32k | size_t flags_len = sizeof(p15_obj->flags); |
1401 | 4.32k | size_t label_len = sizeof(p15_obj->label); |
1402 | 4.32k | size_t access_mode_len = sizeof(p15_obj->access_rules[0].access_mode); |
1403 | 4.32k | int r, ii; |
1404 | | |
1405 | 38.9k | for (ii=0; ii<SC_PKCS15_MAX_ACCESS_RULES; ii++) |
1406 | 34.6k | sc_copy_asn1_entry(c_asn1_access_control_rule, asn1_ac_rule[ii]); |
1407 | 4.32k | sc_copy_asn1_entry(c_asn1_access_control_rules, asn1_ac_rules); |
1408 | | |
1409 | | |
1410 | 4.32k | sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr); |
1411 | 4.32k | sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj); |
1412 | 4.32k | sc_format_asn1_entry(asn1_c_attr + 0, p15_obj->label, &label_len, 0); |
1413 | 4.32k | sc_format_asn1_entry(asn1_c_attr + 1, &p15_obj->flags, &flags_len, 0); |
1414 | 4.32k | sc_format_asn1_entry(asn1_c_attr + 2, &p15_obj->auth_id, NULL, 0); |
1415 | 4.32k | sc_format_asn1_entry(asn1_c_attr + 3, &p15_obj->user_consent, NULL, 0); |
1416 | | |
1417 | 38.9k | for (ii=0; ii<SC_PKCS15_MAX_ACCESS_RULES; ii++) { |
1418 | 34.6k | sc_format_asn1_entry(asn1_ac_rule[ii] + 0, &p15_obj->access_rules[ii].access_mode, &access_mode_len, 0); |
1419 | 34.6k | sc_format_asn1_entry(asn1_ac_rule[ii] + 1, &p15_obj->access_rules[ii].auth_id, NULL, 0); |
1420 | 34.6k | sc_format_asn1_entry(asn1_ac_rules + ii, asn1_ac_rule[ii], NULL, 0); |
1421 | 34.6k | } |
1422 | 4.32k | sc_format_asn1_entry(asn1_c_attr + 4, asn1_ac_rules, NULL, 0); |
1423 | | |
1424 | 4.32k | sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 0); |
1425 | 4.32k | sc_format_asn1_entry(asn1_p15_obj + 1, obj->asn1_class_attr, NULL, 0); |
1426 | 4.32k | sc_format_asn1_entry(asn1_p15_obj + 2, obj->asn1_subclass_attr, NULL, 0); |
1427 | 4.32k | sc_format_asn1_entry(asn1_p15_obj + 3, obj->asn1_type_attr, NULL, 0); |
1428 | | |
1429 | 4.32k | r = asn1_decode(ctx, asn1_p15_obj, in, len, NULL, NULL, 0, depth + 1); |
1430 | 4.32k | return r; |
1431 | 4.32k | } |
1432 | | |
1433 | | static int asn1_encode_p15_object(sc_context_t *ctx, const struct sc_asn1_pkcs15_object *obj, |
1434 | | u8 **buf, size_t *bufsize, int depth) |
1435 | 20.8k | { |
1436 | 20.8k | struct sc_pkcs15_object p15_obj = *obj->p15_obj; |
1437 | 20.8k | struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5]; |
1438 | 20.8k | struct sc_asn1_entry asn1_ac_rules[SC_PKCS15_MAX_ACCESS_RULES + 1], asn1_ac_rule[SC_PKCS15_MAX_ACCESS_RULES][3]; |
1439 | 20.8k | size_t label_len = strlen(p15_obj.label); |
1440 | 20.8k | size_t flags_len; |
1441 | 20.8k | size_t access_mode_len; |
1442 | 20.8k | int r, ii; |
1443 | | |
1444 | 20.8k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "encode p15 obj(type:0x%X,access_mode:0x%X)", p15_obj.type, p15_obj.access_rules[0].access_mode); |
1445 | 20.8k | if (p15_obj.access_rules[0].access_mode) { |
1446 | 0 | for (ii=0; ii<SC_PKCS15_MAX_ACCESS_RULES; ii++) { |
1447 | 0 | sc_copy_asn1_entry(c_asn1_access_control_rule, asn1_ac_rule[ii]); |
1448 | 0 | if (p15_obj.access_rules[ii].auth_id.len == 0) { |
1449 | 0 | asn1_ac_rule[ii][1].type = SC_ASN1_NULL; |
1450 | 0 | asn1_ac_rule[ii][1].tag = SC_ASN1_TAG_NULL; |
1451 | 0 | } |
1452 | 0 | } |
1453 | 0 | sc_copy_asn1_entry(c_asn1_access_control_rules, asn1_ac_rules); |
1454 | 0 | } |
1455 | | |
1456 | 20.8k | sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr); |
1457 | 20.8k | sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj); |
1458 | 20.8k | if (label_len != 0) |
1459 | 19.2k | sc_format_asn1_entry(asn1_c_attr + 0, (void *) p15_obj.label, &label_len, 1); |
1460 | 20.8k | if (p15_obj.flags) { |
1461 | 7.21k | flags_len = sizeof(p15_obj.flags); |
1462 | 7.21k | sc_format_asn1_entry(asn1_c_attr + 1, (void *) &p15_obj.flags, &flags_len, 1); |
1463 | 7.21k | } |
1464 | 20.8k | if (p15_obj.auth_id.len) |
1465 | 2.98k | sc_format_asn1_entry(asn1_c_attr + 2, (void *) &p15_obj.auth_id, NULL, 1); |
1466 | 20.8k | if (p15_obj.user_consent) |
1467 | 73 | sc_format_asn1_entry(asn1_c_attr + 3, (void *) &p15_obj.user_consent, NULL, 1); |
1468 | | |
1469 | 20.8k | if (p15_obj.access_rules[0].access_mode) { |
1470 | 0 | for (ii=0; p15_obj.access_rules[ii].access_mode; ii++) { |
1471 | 0 | access_mode_len = sizeof(p15_obj.access_rules[ii].access_mode); |
1472 | 0 | sc_format_asn1_entry(asn1_ac_rule[ii] + 0, (void *) &p15_obj.access_rules[ii].access_mode, &access_mode_len, 1); |
1473 | 0 | sc_format_asn1_entry(asn1_ac_rule[ii] + 1, (void *) &p15_obj.access_rules[ii].auth_id, NULL, 1); |
1474 | 0 | sc_format_asn1_entry(asn1_ac_rules + ii, asn1_ac_rule[ii], NULL, 1); |
1475 | 0 | } |
1476 | 0 | sc_format_asn1_entry(asn1_c_attr + 4, asn1_ac_rules, NULL, 1); |
1477 | 0 | } |
1478 | | |
1479 | 20.8k | sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 1); |
1480 | 20.8k | sc_format_asn1_entry(asn1_p15_obj + 1, obj->asn1_class_attr, NULL, 1); |
1481 | 20.8k | if (obj->asn1_subclass_attr != NULL && obj->asn1_subclass_attr->name) |
1482 | 70 | sc_format_asn1_entry(asn1_p15_obj + 2, obj->asn1_subclass_attr, NULL, 1); |
1483 | 20.8k | sc_format_asn1_entry(asn1_p15_obj + 3, obj->asn1_type_attr, NULL, 1); |
1484 | | |
1485 | 20.8k | r = asn1_encode(ctx, asn1_p15_obj, buf, bufsize, depth + 1); |
1486 | 20.8k | return r; |
1487 | 20.8k | } |
1488 | | |
1489 | | static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry, |
1490 | | const u8 *obj, size_t objlen, int depth) |
1491 | 222k | { |
1492 | 222k | void *parm = entry->parm; |
1493 | 222k | int (*callback_func)(sc_context_t *nctx, void *arg, const u8 *nobj, |
1494 | 222k | size_t nobjlen, int ndepth); |
1495 | 222k | size_t *len = (size_t *) entry->arg; |
1496 | 222k | int r = 0; |
1497 | | |
1498 | 222k | callback_func = parm; |
1499 | | |
1500 | 222k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "%*.*sdecoding '%s', raw data:%s%s\n", |
1501 | 222k | depth, depth, "", entry->name, |
1502 | 222k | sc_dump_hex(obj, objlen > 16 ? 16 : objlen), |
1503 | 222k | objlen > 16 ? "..." : ""); |
1504 | | |
1505 | 222k | switch (entry->type) { |
1506 | 56.8k | case SC_ASN1_STRUCT: |
1507 | 56.8k | if (parm != NULL) |
1508 | 46.0k | r = asn1_decode(ctx, (struct sc_asn1_entry *) parm, obj, |
1509 | 46.0k | objlen, NULL, NULL, 0, depth + 1); |
1510 | 56.8k | break; |
1511 | 3.20k | case SC_ASN1_NULL: |
1512 | 3.20k | break; |
1513 | 158 | case SC_ASN1_BOOLEAN: |
1514 | 158 | if (parm != NULL) { |
1515 | 158 | if (objlen != 1) { |
1516 | 19 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
1517 | 19 | "invalid ASN.1 object length: %"SC_FORMAT_LEN_SIZE_T"u\n", |
1518 | 19 | objlen); |
1519 | 19 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
1520 | 19 | } else |
1521 | 139 | *((int *) parm) = obj[0] ? 1 : 0; |
1522 | 158 | } |
1523 | 158 | break; |
1524 | 13.8k | case SC_ASN1_INTEGER: |
1525 | 14.0k | case SC_ASN1_ENUMERATED: |
1526 | 14.0k | if (parm != NULL) { |
1527 | 14.0k | r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm, 0); |
1528 | 14.0k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "%*.*sdecoding '%s' returned %d\n", depth, depth, "", |
1529 | 14.0k | entry->name, *((int *) entry->parm)); |
1530 | 14.0k | } |
1531 | 14.0k | break; |
1532 | 4.99k | case SC_ASN1_BIT_STRING_NI: |
1533 | 9.05k | case SC_ASN1_BIT_STRING: |
1534 | 9.05k | if (parm != NULL) { |
1535 | 4.99k | int invert = entry->type == SC_ASN1_BIT_STRING ? 1 : 0; |
1536 | 4.99k | assert(len != NULL); |
1537 | 4.99k | if (objlen < 1) { |
1538 | 56 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
1539 | 56 | break; |
1540 | 56 | } |
1541 | 4.93k | if (entry->flags & SC_ASN1_ALLOC) { |
1542 | 4.93k | u8 **buf = (u8 **) parm; |
1543 | 4.93k | if (objlen > 1) { |
1544 | 4.76k | *buf = malloc(objlen-1); |
1545 | 4.76k | if (*buf == NULL) { |
1546 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1547 | 0 | break; |
1548 | 0 | } |
1549 | 4.76k | } |
1550 | 4.93k | *len = objlen-1; |
1551 | 4.93k | parm = *buf; |
1552 | 4.93k | } |
1553 | 4.93k | r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert, 0); |
1554 | 4.93k | if (r >= 0) { |
1555 | 4.81k | *len = r; |
1556 | 4.81k | r = 0; |
1557 | 4.81k | } |
1558 | 4.93k | } |
1559 | 8.99k | break; |
1560 | 8.99k | case SC_ASN1_BIT_FIELD: |
1561 | 6.04k | if (parm != NULL) |
1562 | 6.04k | r = decode_bit_field(obj, objlen, (u8 *) parm, *len, 0); |
1563 | 6.04k | break; |
1564 | 72.8k | case SC_ASN1_OCTET_STRING: |
1565 | 72.8k | if (parm != NULL) { |
1566 | 72.4k | size_t c; |
1567 | 72.4k | assert(len != NULL); |
1568 | | |
1569 | | /* Strip off padding zero */ |
1570 | 72.4k | if ((entry->flags & SC_ASN1_UNSIGNED) |
1571 | 72.4k | && objlen > 1 && obj[0] == 0x00) { |
1572 | 5.46k | objlen--; |
1573 | 5.46k | obj++; |
1574 | 5.46k | } |
1575 | | |
1576 | | /* Allocate buffer if needed */ |
1577 | 72.4k | if (entry->flags & SC_ASN1_ALLOC) { |
1578 | 32.3k | u8 **buf = (u8 **) parm; |
1579 | 32.3k | if (objlen > 0) { |
1580 | 28.4k | *buf = malloc(objlen); |
1581 | 28.4k | if (*buf == NULL) { |
1582 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1583 | 0 | break; |
1584 | 0 | } |
1585 | 28.4k | } |
1586 | 32.3k | c = *len = objlen; |
1587 | 32.3k | parm = *buf; |
1588 | 32.3k | } else |
1589 | 40.0k | c = objlen > *len ? *len : objlen; |
1590 | | |
1591 | 72.4k | memcpy(parm, obj, c); |
1592 | 72.4k | *len = c; |
1593 | 72.4k | } |
1594 | 72.8k | break; |
1595 | 72.8k | case SC_ASN1_GENERALIZEDTIME: |
1596 | 98 | if (parm != NULL) { |
1597 | 86 | size_t c; |
1598 | 86 | assert(len != NULL); |
1599 | 86 | if (entry->flags & SC_ASN1_ALLOC) { |
1600 | 0 | u8 **buf = (u8 **) parm; |
1601 | 0 | if (objlen > 0) { |
1602 | 0 | *buf = malloc(objlen); |
1603 | 0 | if (*buf == NULL) { |
1604 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1605 | 0 | break; |
1606 | 0 | } |
1607 | 0 | } |
1608 | 0 | c = *len = objlen; |
1609 | 0 | parm = *buf; |
1610 | 0 | } else |
1611 | 86 | c = objlen > *len ? *len : objlen; |
1612 | | |
1613 | 86 | memcpy(parm, obj, c); |
1614 | 86 | *len = c; |
1615 | 86 | } |
1616 | 98 | break; |
1617 | 16.7k | case SC_ASN1_OBJECT: |
1618 | 16.7k | if (parm != NULL) |
1619 | 16.6k | r = sc_asn1_decode_object_id(obj, objlen, (struct sc_object_id *) parm); |
1620 | 16.7k | break; |
1621 | 31 | case SC_ASN1_PRINTABLESTRING: |
1622 | 5.62k | case SC_ASN1_UTF8STRING: |
1623 | 5.62k | if (parm != NULL) { |
1624 | 5.60k | assert(len != NULL); |
1625 | 5.60k | if (entry->flags & SC_ASN1_ALLOC) { |
1626 | 0 | u8 **buf = (u8 **) parm; |
1627 | 0 | *buf = malloc(objlen+1); |
1628 | 0 | if (*buf == NULL) { |
1629 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1630 | 0 | break; |
1631 | 0 | } |
1632 | 0 | *len = objlen+1; |
1633 | 0 | parm = *buf; |
1634 | 0 | } |
1635 | 5.60k | r = sc_asn1_decode_utf8string(obj, objlen, (u8 *) parm, len); |
1636 | 5.60k | if (entry->flags & SC_ASN1_ALLOC) { |
1637 | 0 | *len -= 1; |
1638 | 0 | } |
1639 | 5.60k | } |
1640 | 5.62k | break; |
1641 | 15.5k | case SC_ASN1_PATH: |
1642 | 15.5k | if (entry->parm != NULL) |
1643 | 15.4k | r = asn1_decode_path(ctx, obj, objlen, (sc_path_t *) parm, depth); |
1644 | 15.5k | break; |
1645 | 2.92k | case SC_ASN1_PKCS15_ID: |
1646 | 2.92k | if (entry->parm != NULL) { |
1647 | 2.92k | struct sc_pkcs15_id *id = (struct sc_pkcs15_id *) parm; |
1648 | 2.92k | size_t c = objlen > sizeof(id->value) ? sizeof(id->value) : objlen; |
1649 | | |
1650 | 2.92k | memcpy(id->value, obj, c); |
1651 | 2.92k | id->len = c; |
1652 | 2.92k | } |
1653 | 2.92k | break; |
1654 | 4.36k | case SC_ASN1_PKCS15_OBJECT: |
1655 | 4.36k | if (entry->parm != NULL) |
1656 | 4.32k | r = asn1_decode_p15_object(ctx, obj, objlen, (struct sc_asn1_pkcs15_object *) parm, depth); |
1657 | 4.36k | break; |
1658 | 9.43k | case SC_ASN1_ALGORITHM_ID: |
1659 | 9.43k | if (entry->parm != NULL) |
1660 | 9.43k | r = sc_asn1_decode_algorithm_id(ctx, obj, objlen, (struct sc_algorithm_id *) parm, depth); |
1661 | 9.43k | break; |
1662 | 122 | case SC_ASN1_SE_INFO: |
1663 | 122 | if (entry->parm != NULL) |
1664 | 122 | r = asn1_decode_se_info(ctx, obj, objlen, (sc_pkcs15_sec_env_info_t ***)entry->parm, len, depth); |
1665 | 122 | break; |
1666 | 5.31k | case SC_ASN1_CALLBACK: |
1667 | 5.31k | if (entry->parm != NULL) |
1668 | 5.31k | r = callback_func(ctx, entry->arg, obj, objlen, depth); |
1669 | 5.31k | break; |
1670 | 0 | default: |
1671 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "invalid ASN.1 type: %d\n", entry->type); |
1672 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
1673 | 222k | } |
1674 | 222k | if (r) { |
1675 | 10.8k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "decoding of ASN.1 object '%s' failed: %s\n", entry->name, |
1676 | 10.8k | sc_strerror(r)); |
1677 | 10.8k | return r; |
1678 | 10.8k | } |
1679 | 211k | entry->flags |= SC_ASN1_PRESENT; |
1680 | 211k | return 0; |
1681 | 222k | } |
1682 | | |
1683 | 177k | static void sc_free_entry(struct sc_asn1_entry *asn1) { |
1684 | 177k | int idx = 0; |
1685 | 177k | struct sc_asn1_entry *entry = asn1; |
1686 | | |
1687 | 177k | if (!asn1) |
1688 | 4.46k | return; |
1689 | | |
1690 | 806k | for (idx = 0; asn1[idx].name != NULL; idx++) { |
1691 | 633k | entry = &asn1[idx]; |
1692 | 633k | switch (entry->type) { |
1693 | 41.6k | case SC_ASN1_CHOICE: |
1694 | 131k | case SC_ASN1_STRUCT: |
1695 | 131k | sc_free_entry((struct sc_asn1_entry *) entry->parm); |
1696 | 131k | break; |
1697 | 107k | case SC_ASN1_OCTET_STRING: |
1698 | 107k | case SC_ASN1_BIT_STRING_NI: |
1699 | 107k | case SC_ASN1_BIT_STRING: |
1700 | 110k | case SC_ASN1_GENERALIZEDTIME: |
1701 | 113k | case SC_ASN1_PRINTABLESTRING: |
1702 | 133k | case SC_ASN1_UTF8STRING: |
1703 | 133k | if ((entry->flags & SC_ASN1_ALLOC) && (entry->flags & SC_ASN1_PRESENT)) { |
1704 | 1.16k | u8 **buf = (u8 **)entry->parm; |
1705 | 1.16k | free(*buf); |
1706 | 1.16k | *buf = NULL; |
1707 | 1.16k | } |
1708 | 133k | break; |
1709 | 368k | default: |
1710 | 368k | break; |
1711 | 633k | } |
1712 | 633k | } |
1713 | 172k | } |
1714 | | |
1715 | | static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, |
1716 | | const u8 *in, size_t len, const u8 **newp, size_t *len_left, |
1717 | | int choice, int depth) |
1718 | 267k | { |
1719 | 267k | int r, idx = 0; |
1720 | 267k | const u8 *p = in, *obj; |
1721 | 267k | struct sc_asn1_entry *entry = asn1; |
1722 | 267k | size_t left = len, objlen; |
1723 | | |
1724 | 267k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
1725 | 267k | "%*.*s""called, left=%"SC_FORMAT_LEN_SIZE_T"u, depth %d%s\n", |
1726 | 267k | depth, depth, "", left, depth, choice ? ", choice" : ""); |
1727 | | |
1728 | 267k | if (!p) |
1729 | 18 | return SC_ERROR_ASN1_OBJECT_NOT_FOUND; |
1730 | 267k | if (left < 2) { |
1731 | 46.8k | while (asn1->name && (asn1->flags & SC_ASN1_OPTIONAL)) |
1732 | 24.1k | asn1++; |
1733 | | /* If all elements were optional, there's nothing |
1734 | | * to complain about */ |
1735 | 22.7k | if (asn1->name == NULL) |
1736 | 10.4k | return 0; |
1737 | 12.3k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "End of ASN.1 stream, " |
1738 | 12.3k | "non-optional field \"%s\" not found\n", |
1739 | 12.3k | asn1->name); |
1740 | 12.3k | return SC_ERROR_ASN1_OBJECT_NOT_FOUND; |
1741 | 22.7k | } |
1742 | 244k | if (p[0] == 0 || p[0] == 0xFF || len == 0) |
1743 | 20.8k | return SC_ERROR_ASN1_END_OF_CONTENTS; |
1744 | | |
1745 | 736k | for (idx = 0; asn1[idx].name != NULL; idx++) { |
1746 | 595k | entry = &asn1[idx]; |
1747 | | |
1748 | 595k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "Looking for '%s', tag 0x%x%s%s\n", |
1749 | 595k | entry->name, entry->tag, choice? ", CHOICE" : "", |
1750 | 595k | (entry->flags & SC_ASN1_OPTIONAL)? ", OPTIONAL": ""); |
1751 | | |
1752 | | /* Special case CHOICE has no tag */ |
1753 | 595k | if (entry->type == SC_ASN1_CHOICE) { |
1754 | 7.72k | r = asn1_decode(ctx, |
1755 | 7.72k | (struct sc_asn1_entry *) entry->parm, |
1756 | 7.72k | p, left, &p, &left, 1, depth + 1); |
1757 | 7.72k | if (r >= 0) |
1758 | 1.38k | r = 0; |
1759 | 7.72k | goto decode_ok; |
1760 | 7.72k | } |
1761 | | |
1762 | 587k | obj = sc_asn1_skip_tag(ctx, &p, &left, entry->tag, &objlen); |
1763 | 587k | if (obj == NULL) { |
1764 | 365k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "'%s' not present\n", entry->name); |
1765 | 365k | if (choice) |
1766 | 89.7k | continue; |
1767 | 275k | if (entry->flags & SC_ASN1_OPTIONAL) |
1768 | 229k | continue; |
1769 | 45.7k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "mandatory ASN.1 object '%s' not found\n", entry->name); |
1770 | 45.7k | if (left) { |
1771 | 44.5k | u8 line[128], *linep = line; |
1772 | 44.5k | size_t i; |
1773 | | |
1774 | 44.5k | line[0] = 0; |
1775 | 365k | for (i = 0; i < 10 && i < left; i++) { |
1776 | 320k | sprintf((char *) linep, "%02X ", p[i]); |
1777 | 320k | linep += 3; |
1778 | 320k | } |
1779 | 44.5k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "next tag: %s\n", line); |
1780 | 44.5k | } |
1781 | 45.7k | sc_free_entry(asn1); |
1782 | 45.7k | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_ASN1_OBJECT_NOT_FOUND); |
1783 | 45.7k | } |
1784 | 222k | r = asn1_decode_entry(ctx, entry, obj, objlen, depth); |
1785 | | |
1786 | 230k | decode_ok: |
1787 | 230k | if (r) |
1788 | 17.1k | return r; |
1789 | 212k | if (choice) |
1790 | 19.8k | break; |
1791 | 212k | } |
1792 | 161k | if (choice && asn1[idx].name == NULL) /* No match */ |
1793 | 10.8k | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_ASN1_OBJECT_NOT_FOUND); |
1794 | 150k | if (newp != NULL) |
1795 | 31.6k | *newp = p; |
1796 | 150k | if (len_left != NULL) |
1797 | 31.6k | *len_left = left; |
1798 | 150k | if (choice) |
1799 | 19.8k | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, idx); |
1800 | 130k | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, 0); |
1801 | 130k | } |
1802 | | |
1803 | | int sc_asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, |
1804 | | const u8 *in, size_t len, const u8 **newp, size_t *len_left) |
1805 | 149k | { |
1806 | 149k | return asn1_decode(ctx, asn1, in, len, newp, len_left, 0, 0); |
1807 | 149k | } |
1808 | | |
1809 | | int sc_asn1_decode_choice(sc_context_t *ctx, struct sc_asn1_entry *asn1, |
1810 | | const u8 *in, size_t len, const u8 **newp, size_t *len_left) |
1811 | 33.4k | { |
1812 | 33.4k | return asn1_decode(ctx, asn1, in, len, newp, len_left, 1, 0); |
1813 | 33.4k | } |
1814 | | |
1815 | | static int asn1_encode_entry(sc_context_t *ctx, const struct sc_asn1_entry *entry, |
1816 | | u8 **obj, size_t *objlen, int depth) |
1817 | 660k | { |
1818 | 660k | void *parm = entry->parm; |
1819 | 660k | int (*callback_func)(sc_context_t *nctx, void *arg, u8 **nobj, |
1820 | 660k | size_t *nobjlen, int ndepth); |
1821 | 660k | const size_t *len = (const size_t *) entry->arg; |
1822 | 660k | int r = 0; |
1823 | 660k | u8 * buf = NULL; |
1824 | 660k | size_t buflen = 0; |
1825 | | |
1826 | 660k | callback_func = parm; |
1827 | | |
1828 | 660k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "%*.*sencoding '%s'%s\n", |
1829 | 660k | depth, depth, "", entry->name, |
1830 | 660k | (entry->flags & SC_ASN1_PRESENT)? "" : " (not present)"); |
1831 | 660k | if (!(entry->flags & SC_ASN1_PRESENT)) |
1832 | 261k | goto no_object; |
1833 | 398k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
1834 | 398k | "%*.*stype=%d, tag=0x%02x, parm=%p, len=%"SC_FORMAT_LEN_SIZE_T"u\n", |
1835 | 398k | depth, depth, "", entry->type, entry->tag, parm, |
1836 | 398k | len ? *len : 0); |
1837 | | |
1838 | 398k | if (entry->type == SC_ASN1_CHOICE) { |
1839 | 5.13k | const struct sc_asn1_entry *list, *choice = NULL; |
1840 | | |
1841 | 5.13k | list = (const struct sc_asn1_entry *) parm; |
1842 | 19.2k | while (list->name != NULL) { |
1843 | 14.1k | if (list->flags & SC_ASN1_PRESENT) { |
1844 | 5.13k | if (choice) { |
1845 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
1846 | 0 | "ASN.1 problem: more than " |
1847 | 0 | "one CHOICE when encoding %s: " |
1848 | 0 | "%s and %s both present\n", |
1849 | 0 | entry->name, |
1850 | 0 | choice->name, |
1851 | 0 | list->name); |
1852 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
1853 | 0 | } |
1854 | 5.13k | choice = list; |
1855 | 5.13k | } |
1856 | 14.1k | list++; |
1857 | 14.1k | } |
1858 | 5.13k | if (choice == NULL) |
1859 | 0 | goto no_object; |
1860 | 5.13k | return asn1_encode_entry(ctx, choice, obj, objlen, depth + 1); |
1861 | 5.13k | } |
1862 | | |
1863 | 393k | if (entry->type != SC_ASN1_NULL && parm == NULL) { |
1864 | 96 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "unexpected parm == NULL\n"); |
1865 | 96 | return SC_ERROR_INVALID_ASN1_OBJECT; |
1866 | 96 | } |
1867 | | |
1868 | 393k | switch (entry->type) { |
1869 | 85.8k | case SC_ASN1_STRUCT: |
1870 | 85.8k | r = asn1_encode(ctx, (const struct sc_asn1_entry *) parm, &buf, |
1871 | 85.8k | &buflen, depth + 1); |
1872 | 85.8k | break; |
1873 | 1.95k | case SC_ASN1_NULL: |
1874 | 1.95k | buf = NULL; |
1875 | 1.95k | buflen = 0; |
1876 | 1.95k | break; |
1877 | 102 | case SC_ASN1_BOOLEAN: |
1878 | 102 | buf = malloc(1); |
1879 | 102 | if (buf == NULL) { |
1880 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1881 | 0 | break; |
1882 | 0 | } |
1883 | 102 | buf[0] = *((int *) parm) ? 0xFF : 0; |
1884 | 102 | buflen = 1; |
1885 | 102 | break; |
1886 | 32.5k | case SC_ASN1_INTEGER: |
1887 | 36.0k | case SC_ASN1_ENUMERATED: |
1888 | 36.0k | r = asn1_encode_integer(*((int *) entry->parm), &buf, &buflen); |
1889 | 36.0k | break; |
1890 | 2.70k | case SC_ASN1_BIT_STRING_NI: |
1891 | 2.70k | case SC_ASN1_BIT_STRING: |
1892 | 2.70k | if (len != NULL) { |
1893 | 2.70k | if (entry->type == SC_ASN1_BIT_STRING) |
1894 | 0 | r = encode_bit_string((const u8 *) parm, *len, &buf, &buflen, 1); |
1895 | 2.70k | else |
1896 | 2.70k | r = encode_bit_string((const u8 *) parm, *len, &buf, &buflen, 0); |
1897 | 2.70k | } else { |
1898 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1899 | 0 | } |
1900 | 2.70k | break; |
1901 | 15.6k | case SC_ASN1_BIT_FIELD: |
1902 | 15.6k | if (len != NULL) { |
1903 | 15.6k | r = encode_bit_field((const u8 *) parm, *len, &buf, &buflen); |
1904 | 15.6k | } else { |
1905 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1906 | 0 | } |
1907 | 15.6k | break; |
1908 | 1.34k | case SC_ASN1_PRINTABLESTRING: |
1909 | 106k | case SC_ASN1_OCTET_STRING: |
1910 | 142k | case SC_ASN1_UTF8STRING: |
1911 | 142k | if (len != NULL) { |
1912 | 142k | buf = malloc(*len + 1); |
1913 | 142k | if (buf == NULL) { |
1914 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1915 | 0 | break; |
1916 | 0 | } |
1917 | 142k | buflen = 0; |
1918 | | /* If the integer is supposed to be unsigned, insert |
1919 | | * a padding byte if the MSB is one */ |
1920 | 142k | if ((entry->flags & SC_ASN1_UNSIGNED) |
1921 | 142k | && (((u8 *) parm)[0] & 0x80)) { |
1922 | 1.25k | buf[buflen++] = 0x00; |
1923 | 1.25k | } |
1924 | 142k | memcpy(buf + buflen, parm, *len); |
1925 | 142k | buflen += *len; |
1926 | 142k | } else { |
1927 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1928 | 0 | } |
1929 | 142k | break; |
1930 | 142k | case SC_ASN1_GENERALIZEDTIME: |
1931 | 529 | if (len != NULL) { |
1932 | 529 | buf = malloc(*len); |
1933 | 529 | if (buf == NULL) { |
1934 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1935 | 0 | break; |
1936 | 0 | } |
1937 | 529 | memcpy(buf, parm, *len); |
1938 | 529 | buflen = *len; |
1939 | 529 | } else { |
1940 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1941 | 0 | } |
1942 | 529 | break; |
1943 | 50.7k | case SC_ASN1_OBJECT: |
1944 | 50.7k | r = sc_asn1_encode_object_id(&buf, &buflen, (struct sc_object_id *) parm); |
1945 | 50.7k | break; |
1946 | 25.3k | case SC_ASN1_PATH: |
1947 | 25.3k | r = asn1_encode_path(ctx, (const sc_path_t *) parm, &buf, &buflen, depth, entry->flags); |
1948 | 25.3k | break; |
1949 | 9.01k | case SC_ASN1_PKCS15_ID: |
1950 | 9.01k | { |
1951 | 9.01k | const struct sc_pkcs15_id *id = (const struct sc_pkcs15_id *) parm; |
1952 | | |
1953 | 9.01k | buf = malloc(id->len); |
1954 | 9.01k | if (buf == NULL) { |
1955 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1956 | 0 | break; |
1957 | 0 | } |
1958 | 9.01k | memcpy(buf, id->value, id->len); |
1959 | 9.01k | buflen = id->len; |
1960 | 9.01k | } |
1961 | 0 | break; |
1962 | 20.8k | case SC_ASN1_PKCS15_OBJECT: |
1963 | 20.8k | r = asn1_encode_p15_object(ctx, (const struct sc_asn1_pkcs15_object *) parm, &buf, &buflen, depth); |
1964 | 20.8k | break; |
1965 | 2.70k | case SC_ASN1_ALGORITHM_ID: |
1966 | 2.70k | r = sc_asn1_encode_algorithm_id(ctx, &buf, &buflen, (const struct sc_algorithm_id *) parm, depth); |
1967 | 2.70k | break; |
1968 | 9 | case SC_ASN1_SE_INFO: |
1969 | 9 | if (!len) |
1970 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
1971 | 9 | r = asn1_encode_se_info(ctx, (struct sc_pkcs15_sec_env_info **)parm, *len, &buf, &buflen, depth); |
1972 | 9 | break; |
1973 | 0 | case SC_ASN1_CALLBACK: |
1974 | 0 | r = callback_func(ctx, entry->arg, &buf, &buflen, depth); |
1975 | 0 | break; |
1976 | 0 | default: |
1977 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "invalid ASN.1 type: %d\n", entry->type); |
1978 | 0 | return SC_ERROR_INVALID_ASN1_OBJECT; |
1979 | 393k | } |
1980 | 393k | if (r) { |
1981 | 1.41k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "encoding of ASN.1 object '%s' failed: %s\n", entry->name, |
1982 | 1.41k | sc_strerror(r)); |
1983 | 1.41k | if (buf) |
1984 | 0 | free(buf); |
1985 | 1.41k | return r; |
1986 | 1.41k | } |
1987 | | |
1988 | | /* Treatment of OPTIONAL elements: |
1989 | | * - if the encoding has 0 length, and the element is OPTIONAL, |
1990 | | * we don't write anything (unless it's an ASN1 NULL and the |
1991 | | * SC_ASN1_PRESENT flag is set). |
1992 | | * - if the encoding has 0 length, but the element is non-OPTIONAL, |
1993 | | * constructed, we write a empty element (e.g. a SEQUENCE of |
1994 | | * length 0). In case of an ASN1 NULL just write the tag and |
1995 | | * length (i.e. 0x05,0x00). |
1996 | | * - any other empty objects are considered bogus |
1997 | | */ |
1998 | 653k | no_object: |
1999 | 653k | if (!buflen && entry->flags & SC_ASN1_OPTIONAL && !(entry->flags & SC_ASN1_PRESENT)) { |
2000 | | /* This happens when we try to encode e.g. the |
2001 | | * subClassAttributes, which may be empty */ |
2002 | 261k | *obj = NULL; |
2003 | 261k | *objlen = 0; |
2004 | 261k | r = 0; |
2005 | 392k | } else if (!buflen && (entry->flags & SC_ASN1_EMPTY_ALLOWED)) { |
2006 | 282 | *obj = NULL; |
2007 | 282 | *objlen = 0; |
2008 | 282 | r = asn1_write_element(ctx, entry->tag, buf, buflen, obj, objlen); |
2009 | 282 | if (r) |
2010 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "error writing ASN.1 tag and length: %s\n", sc_strerror(r)); |
2011 | 392k | } else if (buflen || entry->type == SC_ASN1_NULL || entry->tag & SC_ASN1_CONS) { |
2012 | 391k | r = asn1_write_element(ctx, entry->tag, buf, buflen, obj, objlen); |
2013 | 391k | if (r) |
2014 | 0 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "error writing ASN.1 tag and length: %s\n", |
2015 | 391k | sc_strerror(r)); |
2016 | 391k | } else if (!(entry->flags & SC_ASN1_PRESENT)) { |
2017 | 103 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "cannot encode non-optional ASN.1 object: not given by caller\n"); |
2018 | 103 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
2019 | 436 | } else { |
2020 | 436 | sc_debug(ctx, SC_LOG_DEBUG_ASN1, "cannot encode empty non-optional ASN.1 object\n"); |
2021 | 436 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
2022 | 436 | } |
2023 | 653k | if (buf) |
2024 | 388k | free(buf); |
2025 | 653k | if (r >= 0) |
2026 | 653k | sc_debug(ctx, SC_LOG_DEBUG_ASN1, |
2027 | 653k | "%*.*slength of encoded item=%"SC_FORMAT_LEN_SIZE_T"u\n", |
2028 | 653k | depth, depth, "", *objlen); |
2029 | 653k | return r; |
2030 | 393k | } |
2031 | | |
2032 | | static int asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1, |
2033 | | u8 **ptr, size_t *size, int depth) |
2034 | 273k | { |
2035 | 273k | int r, idx = 0; |
2036 | 273k | u8 *obj = NULL, *buf = NULL, *tmp; |
2037 | 273k | size_t total = 0, objsize; |
2038 | | |
2039 | 273k | if (asn1 == NULL) { |
2040 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
2041 | 0 | } |
2042 | | |
2043 | 926k | for (idx = 0; asn1[idx].name != NULL; idx++) { |
2044 | 655k | r = asn1_encode_entry(ctx, &asn1[idx], &obj, &objsize, depth); |
2045 | 655k | if (r) { |
2046 | 2.05k | if (obj) |
2047 | 0 | free(obj); |
2048 | 2.05k | if (buf) |
2049 | 620 | free(buf); |
2050 | 2.05k | return r; |
2051 | 2.05k | } |
2052 | | /* in case of an empty (optional) element continue with |
2053 | | * the next asn1 element */ |
2054 | 653k | if (!objsize) |
2055 | 261k | continue; |
2056 | 391k | tmp = (u8 *) realloc(buf, total + objsize); |
2057 | 391k | if (!tmp) { |
2058 | 0 | if (obj) |
2059 | 0 | free(obj); |
2060 | 0 | if (buf) |
2061 | 0 | free(buf); |
2062 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
2063 | 0 | } |
2064 | 391k | buf = tmp; |
2065 | 391k | memcpy(buf + total, obj, objsize); |
2066 | 391k | free(obj); |
2067 | 391k | obj = NULL; |
2068 | 391k | total += objsize; |
2069 | 391k | } |
2070 | 271k | *ptr = buf; |
2071 | 271k | *size = total; |
2072 | 271k | return 0; |
2073 | 273k | } |
2074 | | |
2075 | | int sc_asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1, |
2076 | | u8 **ptr, size_t *size) |
2077 | 101k | { |
2078 | 101k | return asn1_encode(ctx, asn1, ptr, size, 0); |
2079 | 101k | } |
2080 | | |
2081 | | int _sc_asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1, |
2082 | | u8 **ptr, size_t *size, int depth) |
2083 | 39.6k | { |
2084 | 39.6k | return asn1_encode(ctx, asn1, ptr, size, depth); |
2085 | 39.6k | } |
2086 | | |
2087 | | int |
2088 | | _sc_asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, |
2089 | | const u8 *in, size_t len, const u8 **newp, size_t *left, |
2090 | | int choice, int depth) |
2091 | 11.0k | { |
2092 | 11.0k | return asn1_decode(ctx, asn1, in, len, newp, left, choice, depth); |
2093 | 11.0k | } |
2094 | | |
2095 | | int |
2096 | | sc_der_copy(sc_pkcs15_der_t *dst, const sc_pkcs15_der_t *src) |
2097 | 12.5k | { |
2098 | 12.5k | if (!dst || !src) |
2099 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
2100 | 12.5k | memset(dst, 0, sizeof(*dst)); |
2101 | 12.5k | if (src->len) { |
2102 | 12.5k | if (!src->value) |
2103 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
2104 | 12.5k | dst->value = malloc(src->len); |
2105 | 12.5k | if (!dst->value) |
2106 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
2107 | 12.5k | dst->len = src->len; |
2108 | 12.5k | memcpy(dst->value, src->value, src->len); |
2109 | 12.5k | } |
2110 | 12.5k | return SC_SUCCESS; |
2111 | 12.5k | } |
2112 | | |
2113 | | int |
2114 | | sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id, |
2115 | | unsigned char **out, size_t *size) |
2116 | 35.2k | { |
2117 | 35.2k | static const struct sc_asn1_entry c_asn1_object_id[2] = { |
2118 | 35.2k | { "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_ALLOC, NULL, NULL }, |
2119 | 35.2k | { NULL, 0, 0, 0, NULL, NULL } |
2120 | 35.2k | }; |
2121 | 35.2k | struct sc_asn1_entry asn1_object_id[2]; |
2122 | 35.2k | int rv; |
2123 | | |
2124 | 35.2k | sc_copy_asn1_entry(c_asn1_object_id, asn1_object_id); |
2125 | 35.2k | sc_format_asn1_entry(asn1_object_id + 0, id, NULL, 1); |
2126 | | |
2127 | 35.2k | rv = _sc_asn1_encode(ctx, asn1_object_id, out, size, 1); |
2128 | 35.2k | LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); |
2129 | | |
2130 | 35.2k | return SC_SUCCESS; |
2131 | 35.2k | } |
2132 | | |
2133 | | |
2134 | | #define C_ASN1_SIG_VALUE_SIZE 2 |
2135 | | static struct sc_asn1_entry c_asn1_sig_value[C_ASN1_SIG_VALUE_SIZE] = { |
2136 | | { "ECDSA-Sig-Value", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
2137 | | { NULL, 0, 0, 0, NULL, NULL } |
2138 | | }; |
2139 | | |
2140 | | #define C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE 3 |
2141 | | static struct sc_asn1_entry c_asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE] = { |
2142 | | { "r", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, |
2143 | | { "s", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, |
2144 | | { NULL, 0, 0, 0, NULL, NULL } |
2145 | | }; |
2146 | | |
2147 | | |
2148 | | int |
2149 | | sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char *in, size_t inlen, |
2150 | | unsigned char **buf, size_t *buflen) |
2151 | 522 | { |
2152 | 522 | struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; |
2153 | 522 | struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; |
2154 | 522 | unsigned char *r = in, *s = in + inlen/2; |
2155 | 522 | size_t r_len = inlen/2, s_len = inlen/2; |
2156 | 522 | int rv; |
2157 | | |
2158 | 522 | LOG_FUNC_CALLED(ctx); |
2159 | | |
2160 | | /* R/S are filled up with zeroes, we do not want that in sequence format */ |
2161 | 3.94k | while(r_len > 1 && *r == 0x00) { |
2162 | 3.42k | r++; |
2163 | 3.42k | r_len--; |
2164 | 3.42k | } |
2165 | 1.65M | while(s_len > 1 && *s == 0x00) { |
2166 | 1.65M | s++; |
2167 | 1.65M | s_len--; |
2168 | 1.65M | } |
2169 | | |
2170 | 522 | sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); |
2171 | 522 | sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 1); |
2172 | | |
2173 | 522 | sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); |
2174 | 522 | sc_format_asn1_entry(asn1_sig_value_coefficients + 0, r, &r_len, 1); |
2175 | 522 | sc_format_asn1_entry(asn1_sig_value_coefficients + 1, s, &s_len, 1); |
2176 | | |
2177 | 522 | rv = sc_asn1_encode(ctx, asn1_sig_value, buf, buflen); |
2178 | 522 | LOG_TEST_RET(ctx, rv, "ASN.1 encoding ECDSA-SIg-Value failed"); |
2179 | | |
2180 | 520 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
2181 | 520 | } |
2182 | | |
2183 | | |
2184 | | int |
2185 | | sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, const unsigned char *in, size_t inlen, |
2186 | | unsigned char *buf, size_t buflen) |
2187 | 491 | { |
2188 | 491 | struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; |
2189 | 491 | struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; |
2190 | 491 | unsigned char *r = NULL, *s = NULL; |
2191 | 491 | size_t r_len = 0, s_len = 0, halflen = buflen/2; |
2192 | 491 | int rv; |
2193 | | |
2194 | 491 | LOG_FUNC_CALLED(ctx); |
2195 | 491 | if (!buf || !buflen) |
2196 | 491 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
2197 | | |
2198 | 491 | sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); |
2199 | 491 | sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 0); |
2200 | | |
2201 | 491 | sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); |
2202 | 491 | sc_format_asn1_entry(asn1_sig_value_coefficients + 0, &r, &r_len, 0); |
2203 | 491 | sc_format_asn1_entry(asn1_sig_value_coefficients + 1, &s, &s_len, 0); |
2204 | | |
2205 | 491 | rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL); |
2206 | 491 | LOG_TEST_GOTO_ERR(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed"); |
2207 | | |
2208 | 159 | if (halflen < r_len || halflen < s_len) { |
2209 | 0 | rv = SC_ERROR_BUFFER_TOO_SMALL; |
2210 | 0 | goto err; |
2211 | 0 | } |
2212 | | |
2213 | 159 | memset(buf, 0, buflen); |
2214 | 159 | if (r_len > 0) |
2215 | 71 | memcpy(buf + (halflen - r_len), r, r_len); |
2216 | 159 | if (s_len > 0) |
2217 | 95 | memcpy(buf + (buflen - s_len), s, s_len); |
2218 | | |
2219 | 159 | sc_log(ctx, "r(%"SC_FORMAT_LEN_SIZE_T"u): %s", halflen, |
2220 | 159 | sc_dump_hex(buf, halflen)); |
2221 | 159 | sc_log(ctx, "s(%"SC_FORMAT_LEN_SIZE_T"u): %s", halflen, |
2222 | 159 | sc_dump_hex(buf + halflen, halflen)); |
2223 | | |
2224 | 159 | rv = SC_SUCCESS; |
2225 | 491 | err: |
2226 | 491 | free(r); |
2227 | 491 | free(s); |
2228 | | |
2229 | 491 | LOG_FUNC_RETURN(ctx, rv); |
2230 | 491 | } |
2231 | | |
2232 | 216 | int sc_asn1_decode_ecdsa_signature(sc_context_t *ctx, const u8 *data, size_t datalen, size_t fieldsize, u8 **out, size_t outlen) { |
2233 | 216 | int i, r; |
2234 | 216 | const unsigned char *pseq, *pint, *pend; |
2235 | 216 | unsigned int cla, tag; |
2236 | 216 | size_t seqlen, intlen; |
2237 | | |
2238 | 216 | if (!ctx || !data || !out || !(*out)) { |
2239 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
2240 | 0 | } |
2241 | 216 | if (outlen < 2 * fieldsize) { |
2242 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Output too small for EC signature"); |
2243 | 0 | } |
2244 | | |
2245 | 216 | memset(*out, 0, outlen); |
2246 | | |
2247 | 216 | pseq = data; |
2248 | 216 | r = sc_asn1_read_tag(&pseq, datalen, &cla, &tag, &seqlen); |
2249 | 216 | if (pseq == NULL || r < 0 || seqlen == 0 || (cla | tag) != 0x30) |
2250 | 216 | LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Can not find 0x30 tag"); |
2251 | | |
2252 | 31 | pint = pseq; |
2253 | 31 | pend = pseq + seqlen; |
2254 | 67 | for (i = 0; i < 2; i++) { |
2255 | 53 | r = sc_asn1_read_tag(&pint, (pend - pint), &cla, &tag, &intlen); |
2256 | 53 | if (pint == NULL || r < 0 || intlen == 0 || (cla | tag) != 0x02) { |
2257 | 13 | r = SC_ERROR_INVALID_DATA; |
2258 | 13 | LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_DATA, "Can not find 0x02"); |
2259 | 13 | } |
2260 | | |
2261 | 40 | if (intlen == fieldsize + 1) { /* drop leading 00 if present */ |
2262 | 12 | if (*pint != 0x00) { |
2263 | 2 | r = SC_ERROR_INVALID_DATA; |
2264 | 2 | LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_DATA, "Signature too long"); |
2265 | 2 | } |
2266 | 10 | pint++; |
2267 | 10 | intlen--; |
2268 | 10 | } |
2269 | 38 | if (intlen > fieldsize) { |
2270 | 2 | r = SC_ERROR_INVALID_DATA; |
2271 | 2 | LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_DATA, "Signature too long"); |
2272 | 2 | } |
2273 | 36 | memcpy(*out + fieldsize * i + fieldsize - intlen , pint, intlen); |
2274 | 36 | pint += intlen; /* next integer */ |
2275 | 36 | } |
2276 | 14 | r = (int)(2 * fieldsize); |
2277 | 31 | err: |
2278 | 31 | LOG_FUNC_RETURN(ctx, r); |
2279 | 31 | } |
2280 | | |