Branch data Line data Source code
1 : : /* tasn_enc.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project 2000.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : *
53 : : * This product includes cryptographic software written by Eric Young
54 : : * (eay@cryptsoft.com). This product includes software written by Tim
55 : : * Hudson (tjh@cryptsoft.com).
56 : : *
57 : : */
58 : :
59 : :
60 : : #include <stddef.h>
61 : : #include <string.h>
62 : : #include "cryptlib.h"
63 : : #include <openssl/asn1.h>
64 : : #include <openssl/asn1t.h>
65 : : #include <openssl/objects.h>
66 : :
67 : : static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
68 : : const ASN1_ITEM *it,
69 : : int tag, int aclass);
70 : : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
71 : : int skcontlen, const ASN1_ITEM *item,
72 : : int do_sort, int iclass);
73 : : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
74 : : const ASN1_TEMPLATE *tt,
75 : : int tag, int aclass);
76 : : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
77 : : const ASN1_ITEM *it, int flags);
78 : :
79 : : /* Top level i2d equivalents: the 'ndef' variant instructs the encoder
80 : : * to use indefinite length constructed encoding, where appropriate
81 : : */
82 : :
83 : 172 : int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
84 : : const ASN1_ITEM *it)
85 : : {
86 : 172 : return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
87 : : }
88 : :
89 : 51383 : int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
90 : : {
91 : 51383 : return asn1_item_flags_i2d(val, out, it, 0);
92 : : }
93 : :
94 : : /* Encode an ASN1 item, this is use by the
95 : : * standard 'i2d' function. 'out' points to
96 : : * a buffer to output the data to.
97 : : *
98 : : * The new i2d has one additional feature. If the output
99 : : * buffer is NULL (i.e. *out == NULL) then a buffer is
100 : : * allocated and populated with the encoding.
101 : : */
102 : :
103 : 51555 : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
104 : : const ASN1_ITEM *it, int flags)
105 : : {
106 [ + + ][ + + ]: 51555 : if (out && !*out)
107 : : {
108 : : unsigned char *p, *buf;
109 : : int len;
110 : 6603 : len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
111 [ + - ]: 6603 : if (len <= 0)
112 : : return len;
113 : 6603 : buf = OPENSSL_malloc(len);
114 [ + - ]: 6603 : if (!buf)
115 : : return -1;
116 : 6603 : p = buf;
117 : 6603 : ASN1_item_ex_i2d(&val, &p, it, -1, flags);
118 : 6603 : *out = buf;
119 : 6603 : return len;
120 : : }
121 : :
122 : 44952 : return ASN1_item_ex_i2d(&val, out, it, -1, flags);
123 : : }
124 : :
125 : : /* Encode an item, taking care of IMPLICIT tagging (if any).
126 : : * This function performs the normal item handling: it can be
127 : : * used in external types.
128 : : */
129 : :
130 : 907819 : int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
131 : : const ASN1_ITEM *it, int tag, int aclass)
132 : : {
133 : 907819 : const ASN1_TEMPLATE *tt = NULL;
134 : 907819 : unsigned char *p = NULL;
135 : 907819 : int i, seqcontlen, seqlen, ndef = 1;
136 : : const ASN1_COMPAT_FUNCS *cf;
137 : : const ASN1_EXTERN_FUNCS *ef;
138 : 907819 : const ASN1_AUX *aux = it->funcs;
139 : 907819 : ASN1_aux_cb *asn1_cb = 0;
140 : :
141 [ + + ][ + + ]: 907819 : if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
142 : : return 0;
143 : :
144 [ + + ][ + + ]: 907575 : if (aux && aux->asn1_cb)
145 : 18204 : asn1_cb = aux->asn1_cb;
146 : :
147 [ + + + + : 907575 : switch(it->itype)
- + + - ]
148 : : {
149 : :
150 : : case ASN1_ITYPE_PRIMITIVE:
151 [ + + ]: 464060 : if (it->templates)
152 : 103677 : return asn1_template_ex_i2d(pval, out, it->templates,
153 : : tag, aclass);
154 : 360383 : return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
155 : : break;
156 : :
157 : : case ASN1_ITYPE_MSTRING:
158 : 206190 : return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
159 : :
160 : : case ASN1_ITYPE_CHOICE:
161 [ + + ][ + - ]: 9203 : if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
162 : : return 0;
163 : 9203 : i = asn1_get_choice_selector(pval, it);
164 [ + - ][ + - ]: 9203 : if ((i >= 0) && (i < it->tcount))
165 : : {
166 : : ASN1_VALUE **pchval;
167 : : const ASN1_TEMPLATE *chtt;
168 : 9203 : chtt = it->templates + i;
169 : 9203 : pchval = asn1_get_field_ptr(pval, chtt);
170 : 9203 : return asn1_template_ex_i2d(pchval, out, chtt,
171 : : -1, aclass);
172 : : }
173 : : /* Fixme: error condition if selector out of range */
174 [ # # ]: 0 : if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
175 : : return 0;
176 : : break;
177 : :
178 : : case ASN1_ITYPE_EXTERN:
179 : : /* If new style i2d it does all the work */
180 : 3198 : ef = it->funcs;
181 : 3198 : return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
182 : :
183 : : case ASN1_ITYPE_COMPAT:
184 : : /* old style hackery... */
185 : 0 : cf = it->funcs;
186 [ # # ]: 0 : if (out)
187 : 0 : p = *out;
188 : 0 : i = cf->asn1_i2d(*pval, out);
189 : : /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
190 : : * but so did the old code. Tags > 30 are very rare anyway.
191 : : */
192 [ # # ]: 0 : if (out && (tag != -1))
193 : 0 : *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
194 : 0 : return i;
195 : :
196 : : case ASN1_ITYPE_NDEF_SEQUENCE:
197 : : /* Use indefinite length constructed if requested */
198 [ + + ]: 1377 : if (aclass & ASN1_TFLG_NDEF) ndef = 2;
199 : : /* fall through */
200 : :
201 : : case ASN1_ITYPE_SEQUENCE:
202 : 224924 : i = asn1_enc_restore(&seqcontlen, out, pval, it);
203 : : /* An error occurred */
204 [ + - ]: 224924 : if (i < 0)
205 : : return 0;
206 : : /* We have a valid cached encoding... */
207 [ + + ]: 224924 : if (i > 0)
208 : 20090 : return seqcontlen;
209 : : /* Otherwise carry on */
210 : 204834 : seqcontlen = 0;
211 : : /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
212 [ + + ]: 204834 : if (tag == -1)
213 : : {
214 : 204698 : tag = V_ASN1_SEQUENCE;
215 : : /* Retain any other flags in aclass */
216 : 204698 : aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
217 : : | V_ASN1_UNIVERSAL;
218 : : }
219 [ + + ][ + - ]: 204834 : if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
220 : : return 0;
221 : : /* First work out sequence content length */
222 [ + + ]: 637296 : for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
223 : : {
224 : : const ASN1_TEMPLATE *seqtt;
225 : : ASN1_VALUE **pseqval;
226 : 432462 : seqtt = asn1_do_adb(pval, tt, 1);
227 [ + - ]: 432462 : if (!seqtt)
228 : : return 0;
229 : 432462 : pseqval = asn1_get_field_ptr(pval, seqtt);
230 : : /* FIXME: check for errors in enhanced version */
231 : 432462 : seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
232 : : -1, aclass);
233 : : }
234 : :
235 : 204834 : seqlen = ASN1_object_size(ndef, seqcontlen, tag);
236 [ + + ]: 204834 : if (!out)
237 : : return seqlen;
238 : : /* Output SEQUENCE header */
239 : 68106 : ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
240 [ + + ]: 212557 : for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
241 : : {
242 : : const ASN1_TEMPLATE *seqtt;
243 : : ASN1_VALUE **pseqval;
244 : 144451 : seqtt = asn1_do_adb(pval, tt, 1);
245 [ + - ]: 144451 : if (!seqtt)
246 : : return 0;
247 : 144451 : pseqval = asn1_get_field_ptr(pval, seqtt);
248 : : /* FIXME: check for errors in enhanced version */
249 : 144451 : asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
250 : : }
251 [ + + ]: 68106 : if (ndef == 2)
252 : 254 : ASN1_put_eoc(out);
253 [ + + ][ + - ]: 68106 : if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
254 : : return 0;
255 : 68106 : return seqlen;
256 : :
257 : : default:
258 : : return 0;
259 : :
260 : : }
261 : : return 0;
262 : : }
263 : :
264 : 0 : int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
265 : : const ASN1_TEMPLATE *tt)
266 : : {
267 : 0 : return asn1_template_ex_i2d(pval, out, tt, -1, 0);
268 : : }
269 : :
270 : 689793 : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
271 : : const ASN1_TEMPLATE *tt, int tag, int iclass)
272 : : {
273 : : int i, ret, flags, ttag, tclass, ndef;
274 : 689793 : flags = tt->flags;
275 : : /* Work out tag and class to use: tagging may come
276 : : * either from the template or the arguments, not both
277 : : * because this would create ambiguity. Additionally
278 : : * the iclass argument may contain some additional flags
279 : : * which should be noted and passed down to other levels.
280 : : */
281 [ + + ]: 689793 : if (flags & ASN1_TFLG_TAG_MASK)
282 : : {
283 : : /* Error if argument and template tagging */
284 [ + - ]: 7064 : if (tag != -1)
285 : : /* FIXME: error code here */
286 : : return -1;
287 : : /* Get tagging from template */
288 : 7064 : ttag = tt->tag;
289 : 7064 : tclass = flags & ASN1_TFLG_TAG_CLASS;
290 : : }
291 [ - + ]: 682729 : else if (tag != -1)
292 : : {
293 : : /* No template tagging, get from arguments */
294 : 0 : ttag = tag;
295 : 0 : tclass = iclass & ASN1_TFLG_TAG_CLASS;
296 : : }
297 : : else
298 : : {
299 : : ttag = -1;
300 : : tclass = 0;
301 : : }
302 : : /*
303 : : * Remove any class mask from iflag.
304 : : */
305 : 689793 : iclass &= ~ASN1_TFLG_TAG_CLASS;
306 : :
307 : : /* At this point 'ttag' contains the outer tag to use,
308 : : * 'tclass' is the class and iclass is any flags passed
309 : : * to this function.
310 : : */
311 : :
312 : : /* if template and arguments require ndef, use it */
313 [ + + ][ + + ]: 689793 : if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
314 : : ndef = 2;
315 : 689331 : else ndef = 1;
316 : :
317 [ + + ]: 689793 : if (flags & ASN1_TFLG_SK_MASK)
318 : : {
319 : : /* SET OF, SEQUENCE OF */
320 : 114818 : STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
321 : : int isset, sktag, skaclass;
322 : : int skcontlen, sklen;
323 : : ASN1_VALUE *skitem;
324 : :
325 [ + + ]: 114818 : if (!*pval)
326 : : return 0;
327 : :
328 [ + + ]: 112494 : if (flags & ASN1_TFLG_SET_OF)
329 : : {
330 : 110577 : isset = 1;
331 : : /* 2 means we reorder */
332 [ + + ]: 110577 : if (flags & ASN1_TFLG_SEQUENCE_OF)
333 : 144 : isset = 2;
334 : : }
335 : : else isset = 0;
336 : :
337 : : /* Work out inner tag value: if EXPLICIT
338 : : * or no tagging use underlying type.
339 : : */
340 [ + + ][ + + ]: 112494 : if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
341 : : {
342 : : sktag = ttag;
343 : : skaclass = tclass;
344 : : }
345 : : else
346 : : {
347 : 111040 : skaclass = V_ASN1_UNIVERSAL;
348 [ + + ]: 111040 : if (isset)
349 : : sktag = V_ASN1_SET;
350 : 1328 : else sktag = V_ASN1_SEQUENCE;
351 : : }
352 : :
353 : : /* Determine total length of items */
354 : 112494 : skcontlen = 0;
355 [ + + ]: 230709 : for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
356 : : {
357 : 118215 : skitem = sk_ASN1_VALUE_value(sk, i);
358 : 118215 : skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
359 : 118215 : ASN1_ITEM_ptr(tt->item),
360 : : -1, iclass);
361 : : }
362 : 112494 : sklen = ASN1_object_size(ndef, skcontlen, sktag);
363 : : /* If EXPLICIT need length of surrounding tag */
364 [ + + ]: 112494 : if (flags & ASN1_TFLG_EXPTAG)
365 : 71 : ret = ASN1_object_size(ndef, sklen, ttag);
366 : : else ret = sklen;
367 : :
368 [ + + ]: 112494 : if (!out)
369 : : return ret;
370 : :
371 : : /* Now encode this lot... */
372 : : /* EXPLICIT tag */
373 [ + + ]: 53173 : if (flags & ASN1_TFLG_EXPTAG)
374 : 20 : ASN1_put_object(out, ndef, sklen, ttag, tclass);
375 : : /* SET or SEQUENCE and IMPLICIT tag */
376 : 53173 : ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
377 : : /* And the stuff itself */
378 : 53173 : asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
379 : : isset, iclass);
380 [ - + ]: 53173 : if (ndef == 2)
381 : : {
382 : 0 : ASN1_put_eoc(out);
383 [ # # ]: 0 : if (flags & ASN1_TFLG_EXPTAG)
384 : 0 : ASN1_put_eoc(out);
385 : : }
386 : :
387 : 114818 : return ret;
388 : : }
389 : :
390 [ + + ]: 574975 : if (flags & ASN1_TFLG_EXPTAG)
391 : : {
392 : : /* EXPLICIT tagging */
393 : : /* Find length of tagged item */
394 : 1666 : i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
395 : : -1, iclass);
396 [ + + ]: 1666 : if (!i)
397 : : return 0;
398 : : /* Find length of EXPLICIT tag */
399 : 1313 : ret = ASN1_object_size(ndef, i, ttag);
400 [ + + ]: 1313 : if (out)
401 : : {
402 : : /* Output tag and item */
403 : 330 : ASN1_put_object(out, ndef, i, ttag, tclass);
404 : 330 : ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
405 : : -1, iclass);
406 [ + + ]: 330 : if (ndef == 2)
407 : 120 : ASN1_put_eoc(out);
408 : : }
409 : 1313 : return ret;
410 : : }
411 : :
412 : : /* Either normal or IMPLICIT tagging: combine class and flags */
413 : 573309 : return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
414 : : ttag, tclass | iclass);
415 : :
416 : : }
417 : :
418 : : /* Temporary structure used to hold DER encoding of items for SET OF */
419 : :
420 : : typedef struct {
421 : : unsigned char *data;
422 : : int length;
423 : : ASN1_VALUE *field;
424 : : } DER_ENC;
425 : :
426 : 768 : static int der_cmp(const void *a, const void *b)
427 : : {
428 : 768 : const DER_ENC *d1 = a, *d2 = b;
429 : : int cmplen, i;
430 : 768 : cmplen = (d1->length < d2->length) ? d1->length : d2->length;
431 : 768 : i = memcmp(d1->data, d2->data, cmplen);
432 [ - + ]: 768 : if (i)
433 : : return i;
434 : 0 : return d1->length - d2->length;
435 : : }
436 : :
437 : : /* Output the content octets of SET OF or SEQUENCE OF */
438 : :
439 : 53173 : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
440 : : int skcontlen, const ASN1_ITEM *item,
441 : : int do_sort, int iclass)
442 : : {
443 : : int i;
444 : : ASN1_VALUE *skitem;
445 : 53173 : unsigned char *tmpdat = NULL, *p = NULL;
446 : 53173 : DER_ENC *derlst = NULL, *tder;
447 [ + + ]: 53173 : if (do_sort)
448 : : {
449 : : /* Don't need to sort less than 2 items */
450 [ + + ]: 52419 : if (sk_ASN1_VALUE_num(sk) < 2)
451 : : do_sort = 0;
452 : : else
453 : : {
454 : 218 : derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
455 : : * sizeof(*derlst));
456 [ + - ]: 218 : if (!derlst)
457 : : return 0;
458 : 218 : tmpdat = OPENSSL_malloc(skcontlen);
459 [ - + ]: 218 : if (!tmpdat)
460 : : {
461 : 0 : OPENSSL_free(derlst);
462 : 0 : return 0;
463 : : }
464 : : }
465 : : }
466 : : /* If not sorting just output each item */
467 [ + + ]: 53173 : if (!do_sort)
468 : : {
469 [ + + ]: 107229 : for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
470 : : {
471 : 54274 : skitem = sk_ASN1_VALUE_value(sk, i);
472 : 54274 : ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
473 : : }
474 : : return 1;
475 : : }
476 : 218 : p = tmpdat;
477 : :
478 : : /* Doing sort: build up a list of each member's DER encoding */
479 [ + + ]: 1013 : for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
480 : : {
481 : 795 : skitem = sk_ASN1_VALUE_value(sk, i);
482 : 795 : tder->data = p;
483 : 795 : tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
484 : 795 : tder->field = skitem;
485 : : }
486 : :
487 : : /* Now sort them */
488 : 218 : qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
489 : : /* Output sorted DER encoding */
490 : 218 : p = *out;
491 [ + + ]: 1013 : for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
492 : : {
493 : 795 : memcpy(p, tder->data, tder->length);
494 : 795 : p += tder->length;
495 : : }
496 : 218 : *out = p;
497 : : /* If do_sort is 2 then reorder the STACK */
498 [ + + ]: 218 : if (do_sort == 2)
499 : : {
500 [ + + ]: 359 : for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
501 : 287 : i++, tder++)
502 : 287 : (void)sk_ASN1_VALUE_set(sk, i, tder->field);
503 : : }
504 : 218 : OPENSSL_free(derlst);
505 : 218 : OPENSSL_free(tmpdat);
506 : 218 : return 1;
507 : : }
508 : :
509 : 566573 : static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
510 : : const ASN1_ITEM *it, int tag, int aclass)
511 : : {
512 : : int len;
513 : : int utype;
514 : : int usetag;
515 : 566573 : int ndef = 0;
516 : :
517 : 566573 : utype = it->utype;
518 : :
519 : : /* Get length of content octets and maybe find
520 : : * out the underlying type.
521 : : */
522 : :
523 : 566573 : len = asn1_ex_i2c(pval, NULL, &utype, it);
524 : :
525 : : /* If SEQUENCE, SET or OTHER then header is
526 : : * included in pseudo content octets so don't
527 : : * include tag+length. We need to check here
528 : : * because the call to asn1_ex_i2c() could change
529 : : * utype.
530 : : */
531 [ + + ]: 566573 : if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
532 : : (utype == V_ASN1_OTHER))
533 : : usetag = 0;
534 : 564253 : else usetag = 1;
535 : :
536 : : /* -1 means omit type */
537 : :
538 [ + + ]: 566573 : if (len == -1)
539 : : return 0;
540 : :
541 : : /* -2 return is special meaning use ndef */
542 [ + + ]: 561480 : if (len == -2)
543 : : {
544 : 546 : ndef = 2;
545 : 546 : len = 0;
546 : : }
547 : :
548 : : /* If not implicitly tagged get tag from underlying type */
549 [ + + ]: 561480 : if (tag == -1) tag = utype;
550 : :
551 : : /* Output tag+length followed by content octets */
552 [ + + ]: 561480 : if (out)
553 : : {
554 [ + + ]: 142158 : if (usetag)
555 : 141811 : ASN1_put_object(out, ndef, len, tag, aclass);
556 : 142158 : asn1_ex_i2c(pval, *out, &utype, it);
557 [ + + ]: 142158 : if (ndef)
558 : 86 : ASN1_put_eoc(out);
559 : : else
560 : 142072 : *out += len;
561 : : }
562 : :
563 [ + + ]: 561480 : if (usetag)
564 : 559160 : return ASN1_object_size(ndef, len, tag);
565 : : return len;
566 : : }
567 : :
568 : : /* Produce content octets from a structure */
569 : :
570 : 708731 : int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
571 : : const ASN1_ITEM *it)
572 : : {
573 : 708731 : ASN1_BOOLEAN *tbool = NULL;
574 : : ASN1_STRING *strtmp;
575 : : ASN1_OBJECT *otmp;
576 : : int utype;
577 : : const unsigned char *cont;
578 : : unsigned char c;
579 : : int len;
580 : : const ASN1_PRIMITIVE_FUNCS *pf;
581 : 708731 : pf = it->funcs;
582 [ + + ][ + - ]: 708731 : if (pf && pf->prim_i2c)
583 : 4038 : return pf->prim_i2c(pval, cout, putype, it);
584 : :
585 : : /* Should type be omitted? */
586 [ + + ]: 704693 : if ((it->itype != ASN1_ITYPE_PRIMITIVE)
587 [ + + ]: 446961 : || (it->utype != V_ASN1_BOOLEAN))
588 : : {
589 [ + + ]: 703913 : if (!*pval) return -1;
590 : : }
591 : :
592 [ + + ]: 700200 : if (it->itype == ASN1_ITYPE_MSTRING)
593 : : {
594 : : /* If MSTRING type set the underlying type */
595 : 257732 : strtmp = (ASN1_STRING *)*pval;
596 : 257732 : utype = strtmp->type;
597 : 257732 : *putype = utype;
598 : : }
599 [ + + ]: 442468 : else if (it->utype == V_ASN1_ANY)
600 : : {
601 : : /* If ANY set type and pointer to value */
602 : : ASN1_TYPE *typ;
603 : 45014 : typ = (ASN1_TYPE *)*pval;
604 : 45014 : utype = typ->type;
605 : 45014 : *putype = utype;
606 : 45014 : pval = &typ->value.asn1_value;
607 : : }
608 : 397454 : else utype = *putype;
609 : :
610 [ + + + + : 700200 : switch(utype)
+ + ]
611 : : {
612 : : case V_ASN1_OBJECT:
613 : 309926 : otmp = (ASN1_OBJECT *)*pval;
614 : 309926 : cont = otmp->data;
615 : 309926 : len = otmp->length;
616 : 309926 : break;
617 : :
618 : : case V_ASN1_NULL:
619 : : cont = NULL;
620 : : len = 0;
621 : : break;
622 : :
623 : : case V_ASN1_BOOLEAN:
624 : 780 : tbool = (ASN1_BOOLEAN *)pval;
625 [ + + ]: 780 : if (*tbool == -1)
626 : : return -1;
627 [ + - ]: 222 : if (it->utype != V_ASN1_ANY)
628 : : {
629 : : /* Default handling if value == size field then omit */
630 [ + + ][ + - ]: 222 : if (*tbool && (it->size > 0))
631 : : return -1;
632 [ + + ][ - + ]: 222 : if (!*tbool && !it->size)
633 : : return -1;
634 : : }
635 : 180 : c = (unsigned char)*tbool;
636 : 180 : cont = &c;
637 : 180 : len = 1;
638 : 180 : break;
639 : :
640 : : case V_ASN1_BIT_STRING:
641 [ + + ]: 24813 : return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
642 : 24813 : cout ? &cout : NULL);
643 : : break;
644 : :
645 : : case V_ASN1_INTEGER:
646 : : case V_ASN1_NEG_INTEGER:
647 : : case V_ASN1_ENUMERATED:
648 : : case V_ASN1_NEG_ENUMERATED:
649 : : /* These are all have the same content format
650 : : * as ASN1_INTEGER
651 : : */
652 [ + + ]: 31145 : return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
653 : 31145 : cout ? &cout : NULL);
654 : : break;
655 : :
656 : : case V_ASN1_OCTET_STRING:
657 : : case V_ASN1_NUMERICSTRING:
658 : : case V_ASN1_PRINTABLESTRING:
659 : : case V_ASN1_T61STRING:
660 : : case V_ASN1_VIDEOTEXSTRING:
661 : : case V_ASN1_IA5STRING:
662 : : case V_ASN1_UTCTIME:
663 : : case V_ASN1_GENERALIZEDTIME:
664 : : case V_ASN1_GRAPHICSTRING:
665 : : case V_ASN1_VISIBLESTRING:
666 : : case V_ASN1_GENERALSTRING:
667 : : case V_ASN1_UNIVERSALSTRING:
668 : : case V_ASN1_BMPSTRING:
669 : : case V_ASN1_UTF8STRING:
670 : : case V_ASN1_SEQUENCE:
671 : : case V_ASN1_SET:
672 : : default:
673 : : /* All based on ASN1_STRING and handled the same */
674 : 298576 : strtmp = (ASN1_STRING *)*pval;
675 : : /* Special handling for NDEF */
676 [ + + ]: 298576 : if ((it->size == ASN1_TFLG_NDEF)
677 [ + + ]: 768 : && (strtmp->flags & ASN1_STRING_FLAG_NDEF))
678 : : {
679 [ + + ]: 632 : if (cout)
680 : : {
681 : 86 : strtmp->data = cout;
682 : 86 : strtmp->length = 0;
683 : : }
684 : : /* Special return code */
685 : : return -2;
686 : : }
687 : 297944 : cont = strtmp->data;
688 : 297944 : len = strtmp->length;
689 : :
690 : 297944 : break;
691 : :
692 : : }
693 [ + + ][ + + ]: 643010 : if (cout && len)
694 : 119556 : memcpy(cout, cont, len);
695 : 643010 : return len;
696 : : }
|