Test empty EVP_CIPHER inputs and fix exact memcpy overlap.
See also 8129ac6ac4c0ca3a488c225cde580ede7dabe874 and
81198bf323ea9deda907714170d329ca7d2ff01f from upstream.
In trying to figure out why ASan (which normally catches overlapping
memcpys) didn't flag this, I noticed that we actually don't have tests
for empty inputs. I've added them to cipher_tests.txt where missing and
fixed a bad assert in ofb.c.
ASan still doesn't flag this because LLVM even requires memcpy handle
dst == src. Still, fixing it is less effort than getting a clear answer
from GCC and MSVC. Though this puts us in the frustrating position of
trying to follow a C rule that our main toolchain and sanitizer disavow.
https://bugs.llvm.org/show_bug.cgi?id=11763
https://reviews.llvm.org/D86993
Change-Id: I53c64a84834ddf5cddca0b3d53a29998f666ea2f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46285
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/cipher_extra/test/cipher_tests.txt b/crypto/cipher_extra/test/cipher_tests.txt
index 52fd4af..bf7325e 100644
--- a/crypto/cipher_extra/test/cipher_tests.txt
+++ b/crypto/cipher_extra/test/cipher_tests.txt
@@ -29,6 +29,11 @@
Plaintext = 00000000000000000000
Ciphertext = d6a141a7ec3c38dfbd61
+Cipher = RC4
+Key = ef012345ef012345ef012345ef012345
+Plaintext =
+Ciphertext =
+
# DES EDE3 ECB tests
Cipher = DES-EDE3
@@ -81,6 +86,11 @@
Plaintext = cc7569d005afd1a365f5c5836c14475fc15091199902af4a78460d56c16f91ca
Ciphertext = 64db8af7a30363051a017cc92ed67ac6c0e2e1ffda0c94bbf0eeb803ba6b3d22
+Cipher = DES-EDE3
+Key = 2e8eb05dd8a2b7a5a61a6b8a3830b12da2c4b1bea1e884d5
+Plaintext =
+Ciphertext =
+
# DES EDE3 CBC tests (from destest)
Cipher = DES-EDE3-CBC
@@ -89,6 +99,12 @@
Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
+Cipher = DES-EDE3-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210
+IV = fedcba9876543210
+Plaintext =
+Ciphertext =
+
# DES EDE CBC tests
Cipher = DES-EDE-CBC
@@ -97,6 +113,12 @@
Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B
+Cipher = DES-EDE-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext =
+Ciphertext =
+
# DES EDE tests
Cipher = DES-EDE
@@ -105,6 +127,12 @@
Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F
+Cipher = DES-EDE
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext =
+Ciphertext =
+
# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
Cipher = AES-128-ECB
@@ -112,6 +140,11 @@
Plaintext = 00112233445566778899AABBCCDDEEFF
Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A
+Cipher = AES-128-ECB
+Key = 000102030405060708090A0B0C0D0E0F
+Plaintext =
+Ciphertext =
+
# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
Cipher = AES-256-ECB
@@ -119,6 +152,11 @@
Plaintext = 00112233445566778899AABBCCDDEEFF
Ciphertext = 8EA2B7CA516745BFEAFC49904B496089
+Cipher = AES-256-ECB
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Plaintext =
+Ciphertext =
+
# AES tests from NIST document SP800-38A
# For all ECB encrypts and decrypts, the transformed sequence is
@@ -194,6 +232,12 @@
Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 73BED6B8E3C1743B7116E69E22229516
+Plaintext =
+Ciphertext =
+
# CBC-AES256.Encrypt and CBC-AES256.Decrypt
Cipher = AES-256-CBC
@@ -220,6 +264,12 @@
Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 39F23369A9D9BACFA530E26304231461
+Plaintext =
+Ciphertext =
+
# AES Counter test vectors from RFC3686
Cipher = AES-128-CTR
@@ -247,6 +297,12 @@
Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0
Cipher = AES-256-CTR
+Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104
+IV = 00000060DB5672C97AA8F0B200000001
+Plaintext =
+Ciphertext =
+
+Cipher = AES-256-CTR
Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884
IV = 00FAAC24C1585EF15A43D87500000001
Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
@@ -258,6 +314,12 @@
Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8
+Cipher = AES-256-CTR
+Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D
+IV = 001CC5B751A51D70A1C1114800000001
+Plaintext =
+Ciphertext =
+
# Regression test for https://github.com/openssl/openssl/issues/1916.
Cipher = AES-128-CTR
Key = 7E24067817FAE0D743D6CE1F32539163
@@ -478,6 +540,13 @@
Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = A78819583F0308E7A6BF36B1386ABF23
+Plaintext =
+Ciphertext =
+
+
# OFB-AES192
Cipher = AES-192-OFB
Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
@@ -503,6 +572,13 @@
Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
Ciphertext = 6D9F200857CA6C3E9CAC524BD9ACC92A
+Cipher = AES-192-OFB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = BD5286AC63AABD7EB067AC54B553F71D
+Plaintext =
+Ciphertext =
+
+
# OFB-AES256
Cipher = AES-256-OFB
Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
@@ -528,6 +604,12 @@
Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
Ciphertext = 0126141D67F37BE8538F5A8BE740E484
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 41635BE625B48AFC1666DD42A09D96E7
+Plaintext =
+Ciphertext =
+
# AES-192 CBC-mode test from upstream OpenSSL.
Cipher = AES-192-CBC
@@ -619,3 +701,8 @@
Key = FEDCBA9876543210
Plaintext = 0123456789ABCDEF
Ciphertext = ED39D950FA74BCC4
+
+Cipher = DES-ECB
+Key = FEDCBA9876543210
+Plaintext =
+Ciphertext =
diff --git a/crypto/fipsmodule/modes/cbc.c b/crypto/fipsmodule/modes/cbc.c
index 3f1d777..750c575 100644
--- a/crypto/fipsmodule/modes/cbc.c
+++ b/crypto/fipsmodule/modes/cbc.c
@@ -57,12 +57,15 @@
void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16],
block128_f block) {
+ assert(key != NULL && ivec != NULL);
+ if (len == 0) {
+ // Avoid |ivec| == |iv| in the |memcpy| below, which is not legal in C.
+ return;
+ }
+
+ assert(in != NULL && out != NULL);
size_t n;
const uint8_t *iv = ivec;
-
- assert(key != NULL && ivec != NULL);
- assert(len == 0 || (in != NULL && out != NULL));
-
while (len >= 16) {
for (n = 0; n < 16; n += sizeof(size_t)) {
store_word_le(out + n, load_word_le(in + n) ^ load_word_le(iv + n));
@@ -97,20 +100,25 @@
void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16],
block128_f block) {
- size_t n;
- union {
- size_t t[16 / sizeof(size_t)];
- uint8_t c[16];
- } tmp;
-
assert(key != NULL && ivec != NULL);
- assert(len == 0 || (in != NULL && out != NULL));
+ if (len == 0) {
+ // Avoid |ivec| == |iv| in the |memcpy| below, which is not legal in C.
+ return;
+ }
+
+ assert(in != NULL && out != NULL);
const uintptr_t inptr = (uintptr_t) in;
const uintptr_t outptr = (uintptr_t) out;
// If |in| and |out| alias, |in| must be ahead.
assert(inptr >= outptr || inptr + len <= outptr);
+ size_t n;
+ union {
+ size_t t[16 / sizeof(size_t)];
+ uint8_t c[16];
+ } tmp;
+
if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) {
// If |out| is at least two blocks behind |in| or completely disjoint, there
// is no need to decrypt to a temporary block.
diff --git a/crypto/fipsmodule/modes/ofb.c b/crypto/fipsmodule/modes/ofb.c
index 4c70ce6..9d73d8a 100644
--- a/crypto/fipsmodule/modes/ofb.c
+++ b/crypto/fipsmodule/modes/ofb.c
@@ -60,7 +60,8 @@
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16], unsigned *num,
block128_f block) {
- assert(in && out && key && ivec && num);
+ assert(key != NULL && ivec != NULL && num != NULL);
+ assert(len == 0 || (in != NULL && out != NULL));
unsigned n = *num;