summaryrefslogtreecommitdiff
path: root/gtests/freebl_gtest
diff options
context:
space:
mode:
authorRobert Relyea <rrelyea@redhat.com>2020-12-18 09:24:50 -0800
committerRobert Relyea <rrelyea@redhat.com>2020-12-18 09:24:50 -0800
commit12aee4d4646e475f3d3e795a1a3f0690520a8723 (patch)
tree25ee67508d59209dc5ce0a3fa19296070892b4e8 /gtests/freebl_gtest
parentdc15f1596ab13dd1372a9bf2b08826b05b3e7d88 (diff)
downloadnss-hg-12aee4d4646e475f3d3e795a1a3f0690520a8723.tar.gz
Bug 1651411 New tlsfuzzer code can still detect timing issues in RSA operations.
This patch defeats Bleichenbacher by not trying to hide the size of the decrypted text, but to hide if the text succeeded for failed. This is done by generating a fake returned text that's based on the key and the cipher text, so the fake data is always the same for the same key and cipher text. Both the length and the plain text are generated with a prf. Here's the proposed spec the patch codes to: 1. Use SHA-256 to hash the private exponent encoded as a big-endian integer to a string the same length as the public modulus. Keep this value secret. (this is just an optimisation so that the implementation doesn't have to serialise the key over and over again) 2. Check the length of input according to step one of https://tools.ietf.org/html/rfc8017#section-7.2.2 3. When provided with a ciphertext, use SHA-256 HMAC(key=hash_from_step1, text=ciphertext) to generate the key derivation key 4. Use SHA-256 HMAC with key derivation key as the key and a two-byte big-endian iterator concatenated with byte string "length" with the big-endian representation of 2048 (0x0800) as the bit length of the generated string. - Iterate this PRF 8 times to generate a 256 byte string 5. initialise the length of synthetic message to 0 6. split the PRF output into 2 byte strings, convert into big-endian integers, zero-out high-order bits so that they have the same bit length as the octet length of the maximum acceptable message size (k-11), select the last integer that is no larger than (k-11) or remain at 0 if no integer is smaller than (k-11); this selection needs to be performed using a side-channel free operators 7. Use SHA-256 HMAC with key derivation key as the key and a two-byte big-endian iterator concatenated with byte string "message" with the big-endian representation of k*8 - use this PRF to generate k bytes of output (right-truncate last HMAC call if the number of generated bytes is not a multiple of SHA-256 output size) 8. perform the RSA decryption as described in step 2 of section 7.2.2 of rfc8017 9. Verify the EM message padding as described in step 3 of section 7.2.2 of rfc8017, but instead of outputting "decryption error", return the last l bytes of the "message" PRF, when l is the selected synthetic message length using the "length" PRF, make this decision and copy using side-channel free operation Differential Revision: https://phabricator.services.mozilla.com/D99843
Diffstat (limited to 'gtests/freebl_gtest')
-rw-r--r--gtests/freebl_gtest/Makefile43
-rw-r--r--gtests/freebl_gtest/manifest.mn38
-rw-r--r--gtests/freebl_gtest/rsa_unittest.cc12
3 files changed, 89 insertions, 4 deletions
diff --git a/gtests/freebl_gtest/Makefile b/gtests/freebl_gtest/Makefile
new file mode 100644
index 000000000..0d547e080
--- /dev/null
+++ b/gtests/freebl_gtest/Makefile
@@ -0,0 +1,43 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../common/gtest.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
diff --git a/gtests/freebl_gtest/manifest.mn b/gtests/freebl_gtest/manifest.mn
new file mode 100644
index 000000000..08a510bca
--- /dev/null
+++ b/gtests/freebl_gtest/manifest.mn
@@ -0,0 +1,38 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../..
+DEPTH = ../..
+MODULE = nss
+
+# we'll need to figure out how to get these symbols linked
+# in before we include these tests:
+# mpi_unittest.cc
+# ghash_unittest.cc
+CPPSRCS = \
+ dh_unittest.cc \
+ ecl_unittest.cc \
+ rsa_unittest.cc \
+ cmac_unittests.cc \
+ $(NULL)
+
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
+ -I$(CORE_DEPTH)/lib/freebl/ecl \
+ -I$(CORE_DEPTH)/lib/freebl/mpi \
+ -I$(CORE_DEPTH)/lib/freebl \
+ -I$(CORE_DEPTH)/gtests/common \
+ -I$(CORE_DEPTH)/cpputil
+
+REQUIRES = nspr nss libdbm gtest cpputil
+
+PROGRAM = freebl_gtest
+
+EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)cpputil.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \
+ $(NULL)
+
+USE_STATIC_LIBS=1
diff --git a/gtests/freebl_gtest/rsa_unittest.cc b/gtests/freebl_gtest/rsa_unittest.cc
index 9a6a9c11f..cac685c7e 100644
--- a/gtests/freebl_gtest/rsa_unittest.cc
+++ b/gtests/freebl_gtest/rsa_unittest.cc
@@ -78,18 +78,22 @@ TEST_F(RSATest, DecryptBlockTestErrors) {
uint8_t in[256] = {0};
// This should fail because the padding checks will fail.
+ // however, Bleichenbacher preventions means that failure would be
+ // a different output.
rv = RSA_DecryptBlock(key.get(), out, &outputLen, maxOutputLen, in,
sizeof(in));
- EXPECT_EQ(SECFailure, rv);
- // outputLen should be maxOutputLen.
- EXPECT_EQ(maxOutputLen, outputLen);
+ EXPECT_EQ(SECSuccess, rv);
+ // outputLen should <= 256-11=245.
+ EXPECT_LE(outputLen, 245u);
// This should fail because the padding checks will fail.
+ // however, Bleichenbacher preventions means that failure would be
+ // a different output.
uint8_t out_long[260] = {0};
maxOutputLen = sizeof(out_long);
rv = RSA_DecryptBlock(key.get(), out_long, &outputLen, maxOutputLen, in,
sizeof(in));
- EXPECT_EQ(SECFailure, rv);
+ EXPECT_EQ(SECSuccess, rv);
// outputLen should <= 256-11=245.
EXPECT_LE(outputLen, 245u);
// Everything over 256 must be 0 in the output.