summaryrefslogtreecommitdiffstats
path: root/src/crypto/modes
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/modes')
-rw-r--r--src/crypto/modes/CMakeLists.txt2
-rw-r--r--src/crypto/modes/cbc.c18
-rw-r--r--src/crypto/modes/ctr.c3
-rw-r--r--src/crypto/modes/gcm_test.c3
4 files changed, 22 insertions, 4 deletions
diff --git a/src/crypto/modes/CMakeLists.txt b/src/crypto/modes/CMakeLists.txt
index d50e97b..ffb29b6 100644
--- a/src/crypto/modes/CMakeLists.txt
+++ b/src/crypto/modes/CMakeLists.txt
@@ -58,6 +58,8 @@ add_executable(
gcm_test
gcm_test.c
+
+ $<TARGET_OBJECTS:test_support>
)
target_link_libraries(gcm_test crypto)
diff --git a/src/crypto/modes/cbc.c b/src/crypto/modes/cbc.c
index ba4805b..931b718 100644
--- a/src/crypto/modes/cbc.c
+++ b/src/crypto/modes/cbc.c
@@ -63,7 +63,8 @@ void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
size_t n;
const uint8_t *iv = ivec;
- assert(in && out && key && ivec);
+ assert(key != NULL && ivec != NULL);
+ assert(len == 0 || (in != NULL && out != NULL));
if (STRICT_ALIGNMENT &&
((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
@@ -119,9 +120,17 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
uint8_t c[16];
} tmp;
- assert(in && out && key && ivec);
+ assert(key != NULL && ivec != NULL);
+ assert(len == 0 || (in != NULL && out != NULL));
- if (in != out) {
+ 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);
+
+ 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. */
const uint8_t *iv = ivec;
if (STRICT_ALIGNMENT &&
@@ -152,6 +161,9 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
}
memcpy(ivec, iv, 16);
} else {
+ /* |out| is less than two blocks behind |in|. Decrypting an input block
+ * directly to |out| would overwrite a ciphertext block before it is used as
+ * the next block's IV. Decrypt to a temporary block instead. */
if (STRICT_ALIGNMENT &&
((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
uint8_t c;
diff --git a/src/crypto/modes/ctr.c b/src/crypto/modes/ctr.c
index 306b6f7..64062b2 100644
--- a/src/crypto/modes/ctr.c
+++ b/src/crypto/modes/ctr.c
@@ -88,7 +88,8 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
block128_f block) {
unsigned int n;
- assert(in && out && key && ecount_buf && num);
+ assert(key && ecount_buf && num);
+ assert(len == 0 || (in && out));
assert(*num < 16);
assert((16 % sizeof(size_t)) == 0);
diff --git a/src/crypto/modes/gcm_test.c b/src/crypto/modes/gcm_test.c
index 3548c81..a8819ea 100644
--- a/src/crypto/modes/gcm_test.c
+++ b/src/crypto/modes/gcm_test.c
@@ -347,6 +347,9 @@ static int run_test_case(unsigned test_num, const struct test_case *test) {
}
out = OPENSSL_malloc(plaintext_len);
+ if (out == NULL) {
+ goto out;
+ }
if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
fprintf(stderr, "%u: AES_set_encrypt_key failed.\n", test_num);
goto out;