diff options
Diffstat (limited to 'src/crypto/modes')
-rw-r--r-- | src/crypto/modes/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crypto/modes/cbc.c | 18 | ||||
-rw-r--r-- | src/crypto/modes/ctr.c | 3 | ||||
-rw-r--r-- | src/crypto/modes/gcm_test.c | 3 |
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; |