2 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 #include "internal/cryptlib.h"
13 #include <openssl/asn1.h>
14 #include <openssl/asn1t.h>
15 #include <openssl/objects.h>
16 #include "crypto/asn1.h"
17 #include "asn1_local.h"
19 static int asn1_i2d_ex_primitive(const ASN1_VALUE
**pval
, unsigned char **out
,
20 const ASN1_ITEM
*it
, int tag
, int aclass
);
21 static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE
) *sk
,
23 int skcontlen
, const ASN1_ITEM
*item
,
24 int do_sort
, int iclass
);
25 static int asn1_template_ex_i2d(const ASN1_VALUE
**pval
, unsigned char **out
,
26 const ASN1_TEMPLATE
*tt
, int tag
, int aclass
);
27 static int asn1_item_flags_i2d(const ASN1_VALUE
*val
, unsigned char **out
,
28 const ASN1_ITEM
*it
, int flags
);
29 static int asn1_ex_i2c(const ASN1_VALUE
**pval
, unsigned char *cout
, int *putype
,
33 * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
34 * indefinite length constructed encoding, where appropriate
37 int ASN1_item_ndef_i2d(const ASN1_VALUE
*val
, unsigned char **out
,
40 return asn1_item_flags_i2d(val
, out
, it
, ASN1_TFLG_NDEF
);
43 int ASN1_item_i2d(const ASN1_VALUE
*val
, unsigned char **out
, const ASN1_ITEM
*it
)
45 return asn1_item_flags_i2d(val
, out
, it
, 0);
49 * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
50 * points to a buffer to output the data to. The new i2d has one additional
51 * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
52 * allocated and populated with the encoding.
55 static int asn1_item_flags_i2d(const ASN1_VALUE
*val
, unsigned char **out
,
56 const ASN1_ITEM
*it
, int flags
)
59 unsigned char *p
, *buf
;
62 len
= ASN1_item_ex_i2d(&val
, NULL
, it
, -1, flags
);
65 if ((buf
= OPENSSL_malloc(len
)) == NULL
) {
66 ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D
, ERR_R_MALLOC_FAILURE
);
70 ASN1_item_ex_i2d(&val
, &p
, it
, -1, flags
);
75 return ASN1_item_ex_i2d(&val
, out
, it
, -1, flags
);
79 * Encode an item, taking care of IMPLICIT tagging (if any). This function
80 * performs the normal item handling: it can be used in external types.
83 int ASN1_item_ex_i2d(const ASN1_VALUE
**pval
, unsigned char **out
,
84 const ASN1_ITEM
*it
, int tag
, int aclass
)
86 const ASN1_TEMPLATE
*tt
= NULL
;
87 int i
, seqcontlen
, seqlen
, ndef
= 1;
88 const ASN1_EXTERN_FUNCS
*ef
;
89 const ASN1_AUX
*aux
= it
->funcs
;
90 ASN1_aux_const_cb
*asn1_cb
= NULL
;
92 if ((it
->itype
!= ASN1_ITYPE_PRIMITIVE
) && !*pval
)
96 asn1_cb
= ((aux
->flags
& ASN1_AFLG_CONST_CB
) != 0) ? aux
->asn1_const_cb
97 : (ASN1_aux_const_cb
*)aux
->asn1_cb
; /* backward compatibility */
102 case ASN1_ITYPE_PRIMITIVE
:
104 return asn1_template_ex_i2d(pval
, out
, it
->templates
,
106 return asn1_i2d_ex_primitive(pval
, out
, it
, tag
, aclass
);
108 case ASN1_ITYPE_MSTRING
:
109 return asn1_i2d_ex_primitive(pval
, out
, it
, -1, aclass
);
111 case ASN1_ITYPE_CHOICE
:
112 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_PRE
, pval
, it
, NULL
))
114 i
= asn1_get_choice_selector_const(pval
, it
);
115 if ((i
>= 0) && (i
< it
->tcount
)) {
116 const ASN1_VALUE
**pchval
;
117 const ASN1_TEMPLATE
*chtt
;
118 chtt
= it
->templates
+ i
;
119 pchval
= asn1_get_const_field_ptr(pval
, chtt
);
120 return asn1_template_ex_i2d(pchval
, out
, chtt
, -1, aclass
);
122 /* Fixme: error condition if selector out of range */
123 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_POST
, pval
, it
, NULL
))
127 case ASN1_ITYPE_EXTERN
:
128 /* If new style i2d it does all the work */
130 return ef
->asn1_ex_i2d(pval
, out
, it
, tag
, aclass
);
132 case ASN1_ITYPE_NDEF_SEQUENCE
:
133 /* Use indefinite length constructed if requested */
134 if (aclass
& ASN1_TFLG_NDEF
)
138 case ASN1_ITYPE_SEQUENCE
:
139 i
= asn1_enc_restore(&seqcontlen
, out
, pval
, it
);
140 /* An error occurred */
143 /* We have a valid cached encoding... */
146 /* Otherwise carry on */
148 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
150 tag
= V_ASN1_SEQUENCE
;
151 /* Retain any other flags in aclass */
152 aclass
= (aclass
& ~ASN1_TFLG_TAG_CLASS
)
155 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_PRE
, pval
, it
, NULL
))
157 /* First work out sequence content length */
158 for (i
= 0, tt
= it
->templates
; i
< it
->tcount
; tt
++, i
++) {
159 const ASN1_TEMPLATE
*seqtt
;
160 const ASN1_VALUE
**pseqval
;
162 seqtt
= asn1_do_adb(*pval
, tt
, 1);
165 pseqval
= asn1_get_const_field_ptr(pval
, seqtt
);
166 tmplen
= asn1_template_ex_i2d(pseqval
, NULL
, seqtt
, -1, aclass
);
167 if (tmplen
== -1 || (tmplen
> INT_MAX
- seqcontlen
))
169 seqcontlen
+= tmplen
;
172 seqlen
= ASN1_object_size(ndef
, seqcontlen
, tag
);
173 if (!out
|| seqlen
== -1)
175 /* Output SEQUENCE header */
176 ASN1_put_object(out
, ndef
, seqcontlen
, tag
, aclass
);
177 for (i
= 0, tt
= it
->templates
; i
< it
->tcount
; tt
++, i
++) {
178 const ASN1_TEMPLATE
*seqtt
;
179 const ASN1_VALUE
**pseqval
;
180 seqtt
= asn1_do_adb(*pval
, tt
, 1);
183 pseqval
= asn1_get_const_field_ptr(pval
, seqtt
);
184 /* FIXME: check for errors in enhanced version */
185 asn1_template_ex_i2d(pseqval
, out
, seqtt
, -1, aclass
);
189 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_POST
, pval
, it
, NULL
))
200 static int asn1_template_ex_i2d(const ASN1_VALUE
**pval
, unsigned char **out
,
201 const ASN1_TEMPLATE
*tt
, int tag
, int iclass
)
203 int i
, ret
, flags
, ttag
, tclass
, ndef
;
204 const ASN1_VALUE
*tval
;
208 * If field is embedded then val needs fixing so it is a pointer to
209 * a pointer to a field.
211 if (flags
& ASN1_TFLG_EMBED
) {
212 tval
= (ASN1_VALUE
*)pval
;
216 * Work out tag and class to use: tagging may come either from the
217 * template or the arguments, not both because this would create
218 * ambiguity. Additionally the iclass argument may contain some
219 * additional flags which should be noted and passed down to other
222 if (flags
& ASN1_TFLG_TAG_MASK
) {
223 /* Error if argument and template tagging */
225 /* FIXME: error code here */
227 /* Get tagging from template */
229 tclass
= flags
& ASN1_TFLG_TAG_CLASS
;
230 } else if (tag
!= -1) {
231 /* No template tagging, get from arguments */
233 tclass
= iclass
& ASN1_TFLG_TAG_CLASS
;
239 * Remove any class mask from iflag.
241 iclass
&= ~ASN1_TFLG_TAG_CLASS
;
244 * At this point 'ttag' contains the outer tag to use, 'tclass' is the
245 * class and iclass is any flags passed to this function.
248 /* if template and arguments require ndef, use it */
249 if ((flags
& ASN1_TFLG_NDEF
) && (iclass
& ASN1_TFLG_NDEF
))
254 if (flags
& ASN1_TFLG_SK_MASK
) {
255 /* SET OF, SEQUENCE OF */
256 STACK_OF(const_ASN1_VALUE
) *sk
= (STACK_OF(const_ASN1_VALUE
) *)*pval
;
257 int isset
, sktag
, skaclass
;
258 int skcontlen
, sklen
;
259 const ASN1_VALUE
*skitem
;
264 if (flags
& ASN1_TFLG_SET_OF
) {
266 /* 2 means we reorder */
267 if (flags
& ASN1_TFLG_SEQUENCE_OF
)
273 * Work out inner tag value: if EXPLICIT or no tagging use underlying
276 if ((ttag
!= -1) && !(flags
& ASN1_TFLG_EXPTAG
)) {
280 skaclass
= V_ASN1_UNIVERSAL
;
284 sktag
= V_ASN1_SEQUENCE
;
287 /* Determine total length of items */
289 for (i
= 0; i
< sk_const_ASN1_VALUE_num(sk
); i
++) {
291 skitem
= sk_const_ASN1_VALUE_value(sk
, i
);
292 tmplen
= ASN1_item_ex_i2d(&skitem
, NULL
, ASN1_ITEM_ptr(tt
->item
),
294 if (tmplen
== -1 || (skcontlen
> INT_MAX
- tmplen
))
298 sklen
= ASN1_object_size(ndef
, skcontlen
, sktag
);
301 /* If EXPLICIT need length of surrounding tag */
302 if (flags
& ASN1_TFLG_EXPTAG
)
303 ret
= ASN1_object_size(ndef
, sklen
, ttag
);
307 if (!out
|| ret
== -1)
310 /* Now encode this lot... */
312 if (flags
& ASN1_TFLG_EXPTAG
)
313 ASN1_put_object(out
, ndef
, sklen
, ttag
, tclass
);
314 /* SET or SEQUENCE and IMPLICIT tag */
315 ASN1_put_object(out
, ndef
, skcontlen
, sktag
, skaclass
);
316 /* And the stuff itself */
317 asn1_set_seq_out(sk
, out
, skcontlen
, ASN1_ITEM_ptr(tt
->item
),
321 if (flags
& ASN1_TFLG_EXPTAG
)
328 if (flags
& ASN1_TFLG_EXPTAG
) {
329 /* EXPLICIT tagging */
330 /* Find length of tagged item */
331 i
= ASN1_item_ex_i2d(pval
, NULL
, ASN1_ITEM_ptr(tt
->item
), -1, iclass
);
334 /* Find length of EXPLICIT tag */
335 ret
= ASN1_object_size(ndef
, i
, ttag
);
336 if (out
&& ret
!= -1) {
337 /* Output tag and item */
338 ASN1_put_object(out
, ndef
, i
, ttag
, tclass
);
339 ASN1_item_ex_i2d(pval
, out
, ASN1_ITEM_ptr(tt
->item
), -1, iclass
);
346 /* Either normal or IMPLICIT tagging: combine class and flags */
347 return ASN1_item_ex_i2d(pval
, out
, ASN1_ITEM_ptr(tt
->item
),
348 ttag
, tclass
| iclass
);
352 /* Temporary structure used to hold DER encoding of items for SET OF */
357 const ASN1_VALUE
*field
;
360 static int der_cmp(const void *a
, const void *b
)
362 const DER_ENC
*d1
= a
, *d2
= b
;
364 cmplen
= (d1
->length
< d2
->length
) ? d1
->length
: d2
->length
;
365 i
= memcmp(d1
->data
, d2
->data
, cmplen
);
368 return d1
->length
- d2
->length
;
371 /* Output the content octets of SET OF or SEQUENCE OF */
373 static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE
) *sk
,
375 int skcontlen
, const ASN1_ITEM
*item
,
376 int do_sort
, int iclass
)
379 const ASN1_VALUE
*skitem
;
380 unsigned char *tmpdat
= NULL
, *p
= NULL
;
381 DER_ENC
*derlst
= NULL
, *tder
;
383 /* Don't need to sort less than 2 items */
384 if (sk_const_ASN1_VALUE_num(sk
) < 2)
387 derlst
= OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk
)
391 tmpdat
= OPENSSL_malloc(skcontlen
);
392 if (tmpdat
== NULL
) {
393 OPENSSL_free(derlst
);
398 /* If not sorting just output each item */
400 for (i
= 0; i
< sk_const_ASN1_VALUE_num(sk
); i
++) {
401 skitem
= sk_const_ASN1_VALUE_value(sk
, i
);
402 ASN1_item_ex_i2d(&skitem
, out
, item
, -1, iclass
);
408 /* Doing sort: build up a list of each member's DER encoding */
409 for (i
= 0, tder
= derlst
; i
< sk_const_ASN1_VALUE_num(sk
); i
++, tder
++) {
410 skitem
= sk_const_ASN1_VALUE_value(sk
, i
);
412 tder
->length
= ASN1_item_ex_i2d(&skitem
, &p
, item
, -1, iclass
);
413 tder
->field
= skitem
;
417 qsort(derlst
, sk_const_ASN1_VALUE_num(sk
), sizeof(*derlst
), der_cmp
);
418 /* Output sorted DER encoding */
420 for (i
= 0, tder
= derlst
; i
< sk_const_ASN1_VALUE_num(sk
); i
++, tder
++) {
421 memcpy(p
, tder
->data
, tder
->length
);
425 /* If do_sort is 2 then reorder the STACK */
427 for (i
= 0, tder
= derlst
; i
< sk_const_ASN1_VALUE_num(sk
); i
++, tder
++)
428 (void)sk_const_ASN1_VALUE_set(sk
, i
, tder
->field
);
430 OPENSSL_free(derlst
);
431 OPENSSL_free(tmpdat
);
435 static int asn1_i2d_ex_primitive(const ASN1_VALUE
**pval
, unsigned char **out
,
436 const ASN1_ITEM
*it
, int tag
, int aclass
)
446 * Get length of content octets and maybe find out the underlying type.
449 len
= asn1_ex_i2c(pval
, NULL
, &utype
, it
);
452 * If SEQUENCE, SET or OTHER then header is included in pseudo content
453 * octets so don't include tag+length. We need to check here because the
454 * call to asn1_ex_i2c() could change utype.
456 if ((utype
== V_ASN1_SEQUENCE
) || (utype
== V_ASN1_SET
) ||
457 (utype
== V_ASN1_OTHER
))
462 /* -1 means omit type */
467 /* -2 return is special meaning use ndef */
473 /* If not implicitly tagged get tag from underlying type */
477 /* Output tag+length followed by content octets */
480 ASN1_put_object(out
, ndef
, len
, tag
, aclass
);
481 asn1_ex_i2c(pval
, *out
, &utype
, it
);
489 return ASN1_object_size(ndef
, len
, tag
);
493 /* Produce content octets from a structure */
495 static int asn1_ex_i2c(const ASN1_VALUE
**pval
, unsigned char *cout
, int *putype
,
498 ASN1_BOOLEAN
*tbool
= NULL
;
502 const unsigned char *cont
;
505 const ASN1_PRIMITIVE_FUNCS
*pf
;
507 if (pf
&& pf
->prim_i2c
)
508 return pf
->prim_i2c(pval
, cout
, putype
, it
);
510 /* Should type be omitted? */
511 if ((it
->itype
!= ASN1_ITYPE_PRIMITIVE
)
512 || (it
->utype
!= V_ASN1_BOOLEAN
)) {
517 if (it
->itype
== ASN1_ITYPE_MSTRING
) {
518 /* If MSTRING type set the underlying type */
519 strtmp
= (ASN1_STRING
*)*pval
;
520 utype
= strtmp
->type
;
522 } else if (it
->utype
== V_ASN1_ANY
) {
523 /* If ANY set type and pointer to value */
525 typ
= (ASN1_TYPE
*)*pval
;
528 pval
= (const ASN1_VALUE
**)&typ
->value
.asn1_value
; /* actually is const */
534 otmp
= (ASN1_OBJECT
*)*pval
;
537 if (cont
== NULL
|| len
== 0)
547 tbool
= (ASN1_BOOLEAN
*)pval
;
550 if (it
->utype
!= V_ASN1_ANY
) {
552 * Default handling if value == size field then omit
554 if (*tbool
&& (it
->size
> 0))
556 if (!*tbool
&& !it
->size
)
559 c
= (unsigned char)*tbool
;
564 case V_ASN1_BIT_STRING
:
565 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING
*)*pval
,
566 cout
? &cout
: NULL
);
569 case V_ASN1_ENUMERATED
:
571 * These are all have the same content format as ASN1_INTEGER
573 return i2c_ASN1_INTEGER((ASN1_INTEGER
*)*pval
, cout
? &cout
: NULL
);
575 case V_ASN1_OCTET_STRING
:
576 case V_ASN1_NUMERICSTRING
:
577 case V_ASN1_PRINTABLESTRING
:
578 case V_ASN1_T61STRING
:
579 case V_ASN1_VIDEOTEXSTRING
:
580 case V_ASN1_IA5STRING
:
582 case V_ASN1_GENERALIZEDTIME
:
583 case V_ASN1_GRAPHICSTRING
:
584 case V_ASN1_VISIBLESTRING
:
585 case V_ASN1_GENERALSTRING
:
586 case V_ASN1_UNIVERSALSTRING
:
587 case V_ASN1_BMPSTRING
:
588 case V_ASN1_UTF8STRING
:
589 case V_ASN1_SEQUENCE
:
592 /* All based on ASN1_STRING and handled the same */
593 strtmp
= (ASN1_STRING
*)*pval
;
594 /* Special handling for NDEF */
595 if ((it
->size
== ASN1_TFLG_NDEF
)
596 && (strtmp
->flags
& ASN1_STRING_FLAG_NDEF
)) {
601 /* Special return code */
605 len
= strtmp
->length
;
611 memcpy(cout
, cont
, len
);