summaryrefslogtreecommitdiffstats
path: root/test/evp_libctx_test.c
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-08-05 08:45:29 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-08-05 08:45:29 +1000
commit914f97eecc9166fbfdb50c2d04e2b9f9d0c52198 (patch)
tree1eb588c4623b923dcffc417a611724673eb2947e /test/evp_libctx_test.c
parentc5b356d5d6cfca1128b35f235dfdb893f2888027 (diff)
Fix provider cipher reinit after init/update with a partial update block.
The test added previously used a 16 byte block during the update which does not cause internal buffering in the provider. Some internal variables related to the buffering were not being cleared in the init, which meant that the second update would use the buffered data from the first update. Added test for this scenario with exclusions for ciphers that do not support partial block updates. Found by guidovranken. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/12523)
Diffstat (limited to 'test/evp_libctx_test.c')
-rw-r--r--test/evp_libctx_test.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/test/evp_libctx_test.c b/test/evp_libctx_test.c
index 395c5d99b5..7421e1e3ca 100644
--- a/test/evp_libctx_test.c
+++ b/test/evp_libctx_test.c
@@ -268,6 +268,82 @@ err:
return ret;
}
+/*
+ * This test only uses a partial block (half the block size) of input for each
+ * EVP_EncryptUpdate() in order to test that the second init/update is not using
+ * a leftover buffer from the first init/update.
+ * Note: some ciphers don't need a full block to produce output.
+ */
+static int test_cipher_reinit_partialupdate(int test_id)
+{
+ int ret = 0, out1_len = 0, out2_len = 0, in_len;
+ EVP_CIPHER *cipher = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ unsigned char out1[256];
+ unsigned char out2[256];
+ static const unsigned char in[32] = {
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0xba, 0xbe, 0xba, 0xbe, 0x00, 0x00, 0xba, 0xbe,
+ 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ static const unsigned char key[64] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ };
+ static const unsigned char iv[16] = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
+ };
+ const char *name = sk_OPENSSL_CSTRING_value(cipher_names, test_id);
+
+ if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
+ goto err;
+
+ TEST_note("Fetching %s\n", name);
+ if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL)))
+ goto err;
+
+ in_len = EVP_CIPHER_block_size(cipher) / 2;
+
+ /* skip any ciphers that don't allow partial updates */
+ if (((EVP_CIPHER_flags(cipher)
+ & (EVP_CIPH_FLAG_CTS | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) != 0)
+ || EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE
+ || EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE
+ || EVP_CIPHER_mode(cipher) == EVP_CIPH_WRAP_MODE) {
+ ret = 1;
+ goto err;
+ }
+
+ if (!TEST_true(EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
+ || !TEST_true(EVP_EncryptUpdate(ctx, out1, &out1_len, in, in_len))
+ || !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
+ || !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len)))
+ goto err;
+
+ /* DES3-WRAP uses random every update - so it will give a different value */
+ if (EVP_CIPHER_is_a(cipher, "DES3-WRAP")) {
+ if (!TEST_mem_ne(out1, out1_len, out2, out2_len))
+ goto err;
+ } else {
+ if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+ goto err;
+ }
+ ret = 1;
+err:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
+
static int name_cmp(const char * const *a, const char * const *b)
{
return strcasecmp(*a, *b);
@@ -332,6 +408,8 @@ int setup_tests(void)
EVP_CIPHER_do_all_provided(libctx, collect_cipher_names, cipher_names);
ADD_ALL_TESTS(test_cipher_reinit, sk_OPENSSL_CSTRING_num(cipher_names));
+ ADD_ALL_TESTS(test_cipher_reinit_partialupdate,
+ sk_OPENSSL_CSTRING_num(cipher_names));
return 1;
}