summaryrefslogtreecommitdiffstats
path: root/crypto/asn1
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2021-07-08 13:38:45 +0200
committerRichard Levitte <levitte@openssl.org>2021-07-10 17:05:07 +0200
commit4cd473518777766e303cebe89c5a056dbec7e513 (patch)
tree5c9f49afffbedf2795d58d907aa9c866c72f0cd0 /crypto/asn1
parent2296cc34f3c700b0bc5c45f35e56641fbb840db3 (diff)
ASN.1: Refuse to encode to DER if non-optional items are missing
Fixes #16026 Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/16036)
Diffstat (limited to 'crypto/asn1')
-rw-r--r--crypto/asn1/tasn_enc.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index 2d24320af9..06473d3411 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -217,7 +217,7 @@ static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
const int flags = tt->flags;
- int i, ret, ttag, tclass, ndef;
+ int i, ret, ttag, tclass, ndef, len;
const ASN1_VALUE *tval;
/*
@@ -303,13 +303,16 @@ static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
/* Determine total length of items */
skcontlen = 0;
for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
- int tmplen;
skitem = sk_const_ASN1_VALUE_value(sk, i);
- tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
- -1, iclass);
- if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
+ len = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
+ -1, iclass);
+ if (len == -1 || (skcontlen > INT_MAX - len))
+ return -1;
+ if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
return -1;
- skcontlen += tmplen;
+ }
+ skcontlen += len;
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
if (sklen == -1)
@@ -347,6 +350,10 @@ static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
if (!i)
return 0;
+ if (i == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ return -1;
+ }
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out && ret != -1) {
@@ -360,9 +367,13 @@ static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
}
/* Either normal or IMPLICIT tagging: combine class and flags */
- return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
- ttag, tclass | iclass);
-
+ len = ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
+ ttag, tclass | iclass);
+ if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+ return -1;
+ }
+ return len;
}
/* Temporary structure used to hold DER encoding of items for SET OF */