/src/boringssl/crypto/asn1/tasn_enc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | | * All rights reserved. |
3 | | * |
4 | | * This package is an SSL implementation written |
5 | | * by Eric Young (eay@cryptsoft.com). |
6 | | * The implementation was written so as to conform with Netscapes SSL. |
7 | | * |
8 | | * This library is free for commercial and non-commercial use as long as |
9 | | * the following conditions are aheared to. The following conditions |
10 | | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | | * included with this distribution is covered by the same copyright terms |
13 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | | * |
15 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | | * the code are not to be removed. |
17 | | * If this package is used in a product, Eric Young should be given attribution |
18 | | * as the author of the parts of the library used. |
19 | | * This can be in the form of a textual message at program startup or |
20 | | * in documentation (online or textual) provided with the package. |
21 | | * |
22 | | * Redistribution and use in source and binary forms, with or without |
23 | | * modification, are permitted provided that the following conditions |
24 | | * are met: |
25 | | * 1. Redistributions of source code must retain the copyright |
26 | | * notice, this list of conditions and the following disclaimer. |
27 | | * 2. Redistributions in binary form must reproduce the above copyright |
28 | | * notice, this list of conditions and the following disclaimer in the |
29 | | * documentation and/or other materials provided with the distribution. |
30 | | * 3. All advertising materials mentioning features or use of this software |
31 | | * must display the following acknowledgement: |
32 | | * "This product includes cryptographic software written by |
33 | | * Eric Young (eay@cryptsoft.com)" |
34 | | * The word 'cryptographic' can be left out if the rouines from the library |
35 | | * being used are not cryptographic related :-). |
36 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | | * the apps directory (application code) you must include an acknowledgement: |
38 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | | * SUCH DAMAGE. |
51 | | * |
52 | | * The licence and distribution terms for any publically available version or |
53 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | | * copied and put under another distribution licence |
55 | | * [including the GNU Public Licence.] */ |
56 | | |
57 | | #include <openssl/asn1.h> |
58 | | |
59 | | #include <assert.h> |
60 | | #include <limits.h> |
61 | | #include <string.h> |
62 | | |
63 | | #include <openssl/asn1t.h> |
64 | | #include <openssl/mem.h> |
65 | | |
66 | | #include "../internal.h" |
67 | | #include "internal.h" |
68 | | |
69 | | |
70 | | static int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
71 | | const ASN1_ITEM *it, int tag, int aclass, |
72 | | int optional); |
73 | | static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
74 | | const ASN1_ITEM *it, int tag, int aclass, |
75 | | int optional); |
76 | | static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *out_omit, |
77 | | int *putype, const ASN1_ITEM *it); |
78 | | static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
79 | | int skcontlen, const ASN1_ITEM *item, int do_sort); |
80 | | static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
81 | | const ASN1_TEMPLATE *tt, int tag, int aclass, |
82 | | int optional); |
83 | | |
84 | | // Top level i2d equivalents |
85 | | |
86 | 0 | int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { |
87 | 0 | if (out && !*out) { |
88 | 0 | unsigned char *p, *buf; |
89 | 0 | int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0); |
90 | 0 | if (len <= 0) { |
91 | 0 | return len; |
92 | 0 | } |
93 | 0 | buf = OPENSSL_malloc(len); |
94 | 0 | if (!buf) { |
95 | 0 | return -1; |
96 | 0 | } |
97 | 0 | p = buf; |
98 | 0 | int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0); |
99 | 0 | if (len2 <= 0) { |
100 | 0 | OPENSSL_free(buf); |
101 | 0 | return len2; |
102 | 0 | } |
103 | 0 | assert(len == len2); |
104 | 0 | *out = buf; |
105 | 0 | return len; |
106 | 0 | } |
107 | | |
108 | 0 | return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); |
109 | 0 | } |
110 | | |
111 | | // Encode an item, taking care of IMPLICIT tagging (if any). This function |
112 | | // performs the normal item handling: it can be used in external types. |
113 | | |
114 | | int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
115 | 0 | const ASN1_ITEM *it, int tag, int aclass) { |
116 | 0 | int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0); |
117 | 0 | assert(ret != 0); |
118 | 0 | return ret; |
119 | 0 | } |
120 | | |
121 | | // asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is |
122 | | // non-zero and |*pval| is omitted, it returns zero and writes no bytes. |
123 | | int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
124 | | const ASN1_ITEM *it, int tag, int aclass, |
125 | 0 | int optional) { |
126 | 0 | const ASN1_TEMPLATE *tt = NULL; |
127 | 0 | int i, seqcontlen, seqlen; |
128 | | |
129 | | // Historically, |aclass| was repurposed to pass additional flags into the |
130 | | // encoding process. |
131 | 0 | assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); |
132 | | // If not overridding the tag, |aclass| is ignored and should be zero. |
133 | 0 | assert(tag != -1 || aclass == 0); |
134 | | |
135 | | // All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s. |
136 | | // Optional primitives are handled later. |
137 | 0 | if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { |
138 | 0 | if (optional) { |
139 | 0 | return 0; |
140 | 0 | } |
141 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
142 | 0 | return -1; |
143 | 0 | } |
144 | | |
145 | 0 | switch (it->itype) { |
146 | 0 | case ASN1_ITYPE_PRIMITIVE: |
147 | 0 | if (it->templates) { |
148 | | // This is an |ASN1_ITEM_TEMPLATE|. |
149 | 0 | if (it->templates->flags & ASN1_TFLG_OPTIONAL) { |
150 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
151 | 0 | return -1; |
152 | 0 | } |
153 | 0 | return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass, |
154 | 0 | optional); |
155 | 0 | } |
156 | 0 | return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); |
157 | | |
158 | 0 | case ASN1_ITYPE_MSTRING: |
159 | | // It never makes sense for multi-strings to have implicit tagging, so |
160 | | // if tag != -1, then this looks like an error in the template. |
161 | 0 | if (tag != -1) { |
162 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
163 | 0 | return -1; |
164 | 0 | } |
165 | 0 | return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); |
166 | | |
167 | 0 | case ASN1_ITYPE_CHOICE: { |
168 | | // It never makes sense for CHOICE types to have implicit tagging, so if |
169 | | // tag != -1, then this looks like an error in the template. |
170 | 0 | if (tag != -1) { |
171 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
172 | 0 | return -1; |
173 | 0 | } |
174 | 0 | i = asn1_get_choice_selector(pval, it); |
175 | 0 | if (i < 0 || i >= it->tcount) { |
176 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); |
177 | 0 | return -1; |
178 | 0 | } |
179 | 0 | const ASN1_TEMPLATE *chtt = it->templates + i; |
180 | 0 | if (chtt->flags & ASN1_TFLG_OPTIONAL) { |
181 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
182 | 0 | return -1; |
183 | 0 | } |
184 | 0 | ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt); |
185 | 0 | return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0); |
186 | 0 | } |
187 | | |
188 | 0 | case ASN1_ITYPE_EXTERN: { |
189 | | // We don't support implicit tagging with external types. |
190 | 0 | if (tag != -1) { |
191 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
192 | 0 | return -1; |
193 | 0 | } |
194 | 0 | const ASN1_EXTERN_FUNCS *ef = it->funcs; |
195 | 0 | int ret = ef->asn1_ex_i2d(pval, out, it); |
196 | 0 | if (ret == 0) { |
197 | | // |asn1_ex_i2d| should never return zero. We have already checked |
198 | | // for optional values generically, and |ASN1_ITYPE_EXTERN| fields |
199 | | // must be pointers. |
200 | 0 | OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
201 | 0 | return -1; |
202 | 0 | } |
203 | 0 | return ret; |
204 | 0 | } |
205 | | |
206 | 0 | case ASN1_ITYPE_SEQUENCE: { |
207 | 0 | i = asn1_enc_restore(&seqcontlen, out, pval, it); |
208 | | // An error occurred |
209 | 0 | if (i < 0) { |
210 | 0 | return -1; |
211 | 0 | } |
212 | | // We have a valid cached encoding... |
213 | 0 | if (i > 0) { |
214 | 0 | return seqcontlen; |
215 | 0 | } |
216 | | // Otherwise carry on |
217 | 0 | seqcontlen = 0; |
218 | | // If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL |
219 | 0 | if (tag == -1) { |
220 | 0 | tag = V_ASN1_SEQUENCE; |
221 | 0 | aclass = V_ASN1_UNIVERSAL; |
222 | 0 | } |
223 | | // First work out sequence content length |
224 | 0 | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
225 | 0 | const ASN1_TEMPLATE *seqtt; |
226 | 0 | ASN1_VALUE **pseqval; |
227 | 0 | int tmplen; |
228 | 0 | seqtt = asn1_do_adb(pval, tt, 1); |
229 | 0 | if (!seqtt) { |
230 | 0 | return -1; |
231 | 0 | } |
232 | 0 | pseqval = asn1_get_field_ptr(pval, seqtt); |
233 | 0 | tmplen = |
234 | 0 | asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0); |
235 | 0 | if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) { |
236 | 0 | return -1; |
237 | 0 | } |
238 | 0 | seqcontlen += tmplen; |
239 | 0 | } |
240 | | |
241 | 0 | seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag); |
242 | 0 | if (!out || seqlen == -1) { |
243 | 0 | return seqlen; |
244 | 0 | } |
245 | | // Output SEQUENCE header |
246 | 0 | ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); |
247 | 0 | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
248 | 0 | const ASN1_TEMPLATE *seqtt; |
249 | 0 | ASN1_VALUE **pseqval; |
250 | 0 | seqtt = asn1_do_adb(pval, tt, 1); |
251 | 0 | if (!seqtt) { |
252 | 0 | return -1; |
253 | 0 | } |
254 | 0 | pseqval = asn1_get_field_ptr(pval, seqtt); |
255 | 0 | if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) < |
256 | 0 | 0) { |
257 | 0 | return -1; |
258 | 0 | } |
259 | 0 | } |
260 | 0 | return seqlen; |
261 | 0 | } |
262 | | |
263 | 0 | default: |
264 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
265 | 0 | return -1; |
266 | 0 | } |
267 | 0 | } |
268 | | |
269 | | // asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an |
270 | | // |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an |
271 | | // |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc. |
272 | | static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
273 | | const ASN1_TEMPLATE *tt, int tag, int iclass, |
274 | 0 | int optional) { |
275 | 0 | int i, ret, ttag, tclass; |
276 | 0 | size_t j; |
277 | 0 | uint32_t flags = tt->flags; |
278 | | |
279 | | // Historically, |iclass| was repurposed to pass additional flags into the |
280 | | // encoding process. |
281 | 0 | assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); |
282 | | // If not overridding the tag, |iclass| is ignored and should be zero. |
283 | 0 | assert(tag != -1 || iclass == 0); |
284 | | |
285 | | // Work out tag and class to use: tagging may come either from the |
286 | | // template or the arguments, not both because this would create |
287 | | // ambiguity. |
288 | 0 | if (flags & ASN1_TFLG_TAG_MASK) { |
289 | | // Error if argument and template tagging |
290 | 0 | if (tag != -1) { |
291 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
292 | 0 | return -1; |
293 | 0 | } |
294 | | // Get tagging from template |
295 | 0 | ttag = tt->tag; |
296 | 0 | tclass = flags & ASN1_TFLG_TAG_CLASS; |
297 | 0 | } else if (tag != -1) { |
298 | | // No template tagging, get from arguments |
299 | 0 | ttag = tag; |
300 | 0 | tclass = iclass & ASN1_TFLG_TAG_CLASS; |
301 | 0 | } else { |
302 | 0 | ttag = -1; |
303 | 0 | tclass = 0; |
304 | 0 | } |
305 | | |
306 | | // The template may itself by marked as optional, or this may be the template |
307 | | // of an |ASN1_ITEM_TEMPLATE| type which was contained inside an outer |
308 | | // optional template. (They cannot both be true because the |
309 | | // |ASN1_ITEM_TEMPLATE| codepath rejects optional templates.) |
310 | 0 | assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0); |
311 | 0 | optional = optional || (flags & ASN1_TFLG_OPTIONAL) != 0; |
312 | | |
313 | | // At this point 'ttag' contains the outer tag to use, and 'tclass' is the |
314 | | // class. |
315 | |
|
316 | 0 | if (flags & ASN1_TFLG_SK_MASK) { |
317 | | // SET OF, SEQUENCE OF |
318 | 0 | STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
319 | 0 | int isset, sktag, skaclass; |
320 | 0 | int skcontlen, sklen; |
321 | 0 | ASN1_VALUE *skitem; |
322 | |
|
323 | 0 | if (!*pval) { |
324 | 0 | if (optional) { |
325 | 0 | return 0; |
326 | 0 | } |
327 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
328 | 0 | return -1; |
329 | 0 | } |
330 | | |
331 | 0 | if (flags & ASN1_TFLG_SET_OF) { |
332 | 0 | isset = 1; |
333 | | // Historically, types with both bits set were mutated when |
334 | | // serialized to apply the sort. We no longer support this. |
335 | 0 | assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); |
336 | 0 | } else { |
337 | 0 | isset = 0; |
338 | 0 | } |
339 | | |
340 | | // Work out inner tag value: if EXPLICIT or no tagging use underlying |
341 | | // type. |
342 | 0 | if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { |
343 | 0 | sktag = ttag; |
344 | 0 | skaclass = tclass; |
345 | 0 | } else { |
346 | 0 | skaclass = V_ASN1_UNIVERSAL; |
347 | 0 | if (isset) { |
348 | 0 | sktag = V_ASN1_SET; |
349 | 0 | } else { |
350 | 0 | sktag = V_ASN1_SEQUENCE; |
351 | 0 | } |
352 | 0 | } |
353 | | |
354 | | // Determine total length of items |
355 | 0 | skcontlen = 0; |
356 | 0 | for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { |
357 | 0 | int tmplen; |
358 | 0 | skitem = sk_ASN1_VALUE_value(sk, j); |
359 | 0 | tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); |
360 | 0 | if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) { |
361 | 0 | return -1; |
362 | 0 | } |
363 | 0 | skcontlen += tmplen; |
364 | 0 | } |
365 | 0 | sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag); |
366 | 0 | if (sklen == -1) { |
367 | 0 | return -1; |
368 | 0 | } |
369 | | // If EXPLICIT need length of surrounding tag |
370 | 0 | if (flags & ASN1_TFLG_EXPTAG) { |
371 | 0 | ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); |
372 | 0 | } else { |
373 | 0 | ret = sklen; |
374 | 0 | } |
375 | |
|
376 | 0 | if (!out || ret == -1) { |
377 | 0 | return ret; |
378 | 0 | } |
379 | | |
380 | | // Now encode this lot... |
381 | | // EXPLICIT tag |
382 | 0 | if (flags & ASN1_TFLG_EXPTAG) { |
383 | 0 | ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); |
384 | 0 | } |
385 | | // SET or SEQUENCE and IMPLICIT tag |
386 | 0 | ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); |
387 | | // And the stuff itself |
388 | 0 | if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) { |
389 | 0 | return -1; |
390 | 0 | } |
391 | 0 | return ret; |
392 | 0 | } |
393 | | |
394 | 0 | if (flags & ASN1_TFLG_EXPTAG) { |
395 | | // EXPLICIT tagging |
396 | | // Find length of tagged item |
397 | 0 | i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, |
398 | 0 | optional); |
399 | 0 | if (i <= 0) { |
400 | 0 | return i; |
401 | 0 | } |
402 | | // Find length of EXPLICIT tag |
403 | 0 | ret = ASN1_object_size(/*constructed=*/1, i, ttag); |
404 | 0 | if (out && ret != -1) { |
405 | | // Output tag and item |
406 | 0 | ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); |
407 | 0 | if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) { |
408 | 0 | return -1; |
409 | 0 | } |
410 | 0 | } |
411 | 0 | return ret; |
412 | 0 | } |
413 | | |
414 | | // Either normal or IMPLICIT tagging |
415 | 0 | return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass, |
416 | 0 | optional); |
417 | 0 | } |
418 | | |
419 | | // Temporary structure used to hold DER encoding of items for SET OF |
420 | | |
421 | | typedef struct { |
422 | | unsigned char *data; |
423 | | int length; |
424 | | } DER_ENC; |
425 | | |
426 | 0 | static int der_cmp(const void *a, const void *b) { |
427 | 0 | const DER_ENC *d1 = a, *d2 = b; |
428 | 0 | int cmplen, i; |
429 | 0 | cmplen = (d1->length < d2->length) ? d1->length : d2->length; |
430 | 0 | i = OPENSSL_memcmp(d1->data, d2->data, cmplen); |
431 | 0 | if (i) { |
432 | 0 | return i; |
433 | 0 | } |
434 | 0 | return d1->length - d2->length; |
435 | 0 | } |
436 | | |
437 | | // asn1_set_seq_out writes |sk| to |out| under the i2d output convention, |
438 | | // excluding the tag and length. It returns one on success and zero on error. |
439 | | // |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the |
440 | | // elements are sorted for a SET OF type. Each element of |sk| has type |
441 | | // |item|. |
442 | | static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
443 | 0 | int skcontlen, const ASN1_ITEM *item, int do_sort) { |
444 | | // No need to sort if there are fewer than two items. |
445 | 0 | if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { |
446 | 0 | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
447 | 0 | ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
448 | 0 | if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) { |
449 | 0 | return 0; |
450 | 0 | } |
451 | 0 | } |
452 | 0 | return 1; |
453 | 0 | } |
454 | | |
455 | 0 | int ret = 0; |
456 | 0 | unsigned char *const buf = OPENSSL_malloc(skcontlen); |
457 | 0 | DER_ENC *encoded = OPENSSL_calloc(sk_ASN1_VALUE_num(sk), sizeof(*encoded)); |
458 | 0 | if (encoded == NULL || buf == NULL) { |
459 | 0 | goto err; |
460 | 0 | } |
461 | | |
462 | | // Encode all the elements into |buf| and populate |encoded|. |
463 | 0 | unsigned char *p = buf; |
464 | 0 | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
465 | 0 | ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
466 | 0 | encoded[i].data = p; |
467 | 0 | encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0); |
468 | 0 | if (encoded[i].length < 0) { |
469 | 0 | goto err; |
470 | 0 | } |
471 | 0 | assert(p - buf <= skcontlen); |
472 | 0 | } |
473 | | |
474 | 0 | qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp); |
475 | | |
476 | | // Output the elements in sorted order. |
477 | 0 | p = *out; |
478 | 0 | for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
479 | 0 | OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); |
480 | 0 | p += encoded[i].length; |
481 | 0 | } |
482 | 0 | *out = p; |
483 | |
|
484 | 0 | ret = 1; |
485 | |
|
486 | 0 | err: |
487 | 0 | OPENSSL_free(encoded); |
488 | 0 | OPENSSL_free(buf); |
489 | 0 | return ret; |
490 | 0 | } |
491 | | |
492 | | // asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a |
493 | | // a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|. |
494 | | static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
495 | | const ASN1_ITEM *it, int tag, int aclass, |
496 | 0 | int optional) { |
497 | | // Get length of content octets and maybe find out the underlying type. |
498 | 0 | int omit; |
499 | 0 | int utype = it->utype; |
500 | 0 | int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); |
501 | 0 | if (len < 0) { |
502 | 0 | return -1; |
503 | 0 | } |
504 | 0 | if (omit) { |
505 | 0 | if (optional) { |
506 | 0 | return 0; |
507 | 0 | } |
508 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
509 | 0 | return -1; |
510 | 0 | } |
511 | | |
512 | | // If SEQUENCE, SET or OTHER then header is included in pseudo content |
513 | | // octets so don't include tag+length. We need to check here because the |
514 | | // call to asn1_ex_i2c() could change utype. |
515 | 0 | int usetag = |
516 | 0 | utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER; |
517 | | |
518 | | // If not implicitly tagged get tag from underlying type |
519 | 0 | if (tag == -1) { |
520 | 0 | tag = utype; |
521 | 0 | } |
522 | | |
523 | | // Output tag+length followed by content octets |
524 | 0 | if (out) { |
525 | 0 | if (usetag) { |
526 | 0 | ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); |
527 | 0 | } |
528 | 0 | int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it); |
529 | 0 | if (len2 < 0) { |
530 | 0 | return -1; |
531 | 0 | } |
532 | 0 | assert(len == len2); |
533 | 0 | assert(!omit); |
534 | 0 | *out += len; |
535 | 0 | } |
536 | | |
537 | 0 | if (usetag) { |
538 | 0 | return ASN1_object_size(/*constructed=*/0, len, tag); |
539 | 0 | } |
540 | 0 | return len; |
541 | 0 | } |
542 | | |
543 | | // asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention, |
544 | | // excluding the tag and length. It returns the number of bytes written, |
545 | | // possibly zero, on success or -1 on error. If |*pval| should be omitted, it |
546 | | // returns zero and sets |*out_omit| to true. |
547 | | // |
548 | | // If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|, |
549 | | // which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates |
550 | | // |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a |
551 | | // universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or |
552 | | // |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller |
553 | | // must not do so. |
554 | | // |
555 | | // Otherwise, |*putype| must contain |it->utype|. |
556 | | // |
557 | | // WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero |
558 | | // without omitting the element. ASN.1 values may have empty contents. |
559 | | static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit, |
560 | 0 | int *putype, const ASN1_ITEM *it) { |
561 | 0 | ASN1_BOOLEAN *tbool = NULL; |
562 | 0 | ASN1_STRING *strtmp; |
563 | 0 | ASN1_OBJECT *otmp; |
564 | 0 | int utype; |
565 | 0 | const unsigned char *cont; |
566 | 0 | unsigned char c; |
567 | 0 | int len; |
568 | | |
569 | | // Historically, |it->funcs| for primitive types contained an |
570 | | // |ASN1_PRIMITIVE_FUNCS| table of callbacks. |
571 | 0 | assert(it->funcs == NULL); |
572 | | |
573 | 0 | *out_omit = 0; |
574 | | |
575 | | // Should type be omitted? |
576 | 0 | if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { |
577 | 0 | if (!*pval) { |
578 | 0 | *out_omit = 1; |
579 | 0 | return 0; |
580 | 0 | } |
581 | 0 | } |
582 | | |
583 | 0 | if (it->itype == ASN1_ITYPE_MSTRING) { |
584 | | // If MSTRING type set the underlying type |
585 | 0 | strtmp = (ASN1_STRING *)*pval; |
586 | 0 | utype = strtmp->type; |
587 | 0 | if (utype < 0 && utype != V_ASN1_OTHER) { |
588 | | // MSTRINGs can have type -1 when default-constructed. |
589 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
590 | 0 | return -1; |
591 | 0 | } |
592 | | // Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values |
593 | | // that do not match their corresponding utype values. INTEGERs cannot |
594 | | // participate in MSTRING types, but ENUMERATEDs can. |
595 | | // |
596 | | // TODO(davidben): Is this a bug? Although arguably one of the MSTRING |
597 | | // types should contain more values, rather than less. See |
598 | | // https://crbug.com/boringssl/412. But it is not possible to fit all |
599 | | // possible ANY values into an |ASN1_STRING|, so matching the spec here |
600 | | // is somewhat hopeless. |
601 | 0 | if (utype == V_ASN1_NEG_INTEGER) { |
602 | 0 | utype = V_ASN1_INTEGER; |
603 | 0 | } else if (utype == V_ASN1_NEG_ENUMERATED) { |
604 | 0 | utype = V_ASN1_ENUMERATED; |
605 | 0 | } |
606 | 0 | *putype = utype; |
607 | 0 | } else if (it->utype == V_ASN1_ANY) { |
608 | | // If ANY set type and pointer to value |
609 | 0 | ASN1_TYPE *typ; |
610 | 0 | typ = (ASN1_TYPE *)*pval; |
611 | 0 | utype = typ->type; |
612 | 0 | if (utype < 0 && utype != V_ASN1_OTHER) { |
613 | | // |ASN1_TYPE|s can have type -1 when default-constructed. |
614 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
615 | 0 | return -1; |
616 | 0 | } |
617 | 0 | *putype = utype; |
618 | 0 | pval = &typ->value.asn1_value; |
619 | 0 | } else { |
620 | 0 | utype = *putype; |
621 | 0 | } |
622 | | |
623 | 0 | switch (utype) { |
624 | 0 | case V_ASN1_OBJECT: |
625 | 0 | otmp = (ASN1_OBJECT *)*pval; |
626 | 0 | cont = otmp->data; |
627 | 0 | len = otmp->length; |
628 | 0 | if (len == 0) { |
629 | | // Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized. |
630 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); |
631 | 0 | return -1; |
632 | 0 | } |
633 | 0 | break; |
634 | | |
635 | 0 | case V_ASN1_NULL: |
636 | 0 | cont = NULL; |
637 | 0 | len = 0; |
638 | 0 | break; |
639 | | |
640 | 0 | case V_ASN1_BOOLEAN: |
641 | 0 | tbool = (ASN1_BOOLEAN *)pval; |
642 | 0 | if (*tbool == ASN1_BOOLEAN_NONE) { |
643 | 0 | *out_omit = 1; |
644 | 0 | return 0; |
645 | 0 | } |
646 | 0 | if (it->utype != V_ASN1_ANY) { |
647 | | // Default handling if value == size field then omit |
648 | 0 | if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) { |
649 | 0 | *out_omit = 1; |
650 | 0 | return 0; |
651 | 0 | } |
652 | 0 | } |
653 | 0 | c = *tbool ? 0xff : 0x00; |
654 | 0 | cont = &c; |
655 | 0 | len = 1; |
656 | 0 | break; |
657 | | |
658 | 0 | case V_ASN1_BIT_STRING: { |
659 | 0 | int ret = |
660 | 0 | i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); |
661 | | // |i2c_ASN1_BIT_STRING| returns zero on error instead of -1. |
662 | 0 | return ret <= 0 ? -1 : ret; |
663 | 0 | } |
664 | | |
665 | 0 | case V_ASN1_INTEGER: |
666 | 0 | case V_ASN1_ENUMERATED: { |
667 | | // |i2c_ASN1_INTEGER| also handles ENUMERATED. |
668 | 0 | int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); |
669 | | // |i2c_ASN1_INTEGER| returns zero on error instead of -1. |
670 | 0 | return ret <= 0 ? -1 : ret; |
671 | 0 | } |
672 | | |
673 | 0 | case V_ASN1_OCTET_STRING: |
674 | 0 | case V_ASN1_NUMERICSTRING: |
675 | 0 | case V_ASN1_PRINTABLESTRING: |
676 | 0 | case V_ASN1_T61STRING: |
677 | 0 | case V_ASN1_VIDEOTEXSTRING: |
678 | 0 | case V_ASN1_IA5STRING: |
679 | 0 | case V_ASN1_UTCTIME: |
680 | 0 | case V_ASN1_GENERALIZEDTIME: |
681 | 0 | case V_ASN1_GRAPHICSTRING: |
682 | 0 | case V_ASN1_VISIBLESTRING: |
683 | 0 | case V_ASN1_GENERALSTRING: |
684 | 0 | case V_ASN1_UNIVERSALSTRING: |
685 | 0 | case V_ASN1_BMPSTRING: |
686 | 0 | case V_ASN1_UTF8STRING: |
687 | 0 | case V_ASN1_SEQUENCE: |
688 | 0 | case V_ASN1_SET: |
689 | | // This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|. |
690 | 0 | case V_ASN1_OTHER: |
691 | | // TODO(crbug.com/boringssl/412): This default case should be removed, now |
692 | | // that we've resolved https://crbug.com/boringssl/561. However, it is still |
693 | | // needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE| |
694 | | // broadly doesn't tolerate unrecognized universal tags, but except for |
695 | | // eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the |
696 | | // X509Test.NameAttributeValues test. |
697 | 0 | default: |
698 | | // All based on ASN1_STRING and handled the same |
699 | 0 | strtmp = (ASN1_STRING *)*pval; |
700 | 0 | cont = strtmp->data; |
701 | 0 | len = strtmp->length; |
702 | 0 | break; |
703 | 0 | } |
704 | 0 | if (cout && len) { |
705 | 0 | OPENSSL_memcpy(cout, cont, len); |
706 | 0 | } |
707 | 0 | return len; |
708 | 0 | } |