diff --git a/SOURCES/fix-crypto-memory-leaks.patch b/SOURCES/fix-crypto-memory-leaks.patch
new file mode 100644
index 0000000..daab969
--- /dev/null
+++ b/SOURCES/fix-crypto-memory-leaks.patch
@@ -0,0 +1,235 @@
+diff --git a/src/crypto/internal/boring/goopenssl.h b/src/crypto/internal/boring/goopenssl.h
+index 3585458..ae1607b 100644
+--- a/src/crypto/internal/boring/goopenssl.h
++++ b/src/crypto/internal/boring/goopenssl.h
+@@ -667,6 +667,7 @@ typedef EVP_PKEY GO_EVP_PKEY;
+ DEFINEFUNC(GO_EVP_PKEY *, EVP_PKEY_new, (void), ())
+ DEFINEFUNC(void, EVP_PKEY_free, (GO_EVP_PKEY * arg0), (arg0))
+ DEFINEFUNC(int, EVP_PKEY_set1_RSA, (GO_EVP_PKEY * arg0, GO_RSA *arg1), (arg0, arg1))
++DEFINEFUNC(int, EVP_PKEY_set1_EC_KEY, (GO_EVP_PKEY * arg0, GO_EC_KEY *arg1), (arg0, arg1))
+ DEFINEFUNC(int, EVP_PKEY_verify,
+ 	(EVP_PKEY_CTX *ctx, const unsigned char *sig, unsigned int siglen, const unsigned char *tbs, size_t tbslen),
+ 	(ctx, sig, siglen, tbs, tbslen))
+diff --git a/src/crypto/internal/boring/openssl_ecdsa_signature.c b/src/crypto/internal/boring/openssl_ecdsa_signature.c
+index 4c14cc9..daa1252 100644
+--- a/src/crypto/internal/boring/openssl_ecdsa_signature.c
++++ b/src/crypto/internal/boring/openssl_ecdsa_signature.c
+@@ -9,19 +9,32 @@
+ int
+ _goboringcrypto_ECDSA_sign(EVP_MD* md, const uint8_t *msg, size_t msgLen, uint8_t *sig, unsigned int *slen, GO_EC_KEY *eckey)
+ {
++    int result;
+     EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new();
+-    if (!_goboringcrypto_EVP_PKEY_assign_EC_KEY(key, eckey))
+-        return 0;
+-    return _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key);
++    if (!_goboringcrypto_EVP_PKEY_set1_EC_KEY(key, eckey)) {
++        result = 0;
++        goto err;
++    }
++    result = _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key);
++err:
++    _goboringcrypto_EVP_PKEY_free(key);
++    return result;
+ }
+ 
+ int
+ _goboringcrypto_ECDSA_verify(EVP_MD* md, const uint8_t *msg, size_t msgLen, const uint8_t *sig, unsigned int slen, GO_EC_KEY *eckey)
+ {
+ 
++    int result;
+     EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new();
+-    if (!_goboringcrypto_EVP_PKEY_assign_EC_KEY(key, eckey))
+-        return 0;
++    if (!_goboringcrypto_EVP_PKEY_set1_EC_KEY(key, eckey)) {
++        result = 0;
++        goto err;
++    }
+ 
+-    return _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key);
++    result = _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key);
++
++err:
++    _goboringcrypto_EVP_PKEY_free(key);
++    return result;
+ }
+diff --git a/src/crypto/internal/boring/openssl_port_rsa.c b/src/crypto/internal/boring/openssl_port_rsa.c
+index a8d047d..2e56499 100644
+--- a/src/crypto/internal/boring/openssl_port_rsa.c
++++ b/src/crypto/internal/boring/openssl_port_rsa.c
+@@ -25,14 +25,13 @@ int _goboringcrypto_RSA_digest_and_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_
+ 	EVP_PKEY_CTX *ctx;
+ 	unsigned int siglen;
+ 
++	int ret = 0;
+ 	EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new();
+-	if (!_goboringcrypto_EVP_PKEY_assign_RSA(key, rsa))
+-		return 0;
++	if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa))
++		goto err;
+ 	ctx = _goboringcrypto_EVP_PKEY_CTX_new(key, NULL /* no engine */);
+ 	if (!ctx)
+-		return 0;
+-
+-	int ret = 0;
++		goto err;
+ 
+ 	EVP_MD_CTX *mdctx = NULL;
+ 	if (!(mdctx = _goboringcrypto_EVP_MD_CTX_create()))
+@@ -67,6 +66,10 @@ int _goboringcrypto_RSA_digest_and_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_
+ err:
+ 	if (mdctx)
+ 		_goboringcrypto_EVP_MD_CTX_free(mdctx);
++	if (ctx)
++		_goboringcrypto_EVP_PKEY_CTX_free(ctx);
++	if (key)
++		_goboringcrypto_EVP_PKEY_free(key);
+ 
+ 	return ret;
+ }
+@@ -78,18 +81,17 @@ int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_len, uint8_
+ 	EVP_PKEY *pkey;
+ 	size_t siglen;
+ 
++	int ret = 0;
+ 	pkey = _goboringcrypto_EVP_PKEY_new();
+ 	if (!pkey)
+-		return 0;
++		goto err;
+ 
+ 	if (_goboringcrypto_EVP_PKEY_set1_RSA(pkey, rsa) <= 0)
+-		return 0;
+-	
++		goto err;
++
+ 	ctx = _goboringcrypto_EVP_PKEY_CTX_new(pkey, NULL /* no engine */);
+ 	if (!ctx)
+-		return 0;
+-
+-	int ret = 0;
++		goto err;
+ 
+ 	if (_goboringcrypto_EVP_PKEY_sign_init(ctx) <= 0)
+ 		goto err;
+@@ -101,7 +103,7 @@ int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_len, uint8_
+ 		goto err;
+ 	if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md) <= 0)
+ 		goto err;
+-	
++
+ 	/* Determine buffer length */
+ 	if (_goboringcrypto_EVP_PKEY_sign(ctx, NULL, &siglen, in, in_len) <= 0)
+ 		goto err;
+@@ -116,7 +118,10 @@ int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_len, uint8_
+ 	ret = 1;
+ 
+ err:
+-	_goboringcrypto_EVP_PKEY_CTX_free(ctx);
++	if (ctx)
++		_goboringcrypto_EVP_PKEY_CTX_free(ctx);
++	if (pkey)
++		_goboringcrypto_EVP_PKEY_free(pkey);
+ 
+ 	return ret;
+ }
+@@ -130,14 +135,14 @@ int _goboringcrypto_RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *msg, unsigned i
+ 
+ 	pkey = _goboringcrypto_EVP_PKEY_new();
+ 	if (!pkey)
+-		return 0;
++		goto err;
+ 
+ 	if (_goboringcrypto_EVP_PKEY_set1_RSA(pkey, rsa) <= 0)
+-		return 0;
+-	
++		goto err;
++
+ 	ctx = _goboringcrypto_EVP_PKEY_CTX_new(pkey, NULL /* no engine */);
+ 	if (!ctx)
+-		return 0;
++		goto err;
+ 
+ 	if (_goboringcrypto_EVP_PKEY_verify_init(ctx) <= 0)
+ 		goto err;
+@@ -155,25 +160,40 @@ int _goboringcrypto_RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *msg, unsigned i
+ 	ret = 1;
+ 
+ err:
+-	_goboringcrypto_EVP_PKEY_CTX_free(ctx);
++	if (ctx)
++		_goboringcrypto_EVP_PKEY_CTX_free(ctx);
++	if (pkey)
++		_goboringcrypto_EVP_PKEY_free(pkey);
++
+ 
+ 	return ret;
+ }
+ 
+ int _goboringcrypto_EVP_RSA_sign(EVP_MD *md, const uint8_t *msg, unsigned int msgLen, uint8_t *sig, unsigned int *slen, RSA *rsa)
+ {
++	int result;
+ 	EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new();
+-	if (!_goboringcrypto_EVP_PKEY_assign_RSA(key, rsa))
+-		return 0;
+-	return _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key);
++	if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa)) {
++		result = 0;
++		goto err;
++	}
++	result = _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key);
++err:
++	_goboringcrypto_EVP_PKEY_free(key);
++	return result;
+ }
+ 
+ int _goboringcrypto_EVP_RSA_verify(EVP_MD *md, const uint8_t *msg, unsigned int msgLen, const uint8_t *sig, unsigned int slen, GO_RSA *rsa)
+ {
++	int result;
+ 	EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new();
+-	if (!_goboringcrypto_EVP_PKEY_assign_RSA(key, rsa))
+-	{
+-		return 0;
++	if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa)) {
++		result = 0;
++		goto err;
+ 	}
+-	 return _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key);
++	result =  _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key);
++err:
++	_goboringcrypto_EVP_PKEY_free(key);
++	return result;
++
+ }
+diff --git a/src/crypto/internal/boring/rsa.go b/src/crypto/internal/boring/rsa.go
+index 2eefc27..698c08e 100644
+--- a/src/crypto/internal/boring/rsa.go
++++ b/src/crypto/internal/boring/rsa.go
+@@ -162,12 +162,23 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int,
+ 			return nil, nil, NewOpenSSLError("EVP_PKEY_set_rsa_oaep_md failed")
+ 		}
+ 		// ctx takes ownership of label, so malloc a copy for BoringCrypto to free.
+-		clabel := (*C.uint8_t)(C.malloc(C.size_t(len(label))))
+-		if clabel == nil {
+-			return nil, nil, fail("OPENSSL_malloc")
++		var clabel *C.uint8_t
++		clabel = nil
++		// OpenSSL 1.1.1 does not take ownership of the label if the length is zero.
++		// Depending on the malloc implementation, if clabel is allocated with malloc(0),
++		// metadata for the size-zero allocation is never cleaned up, which is a memory leak.
++		// As such, we must only allocate clabel if the label is of non zero length.
++		if len(label) > 0 {
++			clabel = (*C.uint8_t)(C.malloc(C.size_t(len(label))))
++			if clabel == nil {
++				return nil, nil, fail("OPENSSL_malloc")
++			}
++			copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label)
+ 		}
+-		copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label)
+-		if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.int(len(label))) == 0 {
++		if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.int(len(label))) != 1 {
++			if clabel != nil {
++				C.free(unsafe.Pointer(clabel))
++			}
+ 			return nil, nil, NewOpenSSLError("EVP_PKEY_CTX_set0_rsa_oaep_label failed")
+ 		}
+ 	}
diff --git a/SPECS/golang.spec b/SPECS/golang.spec
index 4e99e8f..a7fec5c 100644
--- a/SPECS/golang.spec
+++ b/SPECS/golang.spec
@@ -101,7 +101,7 @@
 
 Name:           golang
 Version:        %{go_version}
-Release:        1%{?dist}
+Release:        3%{?dist}
 Summary:        The Go Programming Language
 # source tree includes several copies of Mark.Twain-Tom.Sawyer.txt under Public Domain
 License:        BSD and Public Domain
@@ -159,6 +159,9 @@ Patch1955032:   rhbz1955032.patch
 # https://go-review.googlesource.com/c/go/+/315289
 Patch1956891:   rhbz1956891.patch
 
+# Fix FIPS mode memory leaks
+Patch1951877: fix-crypto-memory-leaks.patch
+
 # Having documentation separate was broken
 Obsoletes:      %{name}-docs < 1.1-4
 
@@ -260,6 +263,9 @@ Requires:       %{name} = %{version}-%{release}
 
 %patch1956891 -p1
 
+%patch1951877 -p1
+
+
 cp %{SOURCE1} ./src/runtime/
 
 %build
@@ -526,6 +532,13 @@ cd ..
 %endif
 
 %changelog
+* Thu Jun 17 2021 David Benoit <dbenoit@redhat.com> - 1.16.4-3
+- Fix zero-size allocation memory leak.
+- Related: rhbz#1951877
+
+* Tue Jun 08 2021 David Benoit <dbenoit@redhat.com> - 1.16.4-2
+- Resolves: rhbz#1951877
+
 * Mon May 24 2021 Alejandro Sáez <asm@redhat.com> - 1.16.4-1
 - Rebase to go-1.16.4-1-openssl-fips