]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/asn1/tasn_enc.c
2 * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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 "internal/asn1_int.h"
17 #include "asn1_locl.h"
19 static int asn1_i2d_ex_primitive(ASN1_VALUE
**pval
, unsigned char **out
,
20 const ASN1_ITEM
*it
, int tag
, int aclass
);
21 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE
) *sk
, unsigned char **out
,
22 int skcontlen
, const ASN1_ITEM
*item
,
23 int do_sort
, int iclass
);
24 static int asn1_template_ex_i2d(ASN1_VALUE
**pval
, unsigned char **out
,
25 const ASN1_TEMPLATE
*tt
, int tag
, int aclass
);
26 static int asn1_item_flags_i2d(ASN1_VALUE
*val
, unsigned char **out
,
27 const ASN1_ITEM
*it
, int flags
);
28 static int asn1_ex_i2c(ASN1_VALUE
**pval
, unsigned char *cout
, int *putype
,
32 * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
33 * indefinite length constructed encoding, where appropriate
36 int ASN1_item_ndef_i2d(ASN1_VALUE
*val
, unsigned char **out
,
39 return asn1_item_flags_i2d(val
, out
, it
, ASN1_TFLG_NDEF
);
42 int ASN1_item_i2d(ASN1_VALUE
*val
, unsigned char **out
, const ASN1_ITEM
*it
)
44 return asn1_item_flags_i2d(val
, out
, it
, 0);
48 * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
49 * points to a buffer to output the data to. The new i2d has one additional
50 * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
51 * allocated and populated with the encoding.
54 static int asn1_item_flags_i2d(ASN1_VALUE
*val
, unsigned char **out
,
55 const ASN1_ITEM
*it
, int flags
)
58 unsigned char *p
, *buf
;
60 len
= ASN1_item_ex_i2d(&val
, NULL
, it
, -1, flags
);
63 buf
= OPENSSL_malloc(len
);
67 ASN1_item_ex_i2d(&val
, &p
, it
, -1, flags
);
72 return ASN1_item_ex_i2d(&val
, out
, it
, -1, flags
);
76 * Encode an item, taking care of IMPLICIT tagging (if any). This function
77 * performs the normal item handling: it can be used in external types.
80 int ASN1_item_ex_i2d(ASN1_VALUE
**pval
, unsigned char **out
,
81 const ASN1_ITEM
*it
, int tag
, int aclass
)
83 const ASN1_TEMPLATE
*tt
= NULL
;
84 int i
, seqcontlen
, seqlen
, ndef
= 1;
85 const ASN1_EXTERN_FUNCS
*ef
;
86 const ASN1_AUX
*aux
= it
->funcs
;
87 ASN1_aux_cb
*asn1_cb
= 0;
89 if ((it
->itype
!= ASN1_ITYPE_PRIMITIVE
) && !*pval
)
92 if (aux
&& aux
->asn1_cb
)
93 asn1_cb
= aux
->asn1_cb
;
97 case ASN1_ITYPE_PRIMITIVE
:
99 return asn1_template_ex_i2d(pval
, out
, it
->templates
,
101 return asn1_i2d_ex_primitive(pval
, out
, it
, tag
, aclass
);
103 case ASN1_ITYPE_MSTRING
:
104 return asn1_i2d_ex_primitive(pval
, out
, it
, -1, aclass
);
106 case ASN1_ITYPE_CHOICE
:
107 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_PRE
, pval
, it
, NULL
))
109 i
= asn1_get_choice_selector(pval
, it
);
110 if ((i
>= 0) && (i
< it
->tcount
)) {
112 const ASN1_TEMPLATE
*chtt
;
113 chtt
= it
->templates
+ i
;
114 pchval
= asn1_get_field_ptr(pval
, chtt
);
115 return asn1_template_ex_i2d(pchval
, out
, chtt
, -1, aclass
);
117 /* Fixme: error condition if selector out of range */
118 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_POST
, pval
, it
, NULL
))
122 case ASN1_ITYPE_EXTERN
:
123 /* If new style i2d it does all the work */
125 return ef
->asn1_ex_i2d(pval
, out
, it
, tag
, aclass
);
127 case ASN1_ITYPE_NDEF_SEQUENCE
:
128 /* Use indefinite length constructed if requested */
129 if (aclass
& ASN1_TFLG_NDEF
)
133 case ASN1_ITYPE_SEQUENCE
:
134 i
= asn1_enc_restore(&seqcontlen
, out
, pval
, it
);
135 /* An error occurred */
138 /* We have a valid cached encoding... */
141 /* Otherwise carry on */
143 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
145 tag
= V_ASN1_SEQUENCE
;
146 /* Retain any other flags in aclass */
147 aclass
= (aclass
& ~ASN1_TFLG_TAG_CLASS
)
150 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_PRE
, pval
, it
, NULL
))
152 /* First work out sequence content length */
153 for (i
= 0, tt
= it
->templates
; i
< it
->tcount
; tt
++, i
++) {
154 const ASN1_TEMPLATE
*seqtt
;
155 ASN1_VALUE
**pseqval
;
157 seqtt
= asn1_do_adb(pval
, tt
, 1);
160 pseqval
= asn1_get_field_ptr(pval
, seqtt
);
161 tmplen
= asn1_template_ex_i2d(pseqval
, NULL
, seqtt
, -1, aclass
);
162 if (tmplen
== -1 || (tmplen
> INT_MAX
- seqcontlen
))
164 seqcontlen
+= tmplen
;
167 seqlen
= ASN1_object_size(ndef
, seqcontlen
, tag
);
168 if (!out
|| seqlen
== -1)
170 /* Output SEQUENCE header */
171 ASN1_put_object(out
, ndef
, seqcontlen
, tag
, aclass
);
172 for (i
= 0, tt
= it
->templates
; i
< it
->tcount
; tt
++, i
++) {
173 const ASN1_TEMPLATE
*seqtt
;
174 ASN1_VALUE
**pseqval
;
175 seqtt
= asn1_do_adb(pval
, tt
, 1);
178 pseqval
= asn1_get_field_ptr(pval
, seqtt
);
179 /* FIXME: check for errors in enhanced version */
180 asn1_template_ex_i2d(pseqval
, out
, seqtt
, -1, aclass
);
184 if (asn1_cb
&& !asn1_cb(ASN1_OP_I2D_POST
, pval
, it
, NULL
))
195 static int asn1_template_ex_i2d(ASN1_VALUE
**pval
, unsigned char **out
,
196 const ASN1_TEMPLATE
*tt
, int tag
, int iclass
)
198 int i
, ret
, flags
, ttag
, tclass
, ndef
;
203 * If field is embedded then val needs fixing so it is a pointer to
204 * a pointer to a field.
206 if (flags
& ASN1_TFLG_EMBED
) {
207 tval
= (ASN1_VALUE
*)pval
;
211 * Work out tag and class to use: tagging may come either from the
212 * template or the arguments, not both because this would create
213 * ambiguity. Additionally the iclass argument may contain some
214 * additional flags which should be noted and passed down to other
217 if (flags
& ASN1_TFLG_TAG_MASK
) {
218 /* Error if argument and template tagging */
220 /* FIXME: error code here */
222 /* Get tagging from template */
224 tclass
= flags
& ASN1_TFLG_TAG_CLASS
;
225 } else if (tag
!= -1) {
226 /* No template tagging, get from arguments */
228 tclass
= iclass
& ASN1_TFLG_TAG_CLASS
;
234 * Remove any class mask from iflag.
236 iclass
&= ~ASN1_TFLG_TAG_CLASS
;
239 * At this point 'ttag' contains the outer tag to use, 'tclass' is the
240 * class and iclass is any flags passed to this function.
243 /* if template and arguments require ndef, use it */
244 if ((flags
& ASN1_TFLG_NDEF
) && (iclass
& ASN1_TFLG_NDEF
))
249 if (flags
& ASN1_TFLG_SK_MASK
) {
250 /* SET OF, SEQUENCE OF */
251 STACK_OF(ASN1_VALUE
) *sk
= (STACK_OF(ASN1_VALUE
) *)*pval
;
252 int isset
, sktag
, skaclass
;
253 int skcontlen
, sklen
;
259 if (flags
& ASN1_TFLG_SET_OF
) {
261 /* 2 means we reorder */
262 if (flags
& ASN1_TFLG_SEQUENCE_OF
)
268 * Work out inner tag value: if EXPLICIT or no tagging use underlying
271 if ((ttag
!= -1) && !(flags
& ASN1_TFLG_EXPTAG
)) {
275 skaclass
= V_ASN1_UNIVERSAL
;
279 sktag
= V_ASN1_SEQUENCE
;
282 /* Determine total length of items */
284 for (i
= 0; i
< sk_ASN1_VALUE_num(sk
); i
++) {
286 skitem
= sk_ASN1_VALUE_value(sk
, i
);
287 tmplen
= ASN1_item_ex_i2d(&skitem
, NULL
, ASN1_ITEM_ptr(tt
->item
),
289 if (tmplen
== -1 || (skcontlen
> INT_MAX
- tmplen
))
293 sklen
= ASN1_object_size(ndef
, skcontlen
, sktag
);
296 /* If EXPLICIT need length of surrounding tag */
297 if (flags
& ASN1_TFLG_EXPTAG
)
298 ret
= ASN1_object_size(ndef
, sklen
, ttag
);
302 if (!out
|| ret
== -1)
305 /* Now encode this lot... */
307 if (flags
& ASN1_TFLG_EXPTAG
)
308 ASN1_put_object(out
, ndef
, sklen
, ttag
, tclass
);
309 /* SET or SEQUENCE and IMPLICIT tag */
310 ASN1_put_object(out
, ndef
, skcontlen
, sktag
, skaclass
);
311 /* And the stuff itself */
312 asn1_set_seq_out(sk
, out
, skcontlen
, ASN1_ITEM_ptr(tt
->item
),
316 if (flags
& ASN1_TFLG_EXPTAG
)
323 if (flags
& ASN1_TFLG_EXPTAG
) {
324 /* EXPLICIT tagging */
325 /* Find length of tagged item */
326 i
= ASN1_item_ex_i2d(pval
, NULL
, ASN1_ITEM_ptr(tt
->item
), -1, iclass
);
329 /* Find length of EXPLICIT tag */
330 ret
= ASN1_object_size(ndef
, i
, ttag
);
331 if (out
&& ret
!= -1) {
332 /* Output tag and item */
333 ASN1_put_object(out
, ndef
, i
, ttag
, tclass
);
334 ASN1_item_ex_i2d(pval
, out
, ASN1_ITEM_ptr(tt
->item
), -1, iclass
);
341 /* Either normal or IMPLICIT tagging: combine class and flags */
342 return ASN1_item_ex_i2d(pval
, out
, ASN1_ITEM_ptr(tt
->item
),
343 ttag
, tclass
| iclass
);
347 /* Temporary structure used to hold DER encoding of items for SET OF */
355 static int der_cmp(const void *a
, const void *b
)
357 const DER_ENC
*d1
= a
, *d2
= b
;
359 cmplen
= (d1
->length
< d2
->length
) ? d1
->length
: d2
->length
;
360 i
= memcmp(d1
->data
, d2
->data
, cmplen
);
363 return d1
->length
- d2
->length
;
366 /* Output the content octets of SET OF or SEQUENCE OF */
368 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE
) *sk
, unsigned char **out
,
369 int skcontlen
, const ASN1_ITEM
*item
,
370 int do_sort
, int iclass
)
374 unsigned char *tmpdat
= NULL
, *p
= NULL
;
375 DER_ENC
*derlst
= NULL
, *tder
;
377 /* Don't need to sort less than 2 items */
378 if (sk_ASN1_VALUE_num(sk
) < 2)
381 derlst
= OPENSSL_malloc(sk_ASN1_VALUE_num(sk
)
385 tmpdat
= OPENSSL_malloc(skcontlen
);
386 if (tmpdat
== NULL
) {
387 OPENSSL_free(derlst
);
392 /* If not sorting just output each item */
394 for (i
= 0; i
< sk_ASN1_VALUE_num(sk
); i
++) {
395 skitem
= sk_ASN1_VALUE_value(sk
, i
);
396 ASN1_item_ex_i2d(&skitem
, out
, item
, -1, iclass
);
402 /* Doing sort: build up a list of each member's DER encoding */
403 for (i
= 0, tder
= derlst
; i
< sk_ASN1_VALUE_num(sk
); i
++, tder
++) {
404 skitem
= sk_ASN1_VALUE_value(sk
, i
);
406 tder
->length
= ASN1_item_ex_i2d(&skitem
, &p
, item
, -1, iclass
);
407 tder
->field
= skitem
;
411 qsort(derlst
, sk_ASN1_VALUE_num(sk
), sizeof(*derlst
), der_cmp
);
412 /* Output sorted DER encoding */
414 for (i
= 0, tder
= derlst
; i
< sk_ASN1_VALUE_num(sk
); i
++, tder
++) {
415 memcpy(p
, tder
->data
, tder
->length
);
419 /* If do_sort is 2 then reorder the STACK */
421 for (i
= 0, tder
= derlst
; i
< sk_ASN1_VALUE_num(sk
); i
++, tder
++)
422 (void)sk_ASN1_VALUE_set(sk
, i
, tder
->field
);
424 OPENSSL_free(derlst
);
425 OPENSSL_free(tmpdat
);
429 static int asn1_i2d_ex_primitive(ASN1_VALUE
**pval
, unsigned char **out
,
430 const ASN1_ITEM
*it
, int tag
, int aclass
)
440 * Get length of content octets and maybe find out the underlying type.
443 len
= asn1_ex_i2c(pval
, NULL
, &utype
, it
);
446 * If SEQUENCE, SET or OTHER then header is included in pseudo content
447 * octets so don't include tag+length. We need to check here because the
448 * call to asn1_ex_i2c() could change utype.
450 if ((utype
== V_ASN1_SEQUENCE
) || (utype
== V_ASN1_SET
) ||
451 (utype
== V_ASN1_OTHER
))
456 /* -1 means omit type */
461 /* -2 return is special meaning use ndef */
467 /* If not implicitly tagged get tag from underlying type */
471 /* Output tag+length followed by content octets */
474 ASN1_put_object(out
, ndef
, len
, tag
, aclass
);
475 asn1_ex_i2c(pval
, *out
, &utype
, it
);
483 return ASN1_object_size(ndef
, len
, tag
);
487 /* Produce content octets from a structure */
489 static int asn1_ex_i2c(ASN1_VALUE
**pval
, unsigned char *cout
, int *putype
,
492 ASN1_BOOLEAN
*tbool
= NULL
;
496 const unsigned char *cont
;
499 const ASN1_PRIMITIVE_FUNCS
*pf
;
501 if (pf
&& pf
->prim_i2c
)
502 return pf
->prim_i2c(pval
, cout
, putype
, it
);
504 /* Should type be omitted? */
505 if ((it
->itype
!= ASN1_ITYPE_PRIMITIVE
)
506 || (it
->utype
!= V_ASN1_BOOLEAN
)) {
511 if (it
->itype
== ASN1_ITYPE_MSTRING
) {
512 /* If MSTRING type set the underlying type */
513 strtmp
= (ASN1_STRING
*)*pval
;
514 utype
= strtmp
->type
;
516 } else if (it
->utype
== V_ASN1_ANY
) {
517 /* If ANY set type and pointer to value */
519 typ
= (ASN1_TYPE
*)*pval
;
522 pval
= &typ
->value
.asn1_value
;
528 otmp
= (ASN1_OBJECT
*)*pval
;
531 if (cont
== NULL
|| len
== 0)
541 tbool
= (ASN1_BOOLEAN
*)pval
;
544 if (it
->utype
!= V_ASN1_ANY
) {
546 * Default handling if value == size field then omit
548 if (*tbool
&& (it
->size
> 0))
550 if (!*tbool
&& !it
->size
)
553 c
= (unsigned char)*tbool
;
558 case V_ASN1_BIT_STRING
:
559 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING
*)*pval
,
560 cout
? &cout
: NULL
);
563 case V_ASN1_ENUMERATED
:
565 * These are all have the same content format as ASN1_INTEGER
567 return i2c_ASN1_INTEGER((ASN1_INTEGER
*)*pval
, cout
? &cout
: NULL
);
569 case V_ASN1_OCTET_STRING
:
570 case V_ASN1_NUMERICSTRING
:
571 case V_ASN1_PRINTABLESTRING
:
572 case V_ASN1_T61STRING
:
573 case V_ASN1_VIDEOTEXSTRING
:
574 case V_ASN1_IA5STRING
:
576 case V_ASN1_GENERALIZEDTIME
:
577 case V_ASN1_GRAPHICSTRING
:
578 case V_ASN1_VISIBLESTRING
:
579 case V_ASN1_GENERALSTRING
:
580 case V_ASN1_UNIVERSALSTRING
:
581 case V_ASN1_BMPSTRING
:
582 case V_ASN1_UTF8STRING
:
583 case V_ASN1_SEQUENCE
:
586 /* All based on ASN1_STRING and handled the same */
587 strtmp
= (ASN1_STRING
*)*pval
;
588 /* Special handling for NDEF */
589 if ((it
->size
== ASN1_TFLG_NDEF
)
590 && (strtmp
->flags
& ASN1_STRING_FLAG_NDEF
)) {
595 /* Special return code */
599 len
= strtmp
->length
;
605 memcpy(cout
, cont
, len
);