Backport of:

From c521851116486d0cb351c46506d309dce0ae4c56 Mon Sep 17 00:00:00 2001
From: Matt Caswell <matt@openssl.org>
Date: Thu, 12 Nov 2020 11:58:12 +0000
Subject: [PATCH] Check that multi-strings/CHOICE types don't use implicit
 tagging

It never makes sense for multi-string or CHOICE types to use implicit
tagging since the content would be ambiguous. It is an error in the
template if this ever happens. If we detect it we should stop parsing.

Thanks to David Benjamin from Google for reporting this issue.
---
 crypto/asn1/asn1_err.c    |  1 +
 crypto/asn1/tasn_dec.c    | 19 +++++++++++++++++++
 crypto/err/openssl.txt    |  1 +
 include/openssl/asn1err.h |  1 +
 4 files changed, 22 insertions(+)

--- a/Cryptlib/OpenSSL/crypto/asn1/asn1_err.c
+++ b/Cryptlib/OpenSSL/crypto/asn1/asn1_err.c
@@ -202,6 +202,7 @@ static ERR_STRING_DATA ASN1_str_reasons[
     {ERR_REASON(ASN1_R_AUX_ERROR), "aux error"},
     {ERR_REASON(ASN1_R_BAD_CLASS), "bad class"},
     {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER), "bad object header"},
+    {ERR_REASON(ASN1_R_BAD_TEMPLATE), "bad template"},
     {ERR_REASON(ASN1_R_BAD_PASSWORD_READ), "bad password read"},
     {ERR_REASON(ASN1_R_BAD_TAG), "bad tag"},
     {ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH),
--- a/Cryptlib/OpenSSL/crypto/asn1/tasn_dec.c
+++ b/Cryptlib/OpenSSL/crypto/asn1/tasn_dec.c
@@ -223,6 +223,15 @@ static int asn1_item_ex_d2i(ASN1_VALUE *
         break;
 
     case ASN1_ITYPE_MSTRING:
+        /*
+         * It never makes sense for multi-strings to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_BAD_TEMPLATE);
+            goto err;
+        }
+
         p = *in;
         /* Just read in tag and class */
         ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
@@ -240,6 +249,7 @@ static int asn1_item_ex_d2i(ASN1_VALUE *
             ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL);
             goto err;
         }
+
         /* Check tag matches bit map */
         if (!(ASN1_tag2bit(otag) & it->utype)) {
             /* If OPTIONAL, assume this is OK */
@@ -316,6 +326,15 @@ static int asn1_item_ex_d2i(ASN1_VALUE *
         goto err;
 
     case ASN1_ITYPE_CHOICE:
+        /*
+         * It never makes sense for CHOICE types to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_BAD_TEMPLATE);
+            goto err;
+        }
+
         if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
             goto auxerr;
         if (*pval) {
--- a/Cryptlib/Include/openssl/asn1.h
+++ b/Cryptlib/Include/openssl/asn1.h
@@ -1306,6 +1306,7 @@ void ERR_load_ASN1_strings(void);
 # define ASN1_R_AUX_ERROR                                 100
 # define ASN1_R_BAD_CLASS                                 101
 # define ASN1_R_BAD_OBJECT_HEADER                         102
+# define ASN1_R_BAD_TEMPLATE                              230
 # define ASN1_R_BAD_PASSWORD_READ                         103
 # define ASN1_R_BAD_TAG                                   104
 # define ASN1_R_BMPSTRING_IS_WRONG_LENGTH                 214
