Fix typo in CONTRIBUTING.md
[openssl.git] / test / evp_libctx_test.c
index cb8b3b7fb4e7a2d1843b20c1e0d84d38e8785067..3ca25d12f720bced680eb48b38611a74c56cf560 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -33,7 +33,6 @@
 #include "testutil.h"
 #include "internal/nelem.h"
 #include "crypto/bn_dh.h"   /* _bignum_ffdhe2048_p */
-#include "../e_os.h"        /* strcasecmp */
 
 static OSSL_LIB_CTX *libctx = NULL;
 static OSSL_PROVIDER *nullprov = NULL;
@@ -55,7 +54,7 @@ const OPTIONS *test_get_options(void)
         { "config", OPT_CONFIG_FILE, '<',
           "The configuration file to use for the libctx" },
         { "provider", OPT_PROVIDER_NAME, 's',
-          "The provider to load (The default value is 'default'" },
+          "The provider to load (The default value is 'default')" },
         { NULL }
     };
     return test_options;
@@ -72,6 +71,37 @@ static const char *getname(int id)
 }
 #endif
 
+static int test_evp_cipher_api_safety(void)
+{
+    int ret = 0;
+    EVP_CIPHER_CTX *ctx = NULL;
+
+    ctx = EVP_CIPHER_CTX_new();
+
+    if (!TEST_ptr(ctx))
+        goto err;
+
+    /*
+     * Ensure that EVP_CIPHER_get_block_size returns 0
+     * if we haven't initialized the cipher in this context
+     */
+    if (!TEST_int_eq(EVP_CIPHER_CTX_get_block_size(ctx), 0))
+        goto err_free;
+
+    /*
+     * Ensure that EVP_CIPHER_get_iv_length returns 0
+     * if we haven't initialized the cipher in this context
+     */
+    if (!TEST_int_eq(EVP_CIPHER_CTX_get_iv_length(ctx), 0))
+        goto err_free;
+
+    ret = 1;
+err_free:
+    EVP_CIPHER_CTX_free(ctx);
+err:
+    return ret;
+}
+
 /*
  * We're using some DH specific values in this test, so we skip compilation if
  * we're in a no-dh build.
@@ -314,7 +344,7 @@ err:
 
 static int test_cipher_reinit(int test_id)
 {
-    int ret = 0, diff, ccm, siv;
+    int ret = 0, diff, ccm, siv, no_null_key;
     int out1_len = 0, out2_len = 0, out3_len = 0;
     EVP_CIPHER *cipher = NULL;
     EVP_CIPHER_CTX *ctx = NULL;
@@ -335,7 +365,11 @@ static int test_cipher_reinit(int test_id)
         0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     };
-    unsigned char iv[16] = {
+    unsigned char iv[48] = {
+        0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+        0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
         0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
         0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
     };
@@ -349,10 +383,18 @@ static int test_cipher_reinit(int test_id)
         goto err;
 
     /* ccm fails on the second update - this matches OpenSSL 1_1_1 behaviour */
-    ccm = (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE);
+    ccm = (EVP_CIPHER_get_mode(cipher) == EVP_CIPH_CCM_MODE);
 
     /* siv cannot be called with NULL key as the iv is irrelevant */
-    siv = (EVP_CIPHER_mode(cipher) == EVP_CIPH_SIV_MODE);
+    siv = (EVP_CIPHER_get_mode(cipher) == EVP_CIPH_SIV_MODE);
+
+    /*
+     * Skip init call with a null key for RC4 as the stream cipher does not
+     * handle reinit (1.1.1 behaviour).
+     */
+    no_null_key = EVP_CIPHER_is_a(cipher, "RC4")
+                  || EVP_CIPHER_is_a(cipher, "RC4-40")
+                  || EVP_CIPHER_is_a(cipher, "RC4-HMAC-MD5");
 
     /* DES3-WRAP uses random every update - so it will give a different value */
     diff = EVP_CIPHER_is_a(cipher, "DES3-WRAP");
@@ -362,9 +404,10 @@ static int test_cipher_reinit(int test_id)
         || !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
         || !TEST_int_eq(EVP_EncryptUpdate(ctx, out2, &out2_len, in, sizeof(in)),
                         ccm ? 0 : 1)
-        || !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
+        || (!no_null_key
+        && (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
         || !TEST_int_eq(EVP_EncryptUpdate(ctx, out3, &out3_len, in, sizeof(in)),
-                        ccm || siv ? 0 : 1))
+                        ccm || siv ? 0 : 1))))
         goto err;
 
     if (ccm == 0) {
@@ -375,7 +418,7 @@ static int test_cipher_reinit(int test_id)
                 goto err;
         } else {
             if (!TEST_mem_eq(out1, out1_len, out2, out2_len)
-                || (!siv && !TEST_mem_eq(out1, out1_len, out3, out3_len)))
+                || (!siv && !no_null_key && !TEST_mem_eq(out1, out1_len, out3, out3_len)))
                 goto err;
         }
     }
@@ -417,7 +460,11 @@ static int test_cipher_reinit_partialupdate(int test_id)
         0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     };
-    static const unsigned char iv[16] = {
+    static const unsigned char iv[48] = {
+        0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+        0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+        0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
         0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
         0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
     };
@@ -430,14 +477,18 @@ static int test_cipher_reinit_partialupdate(int test_id)
     if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, name, NULL)))
         goto err;
 
-    in_len = EVP_CIPHER_block_size(cipher) / 2;
+    in_len = EVP_CIPHER_get_block_size(cipher);
+    if (!TEST_int_gt(in_len, 0))
+        goto err;
+    if (in_len > 1)
+        in_len /= 2;
 
     /* skip any ciphers that don't allow partial updates */
-    if (((EVP_CIPHER_flags(cipher)
+    if (((EVP_CIPHER_get_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) {
+        || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_CCM_MODE
+        || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_XTS_MODE
+        || EVP_CIPHER_get_mode(cipher) == EVP_CIPH_WRAP_MODE) {
         ret = 1;
         goto err;
     }
@@ -448,16 +499,18 @@ static int test_cipher_reinit_partialupdate(int test_id)
         || !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len)))
         goto err;
 
-    if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
-        goto err;
+    if (EVP_CIPHER_get_iv_length(cipher) != 0)
+        if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+            goto err;
 
-    if (EVP_CIPHER_mode(cipher) != EVP_CIPH_SIV_MODE) {
+    if (EVP_CIPHER_get_mode(cipher) != EVP_CIPH_SIV_MODE) {
         if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
             || !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len)))
             goto err;
 
-        if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
-            goto err;
+        if (EVP_CIPHER_get_iv_length(cipher) != 0)
+            if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
+                goto err;
     }
     ret = 1;
 err:
@@ -469,13 +522,13 @@ err:
 
 static int name_cmp(const char * const *a, const char * const *b)
 {
-    return strcasecmp(*a, *b);
+    return OPENSSL_strcasecmp(*a, *b);
 }
 
 static void collect_cipher_names(EVP_CIPHER *cipher, void *cipher_names_list)
 {
     STACK_OF(OPENSSL_STRING) *names = cipher_names_list;
-    const char *name = EVP_CIPHER_name(cipher);
+    const char *name = EVP_CIPHER_get0_name(cipher);
     char *namedup = NULL;
 
     assert(name != NULL);
@@ -516,21 +569,23 @@ static int kem_rsa_gen_recover(void)
     int ret = 0;
     EVP_PKEY *pub = NULL;
     EVP_PKEY *priv = NULL;
-    EVP_PKEY_CTX *sctx = NULL, *rctx = NULL;
+    EVP_PKEY_CTX *sctx = NULL, *rctx = NULL, *dctx = NULL;
     unsigned char secret[256] = { 0, };
     unsigned char ct[256] = { 0, };
     unsigned char unwrap[256] = { 0, };
     size_t ctlen = 0, unwraplen = 0, secretlen = 0;
+    int bits = 2048;
 
-    ret = TEST_true(rsa_keygen(2048, &pub, &priv))
+    ret = TEST_true(rsa_keygen(bits, &pub, &priv))
           && TEST_ptr(sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub, NULL))
           && TEST_int_eq(EVP_PKEY_encapsulate_init(sctx, NULL), 1)
           && TEST_int_eq(EVP_PKEY_CTX_set_kem_op(sctx, "RSASVE"), 1)
-          && TEST_int_eq(EVP_PKEY_encapsulate(sctx, NULL, &ctlen, NULL,
+          && TEST_ptr(dctx = EVP_PKEY_CTX_dup(sctx))
+          && TEST_int_eq(EVP_PKEY_encapsulate(dctx, NULL, &ctlen, NULL,
                                               &secretlen), 1)
           && TEST_int_eq(ctlen, secretlen)
-          && TEST_int_eq(ctlen, 2048 / 8)
-          && TEST_int_eq(EVP_PKEY_encapsulate(sctx, ct, &ctlen, secret,
+          && TEST_int_eq(ctlen, bits / 8)
+          && TEST_int_eq(EVP_PKEY_encapsulate(dctx, ct, &ctlen, secret,
                                               &secretlen), 1)
           && TEST_ptr(rctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv, NULL))
           && TEST_int_eq(EVP_PKEY_decapsulate_init(rctx, NULL), 1)
@@ -543,10 +598,38 @@ static int kem_rsa_gen_recover(void)
     EVP_PKEY_free(pub);
     EVP_PKEY_free(priv);
     EVP_PKEY_CTX_free(rctx);
+    EVP_PKEY_CTX_free(dctx);
     EVP_PKEY_CTX_free(sctx);
     return ret;
 }
 
+#ifndef OPENSSL_NO_DES
+/*
+ * This test makes sure that EVP_CIPHER_CTX_rand_key() works correctly
+ * For fips mode this code would produce an error if the flag is not set.
+ */
+static int test_cipher_tdes_randkey(void)
+{
+    int ret;
+    EVP_CIPHER_CTX *ctx = NULL;
+    EVP_CIPHER *tdes_cipher = NULL, *aes_cipher = NULL;
+    unsigned char key[24] = { 0 };
+
+    ret = TEST_ptr(aes_cipher = EVP_CIPHER_fetch(libctx, "AES-256-CBC", NULL))
+          && TEST_int_eq(EVP_CIPHER_get_flags(aes_cipher) & EVP_CIPH_RAND_KEY, 0)
+          && TEST_ptr(tdes_cipher = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", NULL))
+          && TEST_int_ne(EVP_CIPHER_get_flags(tdes_cipher) & EVP_CIPH_RAND_KEY, 0)
+          && TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+          && TEST_true(EVP_CipherInit_ex(ctx, tdes_cipher, NULL, NULL, NULL, 1))
+          && TEST_int_gt(EVP_CIPHER_CTX_rand_key(ctx, key), 0);
+
+    EVP_CIPHER_CTX_free(ctx);
+    EVP_CIPHER_free(tdes_cipher);
+    EVP_CIPHER_free(aes_cipher);
+    return ret;
+}
+#endif /* OPENSSL_NO_DES */
+
 static int kem_rsa_params(void)
 {
     int ret = 0;
@@ -630,7 +713,7 @@ static EVP_PKEY *gen_dh_key(void)
     params[1] = OSSL_PARAM_construct_end();
 
     if (!TEST_ptr(gctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL))
-        || !TEST_true(EVP_PKEY_keygen_init(gctx))
+        || !TEST_int_gt(EVP_PKEY_keygen_init(gctx), 0)
         || !TEST_true(EVP_PKEY_CTX_set_params(gctx, params))
         || !TEST_true(EVP_PKEY_keygen(gctx, &pkey)))
         goto err;
@@ -687,6 +770,8 @@ int setup_tests(void)
     if (!test_get_libctx(&libctx, &nullprov, config_file, &libprov, prov_name))
         return 0;
 
+    ADD_TEST(test_evp_cipher_api_safety);
+
 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
     ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
 #endif
@@ -706,6 +791,9 @@ int setup_tests(void)
     ADD_TEST(kem_rsa_params);
 #ifndef OPENSSL_NO_DH
     ADD_TEST(kem_invalid_keytype);
+#endif
+#ifndef OPENSSL_NO_DES
+    ADD_TEST(test_cipher_tdes_randkey);
 #endif
     return 1;
 }