]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
ASN.1: Refuse to encode to DER if non-optional items are missing
authorRichard Levitte <levitte@openssl.org>
Thu, 8 Jul 2021 11:38:45 +0000 (13:38 +0200)
committerRichard Levitte <levitte@openssl.org>
Sat, 10 Jul 2021 10:05:51 +0000 (12:05 +0200)
Fixes #16026

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16027)

crypto/asn1/tasn_enc.c

index bcc96337bca48c22f01c7f914d92e74b80465d52..6eb300a21ed774da9e7cbee0e744e27c593c7903 100644 (file)
@@ -213,7 +213,7 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
 {
-    int i, ret, flags, ttag, tclass, ndef;
+    int i, ret, flags, ttag, tclass, ndef, len;
     ASN1_VALUE *tval;
     flags = tt->flags;
 
@@ -300,13 +300,17 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         /* Determine total length of items */
         skcontlen = 0;
         for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
-            int tmplen;
             skitem = sk_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) {
+                ASN1err(ASN1_F_ASN1_TEMPLATE_EX_I2D,
+                        ASN1_R_ILLEGAL_ZERO_CONTENT);
                 return -1;
-            skcontlen += tmplen;
+            }
+            skcontlen += len;
         }
         sklen = ASN1_object_size(ndef, skcontlen, sktag);
         if (sklen == -1)
@@ -344,6 +348,10 @@ static int asn1_template_ex_i2d(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) {
+            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_I2D, ASN1_R_ILLEGAL_ZERO_CONTENT);
+            return -1;
+        }
         /* Find length of EXPLICIT tag */
         ret = ASN1_object_size(ndef, i, ttag);
         if (out && ret != -1) {
@@ -357,9 +365,13 @@ static int asn1_template_ex_i2d(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) {
+        ASN1err(ASN1_F_ASN1_TEMPLATE_EX_I2D, ASN1_R_ILLEGAL_ZERO_CONTENT);
+        return -1;
+    }
+    return len;
 }
 
 /* Temporary structure used to hold DER encoding of items for SET OF */