GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/asn1/tasn_enc.c Lines: 208 258 80.6 %
Date: 2016-12-06 Branches: 135 189 71.4 %

Line Branch Exec Source
1
/* $OpenBSD: tasn_enc.c,v 1.20 2016/05/04 15:00:24 tedu Exp $ */
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
#include <stddef.h>
60
#include <string.h>
61
62
#include <openssl/asn1.h>
63
#include <openssl/asn1t.h>
64
#include <openssl/objects.h>
65
66
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
67
    const ASN1_ITEM *it, int tag, int aclass);
68
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
69
    int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass);
70
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
71
    const ASN1_TEMPLATE *tt, int tag, int aclass);
72
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
73
    const ASN1_ITEM *it, int flags);
74
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
75
    const ASN1_ITEM *it);
76
77
/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
78
 * to use indefinite length constructed encoding, where appropriate
79
 */
80
81
int
82
ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
83
{
84
	return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
85
}
86
87
int
88
ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
89
735
{
90
735
	return asn1_item_flags_i2d(val, out, it, 0);
91
}
92
93
/* Encode an ASN1 item, this is use by the
94
 * standard 'i2d' function. 'out' points to
95
 * a buffer to output the data to.
96
 *
97
 * The new i2d has one additional feature. If the output
98
 * buffer is NULL (i.e. *out == NULL) then a buffer is
99
 * allocated and populated with the encoding.
100
 */
101
102
static int
103
asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it,
104
    int flags)
105
735
{
106

735
	if (out && !*out) {
107
		unsigned char *p, *buf;
108
		int len;
109
418
		len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
110
418
		if (len <= 0)
111
			return len;
112
418
		buf = malloc(len);
113
418
		if (!buf)
114
			return -1;
115
418
		p = buf;
116
418
		ASN1_item_ex_i2d(&val, &p, it, -1, flags);
117
418
		*out = buf;
118
418
		return len;
119
	}
120
121
317
	return ASN1_item_ex_i2d(&val, out, it, -1, flags);
122
}
123
124
/* Encode an item, taking care of IMPLICIT tagging (if any).
125
 * This function performs the normal item handling: it can be
126
 * used in external types.
127
 */
128
129
int
130
ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
131
    int tag, int aclass)
132
23614
{
133
23614
	const ASN1_TEMPLATE *tt = NULL;
134
23614
	int i, seqcontlen, seqlen, ndef = 1;
135
	const ASN1_EXTERN_FUNCS *ef;
136
23614
	const ASN1_AUX *aux = it->funcs;
137
23614
	ASN1_aux_cb *asn1_cb = NULL;
138
139

23614
	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
140
		return 0;
141
142

23614
	if (aux && aux->asn1_cb)
143
3304
		asn1_cb = aux->asn1_cb;
144
145

23614
	switch (it->itype) {
146
147
	case ASN1_ITYPE_PRIMITIVE:
148
12475
		if (it->templates)
149
2716
			return asn1_template_ex_i2d(pval, out, it->templates,
150
			    tag, aclass);
151
9759
		return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
152
		break;
153
154
	case ASN1_ITYPE_MSTRING:
155
5408
		return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
156
157
	case ASN1_ITYPE_CHOICE:
158

152
		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
159
			return 0;
160
152
		i = asn1_get_choice_selector(pval, it);
161

152
		if ((i >= 0) && (i < it->tcount)) {
162
			ASN1_VALUE **pchval;
163
			const ASN1_TEMPLATE *chtt;
164
152
			chtt = it->templates + i;
165
152
			pchval = asn1_get_field_ptr(pval, chtt);
166
152
			return asn1_template_ex_i2d(pchval, out, chtt,
167
			    -1, aclass);
168
		}
169
		/* Fixme: error condition if selector out of range */
170
		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
171
			return 0;
172
		break;
173
174
	case ASN1_ITYPE_EXTERN:
175
		/* If new style i2d it does all the work */
176
36
		ef = it->funcs;
177
36
		return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
178
179
	case ASN1_ITYPE_NDEF_SEQUENCE:
180
		/* Use indefinite length constructed if requested */
181
33
		if (aclass & ASN1_TFLG_NDEF)
182
			ndef = 2;
183
		/* fall through */
184
185
	case ASN1_ITYPE_SEQUENCE:
186
5543
		i = asn1_enc_restore(&seqcontlen, out, pval, it);
187
		/* An error occurred */
188
5543
		if (i < 0)
189
			return 0;
190
		/* We have a valid cached encoding... */
191
5543
		if (i > 0)
192
55
			return seqcontlen;
193
		/* Otherwise carry on */
194
5488
		seqcontlen = 0;
195
		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
196
5488
		if (tag == -1) {
197
5488
			tag = V_ASN1_SEQUENCE;
198
			/* Retain any other flags in aclass */
199
5488
			aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) |
200
			    V_ASN1_UNIVERSAL;
201
		}
202

5488
		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
203
			return 0;
204
		/* First work out sequence content length */
205
16667
		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
206
			const ASN1_TEMPLATE *seqtt;
207
			ASN1_VALUE **pseqval;
208
11179
			seqtt = asn1_do_adb(pval, tt, 1);
209
11179
			if (!seqtt)
210
				return 0;
211
11179
			pseqval = asn1_get_field_ptr(pval, seqtt);
212
			/* FIXME: check for errors in enhanced version */
213
11179
			seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
214
			    -1, aclass);
215
		}
216
217
5488
		seqlen = ASN1_object_size(ndef, seqcontlen, tag);
218
5488
		if (!out)
219
3416
			return seqlen;
220
		/* Output SEQUENCE header */
221
2072
		ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
222
6265
		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
223
			const ASN1_TEMPLATE *seqtt;
224
			ASN1_VALUE **pseqval;
225
4193
			seqtt = asn1_do_adb(pval, tt, 1);
226
4193
			if (!seqtt)
227
				return 0;
228
4193
			pseqval = asn1_get_field_ptr(pval, seqtt);
229
			/* FIXME: check for errors in enhanced version */
230
4193
			asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
231
		}
232
2072
		if (ndef == 2)
233
			ASN1_put_eoc(out);
234

2072
		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
235
			return 0;
236
2072
		return seqlen;
237
238
	default:
239
		return 0;
240
241
	}
242
	return 0;
243
}
244
245
int
246
ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
247
    const ASN1_TEMPLATE *tt)
248
{
249
	return asn1_template_ex_i2d(pval, out, tt, -1, 0);
250
}
251
252
static int
253
asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
254
    const ASN1_TEMPLATE *tt, int tag, int iclass)
255
18240
{
256
	int i, ret, flags, ttag, tclass, ndef;
257
18240
	flags = tt->flags;
258
	/* Work out tag and class to use: tagging may come
259
	 * either from the template or the arguments, not both
260
	 * because this would create ambiguity. Additionally
261
	 * the iclass argument may contain some additional flags
262
	 * which should be noted and passed down to other levels.
263
	 */
264
18240
	if (flags & ASN1_TFLG_TAG_MASK) {
265
		/* Error if argument and template tagging */
266
127
		if (tag != -1)
267
			/* FIXME: error code here */
268
			return -1;
269
		/* Get tagging from template */
270
127
		ttag = tt->tag;
271
127
		tclass = flags & ASN1_TFLG_TAG_CLASS;
272
18113
	} else if (tag != -1) {
273
		/* No template tagging, get from arguments */
274
		ttag = tag;
275
		tclass = iclass & ASN1_TFLG_TAG_CLASS;
276
	} else {
277
18113
		ttag = -1;
278
18113
		tclass = 0;
279
	}
280
	/*
281
	 * Remove any class mask from iflag.
282
	 */
283
18240
	iclass &= ~ASN1_TFLG_TAG_CLASS;
284
285
	/* At this point 'ttag' contains the outer tag to use,
286
	 * 'tclass' is the class and iclass is any flags passed
287
	 * to this function.
288
	 */
289
290
	/* if template and arguments require ndef, use it */
291

18240
	if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
292
		ndef = 2;
293
	else
294
18240
		ndef = 1;
295
296
18240
	if (flags & ASN1_TFLG_SK_MASK) {
297
		/* SET OF, SEQUENCE OF */
298
2947
		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
299
		int isset, sktag, skaclass;
300
		int skcontlen, sklen;
301
		ASN1_VALUE *skitem;
302
303
2947
		if (!*pval)
304
40
			return 0;
305
306
2907
		if (flags & ASN1_TFLG_SET_OF) {
307
2869
			isset = 1;
308
			/* 2 means we reorder */
309
2869
			if (flags & ASN1_TFLG_SEQUENCE_OF)
310
4
				isset = 2;
311
		} else
312
38
			isset = 0;
313
314
		/* Work out inner tag value: if EXPLICIT
315
		 * or no tagging use underlying type.
316
		 */
317

2935
		if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
318
28
			sktag = ttag;
319
28
			skaclass = tclass;
320
		} else {
321
2879
			skaclass = V_ASN1_UNIVERSAL;
322
2879
			if (isset)
323
2869
				sktag = V_ASN1_SET;
324
			else
325
10
				sktag = V_ASN1_SEQUENCE;
326
		}
327
328
		/* Determine total length of items */
329
2907
		skcontlen = 0;
330
5929
		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
331
3022
			skitem = sk_ASN1_VALUE_value(sk, i);
332
3022
			skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
333
			    ASN1_ITEM_ptr(tt->item), -1, iclass);
334
		}
335
2907
		sklen = ASN1_object_size(ndef, skcontlen, sktag);
336
		/* If EXPLICIT need length of surrounding tag */
337
2907
		if (flags & ASN1_TFLG_EXPTAG)
338
			ret = ASN1_object_size(ndef, sklen, ttag);
339
		else
340
2907
			ret = sklen;
341
342
2907
		if (!out)
343
1514
			return ret;
344
345
		/* Now encode this lot... */
346
		/* EXPLICIT tag */
347
1393
		if (flags & ASN1_TFLG_EXPTAG)
348
			ASN1_put_object(out, ndef, sklen, ttag, tclass);
349
		/* SET or SEQUENCE and IMPLICIT tag */
350
1393
		ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
351
		/* And the stuff itself */
352
1393
		asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
353
		    isset, iclass);
354
1393
		if (ndef == 2) {
355
			ASN1_put_eoc(out);
356
			if (flags & ASN1_TFLG_EXPTAG)
357
				ASN1_put_eoc(out);
358
		}
359
360
1393
		return ret;
361
	}
362
363
15293
	if (flags & ASN1_TFLG_EXPTAG) {
364
		/* EXPLICIT tagging */
365
		/* Find length of tagged item */
366
43
		i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
367
		    -1, iclass);
368
43
		if (!i)
369
12
			return 0;
370
		/* Find length of EXPLICIT tag */
371
31
		ret = ASN1_object_size(ndef, i, ttag);
372
31
		if (out) {
373
			/* Output tag and item */
374
8
			ASN1_put_object(out, ndef, i, ttag, tclass);
375
8
			ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
376
			    -1, iclass);
377
8
			if (ndef == 2)
378
				ASN1_put_eoc(out);
379
		}
380
31
		return ret;
381
	}
382
383
	/* Either normal or IMPLICIT tagging: combine class and flags */
384
15250
	return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
385
	    ttag, tclass | iclass);
386
}
387
388
/* Temporary structure used to hold DER encoding of items for SET OF */
389
390
typedef	struct {
391
	unsigned char *data;
392
	int length;
393
	ASN1_VALUE *field;
394
} DER_ENC;
395
396
static int
397
der_cmp(const void *a, const void *b)
398
10
{
399
10
	const DER_ENC *d1 = a, *d2 = b;
400
	int cmplen, i;
401
402
10
	cmplen = (d1->length < d2->length) ? d1->length : d2->length;
403
10
	i = memcmp(d1->data, d2->data, cmplen);
404
10
	if (i)
405
10
		return i;
406
	return d1->length - d2->length;
407
}
408
409
/* Output the content octets of SET OF or SEQUENCE OF */
410
411
static int
412
asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen,
413
    const ASN1_ITEM *item, int do_sort, int iclass)
414
1393
{
415
	int i;
416
	ASN1_VALUE *skitem;
417
1393
	unsigned char *tmpdat = NULL, *p = NULL;
418
1393
	DER_ENC *derlst = NULL, *tder;
419
420
1393
	if (do_sort) {
421
		/* Don't need to sort less than 2 items */
422
1383
		if (sk_ASN1_VALUE_num(sk) < 2)
423
1381
			do_sort = 0;
424
		else {
425
2
			derlst = reallocarray(NULL, sk_ASN1_VALUE_num(sk),
426
			    sizeof(*derlst));
427
2
			tmpdat = malloc(skcontlen);
428
2
			if (!derlst || !tmpdat) {
429
				free(derlst);
430
				free(tmpdat);
431
				return 0;
432
			}
433
		}
434
	}
435
	/* If not sorting just output each item */
436
1393
	if (!do_sort) {
437
2817
		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
438
1426
			skitem = sk_ASN1_VALUE_value(sk, i);
439
1426
			ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
440
		}
441
1391
		return 1;
442
	}
443
2
	p = tmpdat;
444
445
	/* Doing sort: build up a list of each member's DER encoding */
446
10
	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
447
8
		skitem = sk_ASN1_VALUE_value(sk, i);
448
8
		tder->data = p;
449
8
		tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
450
8
		tder->field = skitem;
451
	}
452
453
	/* Now sort them */
454
2
	qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
455
	/* Output sorted DER encoding */
456
2
	p = *out;
457
10
	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
458
8
		memcpy(p, tder->data, tder->length);
459
8
		p += tder->length;
460
	}
461
2
	*out = p;
462
	/* If do_sort is 2 then reorder the STACK */
463
2
	if (do_sort == 2) {
464
10
		for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
465
8
			(void)sk_ASN1_VALUE_set(sk, i, tder->field);
466
	}
467
2
	free(derlst);
468
2
	free(tmpdat);
469
2
	return 1;
470
}
471
472
static int
473
asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
474
    const ASN1_ITEM *it, int tag, int aclass)
475
15167
{
476
	int len;
477
	int utype;
478
	int usetag;
479
15167
	int ndef = 0;
480
481
15167
	utype = it->utype;
482
483
	/* Get length of content octets and maybe find
484
	 * out the underlying type.
485
	 */
486
487
15167
	len = asn1_ex_i2c(pval, NULL, &utype, it);
488
489
	/* If SEQUENCE, SET or OTHER then header is
490
	 * included in pseudo content octets so don't
491
	 * include tag+length. We need to check here
492
	 * because the call to asn1_ex_i2c() could change
493
	 * utype.
494
	 */
495
15167
	if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
496
	    (utype == V_ASN1_OTHER))
497
40
		usetag = 0;
498
	else
499
15127
		usetag = 1;
500
501
	/* -1 means omit type */
502
15167
	if (len == -1)
503
88
		return 0;
504
505
	/* -2 return is special meaning use ndef */
506
15079
	if (len == -2) {
507
		ndef = 2;
508
		len = 0;
509
	}
510
511
	/* If not implicitly tagged get tag from underlying type */
512
15079
	if (tag == -1)
513
15063
		tag = utype;
514
515
	/* Output tag+length followed by content octets */
516
15079
	if (out) {
517
4112
		if (usetag)
518
4106
			ASN1_put_object(out, ndef, len, tag, aclass);
519
4112
		asn1_ex_i2c(pval, *out, &utype, it);
520
4112
		if (ndef)
521
			ASN1_put_eoc(out);
522
		else
523
4112
			*out += len;
524
	}
525
526
15079
	if (usetag)
527
15039
		return ASN1_object_size(ndef, len, tag);
528
40
	return len;
529
}
530
531
/* Produce content octets from a structure */
532
533
static int
534
asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
535
    const ASN1_ITEM *it)
536
19279
{
537
19279
	ASN1_BOOLEAN *tbool = NULL;
538
	ASN1_STRING *strtmp;
539
	ASN1_OBJECT *otmp;
540
	int utype;
541
	const unsigned char *cont;
542
	unsigned char c;
543
	int len;
544
	const ASN1_PRIMITIVE_FUNCS *pf;
545
546
19279
	pf = it->funcs;
547

19279
	if (pf && pf->prim_i2c)
548
4460
		return pf->prim_i2c(pval, cout, putype, it);
549
550
	/* Should type be omitted? */
551

14819
	if ((it->itype != ASN1_ITYPE_PRIMITIVE) ||
552
	    (it->utype != V_ASN1_BOOLEAN)) {
553
14819
		if (!*pval)
554
88
			return -1;
555
	}
556
557
14731
	if (it->itype == ASN1_ITYPE_MSTRING) {
558
		/* If MSTRING type set the underlying type */
559
6760
		strtmp = (ASN1_STRING *)*pval;
560
6760
		utype = strtmp->type;
561
6760
		*putype = utype;
562
7971
	} else if (it->utype == V_ASN1_ANY) {
563
		/* If ANY set type and pointer to value */
564
		ASN1_TYPE *typ;
565
371
		typ = (ASN1_TYPE *)*pval;
566
371
		utype = typ->type;
567
371
		*putype = utype;
568
371
		pval = &typ->value.asn1_value;
569
	} else
570
7600
		utype = *putype;
571
572

14731
	switch (utype) {
573
	case V_ASN1_OBJECT:
574
7281
		otmp = (ASN1_OBJECT *)*pval;
575
7281
		cont = otmp->data;
576
7281
		len = otmp->length;
577
7281
		break;
578
579
	case V_ASN1_NULL:
580
161
		cont = NULL;
581
161
		len = 0;
582
161
		break;
583
584
	case V_ASN1_BOOLEAN:
585
		tbool = (ASN1_BOOLEAN *)pval;
586
		if (*tbool == -1)
587
			return -1;
588
		if (it->utype != V_ASN1_ANY) {
589
			/* Default handling if value == size field then omit */
590
			if (*tbool && (it->size > 0))
591
				return -1;
592
			if (!*tbool && !it->size)
593
				return -1;
594
		}
595
		c = (unsigned char)*tbool;
596
		cont = &c;
597
		len = 1;
598
		break;
599
600
	case V_ASN1_BIT_STRING:
601
56
		return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
602
		    cout ? &cout : NULL);
603
		break;
604
605
	case V_ASN1_INTEGER:
606
	case V_ASN1_ENUMERATED:
607
		/* These are all have the same content format
608
		 * as ASN1_INTEGER
609
		 */
610
190
		return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
611
		    cout ? &cout : NULL);
612
		break;
613
614
	case V_ASN1_OCTET_STRING:
615
	case V_ASN1_NUMERICSTRING:
616
	case V_ASN1_PRINTABLESTRING:
617
	case V_ASN1_T61STRING:
618
	case V_ASN1_VIDEOTEXSTRING:
619
	case V_ASN1_IA5STRING:
620
	case V_ASN1_UTCTIME:
621
	case V_ASN1_GENERALIZEDTIME:
622
	case V_ASN1_GRAPHICSTRING:
623
	case V_ASN1_VISIBLESTRING:
624
	case V_ASN1_GENERALSTRING:
625
	case V_ASN1_UNIVERSALSTRING:
626
	case V_ASN1_BMPSTRING:
627
	case V_ASN1_UTF8STRING:
628
	case V_ASN1_SEQUENCE:
629
	case V_ASN1_SET:
630
	default:
631
		/* All based on ASN1_STRING and handled the same */
632
7043
		strtmp = (ASN1_STRING *)*pval;
633
		/* Special handling for NDEF */
634

7043
		if ((it->size == ASN1_TFLG_NDEF) &&
635
		    (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
636
			if (cout) {
637
				strtmp->data = cout;
638
				strtmp->length = 0;
639
			}
640
			/* Special return code */
641
			return -2;
642
		}
643
7043
		cont = strtmp->data;
644
7043
		len = strtmp->length;
645
646
		break;
647
648
	}
649
14485
	if (cout && len)
650
2831
		memcpy(cout, cont, len);
651
14485
	return len;
652
}