From: terrafrost <terrafrost@gmail.com>
Date: Sat, 3 Apr 2021 13:19:15 -0500
Subject: ASN1: make sure constructed bit is what it ought to be

Origin: upstream, https://github.com/phpseclib/phpseclib/commit/bac775ecd557ebe554a578ede28df853346d74e1
Bug: https://github.com/phpseclib/phpseclib/pull/1635
---
 phpseclib/File/ASN1.php | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php
index e875f4f..6f5fc8a 100644
--- a/phpseclib/File/ASN1.php
+++ b/phpseclib/File/ASN1.php
@@ -351,13 +351,16 @@ class ASN1
         switch ($tag) {
             case self::TYPE_BOOLEAN:
                 // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
-                if (strlen($content) != 1) {
+                if ($constructed || strlen($content) != 1) {
                     return false;
                 }
                 $current['content'] = (bool) ord($content[$content_pos]);
                 break;
             case self::TYPE_INTEGER:
             case self::TYPE_ENUMERATED:
+                if ($constructed) {
+                    return false;
+                }
                 $current['content'] = new BigInteger(substr($content, $content_pos), -256);
                 break;
             case self::TYPE_REAL: // not currently supported
@@ -415,12 +418,15 @@ class ASN1
                 break;
             case self::TYPE_NULL:
                 // "The contents octets shall not contain any octets." -- paragraph 8.8.2
-                if (strlen($content)) {
+                if ($constructed || strlen($content)) {
                     return false;
                 }
                 break;
             case self::TYPE_SEQUENCE:
             case self::TYPE_SET:
+                if (!$constructed) {
+                    return false;
+                }
                 $offset = 0;
                 $current['content'] = array();
                 $content_len = strlen($content);
@@ -441,6 +447,9 @@ class ASN1
                 }
                 break;
             case self::TYPE_OBJECT_IDENTIFIER:
+                if ($constructed) {
+                    return false;
+                }
                 $current['content'] = $this->_decodeOID(substr($content, $content_pos));
                 if ($current['content'] === false) {
                     return false;
@@ -474,10 +483,16 @@ class ASN1
             case self::TYPE_UTF8_STRING:
                 // ????
             case self::TYPE_BMP_STRING:
+                if ($constructed) {
+                    return false;
+                }
                 $current['content'] = substr($content, $content_pos);
                 break;
             case self::TYPE_UTC_TIME:
             case self::TYPE_GENERALIZED_TIME:
+                if ($constructed) {
+                    return false;
+                }
                 $current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
             default:
         }
