diff options
author | Richard Levitte <levitte@openssl.org> | 2021-07-08 13:38:45 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2021-07-10 17:05:07 +0200 |
commit | 4cd473518777766e303cebe89c5a056dbec7e513 (patch) | |
tree | 5c9f49afffbedf2795d58d907aa9c866c72f0cd0 | |
parent | 2296cc34f3c700b0bc5c45f35e56641fbb840db3 (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)
-rw-r--r-- | crypto/asn1/tasn_enc.c | 29 |
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 */ |