diff --git a/SOURCES/openssl-1.0.2k-cve-2021-3712.patch b/SOURCES/openssl-1.0.2k-cve-2021-3712.patch
new file mode 100644
index 0000000..43a1687
--- /dev/null
+++ b/SOURCES/openssl-1.0.2k-cve-2021-3712.patch
@@ -0,0 +1,307 @@
+diff -up openssl-1.0.2k/crypto/asn1/t_spki.c.read-buff openssl-1.0.2k/crypto/asn1/t_spki.c
+--- openssl-1.0.2k/crypto/asn1/t_spki.c.read-buff	2017-01-26 14:22:03.000000000 +0100
++++ openssl-1.0.2k/crypto/asn1/t_spki.c	2021-11-19 12:14:17.572630962 +0100
+@@ -90,7 +90,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCA
+     }
+     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 -up openssl-1.0.2k/crypto/crypto.h.read-buff openssl-1.0.2k/crypto/crypto.h
+--- openssl-1.0.2k/crypto/crypto.h.read-buff	2021-11-19 15:10:25.738928196 +0100
++++ openssl-1.0.2k/crypto/crypto.h	2021-11-19 17:51:47.062694785 +0100
+@@ -380,6 +380,8 @@ int CRYPTO_is_mem_check_on(void);
+ 
+ # define OPENSSL_malloc(num)     CRYPTO_malloc((int)num,__FILE__,__LINE__)
+ # define OPENSSL_strdup(str)     CRYPTO_strdup((str),__FILE__,__LINE__)
++# define OPENSSL_strndup(str, n) \
++        CRYPTO_strndup((str), n, __FILE__, __LINE__)
+ # define OPENSSL_realloc(addr,num) \
+         CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
+ # define OPENSSL_realloc_clean(addr,old_num,num) \
+@@ -393,6 +395,8 @@ int CRYPTO_is_mem_check_on(void);
+         CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
+ # define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+ 
++size_t OPENSSL_strnlen(const char *str, size_t maxlen);
++
+ const char *SSLeay_version(int type);
+ unsigned long SSLeay(void);
+ 
+@@ -533,6 +537,7 @@ void *CRYPTO_malloc_locked(int num, cons
+ void CRYPTO_free_locked(void *ptr);
+ void *CRYPTO_malloc(int num, const char *file, int line);
+ char *CRYPTO_strdup(const char *str, const char *file, int line);
++char *CRYPTO_strndup(const char *str, size_t s, const char *file, int line);
+ void CRYPTO_free(void *ptr);
+ void *CRYPTO_realloc(void *addr, int num, const char *file, int line);
+ void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file,
+diff -up openssl-1.0.2k/crypto/ec/ec_asn1.c.read-buff openssl-1.0.2k/crypto/ec/ec_asn1.c
+--- openssl-1.0.2k/crypto/ec/ec_asn1.c.read-buff	2017-01-26 14:22:03.000000000 +0100
++++ openssl-1.0.2k/crypto/ec/ec_asn1.c	2021-11-19 12:14:17.572630962 +0100
+@@ -860,7 +860,10 @@ static EC_GROUP *ec_asn1_parameters2grou
+         ret->seed_len = params->curve->seed->length;
+     }
+ 
+-    if (!params->order || !params->base || !params->base->data) {
++    if (params->order == NULL
++            || params->base == NULL
++            || params->base->data == NULL
++            || params->base->length == 0) {
+         ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+         goto err;
+     }
+diff -up openssl-1.0.2k/crypto/mem.c.read-buff openssl-1.0.2k/crypto/mem.c
+--- openssl-1.0.2k/crypto/mem.c.read-buff	2021-11-19 15:54:38.937427447 +0100
++++ openssl-1.0.2k/crypto/mem.c	2021-11-19 15:55:21.234906752 +0100
+@@ -364,6 +364,24 @@ char *CRYPTO_strdup(const char *str, con
+     return ret;
+ }
+ 
++char *CRYPTO_strndup(const char *str, size_t s, const char* file, int line)
++{
++    size_t maxlen;
++    char *ret;
++
++    if (str == NULL)
++        return NULL;
++
++    maxlen = OPENSSL_strnlen(str, s);
++
++    ret = CRYPTO_malloc(maxlen + 1, file, line);
++    if (ret) {
++        memcpy(ret, str, maxlen);
++        ret[maxlen] = '\0';
++    }
++    return ret;
++}
++
+ void *CRYPTO_realloc(void *str, int num, const char *file, int line)
+ {
+     void *ret = NULL;
+diff -up openssl-1.0.2k/crypto/o_str.c.read-buff openssl-1.0.2k/crypto/o_str.c
+--- openssl-1.0.2k/crypto/o_str.c.read-buff	2021-11-19 15:57:18.812239108 +0100
++++ openssl-1.0.2k/crypto/o_str.c	2021-11-19 15:58:22.704963124 +0100
+@@ -114,3 +114,12 @@ int OPENSSL_memcmp(const void *v1, const
+ 
+     return ret;
+ }
++
++size_t OPENSSL_strnlen(const char *str, size_t maxlen)
++{
++    const char *p;
++
++    for (p = str; maxlen-- != 0 && *p != '\0'; ++p) ;
++
++    return p - str;
++}
+diff -up openssl-1.0.2k/crypto/x509v3/v3_cpols.c.read-buff openssl-1.0.2k/crypto/x509v3/v3_cpols.c
+--- openssl-1.0.2k/crypto/x509v3/v3_cpols.c.read-buff	2017-01-26 14:22:04.000000000 +0100
++++ openssl-1.0.2k/crypto/x509v3/v3_cpols.c	2021-11-19 12:14:17.572630962 +0100
+@@ -423,7 +423,8 @@ static void print_qualifiers(BIO *out, S
+         qualinfo = sk_POLICYQUALINFO_value(quals, i);
+         switch (OBJ_obj2nid(qualinfo->pqualid)) {
+         case NID_id_qt_cps:
+-            BIO_printf(out, "%*sCPS: %s\n", indent, "",
++            BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
++                       qualinfo->d.cpsuri->length,
+                        qualinfo->d.cpsuri->data);
+             break;
+ 
+@@ -448,7 +449,8 @@ static void print_notice(BIO *out, USERN
+     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" : "");
+@@ -465,7 +467,8 @@ static void print_notice(BIO *out, USERN
+         BIO_puts(out, "\n");
+     }
+     if (notice->exptext)
+-        BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
++        BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
++                   notice->exptext->length,
+                    notice->exptext->data);
+ }
+ 
+diff -up openssl-1.0.2k/crypto/x509v3/v3_ncons.c.read-buff openssl-1.0.2k/crypto/x509v3/v3_ncons.c
+--- openssl-1.0.2k/crypto/x509v3/v3_ncons.c.read-buff	2017-01-26 14:22:04.000000000 +0100
++++ openssl-1.0.2k/crypto/x509v3/v3_ncons.c	2021-11-19 12:14:17.573630970 +0100
+@@ -107,6 +107,27 @@ 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];
++}
++
+ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+                                   X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+ {
+@@ -372,8 +393,12 @@ static int nc_dns(ASN1_IA5STRING *dns, A
+     char *baseptr = (char *)base->data;
+     char *dnsptr = (char *)dns->data;
+     /* Empty matches everything */
+-    if (!*baseptr)
++    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.
+@@ -384,7 +409,7 @@ static int nc_dns(ASN1_IA5STRING *dns, A
+             return X509_V_ERR_PERMITTED_VIOLATION;
+     }
+ 
+-    if (strcasecmp(baseptr, dnsptr))
++    if (strncasecmp(baseptr, dnsptr, base->length))
+         return X509_V_ERR_PERMITTED_VIOLATION;
+ 
+     return X509_V_OK;
+@@ -395,16 +420,17 @@ static int nc_email(ASN1_IA5STRING *eml,
+ {
+     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 = strchr(baseptr, '@');
+-    const char *emlat = strchr(emlptr, '@');
+     if (!emlat)
+         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+     /* Special case: inital '.' is RHS match */
+-    if (!baseat && (*baseptr == '.')) {
++    if (!baseat && base->length > 0 && (*baseptr == '.')) {
+         if (eml->length > base->length) {
+             emlptr += eml->length - base->length;
+-            if (!strcasecmp(baseptr, emlptr))
++            if (!strncasecmp(baseptr, emlptr, base->length))
+                 return X509_V_OK;
+         }
+         return X509_V_ERR_PERMITTED_VIOLATION;
+@@ -424,8 +450,10 @@ static int nc_email(ASN1_IA5STRING *eml,
+         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 (strcasecmp(baseptr, emlptr))
++    if (basehostlen != emlhostlen || strncasecmp(baseptr, emlptr, emlhostlen))
+         return X509_V_ERR_PERMITTED_VIOLATION;
+ 
+     return X509_V_OK;
+@@ -436,10 +464,13 @@ static int nc_uri(ASN1_IA5STRING *uri, A
+ {
+     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 || (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;
+ 
+@@ -447,10 +478,10 @@ static int nc_uri(ASN1_IA5STRING *uri, A
+ 
+     /* Look for a port indicator as end of hostname first */
+ 
+-    p = strchr(hostptr, ':');
++    p = ia5memchr(uri, hostptr, ':');
+     /* Otherwise look for trailing slash */
+-    if (!p)
+-        p = strchr(hostptr, '/');
++    if (p == NULL)
++        p = ia5memchr(uri, hostptr, '/');
+ 
+     if (!p)
+         hostlen = strlen(hostptr);
+@@ -461,7 +492,7 @@ static int nc_uri(ASN1_IA5STRING *uri, A
+         return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+ 
+     /* Special case: inital '.' is RHS match */
+-    if (*baseptr == '.') {
++    if (base->length > 0 && *baseptr == '.') {
+         if (hostlen > base->length) {
+             p = hostptr + hostlen - base->length;
+             if (!strncasecmp(p, baseptr, base->length))
+diff -up openssl-1.0.2k/crypto/x509v3/v3_pci.c.read-buff openssl-1.0.2k/crypto/x509v3/v3_pci.c
+--- openssl-1.0.2k/crypto/x509v3/v3_pci.c.read-buff	2017-01-26 14:22:04.000000000 +0100
++++ openssl-1.0.2k/crypto/x509v3/v3_pci.c	2021-11-19 12:14:17.572630962 +0100
+@@ -68,7 +68,8 @@ static int i2r_pci(X509V3_EXT_METHOD *me
+     i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
+     BIO_puts(out, "\n");
+     if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
+-        BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
++        BIO_printf(out, "%*sPolicy Text: %.*s\n", indent, "",
++                   pci->proxyPolicy->policy->length,
+                    pci->proxyPolicy->policy->data);
+     return 1;
+ }
+diff -up openssl-1.0.2k/crypto/x509v3/v3_utl.c.read-buff openssl-1.0.2k/crypto/x509v3/v3_utl.c
+--- openssl-1.0.2k/crypto/x509v3/v3_utl.c.read-buff	2017-01-26 14:22:04.000000000 +0100
++++ openssl-1.0.2k/crypto/x509v3/v3_utl.c	2021-11-19 12:14:17.573630970 +0100
+@@ -609,17 +609,26 @@ static int append_ia5(STACK_OF(OPENSSL_S
+     /* 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)
+         *sk = sk_OPENSSL_STRING_new(sk_strcmp);
+     if (!*sk)
+         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 = BUF_strdup((char *)email->data);
+-    if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
++    }
++    if (sk_OPENSSL_STRING_push(*sk, emtmp)) {
++        OPENSSL_free(emtmp);
+         X509_email_free(*sk);
+         *sk = NULL;
+         return 0;
diff --git a/SPECS/openssl.spec b/SPECS/openssl.spec
index 9168bfc..2c52b48 100644
--- a/SPECS/openssl.spec
+++ b/SPECS/openssl.spec
@@ -23,7 +23,7 @@
 Summary: Utilities from the general purpose cryptography library with TLS implementation
 Name: openssl
 Version: 1.0.2k
-Release: 22%{?dist}
+Release: 23%{?dist}
 Epoch: 1
 # We have to remove certain patented algorithms from the openssl source
 # tarball with the hobble-openssl script which is included below.
@@ -113,6 +113,7 @@ Patch111: openssl-1.0.2k-fix-9-lives.patch
 Patch112: openssl-1.0.2k-cve-2020-1971.patch
 Patch113: openssl-1.0.2k-cve-2021-23840.patch
 Patch114: openssl-1.0.2k-cve-2021-23841.patch
+Patch115: openssl-1.0.2k-cve-2021-3712.patch
 
 License: OpenSSL
 Group: System Environment/Libraries
@@ -258,6 +259,7 @@ cp %{SOURCE12} %{SOURCE13} crypto/ec/
 %patch112 -p1 -b .null-dereference
 %patch113 -p1 -b .int-overflow
 %patch114 -p1 -b .null-hash-deref
+%patch115 -p1 -b .read-buff
 
 sed -i 's/SHLIB_VERSION_NUMBER "1.0.0"/SHLIB_VERSION_NUMBER "%{version}"/' crypto/opensslv.h
 
@@ -557,6 +559,10 @@ rm -rf $RPM_BUILD_ROOT/%{_libdir}/fipscanister.*
 %postun libs -p /sbin/ldconfig
 
 %changelog
+* Sat Nov 20 2021 Sahana Prasad <sahana@redhat.com> 1.0.2k-23
+- fixes CVE-2021-3712 openssl: Read buffer overruns processing ASN.1 strings
+- Resolves: rhbz#1996054
+
 * Wed Sep  1 2021 Sahana Prasad <sahana@redhat.com> 1.0.2k-22
 - fix CVE-2021-23841 openssl: NULL pointer dereference
   in X509_issuer_and_serial_hash()