[openssl] master update

Matt Caswell matt at openssl.org
Tue Aug 24 13:48:21 UTC 2021


The branch master has been updated
       via  796f4f7085ac95a1b0ccee8ff3c6c183219cdab2 (commit)
       via  ad1ca777f9702f355a2f74dc5eed713476825f23 (commit)
       via  d07036b98d2ea8b3d9a93181bd8b0cb33a6c8ba1 (commit)
       via  36cf45ef3ba71e44a8be06ee81cb31aa02cb0010 (commit)
       via  4b8a8bb75229b64d1c7598d845fdc3c7e7d7eee2 (commit)
       via  e20fc2ee4fc90ac1476b3a9b15b37542bfb1af73 (commit)
       via  030c5aba94788f152f9ceef3549815df45bef702 (commit)
       via  7c038a6bcd98d4bbfd2c2892a87a1138d2f7c5f3 (commit)
       via  98624776c4d501c8badd6f772ab7048ac9191cb9 (commit)
       via  1f365708a3318a5f1a395f90c38b584a58d37fb9 (commit)
       via  95f8c1e142df835d03b5b62521383a462fc5470d (commit)
       via  d2015a783e64613d8e4a142fa05048d1863df944 (commit)
       via  918430ba80d94ec8f05383b43b1872b1ebb13e1a (commit)
       via  b2b3b9c9936b91315adc0f3254879cb2fd5ca2bd (commit)
       via  1747d4658b3830951068a6a6c1fa2b45c4731fb3 (commit)
       via  ad6ac17489241574136b7d035f01f6175dd9c941 (commit)
      from  ed3f51ec7d2f8956bff7bedf99b65ff1595e02e8 (commit)


- Log -----------------------------------------------------------------
commit 796f4f7085ac95a1b0ccee8ff3c6c183219cdab2
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Aug 24 13:37:49 2021 +0100

    Updates CHANGES.md and NEWS.md for new 1.1.1 release
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit ad1ca777f9702f355a2f74dc5eed713476825f23
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 13 16:58:21 2021 +0100

    Check the plaintext buffer is large enough when decrypting SM2
    
    Previously there was no check that the supplied buffer was large enough.
    It was just assumed to be sufficient. Instead we should check and fail if
    not.
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>

commit d07036b98d2ea8b3d9a93181bd8b0cb33a6c8ba1
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 13 14:49:47 2021 +0100

    Extend tests for SM2 decryption
    
    Check the case where C1y < 32 bytes in length (i.e. short overhead), and
    also the case with longer plaintext and C1x and C1y > 32 bytes in length
    (i.e. long overhead)
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>

commit 36cf45ef3ba71e44a8be06ee81cb31aa02cb0010
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 13 14:14:51 2021 +0100

    Correctly calculate the length of SM2 plaintext given the ciphertext
    
    Previously the length of the SM2 plaintext could be incorrectly calculated.
    The plaintext length was calculated by taking the ciphertext length and
    taking off an "overhead" value.
    
    The overhead value was assumed to have a "fixed" element of 10 bytes.
    This is incorrect since in some circumstances it can be more than 10 bytes.
    Additionally the overhead included the length of two integers C1x and C1y,
    which were assumed to be the same length as the field size (32 bytes for
    the SM2 curve). However in some cases these integers can have an additional
    padding byte when the msb is set, to disambiguate them from negative
    integers. Additionally the integers can also be less than 32 bytes in
    length in some cases.
    
    If the calculated overhead is incorrect and larger than the actual value
    this can result in the calculated plaintext length being too small.
    Applications are likely to allocate buffer sizes based on this and therefore
    a buffer overrun can occur.
    
    CVE-2021-3711
    
    Issue reported by John Ouyang.
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>

commit 4b8a8bb75229b64d1c7598d845fdc3c7e7d7eee2
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 20 15:23:32 2021 +0100

    Fix the error handling in i2v_AUTHORITY_KEYID
    
    Previously if an error path is entered a leak could result.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit e20fc2ee4fc90ac1476b3a9b15b37542bfb1af73
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 19 15:25:04 2021 +0100

    Allow fuzz builds to detect string overruns
    
    If FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is defined then we don't NUL
    terminate ASN1_STRING datatypes. This shouldn't be necessary but we add it
    any for safety in normal builds.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 030c5aba94788f152f9ceef3549815df45bef702
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 19 12:24:17 2021 +0100

    Fix EC_GROUP_new_from_ecparameters to check the base length
    
    Check that there's at least one byte in params->base before trying to
    read it.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 7c038a6bcd98d4bbfd2c2892a87a1138d2f7c5f3
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 19 12:23:38 2021 +0100

    Fix NETSCAPE_SPKI_print function to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 98624776c4d501c8badd6f772ab7048ac9191cb9
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 17:58:23 2021 +0100

    Fix append_ia5 function to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 1f365708a3318a5f1a395f90c38b584a58d37fb9
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 17:37:41 2021 +0100

    Fix test code to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 95f8c1e142df835d03b5b62521383a462fc5470d
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 17:37:23 2021 +0100

    Fix CMP code to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit d2015a783e64613d8e4a142fa05048d1863df944
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 17:08:58 2021 +0100

    Fix the name constraints code to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 918430ba80d94ec8f05383b43b1872b1ebb13e1a
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 14:02:40 2021 +0100

    Fix printing of PROXY_CERT_INFO_EXTENSION to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit b2b3b9c9936b91315adc0f3254879cb2fd5ca2bd
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 12:34:55 2021 +0100

    Fix GENERAL_NAME_print to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit 1747d4658b3830951068a6a6c1fa2b45c4731fb3
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 12:31:38 2021 +0100

    Fix POLICYINFO printing to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

commit ad6ac17489241574136b7d035f01f6175dd9c941
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Aug 18 12:24:22 2021 +0100

    Fix i2v_GENERAL_NAME to not assume NUL terminated strings
    
    ASN.1 strings may not be NUL terminated. Don't assume they are.
    
    CVE-2021-3712
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: David Benjamin <davidben at google.com>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                                         |  69 ++++++++++-
 NEWS.md                                            |   6 +-
 crypto/asn1/asn1_lib.c                             |  12 +-
 crypto/asn1/t_spki.c                               |   2 +-
 crypto/cmp/cmp_hdr.c                               |   3 +-
 crypto/cmp/cmp_local.h                             |   2 +-
 crypto/cmp/cmp_msg.c                               |   6 +-
 crypto/cmp/cmp_status.c                            |   3 +-
 crypto/cmp/cmp_util.c                              |   4 +-
 crypto/ec/ec_asn1.c                                |   3 +-
 crypto/sm2/sm2_crypt.c                             |  28 ++---
 crypto/x509/v3_akid.c                              |  33 +++--
 crypto/x509/v3_cpols.c                             |   9 +-
 crypto/x509/v3_ncons.c                             | 135 ++++++++++++++-------
 crypto/x509/v3_pci.c                               |   3 +-
 crypto/x509/v3_san.c                               |  46 ++++---
 crypto/x509/v3_utl.c                               |  51 ++++++--
 ...67 => 0bf7ea6564ba1096f9760bbd6ed02f25aa0d583c} | Bin 457 -> 457 bytes
 include/crypto/sm2.h                               |   4 +-
 include/crypto/x509.h                              |   3 +
 providers/implementations/asymciphers/sm2_enc.c    |   2 +-
 test/cmp_status_test.c                             |   3 +-
 test/helpers/pkcs12.c                              |   7 +-
 test/recipes/30-test_evp_data/evppkey_sm2.txt      |  12 ++
 test/sm2_internal_test.c                           |   2 +-
 test/x509_time_test.c                              |  10 +-
 26 files changed, 340 insertions(+), 118 deletions(-)
 copy fuzz/corpora/x509/{a936a50b93a82a7d311aa3cda7f634602b524767 => 0bf7ea6564ba1096f9760bbd6ed02f25aa0d583c} (68%)

diff --git a/CHANGES.md b/CHANGES.md
index bcb1601d26..5fdec520b7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1358,7 +1358,74 @@ breaking changes, and mappings for the large list of deprecated functions.
 OpenSSL 1.1.1
 -------------
 
-### Changes between 1.1.1j and 1.1.1k [xx XXX xxxx]
+### Changes between 1.1.1k and 1.1.1l [24 Aug 2021]
+
+ * Fixed an SM2 Decryption Buffer Overflow.
+
+   In order to decrypt SM2 encrypted data an application is expected to call the
+   API function EVP_PKEY_decrypt(). Typically an application will call this
+   function twice. The first time, on entry, the "out" parameter can be NULL and,
+   on exit, the "outlen" parameter is populated with the buffer size required to
+   hold the decrypted plaintext. The application can then allocate a sufficiently
+   sized buffer and call EVP_PKEY_decrypt() again, but this time passing a non-NULL
+   value for the "out" parameter.
+
+   A bug in the implementation of the SM2 decryption code means that the
+   calculation of the buffer size required to hold the plaintext returned by the
+   first call to EVP_PKEY_decrypt() can be smaller than the actual size required by
+   the second call. This can lead to a buffer overflow when EVP_PKEY_decrypt() is
+   called by the application a second time with a buffer that is too small.
+
+   A malicious attacker who is able present SM2 content for decryption to an
+   application could cause attacker chosen data to overflow the buffer by up to a
+   maximum of 62 bytes altering the contents of other data held after the
+   buffer, possibly changing application behaviour or causing the application to
+   crash. The location of the buffer is application dependent but is typically
+   heap allocated.
+   ([CVE-2021-3711])
+
+   *Matt Caswell*
+
+  * Fixed various read buffer overruns processing ASN.1 strings
+
+    ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING
+    structure which contains a buffer holding the string data and a field holding
+    the buffer length. This contrasts with normal C strings which are repesented as
+    a buffer for the string data which is terminated with a NUL (0) byte.
+
+    Although not a strict requirement, ASN.1 strings that are parsed using OpenSSL's
+    own "d2i" functions (and other similar parsing functions) as well as any string
+    whose value has been set with the ASN1_STRING_set() function will additionally
+    NUL terminate the byte array in the ASN1_STRING structure.
+
+    However, it is possible for applications to directly construct valid ASN1_STRING
+    structures which do not NUL terminate the byte array by directly setting the
+    "data" and "length" fields in the ASN1_STRING array. This can also happen by
+    using the ASN1_STRING_set0() function.
+
+    Numerous OpenSSL functions that print ASN.1 data have been found to assume that
+    the ASN1_STRING byte array will be NUL terminated, even though this is not
+    guaranteed for strings that have been directly constructed. Where an application
+    requests an ASN.1 structure to be printed, and where that ASN.1 structure
+    contains ASN1_STRINGs that have been directly constructed by the application
+    without NUL terminating the "data" field, then a read buffer overrun can occur.
+
+    The same thing can also occur during name constraints processing of certificates
+    (for example if a certificate has been directly constructed by the application
+    instead of loading it via the OpenSSL parsing functions, and the certificate
+    contains non NUL terminated ASN1_STRING structures). It can also occur in the
+    X509_get1_email(), X509_REQ_get1_email() and X509_get1_ocsp() functions.
+
+    If a malicious actor can cause an application to directly construct an
+    ASN1_STRING and then process it through one of the affected OpenSSL functions
+    then this issue could be hit. This might result in a crash (causing a Denial of
+    Service attack). It could also result in the disclosure of private memory
+    contents (such as private keys, or sensitive plaintext).
+    ([CVE-2021-3712])
+
+   *Matt Caswell*
+
+### Changes between 1.1.1j and 1.1.1k [25 Mar 2021]
 
  * Fixed a problem with verifying a certificate chain when using the
    X509_V_FLAG_X509_STRICT flag. This flag enables additional security checks of
diff --git a/NEWS.md b/NEWS.md
index 13a4e1bbf6..02227ef755 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -89,7 +89,11 @@ OpenSSL 3.0
 OpenSSL 1.1.1
 -------------
 
-### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [under development]
+### Major changes between OpenSSL 1.1.1k and OpenSSL 1.1.1l [24 Aug 2021]
+  * Fixed an SM2 Decryption Buffer Overflow ([CVE-2021-3711])
+  * Fixed various read buffer overruns processing ASN.1 strings ([CVE-2021-3712])
+
+### Major changes between OpenSSL 1.1.1j and OpenSSL 1.1.1k [25 Mar 2021]
 
   * Fixed a problem with verifying a certificate chain when using the
     X509_V_FLAG_X509_STRICT flag ([CVE-2021-3450])
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index bdd0ec488d..02c34a4438 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -301,7 +301,12 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
     }
     if ((size_t)str->length <= len || str->data == NULL) {
         c = str->data;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        /* No NUL terminator in fuzzing builds */
+        str->data = OPENSSL_realloc(c, len);
+#else
         str->data = OPENSSL_realloc(c, len + 1);
+#endif
         if (str->data == NULL) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             str->data = c;
@@ -311,8 +316,13 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
     str->length = len;
     if (data != NULL) {
         memcpy(str->data, data, len);
-        /* an allowance for strings :-) */
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+        /*
+         * Add a NUL terminator. This should not be necessary - but we add it as
+         * a safety precaution
+         */
         str->data[len] = '\0';
+#endif
     }
     return 1;
 }
diff --git a/crypto/asn1/t_spki.c b/crypto/asn1/t_spki.c
index b634808c43..3d85e08686 100644
--- a/crypto/asn1/t_spki.c
+++ b/crypto/asn1/t_spki.c
@@ -38,7 +38,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
     }
     chal = spki->spkac->challenge;
     if (chal->length)
-        BIO_printf(out, "  Challenge String: %s\n", chal->data);
+        BIO_printf(out, "  Challenge String: %.*s\n", chal->length, chal->data);
     i = OBJ_obj2nid(spki->sig_algor.algorithm);
     BIO_printf(out, "  Signature Algorithm: %s",
                (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c
index 86be2546d5..8c553af61a 100644
--- a/crypto/cmp/cmp_hdr.c
+++ b/crypto/cmp/cmp_hdr.c
@@ -181,7 +181,8 @@ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
         return 0;
 
     return
-        ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data);
+        ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data,
+                                             text->length);
 }
 
 int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
index f2a0587ca4..3da021043b 100644
--- a/crypto/cmp/cmp_local.h
+++ b/crypto/cmp/cmp_local.h
@@ -744,7 +744,7 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
                                    int only_self_issued);
 STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
 int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
-                                         const char *text);
+                                         const char *text, int len);
 int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
                                     const ASN1_OCTET_STRING *src);
 int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index 5fb67ae2cb..10ef4cd922 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -758,13 +758,13 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
             goto err;
         msg->body->value.error->errorDetails = ft;
         if (lib != NULL && *lib != '\0'
-                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib))
+                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, lib, -1))
             goto err;
         if (reason != NULL && *reason != '\0'
-                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason))
+                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, reason, -1))
             goto err;
         if (details != NULL
-                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
+                && !ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details, -1))
             goto err;
     }
 
diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c
index dc14f754de..f1e7b4bc02 100644
--- a/crypto/cmp/cmp_status.c
+++ b/crypto/cmp/cmp_status.c
@@ -220,7 +220,8 @@ char *snprint_PKIStatusInfo_parts(int status, int fail_info,
         ADVANCE_BUFFER;
         for (i = 0; i < n_status_strings; i++) {
             text = sk_ASN1_UTF8STRING_value(status_strings, i);
-            printed_chars = BIO_snprintf(write_ptr, bufsize, "\"%s\"%s",
+            printed_chars = BIO_snprintf(write_ptr, bufsize, "\"%.*s\"%s",
+                                         ASN1_STRING_length(text),
                                          ASN1_STRING_get0_data(text),
                                          i < n_status_strings - 1 ? ", " : "");
             ADVANCE_BUFFER;
diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c
index fbb8d1e249..ed611d64dd 100644
--- a/crypto/cmp/cmp_util.c
+++ b/crypto/cmp/cmp_util.c
@@ -221,7 +221,7 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
 }
 
 int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
-                                         const char *text)
+                                         const char *text, int len)
 {
     ASN1_UTF8STRING *utf8string;
 
@@ -229,7 +229,7 @@ int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
         return 0;
     if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
         return 0;
-    if (!ASN1_STRING_set(utf8string, text, -1))
+    if (!ASN1_STRING_set(utf8string, text, len))
         goto err;
     if (!sk_ASN1_UTF8STRING_push(sk, utf8string))
         goto err;
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index 0e37b21ac3..b3a791eb64 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -699,7 +699,8 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
 
     if (params->order == NULL
             || params->base == NULL
-            || params->base->data == NULL) {
+            || params->base->data == NULL
+            || params->base->length == 0) {
         ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR);
         goto err;
     }
diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c
index 105dd4ce70..e26b48390a 100644
--- a/crypto/sm2/sm2_crypt.c
+++ b/crypto/sm2/sm2_crypt.c
@@ -67,29 +67,21 @@ static size_t ec_field_size(const EC_GROUP *group)
     return field_size;
 }
 
-int ossl_sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest,
-                            size_t msg_len, size_t *pt_size)
+int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size,
+                            size_t *pt_size)
 {
-    const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
-    const int md_size = EVP_MD_get_size(digest);
-    size_t overhead;
+    struct SM2_Ciphertext_st *sm2_ctext = NULL;
 
-    if (md_size < 0) {
-        ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
-        return 0;
-    }
-    if (field_size == 0) {
-        ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_FIELD);
-        return 0;
-    }
+    sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size);
 
-    overhead = 10 + 2 * field_size + (size_t)md_size;
-    if (msg_len <= overhead) {
+    if (sm2_ctext == NULL) {
         ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
         return 0;
     }
 
-    *pt_size = msg_len - overhead;
+    *pt_size = sm2_ctext->C2->length;
+    SM2_Ciphertext_free(sm2_ctext);
+
     return 1;
 }
 
@@ -320,6 +312,10 @@ int ossl_sm2_decrypt(const EC_KEY *key,
     C2 = sm2_ctext->C2->data;
     C3 = sm2_ctext->C3->data;
     msg_len = sm2_ctext->C2->length;
+    if (*ptext_len < (size_t)msg_len) {
+        SM2err(SM2_F_SM2_DECRYPT, SM2_R_BUFFER_TOO_SMALL);
+        goto done;
+    }
 
     ctx = BN_CTX_new_ex(libctx);
     if (ctx == NULL) {
diff --git a/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c
index c8693a4ef5..5abd35d644 100644
--- a/crypto/x509/v3_akid.c
+++ b/crypto/x509/v3_akid.c
@@ -40,29 +40,48 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
                                                  STACK_OF(CONF_VALUE)
                                                  *extlist)
 {
-    char *tmp;
+    char *tmp = NULL;
+    STACK_OF(CONF_VALUE) *origextlist = extlist, *tmpextlist;
+
     if (akeyid->keyid) {
         tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length);
         if (tmp == NULL) {
             ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
             return NULL;
         }
-        X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL,
-                         tmp, &extlist);
+        if (!X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL,
+                              tmp, &extlist)) {
+            OPENSSL_free(tmp);
+            ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
+            goto err;
+        }
         OPENSSL_free(tmp);
     }
-    if (akeyid->issuer)
-        extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+    if (akeyid->issuer) {
+        tmpextlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+        if (tmpextlist == NULL) {
+            ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB);
+            goto err;
+        }
+        extlist = tmpextlist;
+    }
     if (akeyid->serial) {
         tmp = OPENSSL_buf2hexstr(akeyid->serial->data, akeyid->serial->length);
         if (tmp == NULL) {
             ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
-            return NULL;
+            goto err;
+        }
+        if (!X509V3_add_value("serial", tmp, &extlist)) {
+            OPENSSL_free(tmp);
+            goto err;
         }
-        X509V3_add_value("serial", tmp, &extlist);
         OPENSSL_free(tmp);
     }
     return extlist;
+ err:
+    if (origextlist == NULL)
+        sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
+    return NULL;
 }
 
 /*-
diff --git a/crypto/x509/v3_cpols.c b/crypto/x509/v3_cpols.c
index 3ccf67ef75..5353a69167 100644
--- a/crypto/x509/v3_cpols.c
+++ b/crypto/x509/v3_cpols.c
@@ -426,7 +426,8 @@ static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
         qualinfo = sk_POLICYQUALINFO_value(quals, i);
         switch (OBJ_obj2nid(qualinfo->pqualid)) {
         case NID_id_qt_cps:
-            BIO_printf(out, "%*sCPS: %s", indent, "",
+            BIO_printf(out, "%*sCPS: %.*s", indent, "",
+                       qualinfo->d.cpsuri->length,
                        qualinfo->d.cpsuri->data);
             break;
 
@@ -450,7 +451,8 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
     if (notice->noticeref) {
         NOTICEREF *ref;
         ref = notice->noticeref;
-        BIO_printf(out, "%*sOrganization: %s\n", indent, "",
+        BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
+                   ref->organization->length,
                    ref->organization->data);
         BIO_printf(out, "%*sNumber%s: ", indent, "",
                    sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
@@ -474,7 +476,8 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
             BIO_puts(out, "\n");
     }
     if (notice->exptext)
-        BIO_printf(out, "%*sExplicit Text: %s", indent, "",
+        BIO_printf(out, "%*sExplicit Text: %.*s", indent, "",
+                   notice->exptext->length,
                    notice->exptext->data);
 }
 
diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c
index d3b9e8c6f1..dc56fe2c0c 100644
--- a/crypto/x509/v3_ncons.c
+++ b/crypto/x509/v3_ncons.c
@@ -66,8 +66,31 @@ ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
 
+
+#define IA5_OFFSET_LEN(ia5base, offset) \
+    ((ia5base)->length - ((unsigned char *)(offset) - (ia5base)->data))
+
+/* Like memchr but for ASN1_IA5STRING. Additionally you can specify the
+ * starting point to search from
+ */
+# define ia5memchr(str, start, c) memchr(start, c, IA5_OFFSET_LEN(str, start))
+
+/* Like memrrchr but for ASN1_IA5STRING */
+static char *ia5memrchr(ASN1_IA5STRING *str, int c)
+{
+    int i;
+
+    for (i = str->length; i > 0 && str->data[i - 1] != c; i--);
+
+    if (i == 0)
+        return NULL;
+
+    return (char *)&str->data[i - 1];
+}
+
 /*
- * We cannot use strncasecmp here because that applies locale specific rules.
+ * We cannot use strncasecmp here because that applies locale specific rules. It
+ * also doesn't work with ASN1_STRINGs that may have embedded NUL characters.
  * For example in Turkish 'I' is not the uppercase character for 'i'. We need to
  * do a simple ASCII case comparison ignoring the locale (that is why we use
  * numeric constants below).
@@ -92,20 +115,12 @@ static int ia5ncasecmp(const char *s1, const char *s2, size_t n)
 
             /* c1 > c2 */
             return 1;
-        } else if (*s1 == 0) {
-            /* If we get here we know that *s2 == 0 too */
-            return 0;
         }
     }
 
     return 0;
 }
 
-static int ia5casecmp(const char *s1, const char *s2)
-{
-    return ia5ncasecmp(s1, s2, SIZE_MAX);
-}
-
 static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
                                   X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
 {
@@ -334,7 +349,7 @@ static int cn2dnsid(ASN1_STRING *cn, unsigned char **dnsid, size_t *idlen)
         --utf8_length;
 
     /* Reject *embedded* NULs */
-    if ((size_t)utf8_length != strlen((char *)utf8_value)) {
+    if (memchr(utf8_value, 0, utf8_length) != NULL) {
         OPENSSL_free(utf8_value);
         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
     }
@@ -571,8 +586,12 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
     char *dnsptr = (char *)dns->data;
 
     /* Empty matches everything */
-    if (*baseptr == '\0')
+    if (base->length == 0)
         return X509_V_OK;
+
+    if (dns->length < base->length)
+        return X509_V_ERR_PERMITTED_VIOLATION;
+
     /*
      * Otherwise can add zero or more components on the left so compare RHS
      * and if dns is longer and expect '.' as preceding character.
@@ -583,7 +602,7 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
             return X509_V_ERR_PERMITTED_VIOLATION;
     }
 
-    if (ia5casecmp(baseptr, dnsptr))
+    if (ia5ncasecmp(baseptr, dnsptr, base->length))
         return X509_V_ERR_PERMITTED_VIOLATION;
 
     return X509_V_OK;
@@ -600,63 +619,90 @@ static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
 static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base)
 {
     ASN1_UTF8STRING *eml;
-    const char *baseptr = (char *)base->data;
+    char *baseptr = NULL;
     const char *emlptr;
     const char *emlat;
     char ulabel[256];
     size_t size = sizeof(ulabel) - 1;
+    int ret = X509_V_OK;
+    size_t emlhostlen;
 
-    if (emltype->type != V_ASN1_UTF8STRING)
+    /* We do not accept embedded NUL characters */
+    if (base->length > 0 && memchr(base->data, 0, base->length) != NULL)
         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
 
+    /* 'base' may not be NUL terminated. Create a copy that is */
+    baseptr = OPENSSL_strndup((char *)base->data, base->length);
+    if (baseptr == NULL)
+        return X509_V_ERR_OUT_OF_MEM;
+
+    if (emltype->type != V_ASN1_UTF8STRING) {
+        ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+        goto end;
+    }
+
     eml = emltype->value.utf8string;
     emlptr = (char *)eml->data;
-    emlat = strrchr(emlptr, '@');
+    emlat = ia5memrchr(eml, '@');
 
-    if (emlat == NULL)
-        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+    if (emlat == NULL) {
+        ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+        goto end;
+    }
 
     memset(ulabel, 0, sizeof(ulabel));
     /* Special case: initial '.' is RHS match */
     if (*baseptr == '.') {
         ulabel[0] = '.';
         size -= 1;
-        if (ossl_a2ulabel(baseptr, ulabel + 1, &size) <= 0)
-            return X509_V_ERR_UNSPECIFIED;
+        if (ossl_a2ulabel(baseptr, ulabel + 1, &size) <= 0) {
+            ret = X509_V_ERR_UNSPECIFIED;
+            goto end;
+        }
 
-        if ((size_t)eml->length > size + 1) {
-            emlptr += eml->length - (size + 1);
-            if (ia5casecmp(ulabel, emlptr) == 0)
-                return X509_V_OK;
+        if ((size_t)eml->length > strlen(ulabel)) {
+            emlptr += eml->length - (strlen(ulabel));
+            /* X509_V_OK */
+            if (ia5ncasecmp(ulabel, emlptr, strlen(ulabel)) == 0)
+                goto end;
         }
-        return X509_V_ERR_PERMITTED_VIOLATION;
+        ret = X509_V_ERR_PERMITTED_VIOLATION;
+        goto end;
     }
 
-    emlptr = emlat + 1;
-    if (ossl_a2ulabel(baseptr, ulabel, &size) <= 0)
-        return X509_V_ERR_UNSPECIFIED;
+    if (ossl_a2ulabel(baseptr, ulabel, &size) <= 0) {
+        ret = X509_V_ERR_UNSPECIFIED;
+        goto end;
+    }
     /* Just have hostname left to match: case insensitive */
-    if (ia5casecmp(ulabel, emlptr))
-        return X509_V_ERR_PERMITTED_VIOLATION;
-
-    return X509_V_OK;
+    emlptr = emlat + 1;
+    emlhostlen = IA5_OFFSET_LEN(eml, emlptr);
+    if (emlhostlen != strlen(ulabel)
+            || ia5ncasecmp(ulabel, emlptr, emlhostlen) != 0) {
+        ret = X509_V_ERR_PERMITTED_VIOLATION;
+        goto end;
+    }
 
+ end:
+    OPENSSL_free(baseptr);
+    return ret;
 }
 
 static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
 {
     const char *baseptr = (char *)base->data;
     const char *emlptr = (char *)eml->data;
+    const char *baseat = ia5memrchr(base, '@');
+    const char *emlat = ia5memrchr(eml, '@');
+    size_t basehostlen, emlhostlen;
 
-    const char *baseat = strrchr(baseptr, '@');
-    const char *emlat = strrchr(emlptr, '@');
     if (!emlat)
         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
     /* Special case: initial '.' is RHS match */
-    if (!baseat && (*baseptr == '.')) {
+    if (!baseat && base->length > 0 && (*baseptr == '.')) {
         if (eml->length > base->length) {
             emlptr += eml->length - base->length;
-            if (ia5casecmp(baseptr, emlptr) == 0)
+            if (ia5ncasecmp(baseptr, emlptr, base->length) == 0)
                 return X509_V_OK;
         }
         return X509_V_ERR_PERMITTED_VIOLATION;
@@ -676,8 +722,10 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
         baseptr = baseat + 1;
     }
     emlptr = emlat + 1;
+    basehostlen = IA5_OFFSET_LEN(base, baseptr);
+    emlhostlen = IA5_OFFSET_LEN(eml, emlptr);
     /* Just have hostname left to match: case insensitive */
-    if (ia5casecmp(baseptr, emlptr))
+    if (basehostlen != emlhostlen || ia5ncasecmp(baseptr, emlptr, emlhostlen))
         return X509_V_ERR_PERMITTED_VIOLATION;
 
     return X509_V_OK;
@@ -688,11 +736,14 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
 {
     const char *baseptr = (char *)base->data;
     const char *hostptr = (char *)uri->data;
-    const char *p = strchr(hostptr, ':');
+    const char *p = ia5memchr(uri, (char *)uri->data, ':');
     int hostlen;
 
     /* Check for foo:// and skip past it */
-    if (p == NULL || p[1] != '/' || p[2] != '/')
+    if (p == NULL
+            || IA5_OFFSET_LEN(uri, p) < 3
+            || p[1] != '/'
+            || p[2] != '/')
         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
     hostptr = p + 3;
 
@@ -700,13 +751,13 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
 
     /* Look for a port indicator as end of hostname first */
 
-    p = strchr(hostptr, ':');
+    p = ia5memchr(uri, hostptr, ':');
     /* Otherwise look for trailing slash */
     if (p == NULL)
-        p = strchr(hostptr, '/');
+        p = ia5memchr(uri, hostptr, '/');
 
     if (p == NULL)
-        hostlen = strlen(hostptr);
+        hostlen = IA5_OFFSET_LEN(uri, hostptr);
     else
         hostlen = p - hostptr;
 
@@ -714,7 +765,7 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
 
     /* Special case: initial '.' is RHS match */
-    if (*baseptr == '.') {
+    if (base->length > 0 && *baseptr == '.') {
         if (hostlen > base->length) {
             p = hostptr + hostlen - base->length;
             if (ia5ncasecmp(p, baseptr, base->length) == 0)
diff --git a/crypto/x509/v3_pci.c b/crypto/x509/v3_pci.c
index 7a7c91f776..a931e01a9c 100644
--- a/crypto/x509/v3_pci.c
+++ b/crypto/x509/v3_pci.c
@@ -76,7 +76,8 @@ static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
     BIO_printf(out, "%*sPolicy Language: ", indent, "");
     i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
     if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
-        BIO_printf(out, "\n%*sPolicy Text: %s", indent, "",
+        BIO_printf(out, "\n%*sPolicy Text: %.*s", indent, "",
+                   pci->proxyPolicy->policy->length,
                    pci->proxyPolicy->policy->data);
     return 1;
 }
diff --git a/crypto/x509/v3_san.c b/crypto/x509/v3_san.c
index ef9200cbaa..26708aefae 100644
--- a/crypto/x509/v3_san.c
+++ b/crypto/x509/v3_san.c
@@ -9,6 +9,7 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
+#include "crypto/x509.h"
 #include <openssl/conf.h>
 #include <openssl/x509v3.h>
 #include <openssl/bio.h>
@@ -87,36 +88,41 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
         switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
         case NID_id_on_SmtpUTF8Mailbox:
             if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
-                    || !X509V3_add_value_uchar("othername: SmtpUTF8Mailbox:",
+                    || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:",
                             gen->d.otherName->value->value.utf8string->data,
+                            gen->d.otherName->value->value.utf8string->length,
                             &ret))
                 return NULL;
             break;
         case NID_XmppAddr:
             if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
-                    || !X509V3_add_value_uchar("othername: XmppAddr:",
+                    || !x509v3_add_len_value_uchar("othername: XmppAddr:",
                             gen->d.otherName->value->value.utf8string->data,
+                            gen->d.otherName->value->value.utf8string->length,
                             &ret))
                 return NULL;
             break;
         case NID_SRVName:
             if (gen->d.otherName->value->type != V_ASN1_IA5STRING
-                    || !X509V3_add_value_uchar("othername: SRVName:",
+                    || !x509v3_add_len_value_uchar("othername: SRVName:",
                             gen->d.otherName->value->value.ia5string->data,
+                            gen->d.otherName->value->value.ia5string->length,
                             &ret))
                 return NULL;
             break;
         case NID_ms_upn:
             if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
-                    || !X509V3_add_value_uchar("othername: UPN:",
+                    || !x509v3_add_len_value_uchar("othername: UPN:",
                             gen->d.otherName->value->value.utf8string->data,
+                            gen->d.otherName->value->value.utf8string->length,
                             &ret))
                 return NULL;
             break;
         case NID_NAIRealm:
             if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
-                    || !X509V3_add_value_uchar("othername: NAIRealm:",
+                    || !x509v3_add_len_value_uchar("othername: NAIRealm:",
                             gen->d.otherName->value->value.utf8string->data,
+                            gen->d.otherName->value->value.utf8string->length,
                             &ret))
                 return NULL;
             break;
@@ -129,14 +135,16 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
 
             /* check if the value is something printable */
             if (gen->d.otherName->value->type == V_ASN1_IA5STRING) {
-                if (X509V3_add_value_uchar(othername,
+                if (x509v3_add_len_value_uchar(othername,
                              gen->d.otherName->value->value.ia5string->data,
+                             gen->d.otherName->value->value.ia5string->length,
                              &ret)) 
                     return ret;
             }
             if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
-                if (X509V3_add_value_uchar(othername,
+                if (x509v3_add_len_value_uchar(othername,
                              gen->d.otherName->value->value.utf8string->data,
+                             gen->d.otherName->value->value.utf8string->length,
                              &ret)) 
                     return ret;
             }
@@ -157,17 +165,20 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
         break;
 
     case GEN_EMAIL:
-        if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
+        if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
+                                        gen->d.ia5->length, &ret))
             return NULL;
         break;
 
     case GEN_DNS:
-        if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
+        if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
+                                        gen->d.ia5->length, &ret))
             return NULL;
         break;
 
     case GEN_URI:
-        if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
+        if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
+                                        gen->d.ia5->length, &ret))
             return NULL;
         break;
 
@@ -212,23 +223,28 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
 
         switch (nid) {
         case NID_id_on_SmtpUTF8Mailbox:
-            BIO_printf(out, "othername:SmtpUTF8Mailbox:%s",
+            BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s",
+                       gen->d.otherName->value->value.utf8string->length,
                        gen->d.otherName->value->value.utf8string->data);
             break;
         case NID_XmppAddr:
-            BIO_printf(out, "othername:XmppAddr:%s",
+            BIO_printf(out, "othername:XmppAddr:%.*s",
+                       gen->d.otherName->value->value.utf8string->length,
                        gen->d.otherName->value->value.utf8string->data);
             break;
         case NID_SRVName:
-            BIO_printf(out, "othername:SRVName:%s",
+            BIO_printf(out, "othername:SRVName:%.*s",
+                       gen->d.otherName->value->value.ia5string->length,
                        gen->d.otherName->value->value.ia5string->data);
             break;
         case NID_ms_upn:
-            BIO_printf(out, "othername:UPN:%s",
+            BIO_printf(out, "othername:UPN:%.*s",
+                       gen->d.otherName->value->value.utf8string->length,
                        gen->d.otherName->value->value.utf8string->data);
             break;
         case NID_NAIRealm:
-            BIO_printf(out, "othername:NAIRealm:%s",
+            BIO_printf(out, "othername:NAIRealm:%.*s",
+                       gen->d.otherName->value->value.utf8string->length,
                        gen->d.otherName->value->value.utf8string->data);
             break;
         default:
diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c
index 77d5421349..5c63d2d9d8 100644
--- a/crypto/x509/v3_utl.c
+++ b/crypto/x509/v3_utl.c
@@ -12,6 +12,7 @@
 #include "e_os.h"
 #include "internal/cryptlib.h"
 #include <stdio.h>
+#include <string.h>
 #include "crypto/ctype.h"
 #include <openssl/conf.h>
 #include <openssl/crypto.h>
@@ -36,17 +37,23 @@ static int ipv6_hex(unsigned char *out, const char *in, int inlen);
 
 /* Add a CONF_VALUE name value pair to stack */
 
-int X509V3_add_value(const char *name, const char *value,
-                     STACK_OF(CONF_VALUE) **extlist)
+static int x509v3_add_len_value(const char *name, const char *value,
+                                size_t vallen, STACK_OF(CONF_VALUE) **extlist)
 {
     CONF_VALUE *vtmp = NULL;
     char *tname = NULL, *tvalue = NULL;
     int sk_allocated = (*extlist == NULL);
 
-    if (name && (tname = OPENSSL_strdup(name)) == NULL)
-        goto err;
-    if (value && (tvalue = OPENSSL_strdup(value)) == NULL)
+    if (name != NULL && (tname = OPENSSL_strdup(name)) == NULL)
         goto err;
+    if (value != NULL) {
+        /* We don't allow embeded NUL characters */
+        if (memchr(value, 0, vallen) != NULL)
+            goto err;
+        tvalue = OPENSSL_strndup(value, vallen);
+        if (tvalue == NULL)
+            goto err;
+    }
     if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL)
         goto err;
     if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL)
@@ -69,10 +76,26 @@ int X509V3_add_value(const char *name, const char *value,
     return 0;
 }
 
+int X509V3_add_value(const char *name, const char *value,
+                     STACK_OF(CONF_VALUE) **extlist)
+{
+    return x509v3_add_len_value(name, value,
+                                value != NULL ? strlen((const char *)value) : 0,
+                                extlist);
+}
+
 int X509V3_add_value_uchar(const char *name, const unsigned char *value,
                            STACK_OF(CONF_VALUE) **extlist)
 {
-    return X509V3_add_value(name, (const char *)value, extlist);
+    return x509v3_add_len_value(name, (const char *)value,
+                                value != NULL ? strlen((const char *)value) : 0,
+                                extlist);
+}
+
+int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
+                               size_t vallen, STACK_OF(CONF_VALUE) **extlist)
+{
+    return x509v3_add_len_value(name, (const char *)value, vallen, extlist);
 }
 
 /* Free function for STACK_OF(CONF_VALUE) */
@@ -506,17 +529,25 @@ static int append_ia5(STACK_OF(OPENSSL_STRING) **sk,
     /* First some sanity checks */
     if (email->type != V_ASN1_IA5STRING)
         return 1;
-    if (!email->data || !email->length)
+    if (email->data == NULL || email->length == 0)
+        return 1;
+    if (memchr(email->data, 0, email->length) != NULL)
         return 1;
     if (*sk == NULL)
         *sk = sk_OPENSSL_STRING_new(sk_strcmp);
     if (*sk == NULL)
         return 0;
+
+    emtmp = OPENSSL_strndup((char *)email->data, email->length);
+    if (emtmp == NULL)
+        return 0;
+
     /* Don't add duplicates */
-    if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
+    if (sk_OPENSSL_STRING_find(*sk, emtmp) != -1) {
+        OPENSSL_free(emtmp);
         return 1;
-    emtmp = OPENSSL_strdup((char *)email->data);
-    if (emtmp == NULL || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
+    }
+    if (!sk_OPENSSL_STRING_push(*sk, emtmp)) {
         OPENSSL_free(emtmp); /* free on push failure */
         X509_email_free(*sk);
         *sk = NULL;
diff --git a/fuzz/corpora/x509/a936a50b93a82a7d311aa3cda7f634602b524767 b/fuzz/corpora/x509/0bf7ea6564ba1096f9760bbd6ed02f25aa0d583c
similarity index 68%
copy from fuzz/corpora/x509/a936a50b93a82a7d311aa3cda7f634602b524767
copy to fuzz/corpora/x509/0bf7ea6564ba1096f9760bbd6ed02f25aa0d583c
index f06d9cb014..afb6c2d916 100644
Binary files a/fuzz/corpora/x509/a936a50b93a82a7d311aa3cda7f634602b524767 and b/fuzz/corpora/x509/0bf7ea6564ba1096f9760bbd6ed02f25aa0d583c differ
diff --git a/include/crypto/sm2.h b/include/crypto/sm2.h
index 165c01810f..9ab6c0b722 100644
--- a/include/crypto/sm2.h
+++ b/include/crypto/sm2.h
@@ -67,8 +67,8 @@ int ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen,
 int ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest,
                              size_t msg_len, size_t *ct_size);
 
-int ossl_sm2_plaintext_size(const EC_KEY *key, const EVP_MD *digest,
-                            size_t msg_len, size_t *pt_size);
+int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size,
+                            size_t *pt_size);
 
 int ossl_sm2_encrypt(const EC_KEY *key,
                      const EVP_MD *digest,
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index db83db0c92..599db841a7 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -361,3 +361,6 @@ int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp);
 EVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
                                  long length);
 #endif
+
+int x509v3_add_len_value_uchar(const char *name, const unsigned char *value,
+                               size_t vallen, STACK_OF(CONF_VALUE) **extlist);
diff --git a/providers/implementations/asymciphers/sm2_enc.c b/providers/implementations/asymciphers/sm2_enc.c
index c9dba32ffb..9577d16e83 100644
--- a/providers/implementations/asymciphers/sm2_enc.c
+++ b/providers/implementations/asymciphers/sm2_enc.c
@@ -110,7 +110,7 @@ static int sm2_asym_decrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen,
         return 0;
 
     if (out == NULL) {
-        if (!ossl_sm2_plaintext_size(psm2ctx->key, md, inlen, outlen))
+        if (!ossl_sm2_plaintext_size(in, inlen, outlen))
             return 0;
         return 1;
     }
diff --git a/test/cmp_status_test.c b/test/cmp_status_test.c
index 6248cc9b32..09a8e69181 100644
--- a/test/cmp_status_test.c
+++ b/test/cmp_status_test.c
@@ -58,7 +58,8 @@ static int execute_PKISI_test(CMP_STATUS_TEST_FIXTURE *fixture)
     if (!TEST_ptr(statusString =
                   sk_ASN1_UTF8STRING_value(ossl_cmp_pkisi_get0_statusString(si),
                                            0))
-            || !TEST_str_eq(fixture->text, (char *)statusString->data))
+            || !TEST_mem_eq(fixture->text, strlen(fixture->text),
+                            (char *)statusString->data, statusString->length))
         goto end;
 
     if (!TEST_int_eq(fixture->pkifailure,
diff --git a/test/helpers/pkcs12.c b/test/helpers/pkcs12.c
index cb94be7b88..a87683dc95 100644
--- a/test/helpers/pkcs12.c
+++ b/test/helpers/pkcs12.c
@@ -479,12 +479,15 @@ static int check_asn1_string(const ASN1_TYPE *av, const char *txt)
         break;
 
     case V_ASN1_UTF8STRING:
-        if (!TEST_str_eq(txt, (char *)av->value.utf8string->data))
+        if (!TEST_mem_eq(txt, strlen(txt), (char *)av->value.utf8string->data,
+                         av->value.utf8string->length))
             goto err;
         break;
 
     case V_ASN1_OCTET_STRING:
-        if (!TEST_str_eq(txt, (char *)av->value.octet_string->data))
+        if (!TEST_mem_eq(txt, strlen(txt),
+                         (char *)av->value.octet_string->data,
+                         av->value.octet_string->length))
             goto err;
         break;
 
diff --git a/test/recipes/30-test_evp_data/evppkey_sm2.txt b/test/recipes/30-test_evp_data/evppkey_sm2.txt
index c32142d833..410be7abee 100644
--- a/test/recipes/30-test_evp_data/evppkey_sm2.txt
+++ b/test/recipes/30-test_evp_data/evppkey_sm2.txt
@@ -53,6 +53,18 @@ Ctrl = digest:SM3
 Input = 30818A0220466BE2EF5C11782EC77864A0055417F407A5AFC11D653C6BCE69E417BB1D05B6022062B572E21FF0DDF5C726BD3F9FF2EAE56E6294713A607E9B9525628965F62CC804203C1B5713B5DB2728EB7BF775E44F4689FC32668BDC564F52EA45B09E8DF2A5F40422084A9D0CC2997092B7D3C404FCE95956EB604D732B2307A8E5B8900ED6608CA5B197
 Output = "The floofy bunnies hop at midnight"
 
+# Test with an C1y value < 32 bytes in length (self generated)
+Availablein = default
+Decrypt = SM2_key1
+Input = 3072022070DAD60CDA7C30D64CF4F278A849003581223F5324BFEC9BB329229BFFAD21A6021F18AFAB2B35459D2643243B242BE4EA80C6FA5071D2D847340CC57EB9309E5D04200B772E4DB664B2601E3B85E39C4AA8C2C1910308BE13B331E009C5A9258C29FD040B6D588BE9260A94DA18E0E6
+Output = "Hello World"
+
+# Test with an C1x and C1y valuey > 32 bytes in length, and longer plaintext (self generated)
+Availablein = default
+Decrypt = SM2_key1
+Input = 3081DD022100CD49634BBCB21CAFFFA6D33669A5A867231CB2A942A14352EF4CAF6DC3344D54022100C35B41D4DEBB3A2735EFEE821B9EBA566BD86900176A0C06672E30EE5CC04E930420C4190A3D80D86C4BD20E99F7E4B59BF6427C6808793533EEA9591D1188EC56B50473747295470E81D951BED279AC1B86A1AFE388CD2833FA9632799EC199C7D364E5663D5A94888BB2358CFCBF6283184DE0CBC41CCEA91D24746E99D231A1DA77AFD83CDF908190ED628B7369724494568A27C782A1D1D7294BCAD80C34569ED22859896301128A8118F48924D8CCD43E998D9533
+Output = "Some longer plaintext for testing SM2 decryption. Blah blah blah blah blah blah blah blah blah blah blah blah blah."
+
 # This is a "fake" test as it does only verify that the SM2 EVP_PKEY interface
 # is capable of creating a signature without failing, but it does not say
 # anything about the generated signature being valid, nor does it test the
diff --git a/test/sm2_internal_test.c b/test/sm2_internal_test.c
index e91a1a4898..22d23b6c5c 100644
--- a/test/sm2_internal_test.c
+++ b/test/sm2_internal_test.c
@@ -183,7 +183,7 @@ static int test_sm2_crypt(const EC_GROUP *group,
     if (!TEST_mem_eq(ctext, ctext_len, expected, ctext_len))
         goto done;
 
-    if (!TEST_true(ossl_sm2_plaintext_size(key, digest, ctext_len, &ptext_len))
+    if (!TEST_true(ossl_sm2_plaintext_size(ctext, ctext_len, &ptext_len))
             || !TEST_int_eq(ptext_len, msg_len))
         goto done;
 
diff --git a/test/x509_time_test.c b/test/x509_time_test.c
index d6f4330a55..711dfcb5b6 100644
--- a/test/x509_time_test.c
+++ b/test/x509_time_test.c
@@ -382,10 +382,12 @@ static int test_x509_time(int idx)
 
     /* if t is not NULL but expected_string is NULL, it is an 'OK' case too */
     if (t != NULL && x509_format_tests[idx].expected_string) {
-        if (!TEST_str_eq((const char *)t->data,
-                    x509_format_tests[idx].expected_string)) {
-            TEST_info("test_x509_time(%d) failed: expected_string %s, got %s\n",
-                    idx, x509_format_tests[idx].expected_string, t->data);
+        if (!TEST_mem_eq((const char *)t->data, t->length,
+                    x509_format_tests[idx].expected_string,
+                    strlen(x509_format_tests[idx].expected_string))) {
+            TEST_info("test_x509_time(%d) failed: expected_string %s, got %.*s\n",
+                    idx, x509_format_tests[idx].expected_string, t->length,
+                    t->data);
             goto out;
         }
     }


More information about the openssl-commits mailing list