]> 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 15:05:07 +0000 (17:05 +0200)
Fixes #16026

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

crypto/asn1/tasn_enc.c

index 2d24320af9ad5f94a0b849198d4826f673ef06a1..06473d3411a85ac89858ad92f368150deca0d4dd 100644 (file)
@@ -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 */