CKM: Cipher API tests
[platform/core/test/security-tests.git] / src / ckm / unprivileged / encryption-decryption.cpp
index c183c81..cf9e67a 100644 (file)
@@ -23,6 +23,7 @@
 #include <string>
 #include <vector>
 #include <unordered_map>
+#include <thread>
 
 #include <dpl/test/test_runner.h>
 #include <ckm-common.h>
@@ -45,6 +46,7 @@ const size_t BUF_LEN = 86; // must be less than 1024/8-41 to support RSA OAEP 10
 // Environment
 SyncApi g_syncApi;
 AsyncApi g_asyncApi;
+CipherApi g_cipherApi;
 
 EncryptionApi* g_api = &g_syncApi;
 
@@ -133,6 +135,18 @@ struct AsyncEnv {
     static std::string suffix() { return "_async"; }
 };
 
+struct CipherEnv {
+    void init(const std::string&) {
+        g_api = &g_cipherApi;
+    }
+
+    void finish() {
+        g_api = nullptr;
+    }
+
+    static std::string suffix() { return "_cipher"; }
+};
+
 struct Algo {
     ckmc_algo_type_e type;
     size_t keyLen;
@@ -151,6 +165,7 @@ enum KeyIdx {
 RawBufferPtr PLAIN_DATA;
 RawBufferPtr BIG_DATA;
 ckmc_raw_buffer_s* DEFAULT_IV;
+ckmc_raw_buffer_s* IV1;
 ckmc_raw_buffer_s* IV11;
 ckmc_raw_buffer_s* IV12;
 ckmc_raw_buffer_s* IV15;
@@ -200,9 +215,10 @@ public:
 #ifdef TZ_BACKEND
         BIG_DATA = create_raw_buffer(createRandomBufferCAPI(1000));
 #else
-        BIG_DATA = create_raw_buffer(createRandomBufferCAPI(5000000));
+        BIG_DATA = create_raw_buffer(createRandomBufferCAPI(500000));
 #endif
         DEFAULT_IV = createRandomBufferCAPI(DEFAULT_IV_LEN);
+        IV1 = createRandomBufferCAPI(1);
         IV11 = createRandomBufferCAPI(11);
         IV12 = createRandomBufferCAPI(12);
         IV15 = createRandomBufferCAPI(15);
@@ -275,6 +291,7 @@ public:
         ckmc_buffer_free(IV15);
         ckmc_buffer_free(IV12);
         ckmc_buffer_free(IV11);
+        ckmc_buffer_free(IV1);
         ckmc_buffer_free(DEFAULT_IV);
 
         int ret = ckmc_lock_user_key(UID);
@@ -287,21 +304,6 @@ private:
     PolicyBackend m_backend;
 };
 
-
-void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
-{
-    int ret = ckmc_param_list_set_buffer(params.get(), name, buffer);
-    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
-                      "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
-}
-
-void setParam(ParamListPtr& params, ckmc_param_name_e name, int integer)
-{
-    int ret = ckmc_param_list_set_integer(params.get(), name, integer);
-    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
-                      "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
-}
-
 struct EncryptionResult
 {
     RawBufferPtr encrypted;
@@ -336,8 +338,7 @@ EncryptionResult encrypt(const Algo& algo,
     return ret;
 }
 
-void testAllAlgorithms(
-        const std::function<void(const Algo& algo)>& test)
+void testAllAlgorithms(const std::function<void(const Algo& algo)>& test)
 {
     test( { CKMC_ALGO_AES_CBC, 128 });
     test( { CKMC_ALGO_AES_CBC, 192 });
@@ -351,9 +352,12 @@ void testAllAlgorithms(
     test( { CKMC_ALGO_AES_CFB, 128 });
     test( { CKMC_ALGO_AES_CFB, 192 });
     test( { CKMC_ALGO_AES_CFB, 256 });
-    test( { CKMC_ALGO_RSA_OAEP, 1024 });
-    test( { CKMC_ALGO_RSA_OAEP, 2048 });
-    test( { CKMC_ALGO_RSA_OAEP, 4096 });
+
+    if (!g_api->symmetricOnly()) {
+        test( { CKMC_ALGO_RSA_OAEP, 1024 });
+        test( { CKMC_ALGO_RSA_OAEP, 2048 });
+        test( { CKMC_ALGO_RSA_OAEP, 4096 });
+    }
 }
 
 void testNoIvEnc(const Algo& algo)
@@ -490,7 +494,7 @@ void encryptionWithCustomData(const Algo& algo, ckmc_param_name_e name)
     RawBufferPtr tmpDec = create_raw_buffer(decrypted);
 
     // check
-    assert_buffers_equal(*PLAIN_DATA.get(), *tmpDec.get());
+    assert_buffers_equal(PLAIN_DATA.get(), tmpDec.get());
     tmpDec.reset();
     decrypted = nullptr;
 
@@ -546,7 +550,7 @@ void testGcmIvSize(ckmc_raw_buffer_s* iv,
                            &decryptedTmp);
     decrypted = create_raw_buffer(decryptedTmp);
 
-    assert_buffers_equal(*PLAIN_DATA.get(), *decrypted.get());
+    assert_buffers_equal(PLAIN_DATA.get(), decrypted.get());
 }
 
 void testIntegrity(const Algo& algo)
@@ -569,7 +573,7 @@ void testIntegrity(const Algo& algo)
                            &decrypted);
 
     RawBufferPtr tmp = create_raw_buffer(decrypted);
-    assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
+    assert_buffers_equal(PLAIN_DATA.get(), decrypted, false);
 }
 
 void testCtrEncryptionInvalidLength(const Algo& algo)
@@ -598,9 +602,7 @@ void testCtrEncryptionInvalidLength(const Algo& algo)
         encryptedTmp = nullptr;
     };
     // invalid counter size
-    setParam(params, CKMC_PARAM_ED_CTR_LEN, -1);
-    test();
-    setParam(params, CKMC_PARAM_ED_CTR_LEN, 0);
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, 0ULL);
     test();
     setParam(params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
     test();
@@ -662,9 +664,7 @@ void testCtrDecryptionInvalidLength(const Algo& algo)
         decrypted = nullptr;
     };
     // invalid counter size
-    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, -1);
-    test();
-    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 0);
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 0ULL);
     test();
     setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
     test();
@@ -688,7 +688,7 @@ void testCtrDecryptionValidLength(const Algo& algo)
                                &decrypted);
         ckmc_buffer_free(decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
-        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+        assert_buffers_equal(PLAIN_DATA.get(), decrypted);
     };
     // invalid counter size
     setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 1);
@@ -833,7 +833,8 @@ void testGcmDifferentIvSizes(const Algo& algo)
     // add AES GCM key
     KeyAliasPair aliases = getKey(algo, PRIMARY);
 
-    testGcmIvSize(IV11,  aliases, EncryptionError::SERVER_ERROR); // 12B is the smallest
+    testGcmIvSize(IV1,   aliases);
+    testGcmIvSize(IV11,  aliases);
     testGcmIvSize(IV12,  aliases);
     testGcmIvSize(IV17,  aliases);
     testGcmIvSize(IV128, aliases);
@@ -855,7 +856,7 @@ void testEncryptDecryptBigData(const Algo& algo)
                     &decrypted);
     RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-    assert_buffers_equal(*BIG_DATA.get(), *decrypted);
+    assert_buffers_equal(BIG_DATA.get(), decrypted);
 }
 
 void testEncryptDecryptDifferentKeys(const Algo& algo, bool success)
@@ -879,7 +880,7 @@ void testEncryptDecryptDifferentKeys(const Algo& algo, bool success)
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
+        assert_buffers_equal(PLAIN_DATA.get(), decrypted, false);
     } else {
         assert_crypto_result(EncryptionError::INVALID_PARAM,
                              apiDecrypt,
@@ -908,7 +909,7 @@ void testRsaLongestData(const Algo& algo, size_t dataSize)
                            &decrypted);
     RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-    assert_buffers_equal(*plain.get(), *decrypted);
+    assert_buffers_equal(plain.get(), decrypted);
 }
 
 void testRsaDataTooLong(const Algo& algo, size_t dataSize)
@@ -933,6 +934,19 @@ void testRsaDataTooLong(const Algo& algo, size_t dataSize)
                          &encrypted);
 }
 
+std::pair<Alias, ParamListPtr> defaultGcmCipherSetup()
+{
+    Algo algo = {CKMC_ALGO_AES_GCM, 256};
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
+
+    ckmc_param_list_h handle = NULL;
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
+    auto params = ParamListPtr(handle, ckmc_param_list_free);
+    setParam(params, CKMC_PARAM_ED_IV, IV12);
+
+    return std::make_pair(aliases.prv, params);
+}
+
 } // namespace anonymous
 
 RUNNER_TEST_GROUP_INIT_ENV(CKM_ENCRYPTION_DECRYPTION, EncGroupFixture);
@@ -941,7 +955,7 @@ RUNNER_TEST_GROUP_INIT_ENV(CKM_ENCRYPTION_DECRYPTION, EncGroupFixture);
 // Generic encryption decryption tests
 /////////////////////////////////////////
 
-RUNNER_TEST_MULTIPLE(TED_0010_encrypt_invalid_param_list, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0010_encrypt_invalid_param_list, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -969,7 +983,7 @@ RUNNER_TEST_MULTIPLE(TED_0010_encrypt_invalid_param_list, SyncEnv, AsyncEnv)
     });
 }
 
-RUNNER_TEST_MULTIPLE(TED_0020_encrypt_missing_key, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0020_encrypt_missing_key, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -1040,7 +1054,7 @@ RUNNER_TEST_MULTIPLE(TED_0040_encrypt_no_output_buffer, SyncEnv, AsyncEnv)
     });
 }
 
-RUNNER_TEST_MULTIPLE(TED_0110_decrypt_invalid_param_list, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0110_decrypt_invalid_param_list, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -1068,7 +1082,7 @@ RUNNER_TEST_MULTIPLE(TED_0110_decrypt_invalid_param_list, SyncEnv, AsyncEnv)
     });
 }
 
-RUNNER_TEST_MULTIPLE(TED_0120_decrypt_missing_key, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0120_decrypt_missing_key, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -1131,7 +1145,7 @@ RUNNER_TEST_MULTIPLE(TED_0140_decrypt_no_output_buffer, SyncEnv, AsyncEnv)
     });
 }
 
-RUNNER_TEST_MULTIPLE(TED_0200_encrypt_decrypt_different_keys, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0200_encrypt_decrypt_different_keys, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_GCM, 128}, false);
     testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_GCM, 192}, false);
@@ -1142,12 +1156,15 @@ RUNNER_TEST_MULTIPLE(TED_0200_encrypt_decrypt_different_keys, SyncEnv, AsyncEnv)
     testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 128}, true);
     testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 192}, true);
     testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 256}, true);
-    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 1024}, false);
-    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 2048}, false);
-    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 4096}, false);
+
+    if (!g_api->symmetricOnly()) {
+        testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 1024}, false);
+        testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 2048}, false);
+        testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 4096}, false);
+    }
 }
 
-RUNNER_TEST_MULTIPLE(TED_0300_encrypt_decrypt, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0300_encrypt_decrypt, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -1164,11 +1181,11 @@ RUNNER_TEST_MULTIPLE(TED_0300_encrypt_decrypt, SyncEnv, AsyncEnv)
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+        assert_buffers_equal(PLAIN_DATA.get(), decrypted);
     });
 }
 
-RUNNER_TEST_MULTIPLE(TED_0310_encrypt_decrypt_password, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0310_encrypt_decrypt_password, SyncEnv, AsyncEnv, CipherEnv)
 {
     testAllAlgorithms([](const Algo& algo){
         // prepare buffers
@@ -1195,67 +1212,67 @@ RUNNER_TEST_MULTIPLE(TED_0310_encrypt_decrypt_password, SyncEnv, AsyncEnv)
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted); // guarantees deletion
 
-        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+        assert_buffers_equal(PLAIN_DATA.get(), decrypted);
     });
 }
 
 // long test split into smaller ones
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_128, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_192, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_256, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_128, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_192, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_256, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_128, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_192, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_256, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_128, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_192, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_256, SyncEnv, AsyncEnv, CipherEnv)
 {
     testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 256});
 }
@@ -1264,7 +1281,7 @@ RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_256, SyncEnv, Asy
 // Algorithm specific tests
 /////////////////////////////////////////
 
-RUNNER_TEST_MULTIPLE(TED_1005_no_iv_enc, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1005_no_iv_enc, SyncEnv, AsyncEnv, CipherEnv)
 {
     testNoIvEnc({CKMC_ALGO_AES_CTR, 128});
     testNoIvEnc({CKMC_ALGO_AES_CTR, 192});
@@ -1280,7 +1297,7 @@ RUNNER_TEST_MULTIPLE(TED_1005_no_iv_enc, SyncEnv, AsyncEnv)
     testNoIvEnc({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1010_invalid_iv_enc, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1010_invalid_iv_enc, SyncEnv, AsyncEnv, CipherEnv)
 {
     testInvalidIvEnc({CKMC_ALGO_AES_CTR, 128});
     testInvalidIvEnc({CKMC_ALGO_AES_CTR, 192});
@@ -1293,7 +1310,7 @@ RUNNER_TEST_MULTIPLE(TED_1010_invalid_iv_enc, SyncEnv, AsyncEnv)
     testInvalidIvEnc({CKMC_ALGO_AES_CFB, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1015_no_iv_dec, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1015_no_iv_dec, SyncEnv, AsyncEnv, CipherEnv)
 {
     testNoIvDec({CKMC_ALGO_AES_CTR, 128});
     testNoIvDec({CKMC_ALGO_AES_CTR, 192});
@@ -1309,7 +1326,7 @@ RUNNER_TEST_MULTIPLE(TED_1015_no_iv_dec, SyncEnv, AsyncEnv)
     testNoIvDec({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1020_invalid_iv_dec, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1020_invalid_iv_dec, SyncEnv, AsyncEnv, CipherEnv)
 {
     testInvalidIvDec({CKMC_ALGO_AES_CTR, 128});
     testInvalidIvDec({CKMC_ALGO_AES_CTR, 192});
@@ -1322,7 +1339,7 @@ RUNNER_TEST_MULTIPLE(TED_1020_invalid_iv_dec, SyncEnv, AsyncEnv)
     testInvalidIvDec({CKMC_ALGO_AES_CFB, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1050_data_integrity, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1050_data_integrity, SyncEnv, AsyncEnv, CipherEnv)
 {
     testIntegrity({CKMC_ALGO_AES_CTR, 128});
     testIntegrity({CKMC_ALGO_AES_CTR, 192});
@@ -1335,14 +1352,14 @@ RUNNER_TEST_MULTIPLE(TED_1050_data_integrity, SyncEnv, AsyncEnv)
     testIntegrity({CKMC_ALGO_AES_CFB, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1100_ctr_encryption_invalid_length, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1100_ctr_encryption_invalid_length, SyncEnv, AsyncEnv, CipherEnv)
 {
     testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 128});
     testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 192});
     testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1105_ctr_encryption_valid_length, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1105_ctr_encryption_valid_length, SyncEnv, AsyncEnv, CipherEnv)
 {
     RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
     testCtrEncryptionValidLength({CKMC_ALGO_AES_CTR, 128});
@@ -1350,14 +1367,14 @@ RUNNER_TEST_MULTIPLE(TED_1105_ctr_encryption_valid_length, SyncEnv, AsyncEnv)
     testCtrEncryptionValidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1110_ctr_decryption_invalid_length, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1110_ctr_decryption_invalid_length, SyncEnv, AsyncEnv, CipherEnv)
 {
     testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 128});
     testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 192});
     testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1115_ctr_decryption_valid_length, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1115_ctr_decryption_valid_length, SyncEnv, AsyncEnv, CipherEnv)
 {
     RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
     testCtrDecryptionValidLength({CKMC_ALGO_AES_CTR, 128});
@@ -1365,35 +1382,35 @@ RUNNER_TEST_MULTIPLE(TED_1115_ctr_decryption_valid_length, SyncEnv, AsyncEnv)
     testCtrDecryptionValidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1200_gcm_encryption_tag_len, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1200_gcm_encryption_tag_len, SyncEnv, AsyncEnv, CipherEnv)
 {
     testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 128});
     testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 192});
     testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1210_gcm_decryption_tag_len, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1210_gcm_decryption_tag_len, SyncEnv, AsyncEnv, CipherEnv)
 {
     testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 128});
     testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 192});
     testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1230_gcm_wrong_tag, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1230_gcm_wrong_tag, SyncEnv, AsyncEnv, CipherEnv)
 {
     testGcmWrongTag({CKMC_ALGO_AES_GCM, 128});
     testGcmWrongTag({CKMC_ALGO_AES_GCM, 192});
     testGcmWrongTag({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1240_gcm_different_iv_sizes, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1240_gcm_different_iv_sizes, SyncEnv, AsyncEnv, CipherEnv)
 {
     testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 128});
     testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 192});
     testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_1250_gcm_aad, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_1250_gcm_aad, SyncEnv, AsyncEnv, CipherEnv)
 {
     encryptionWithCustomData({CKMC_ALGO_AES_GCM, 128}, CKMC_PARAM_ED_AAD);
     encryptionWithCustomData({CKMC_ALGO_AES_GCM, 192}, CKMC_PARAM_ED_AAD);
@@ -1464,3 +1481,167 @@ RUNNER_TEST(TED_2010_dec_no_observer_async, AsyncEnv)
                          encrypted);
     });
 }
+
+/////////////////////////////////////////
+// Mulithreaded test for synchronous API
+/////////////////////////////////////////
+RUNNER_TEST_MULTIPLE(TED_3000_multiple_threads, SyncEnv, CipherEnv)
+{
+    std::vector<std::thread> threads;
+    threads.reserve(10);
+    for(unsigned i = 0; i < 10;++i)
+        threads.emplace_back([]{ testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 256}); });
+    for (auto& thread : threads)
+        thread.join();
+}
+
+/////////////////////////////////////////
+// Cipher API only
+/////////////////////////////////////////
+RUNNER_TEST(TED_4000_cipher_missing_arguments)
+{
+    ckmc_raw_buffer_s* encrypted = nullptr;
+
+    auto [alias, params] = defaultGcmCipherSetup();
+
+    ckmc_cipher_ctx_h ctx = nullptr;
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    auto ctxPtr = create_cipher_ctx(ctx);
+
+    // no AAD
+    assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+
+    // missing arguments
+    assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+    assert_invalid_param(ckmc_cipher_update, nullptr, *PLAIN_DATA.get(), &encrypted);
+    assert_invalid_param(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), nullptr);
+    assert_invalid_param(ckmc_cipher_finalize, nullptr, nullptr, &encrypted);
+    assert_invalid_param(ckmc_cipher_finalize, nullptr, nullptr, nullptr);
+}
+
+RUNNER_TEST(TED_4010_cipher_reinitialize_without_aad)
+{
+    auto [alias, params] = defaultGcmCipherSetup();
+
+    ckmc_cipher_ctx_h ctx = nullptr;
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    auto ctxPtr = create_cipher_ctx(ctx);
+
+    // no AAD
+    assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+}
+
+RUNNER_TEST(TED_4020_cipher_tag_during_encryption)
+{
+    ckmc_raw_buffer_s* encrypted = nullptr;
+
+    auto [alias, params] = defaultGcmCipherSetup();
+
+    ckmc_cipher_ctx_h ctx = nullptr;
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    auto ctxPtr = create_cipher_ctx(ctx);
+
+    // tag input during encryption
+    assert_invalid_param(ckmc_cipher_finalize, ctx, PLAIN_DATA.get(), &encrypted);
+}
+
+RUNNER_TEST(TED_4030_cipher_wrong_order)
+{
+    ckmc_raw_buffer_s* encrypted = nullptr;
+
+    auto [alias, params] = defaultGcmCipherSetup();
+
+    ckmc_cipher_ctx_h ctx = nullptr;
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    auto ctxPtr = create_cipher_ctx(ctx);
+
+    assert_positive(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+    ckmc_buffer_free(encrypted);
+
+    // initialize after update
+    setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+    assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+
+    assert_positive(ckmc_cipher_finalize, ctx, nullptr, &encrypted);
+    ckmc_buffer_free(encrypted);
+
+    // initialize after finalize
+    assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+
+    // update after finalize
+    assert_invalid_param(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+}
+
+RUNNER_TEST(TED_4040_cipher_gcm_aad_and_tag)
+{
+    ckmc_raw_buffer_s* encrypted = nullptr;
+
+    auto [alias, params] = defaultGcmCipherSetup();
+    setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+
+    ckmc_cipher_ctx_h ctx = nullptr;
+
+    // encrypt
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    auto ctxPtr = create_cipher_ctx(ctx);
+
+    // 2 more AAD chunks
+    setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+    setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+
+    ckmc_raw_buffer_s* tag = nullptr;
+
+    assert_positive(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+    auto encryptedPtr = create_raw_buffer(encrypted);
+    assert_positive(ckmc_cipher_finalize, ctx, nullptr, &tag);
+
+    ctxPtr.reset();
+    ctx = nullptr;
+
+    ckmc_raw_buffer_s* decrypted = nullptr;
+    ckmc_raw_buffer_s* empty = nullptr;
+
+    // decrypt with invalid AAD
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+    ctxPtr = create_cipher_ctx(ctx);
+
+    assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+    ckmc_buffer_free(decrypted);
+    assert_invalid_param(ckmc_cipher_finalize, ctx, tag, &empty);
+
+    ctxPtr.reset();
+    ctx = nullptr;
+
+    // decrypt without TAG
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+    ctxPtr = create_cipher_ctx(ctx);
+    setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+    setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+
+    assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+    ckmc_buffer_free(decrypted);
+    assert_invalid_param(ckmc_cipher_finalize, ctx, nullptr, &empty);
+
+    ctxPtr.reset();
+    ctx = nullptr;
+
+    // correct decrypt
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+    ctxPtr = create_cipher_ctx(ctx);
+    setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+    setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+    assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+
+    assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+    auto decryptedPtr = create_raw_buffer(decrypted);
+    assert_positive(ckmc_cipher_finalize, ctx, tag, &empty);
+
+    RUNNER_ASSERT(empty == nullptr);
+
+    assert_buffers_equal(PLAIN_DATA.get(), decrypted);
+}