CKM: Add tests for encryption/decryption 05/39705/28
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 21 May 2015 09:05:35 +0000 (11:05 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 28 Jul 2015 09:10:53 +0000 (02:10 -0700)
[Problem] No tests for encryption/decryption
[Solution] Tests added

[Verification] Run test: ckm-test --group=CKM_ENCRYPTION_DECRYPTION

Change-Id: I4a50ccccf692d8dd211247951bfd30fb892e898d

src/ckm/CMakeLists.txt
src/ckm/ckm-common.cpp
src/ckm/ckm-common.h
src/ckm/encryption-decryption.cpp [new file with mode: 0644]

index 560e706..5d67118 100644 (file)
@@ -52,6 +52,7 @@ SET(CKM_SOURCES
     ${PROJECT_SOURCE_DIR}/src/ckm/clean-env.cpp
     ${PROJECT_SOURCE_DIR}/src/ckm/test-certs.cpp
     ${PROJECT_SOURCE_DIR}/src/ckm/algo-params.cpp
+    ${PROJECT_SOURCE_DIR}/src/ckm/encryption-decryption.cpp
 )
 
 INCLUDE_DIRECTORIES(SYSTEM ${CKM_DEP_INCLUDE_DIRS})
index 9b5cb77..60c7c34 100644 (file)
@@ -550,3 +550,8 @@ void assert_buffers_equal(const ckmc_raw_buffer_s b1, const ckmc_raw_buffer_s b2
                           "Buffers should be different");
     }
 }
+
+RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer)
+{
+    return RawBufferPtr(buffer, ckmc_buffer_free);
+}
index 6f3969b..2f9d92e 100644 (file)
@@ -221,3 +221,5 @@ typedef std::shared_ptr<ckmc_param_list_s> ParamListPtr;
 ParamListPtr createParamListPtr();
 
 void assert_buffers_equal(const ckmc_raw_buffer_s b1, const ckmc_raw_buffer_s b2, bool equal=true);
+
+RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer);
diff --git a/src/ckm/encryption-decryption.cpp b/src/ckm/encryption-decryption.cpp
new file mode 100644 (file)
index 0000000..3b752be
--- /dev/null
@@ -0,0 +1,1394 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       encryption-decryption.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+
+#include <string>
+#include <vector>
+#include <map>
+#include <sstream>
+
+#include <dpl/test/test_runner.h>
+#include <ckm-common.h>
+#include <ckmc/ckmc-manager.h>
+#include <ckm/ckm-type.h>
+#include <access_provider2.h>
+
+namespace {
+
+const char* PASSWORD = "test-password";
+const uid_t UID = 5555;
+const gid_t GID = 5555;
+const size_t CTR_DEFAULT_LEN = 16*8;
+const size_t DEFAULT_IV_LEN = 16;
+const size_t BUF_LEN = 86; // must be less than 1024/8-41 to support RSA OAEP 1024
+
+struct TagTest {
+    int tagLen;
+    int expected;
+};
+
+struct KeyAliasPair
+{
+    CKM::Alias prv;
+    CKM::Alias pub;
+};
+
+class EncEnv : public RemoveDataEnv<UID> {
+public:
+    EncEnv() : m_dbu(NULL), m_sap(NULL) {}
+    ~EncEnv() { delete m_sap; delete m_dbu; }
+
+    void init(const std::string& str) {
+        RemoveDataEnv<UID>::init(str);
+        m_dbu = new ScopedDBUnlock(UID, "db-pass"); // unlock user's database
+        m_sap = new ScopedAccessProvider("my-label");    // setup label
+
+        // setup smack rules and switch user
+        m_sap->allowAPI("key-manager::api-storage", "rw");
+        m_sap->allowAPI("key-manager::api-encryption", "rw");
+        m_sap->applyAndSwithToUser(UID, GID);
+    }
+
+    void finish() {
+        delete m_sap;
+        m_sap = NULL;
+        delete m_dbu;
+        m_dbu = NULL;
+        RemoveDataEnv<UID>::finish();
+    }
+
+    ScopedDBUnlock* m_dbu;
+    ScopedAccessProvider* m_sap;
+};
+
+struct AlgoBase {
+    ckmc_algo_type_e m_type;
+    size_t m_keyLen;
+
+    AlgoBase(ckmc_algo_type_e type, size_t keyLen) : m_type(type), m_keyLen(keyLen) {}
+
+    virtual KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr) = 0;
+};
+
+typedef std::shared_ptr<AlgoBase> AlgoBasePtr;
+
+template <typename T>
+AlgoBasePtr createAlgo(ckmc_algo_type_e type, size_t keyLen) {
+    return AlgoBasePtr(new T(type, keyLen));
+}
+
+struct AlgoAes : public AlgoBase {
+    AlgoAes(ckmc_algo_type_e type, size_t keyLen) : AlgoBase(type, keyLen) {}
+    KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr);
+};
+
+KeyAliasPair AlgoAes::keyGen(const char* pass, const char* suffix)
+{
+    KeyAliasPair aliases;
+    std::ostringstream oss;
+    CharPtr my_label = get_label();
+    CharPtr passPtr(nullptr, free);
+    if (pass)
+        passPtr.reset(strdup(pass));
+
+    oss << "aes_" << static_cast<int>(m_type) << "_" << m_keyLen << "_key_alias";
+    if (suffix)
+        oss << suffix;
+    aliases.prv = aliasWithLabel(my_label.get(),oss.str().c_str());
+    aliases.pub = aliasWithLabel(my_label.get(), oss.str().c_str());
+
+    ckmc_policy_s policy;
+    policy.extractable = false;
+    policy.password = passPtr.get();
+
+    assert_positive(ckmc_create_key_aes, m_keyLen, aliases.prv.c_str(), policy);
+    return aliases;
+}
+
+struct AlgoRsa : public AlgoBase {
+    AlgoRsa(ckmc_algo_type_e type, size_t keyLen) : AlgoBase(type, keyLen) {}
+    KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr);
+};
+
+KeyAliasPair AlgoRsa::keyGen(const char* pass, const char* suffix)
+{
+    std::ostringstream oss_prv, oss_pub;
+    oss_prv << "rsa_oaep_prv_alias_" << m_keyLen;
+    oss_pub << "rsa_oaep_pub_alias_" << m_keyLen;
+    if (suffix) {
+        oss_prv << suffix;
+        oss_pub << suffix;
+    }
+    KeyAliasPair aliases = {
+            aliasWithLabel(get_label().get(), oss_prv.str().c_str()),
+            aliasWithLabel(get_label().get(), oss_pub.str().c_str())
+    };
+    CharPtr passPtr(nullptr, free);
+    if (pass)
+        passPtr.reset(strdup(pass));
+
+    ckmc_policy_s policyPrv;
+    policyPrv.password = passPtr.get();
+    policyPrv.extractable = 0;
+
+    ckmc_policy_s policyPub;
+    policyPub.password = passPtr.get();
+    policyPub.extractable = 0;
+
+    assert_positive(ckmc_create_key_pair_rsa,
+                    m_keyLen,
+                    aliases.prv.c_str(),
+                    aliases.pub.c_str(),
+                    policyPrv,
+                    policyPub);
+    return aliases;
+}
+
+enum Algorithm {
+    AES_CBC_128,
+    AES_CBC_192,
+    AES_CBC_256,
+    AES_GCM_128,
+    AES_GCM_192,
+    AES_GCM_256,
+    AES_CTR_128,
+    AES_CTR_192,
+    AES_CTR_256,
+    AES_CFB_128,
+    AES_CFB_192,
+    AES_CFB_256,
+    RSA_OAEP_1024,
+    RSA_OAEP_2048,
+    RSA_OAEP_4096,
+};
+
+std::map<Algorithm, AlgoBasePtr> g_algorithms = {
+        { AES_CBC_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 128) },
+        { AES_CBC_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 192) },
+        { AES_CBC_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 256) },
+        { AES_GCM_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 128) },
+        { AES_GCM_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 192) },
+        { AES_GCM_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 256) },
+        { AES_CTR_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 128) },
+        { AES_CTR_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 192) },
+        { AES_CTR_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 256) },
+        { AES_CFB_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 128) },
+        { AES_CFB_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 192) },
+        { AES_CFB_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 256) },
+        { RSA_OAEP_1024, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 1024) },
+        { RSA_OAEP_2048, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 2048) },
+        { RSA_OAEP_4096, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 4096) },
+};
+
+void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
+{
+    int ret = ckmc_param_list_add_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_add_integer(params.get(), name, integer);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
+                      "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
+}
+
+struct EncryptionResult
+{
+    RawBufferPtr encrypted;
+    ParamListPtr params;
+    CKM::Alias prvKey;
+    CKM::Alias pubKey;
+};
+
+EncryptionResult encrypt(const AlgoBasePtr& algo,
+                         const RawBufferPtr& plain,
+                         const char* pass = nullptr)
+{
+    EncryptionResult ret;
+    ckmc_raw_buffer_s* encrypted = nullptr;
+    KeyAliasPair aliases = algo->keyGen(pass);
+
+    ret.params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, ret.params.get());
+    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+    assert_positive(ckmc_encrypt_data,
+                    ret.params.get(),
+                    aliases.pub.c_str(),
+                    pass,
+                    *plain.get(),
+                    &encrypted);
+
+    ret.encrypted = create_raw_buffer(encrypted);
+    ret.prvKey = aliases.prv;
+    ret.pubKey = aliases.pub;
+    return ret;
+}
+
+void testAllAlgorithms(
+        const std::function<void(const AlgoBasePtr& algo)>& test)
+{
+    for(const auto& it : g_algorithms)
+        test(it.second);
+}
+
+void testNoIvEnc(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encrypted = nullptr;
+
+    // add key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // param list with algo type only
+    ParamListPtr params = createParamListPtr();
+    setParam(params, CKMC_PARAM_ALGO_TYPE, algo->m_type);
+    assert_invalid_param(ckmc_encrypt_data,
+                         params.get(),
+                         aliases.pub.c_str(),
+                         nullptr,
+                         *plain.get(),
+                         &encrypted);
+}
+
+void testNoIvDec(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt;
+    auto ret = encrypt(algo, plain);
+
+    // param list with algo type only
+    ParamListPtr params = createParamListPtr();
+    setParam(params, CKMC_PARAM_ALGO_TYPE, algo->m_type);
+    assert_invalid_param(ckmc_decrypt_data,
+                         params.get(),
+                         ret.prvKey.c_str(),
+                         nullptr,
+                         *ret.encrypted.get(),
+                         &decrypted);
+}
+
+void testInvalidIvEnc(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encryptedTmp = nullptr;
+
+    // add key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, params.get());
+
+    // invalid encryption
+    auto test = [&](){
+        assert_invalid_param(ckmc_encrypt_data,
+                             params.get(),
+                             aliases.pub.c_str(),
+                             nullptr,
+                             *plain.get(),
+                             &encryptedTmp);
+        ckmc_buffer_free(encryptedTmp);
+        encryptedTmp = nullptr;
+    };
+    // invalid iv size
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN-1));
+    test();
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN+1));
+    test();
+};
+
+void testInvalidIvDec(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // valid encryption
+    auto ret = encrypt(algo, plain);
+
+    // decryption
+    auto test2 = [&](){
+        assert_invalid_param(ckmc_decrypt_data,
+                             ret.params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+        ckmc_buffer_free(decrypted);
+        decrypted = nullptr;
+    };
+
+    // invalid iv size
+    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN-1));
+    test2();
+    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN+1));
+    test2();
+};
+
+void encryptionWithCustomData(Algorithm type, ckmc_param_name_e name)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encrypted = nullptr;
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // add key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, params.get());
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+    // set AAD
+    setParam(params, name, createRandomBufferCAPI(64));
+
+    // encrypt
+    assert_positive(ckmc_encrypt_data,
+                    params.get(),
+                    aliases.pub.c_str(),
+                    nullptr,
+                    *plain.get(),
+                    &encrypted);
+    RawBufferPtr tmpEnc = create_raw_buffer(encrypted);
+
+    // decrypt
+    assert_positive(ckmc_decrypt_data,
+                    params.get(),
+                    aliases.prv.c_str(),
+                    nullptr,
+                    *tmpEnc.get(),
+                    &decrypted);
+    RawBufferPtr tmpDec = create_raw_buffer(decrypted);
+
+    // check
+    assert_buffers_equal(*plain.get(), *tmpDec.get());
+    tmpDec.reset();
+    decrypted = nullptr;
+
+    // set wrong AAD
+    setParam(params, name, createRandomBufferCAPI(32));
+
+    // decrypt
+    assert_result(CKMC_ERROR_SERVER_ERROR,
+                  ckmc_decrypt_data,
+                  params.get(),
+                  aliases.prv.c_str(),
+                  nullptr,
+                  *tmpEnc.get(),
+                  &decrypted);
+}
+
+void testGcmIvSize(size_t size, const KeyAliasPair& aliases, int error = CKMC_ERROR_NONE)
+{
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    RawBufferPtr encrypted;
+    RawBufferPtr decrypted;
+    ckmc_raw_buffer_s* encryptedTmp = nullptr;
+    ckmc_raw_buffer_s* decryptedTmp = nullptr;
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, CKMC_ALGO_AES_GCM, params.get());
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(size));
+
+    // encryption
+    assert_result(error,
+                  ckmc_encrypt_data,
+                  params.get(),
+                  aliases.pub.c_str(),
+                  nullptr,
+                  *plain.get(),
+                  &encryptedTmp);
+
+    if(error != CKMC_ERROR_NONE)
+        return;
+    encrypted = create_raw_buffer(encryptedTmp);
+
+    // decryption
+    assert_positive(ckmc_decrypt_data,
+                    params.get(),
+                    aliases.prv.c_str(),
+                    nullptr,
+                    *encrypted.get(),
+                    &decryptedTmp);
+    decrypted = create_raw_buffer(decryptedTmp);
+
+    assert_buffers_equal(*plain.get(), *decrypted.get());
+}
+
+void testIntegrity(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt
+    auto ret = encrypt(algo, plain);
+
+    // break the encrypted data
+    ret.encrypted->data[BUF_LEN/2]++;
+
+    // no data integrity check
+    assert_positive(ckmc_decrypt_data,
+                    ret.params.get(),
+                    ret.prvKey.c_str(),
+                    nullptr,
+                    *ret.encrypted.get(),
+                     &decrypted);
+
+    RawBufferPtr tmp = create_raw_buffer(decrypted);
+    assert_buffers_equal(*plain.get(), *decrypted, false);
+}
+
+void testCtrEncryptionInvalidLength(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encryptedTmp = nullptr;
+
+    // add AES CTR key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, params.get());
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+    // encryption
+    auto test = [&](){
+        assert_invalid_param(ckmc_encrypt_data,
+                             params.get(),
+                             aliases.pub.c_str(),
+                             nullptr,
+                             *plain.get(),
+                             &encryptedTmp);
+        ckmc_buffer_free(encryptedTmp);
+        encryptedTmp = nullptr;
+    };
+    // invalid counter size
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, -1);
+    test();
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, 0);
+    test();
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
+    test();
+}
+
+void testCtrEncryptionValidLength(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encryptedTmp = nullptr;
+
+    // add AES CTR key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, params.get());
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+    // encryption
+    auto test = [&](){
+        assert_positive(ckmc_encrypt_data,
+                        params.get(),
+                        aliases.pub.c_str(),
+                        nullptr,
+                        *plain.get(),
+                        &encryptedTmp);
+        ckmc_buffer_free(encryptedTmp);
+        encryptedTmp = nullptr;
+    };
+    // valid counter sizez
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, 1);
+    test();
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, 4);
+    test();
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN-1);
+    test();
+    setParam(params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN);
+    test();
+}
+
+void testCtrDecryptionInvalidLength(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // add AES CTR key & encrypt
+    auto ret = encrypt(algo, plain);
+
+    // decryption
+    auto test = [&](){
+        assert_invalid_param(ckmc_decrypt_data,
+                             ret.params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+        ckmc_buffer_free(decrypted);
+        decrypted = nullptr;
+    };
+    // invalid counter size
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, -1);
+    test();
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 0);
+    test();
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
+    test();
+}
+
+void testCtrDecryptionValidLength(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // add AES CTR key & encrypt
+    auto ret = encrypt(algo, plain);
+
+    // decryption
+    auto test = [&](){
+        assert_positive(ckmc_decrypt_data,
+                             ret.params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+        ckmc_buffer_free(decrypted);
+        RawBufferPtr tmp = create_raw_buffer(decrypted);
+        assert_buffers_equal(*plain.get(), *decrypted);
+    };
+    // invalid counter size
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 1);
+    test();
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 4);
+    test();
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN-1);
+    test();
+    setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN);
+    test();
+}
+
+void testGcmEncryptionTagLen(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* encryptedTmp = nullptr;
+
+    // add AES GCM key
+    KeyAliasPair aliases = algo->keyGen();
+
+    // setup params
+    ParamListPtr params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, params.get());
+    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+    std::vector<TagTest> testData = {
+            // illegal tag lengths
+            { -1,   CKMC_ERROR_INVALID_PARAMETER },
+            { 0,    CKMC_ERROR_INVALID_PARAMETER },
+            { 16,   CKMC_ERROR_INVALID_PARAMETER },
+            { 48,   CKMC_ERROR_INVALID_PARAMETER },
+            { 72,   CKMC_ERROR_INVALID_PARAMETER },
+            { 100,  CKMC_ERROR_INVALID_PARAMETER },
+            { 108,  CKMC_ERROR_INVALID_PARAMETER },
+            { 116,  CKMC_ERROR_INVALID_PARAMETER },
+            { 124,  CKMC_ERROR_INVALID_PARAMETER },
+            { 256,  CKMC_ERROR_INVALID_PARAMETER },
+            // legal tag lengths
+            { 32,   CKMC_ERROR_NONE },
+            { 64,   CKMC_ERROR_NONE },
+            { 96,   CKMC_ERROR_NONE },
+            { 104,  CKMC_ERROR_NONE },
+            { 112,  CKMC_ERROR_NONE },
+            { 120,  CKMC_ERROR_NONE },
+            { 128,  CKMC_ERROR_NONE },
+    };
+
+    // encryption
+    for(const auto& it : testData)
+    {
+        setParam(params, CKMC_PARAM_ED_TAG_LEN, it.tagLen);
+        assert_result(it.expected,
+                      ckmc_encrypt_data,
+                      params.get(),
+                      aliases.pub.c_str(),
+                      nullptr,
+                      *plain.get(),
+                      &encryptedTmp);
+        ckmc_buffer_free(encryptedTmp);
+        encryptedTmp = nullptr;
+    }
+}
+
+void testGcmDecryptionTagLen(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // add AES GCM key & encrypt
+    auto ret = encrypt(algo, plain);
+
+    std::vector<TagTest> testData = {
+            // illegal tag lengths
+            { -1,   CKMC_ERROR_INVALID_PARAMETER },
+            { 0,    CKMC_ERROR_INVALID_PARAMETER },
+            { 16,   CKMC_ERROR_INVALID_PARAMETER },
+            { 48,   CKMC_ERROR_INVALID_PARAMETER },
+            { 72,   CKMC_ERROR_INVALID_PARAMETER },
+            { 100,  CKMC_ERROR_INVALID_PARAMETER },
+            { 108,  CKMC_ERROR_INVALID_PARAMETER },
+            { 116,  CKMC_ERROR_INVALID_PARAMETER },
+            { 124,  CKMC_ERROR_INVALID_PARAMETER },
+            { 256,  CKMC_ERROR_INVALID_PARAMETER },
+            // legal tag lengths (EVP_CipherFinal fails but we can't get the error code)
+            { 32,   CKMC_ERROR_SERVER_ERROR },
+            { 64,   CKMC_ERROR_SERVER_ERROR },
+            { 96,   CKMC_ERROR_SERVER_ERROR },
+            { 104,  CKMC_ERROR_SERVER_ERROR },
+            { 112,  CKMC_ERROR_SERVER_ERROR },
+            { 120,  CKMC_ERROR_SERVER_ERROR },
+            // legal tag length that was actually used for encryption (default)
+            { 128,  CKMC_ERROR_NONE },
+    };
+
+    // decryption
+    for(const auto& it : testData)
+    {
+        setParam(ret.params, CKMC_PARAM_ED_TAG_LEN, it.tagLen);
+        assert_result(it.expected,
+                      ckmc_decrypt_data,
+                      ret.params.get(),
+                      ret.prvKey.c_str(),
+                      nullptr,
+                      *ret.encrypted.get(),
+                      &decrypted);
+        ckmc_buffer_free(decrypted);
+        decrypted = nullptr;
+    }
+}
+
+void testGcmWrongTag(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt with AES GCM
+    auto ret = encrypt(algo, plain);
+
+    // modify tag (last 16B of encrypted message)
+    ret.encrypted->data[ret.encrypted->size-1]++;
+
+    // EVP_CipherFinal fails but we can't get error code
+    assert_result(CKMC_ERROR_SERVER_ERROR,
+                  ckmc_decrypt_data,
+                  ret.params.get(),
+                  ret.prvKey.c_str(),
+                  nullptr,
+                  *ret.encrypted.get(),
+                  &decrypted);
+}
+
+void testGcmDifferentIvSizes(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // add AES GCM key
+    KeyAliasPair aliases = algo->keyGen();
+
+    testGcmIvSize(11,   aliases, CKMC_ERROR_SERVER_ERROR); // 12B is the smallest
+    testGcmIvSize(12,  aliases);
+    testGcmIvSize(17,  aliases);
+    testGcmIvSize(128, aliases);
+}
+
+void testEncryptDecryptBigData(Algorithm type)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(5000000));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt
+    auto ret = encrypt(algo, plain);
+
+    assert_positive(ckmc_decrypt_data,
+                    ret.params.get(),
+                    ret.prvKey.c_str(),
+                    nullptr,
+                    *ret.encrypted.get(),
+                    &decrypted);
+    RawBufferPtr tmp = create_raw_buffer(decrypted);
+
+    assert_buffers_equal(*plain.get(), *decrypted);
+}
+
+void testEncryptDecryptDifferentKeys(Algorithm type, bool success)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt
+    auto ret = encrypt(algo, plain);
+
+    // add different key
+    KeyAliasPair differentKeys = algo->keyGen(nullptr, "_wrong");
+
+
+    if (success) {
+        // some algorithms don't verify key validity
+        assert_positive(ckmc_decrypt_data,
+                        ret.params.get(),
+                        differentKeys.prv.c_str(),
+                        nullptr,
+                        *ret.encrypted.get(),
+                        &decrypted);
+        RawBufferPtr tmp = create_raw_buffer(decrypted);
+
+        assert_buffers_equal(*plain.get(), *decrypted, false);
+    } else {
+        // different key should not be accepted
+        assert_result(CKMC_ERROR_SERVER_ERROR,
+                      ckmc_decrypt_data,
+                      ret.params.get(),
+                      differentKeys.prv.c_str(),
+                      nullptr,
+                      *ret.encrypted.get(),
+                      &decrypted);
+    }
+
+    // Cleanup before testing next algorithm. Ignore results because not all keys are present
+    ckmc_remove_alias(ret.prvKey.c_str());
+    ckmc_remove_alias(ret.pubKey.c_str());
+    ckmc_remove_alias(differentKeys.prv.c_str());
+    ckmc_remove_alias(differentKeys.pub.c_str());
+}
+
+void testRsaLongestData(Algorithm type, size_t dataSize)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(dataSize));
+    ckmc_raw_buffer_s* decrypted = nullptr;
+
+    // encrypt
+    auto ret = encrypt(algo, plain);
+
+    assert_positive(ckmc_decrypt_data,
+                    ret.params.get(),
+                    ret.prvKey.c_str(),
+                    nullptr,
+                    *ret.encrypted.get(),
+                    &decrypted);
+    RawBufferPtr tmp = create_raw_buffer(decrypted);
+
+    assert_buffers_equal(*plain.get(), *decrypted);
+}
+
+void testRsaDataTooLong(Algorithm type, size_t dataSize)
+{
+    const AlgoBasePtr& algo = g_algorithms.at(type);
+    // prepare buffers
+    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(dataSize));
+
+    // encrypt
+    EncryptionResult ret;
+    ckmc_raw_buffer_s* encrypted = nullptr;
+    KeyAliasPair aliases = algo->keyGen();
+
+    ret.params = createParamListPtr();
+    assert_positive(ckmc_generate_params, algo->m_type, ret.params.get());
+    assert_result(CKMC_ERROR_SERVER_ERROR,
+                  ckmc_encrypt_data,
+                  ret.params.get(),
+                  aliases.pub.c_str(),
+                  nullptr,
+                  *plain.get(),
+                  &encrypted);
+}
+
+} // namespace anonymous
+
+
+RUNNER_TEST_GROUP_INIT(CKM_ENCRYPTION_DECRYPTION);
+
+/////////////////////////////////////////
+// Generic encryption decryption tests
+/////////////////////////////////////////
+
+RUNNER_TEST(TED_0010_encrypt_invalid_param_list, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* encrypted = nullptr;
+
+        // add key
+        KeyAliasPair aliases = algo->keyGen();
+
+        // null param list
+        assert_invalid_param(ckmc_encrypt_data,
+                             nullptr,
+                             aliases.pub.c_str(),
+                             nullptr,
+                             *plain.get(),
+                             &encrypted);
+
+        // empty param list
+        ParamListPtr params = createParamListPtr();
+        assert_invalid_param(ckmc_encrypt_data,
+                             params.get(),
+                             aliases.pub.c_str(),
+                             nullptr,
+                             *plain.get(),
+                             &encrypted);
+    });
+}
+
+RUNNER_TEST(TED_0020_encrypt_missing_key, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* encrypted = nullptr;
+
+        // setup params
+        ParamListPtr params = createParamListPtr();
+        assert_positive(ckmc_generate_params, algo->m_type, params.get());
+        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+        assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                      ckmc_encrypt_data,
+                      params.get(),
+                      "non-existing-key-alias",
+                      nullptr,
+                      *plain.get(),
+                      &encrypted);
+    });
+}
+
+RUNNER_TEST(TED_0030_encrypt_no_plain_text, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        ckmc_raw_buffer_s plain = { nullptr, 0 };
+        ckmc_raw_buffer_s* encrypted = nullptr;
+
+        // add key
+        KeyAliasPair aliases = algo->keyGen();
+
+        // setup params
+        ParamListPtr params = createParamListPtr();
+        assert_positive(ckmc_generate_params, algo->m_type, params.get());
+        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+        assert_invalid_param(ckmc_encrypt_data,
+                             params.get(),
+                             aliases.pub.c_str(),
+                             nullptr,
+                             plain,
+                             &encrypted);
+    });
+}
+
+RUNNER_TEST(TED_0040_encrypt_no_output_buffer, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s** encrypted = nullptr;
+
+        // add key
+        KeyAliasPair aliases = algo->keyGen();
+
+        // setup params
+        ParamListPtr params = createParamListPtr();
+        assert_positive(ckmc_generate_params, algo->m_type, params.get());
+        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+        assert_invalid_param(ckmc_encrypt_data,
+                             params.get(),
+                             aliases.pub.c_str(),
+                             nullptr,
+                             *plain.get(),
+                             encrypted);
+    });
+}
+
+RUNNER_TEST(TED_0110_decrypt_invalid_param_list, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // encrypt;
+        auto ret = encrypt(algo, plain);
+
+        // null param list
+        assert_invalid_param(ckmc_decrypt_data,
+                             nullptr,
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+
+        // empty param list
+        ParamListPtr params = createParamListPtr();
+        assert_invalid_param(ckmc_decrypt_data,
+                             params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0120_decrypt_missing_key, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // encrypt
+        auto ret = encrypt(algo, plain);
+
+        // remove key
+        assert_positive(ckmc_remove_alias, ret.prvKey.c_str());
+
+        // try to decrypt
+        assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                      ckmc_decrypt_data,
+                      ret.params.get(),
+                      ret.prvKey.c_str(),
+                      nullptr,
+                      *ret.encrypted.get(),
+                      &decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0130_decrypt_no_encrypted_text, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        ckmc_raw_buffer_s encrypted = { nullptr, 0 };
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // add key
+        KeyAliasPair aliases = algo->keyGen();
+
+        // setup params
+        ParamListPtr params = createParamListPtr();
+        assert_positive(ckmc_generate_params, algo->m_type, params.get());
+        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+        assert_invalid_param(ckmc_decrypt_data,
+                             params.get(),
+                             aliases.prv.c_str(),
+                             nullptr,
+                             encrypted,
+                             &decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0140_decrypt_no_output_buffer, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s** decrypted = nullptr;
+
+        // encrypt
+        auto ret = encrypt(algo, plain);
+
+        assert_invalid_param(ckmc_decrypt_data,
+                             ret.params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0200_encrypt_decrypt_different_keys, EncEnv)
+{
+    testEncryptDecryptDifferentKeys(AES_CBC_128, false);
+    testEncryptDecryptDifferentKeys(AES_CBC_192, false);
+    testEncryptDecryptDifferentKeys(AES_CBC_256, false);
+    testEncryptDecryptDifferentKeys(AES_GCM_128, false);
+    testEncryptDecryptDifferentKeys(AES_GCM_192, false);
+    testEncryptDecryptDifferentKeys(AES_GCM_256, false);
+    testEncryptDecryptDifferentKeys(AES_CTR_128, true);
+    testEncryptDecryptDifferentKeys(AES_CTR_192, true);
+    testEncryptDecryptDifferentKeys(AES_CTR_256, true);
+    testEncryptDecryptDifferentKeys(AES_CFB_128, true);
+    testEncryptDecryptDifferentKeys(AES_CFB_192, true);
+    testEncryptDecryptDifferentKeys(AES_CFB_256, true);
+    testEncryptDecryptDifferentKeys(RSA_OAEP_1024, false);
+    testEncryptDecryptDifferentKeys(RSA_OAEP_2048, false);
+    testEncryptDecryptDifferentKeys(RSA_OAEP_4096, false);
+}
+
+RUNNER_TEST(TED_0210_encrypt_decrypt_different_params, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // encrypt
+        auto ret = encrypt(algo, plain);
+
+        // setup different params
+        ParamListPtr params = createParamListPtr();
+        assert_positive(ckmc_generate_params, CKMC_ALGO_RSA_GEN, params.get());
+        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+
+        assert_invalid_param(ckmc_decrypt_data,
+                             params.get(),
+                             ret.prvKey.c_str(),
+                             nullptr,
+                             *ret.encrypted.get(),
+                             &decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0300_encrypt_decrypt, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // encrypt
+        auto ret = encrypt(algo, plain);
+
+        assert_positive(ckmc_decrypt_data,
+                        ret.params.get(),
+                        ret.prvKey.c_str(),
+                        nullptr,
+                        *ret.encrypted.get(),
+                        &decrypted);
+        RawBufferPtr tmp = create_raw_buffer(decrypted);
+
+        assert_buffers_equal(*plain.get(), *decrypted);
+    });
+}
+
+RUNNER_TEST(TED_0310_encrypt_decrypt_password, EncEnv)
+{
+    testAllAlgorithms([](const AlgoBasePtr& algo){
+        // prepare buffers
+        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+        ckmc_raw_buffer_s* decrypted = nullptr;
+
+        // encrypt
+        auto ret = encrypt(algo, plain, PASSWORD);
+
+        // wrong password
+        assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                      ckmc_decrypt_data,
+                      ret.params.get(),
+                      ret.prvKey.c_str(),
+                      "wrong-password",
+                      *ret.encrypted.get(),
+                      &decrypted);
+
+        // correct password
+        assert_positive(ckmc_decrypt_data,
+                        ret.params.get(),
+                        ret.prvKey.c_str(),
+                        PASSWORD,
+                        *ret.encrypted.get(),
+                        &decrypted);
+        RawBufferPtr tmp = create_raw_buffer(decrypted); // guarantees deletion
+
+        assert_buffers_equal(*plain.get(), *decrypted);
+    });
+}
+
+// long test split into smaller ones
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cbc_128, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CBC_128);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cbc_192, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CBC_192);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cbc_256, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CBC_256);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_gcm_128, EncEnv)
+{
+    testEncryptDecryptBigData(AES_GCM_128);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_gcm_192, EncEnv)
+{
+    testEncryptDecryptBigData(AES_GCM_192);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_gcm_256, EncEnv)
+{
+    testEncryptDecryptBigData(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_ctr_128, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CTR_128);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_ctr_192, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CTR_192);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_ctr_256, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CTR_256);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cfb_128, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CFB_128);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cfb_192, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CFB_192);
+}
+
+RUNNER_TEST(TED_0400_encrypt_decrypt_big_data_aes_cfb_256, EncEnv)
+{
+    testEncryptDecryptBigData(AES_CFB_256);
+}
+
+/////////////////////////////////////////
+// Algorithm specific tests
+/////////////////////////////////////////
+
+RUNNER_TEST(TED_1005_no_iv_enc, EncEnv)
+{
+    testNoIvEnc(AES_CTR_128);
+    testNoIvEnc(AES_CTR_192);
+    testNoIvEnc(AES_CTR_256);
+    testNoIvEnc(AES_CBC_128);
+    testNoIvEnc(AES_CBC_192);
+    testNoIvEnc(AES_CBC_256);
+    testNoIvEnc(AES_CFB_128);
+    testNoIvEnc(AES_CFB_192);
+    testNoIvEnc(AES_CFB_256);
+    testNoIvEnc(AES_GCM_128);
+    testNoIvEnc(AES_GCM_192);
+    testNoIvEnc(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1010_invalid_iv_enc, EncEnv)
+{
+    testInvalidIvEnc(AES_CTR_128);
+    testInvalidIvEnc(AES_CTR_192);
+    testInvalidIvEnc(AES_CTR_256);
+    testInvalidIvEnc(AES_CBC_128);
+    testInvalidIvEnc(AES_CBC_192);
+    testInvalidIvEnc(AES_CBC_256);
+    testInvalidIvEnc(AES_CFB_128);
+    testInvalidIvEnc(AES_CFB_192);
+    testInvalidIvEnc(AES_CFB_256);
+}
+
+RUNNER_TEST(TED_1015_no_iv_dec, EncEnv)
+{
+    testNoIvDec(AES_CTR_128);
+    testNoIvDec(AES_CTR_192);
+    testNoIvDec(AES_CTR_256);
+    testNoIvDec(AES_CBC_128);
+    testNoIvDec(AES_CBC_192);
+    testNoIvDec(AES_CBC_256);
+    testNoIvDec(AES_CFB_128);
+    testNoIvDec(AES_CFB_192);
+    testNoIvDec(AES_CFB_256);
+    testNoIvDec(AES_GCM_128);
+    testNoIvDec(AES_GCM_192);
+    testNoIvDec(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1020_invalid_iv_dec, EncEnv)
+{
+    testInvalidIvDec(AES_CTR_128);
+    testInvalidIvDec(AES_CTR_192);
+    testInvalidIvDec(AES_CTR_256);
+    testInvalidIvDec(AES_CBC_128);
+    testInvalidIvDec(AES_CBC_192);
+    testInvalidIvDec(AES_CBC_256);
+    testInvalidIvDec(AES_CFB_128);
+    testInvalidIvDec(AES_CFB_192);
+    testInvalidIvDec(AES_CFB_256);
+}
+
+RUNNER_TEST(TED_1050_data_integrity, EncEnv)
+{
+    testIntegrity(AES_CTR_128);
+    testIntegrity(AES_CTR_192);
+    testIntegrity(AES_CTR_256);
+    testIntegrity(AES_CBC_128);
+    testIntegrity(AES_CBC_192);
+    testIntegrity(AES_CBC_256);
+    testIntegrity(AES_CFB_128);
+    testIntegrity(AES_CFB_192);
+    testIntegrity(AES_CFB_256);
+}
+
+RUNNER_TEST(TED_1100_ctr_encryption_invalid_length, EncEnv)
+{
+    testCtrEncryptionInvalidLength(AES_CTR_128);
+    testCtrEncryptionInvalidLength(AES_CTR_192);
+    testCtrEncryptionInvalidLength(AES_CTR_256);
+}
+
+RUNNER_TEST(TED_1105_ctr_encryption_valid_length, EncEnv)
+{
+    RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
+    testCtrEncryptionValidLength(AES_CTR_128);
+    testCtrEncryptionValidLength(AES_CTR_192);
+    testCtrEncryptionValidLength(AES_CTR_256);
+}
+
+RUNNER_TEST(TED_1110_ctr_decryption_invalid_length, EncEnv)
+{
+    testCtrDecryptionInvalidLength(AES_CTR_128);
+    testCtrDecryptionInvalidLength(AES_CTR_192);
+    testCtrDecryptionInvalidLength(AES_CTR_256);
+}
+
+RUNNER_TEST(TED_1115_ctr_decryption_valid_length, EncEnv)
+{
+    RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
+    testCtrDecryptionValidLength(AES_CTR_128);
+    testCtrDecryptionValidLength(AES_CTR_192);
+    testCtrDecryptionValidLength(AES_CTR_256);
+}
+
+RUNNER_TEST(TED_1200_gcm_encryption_tag_len, EncEnv)
+{
+    testGcmEncryptionTagLen(AES_GCM_128);
+    testGcmEncryptionTagLen(AES_GCM_192);
+    testGcmEncryptionTagLen(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1210_gcm_decryption_tag_len, EncEnv)
+{
+    testGcmDecryptionTagLen(AES_GCM_128);
+    testGcmDecryptionTagLen(AES_GCM_192);
+    testGcmDecryptionTagLen(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1230_gcm_wrong_tag, EncEnv)
+{
+    testGcmWrongTag(AES_GCM_128);
+    testGcmWrongTag(AES_GCM_192);
+    testGcmWrongTag(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1240_gcm_different_iv_sizes, EncEnv)
+{
+    testGcmDifferentIvSizes(AES_GCM_128);
+    testGcmDifferentIvSizes(AES_GCM_192);
+    testGcmDifferentIvSizes(AES_GCM_256);
+}
+
+RUNNER_TEST(TED_1250_gcm_aad, EncEnv)
+{
+    encryptionWithCustomData(AES_GCM_128, CKMC_PARAM_ED_AAD);
+    encryptionWithCustomData(AES_GCM_192, CKMC_PARAM_ED_AAD);
+    encryptionWithCustomData(AES_GCM_256, CKMC_PARAM_ED_AAD);
+}
+
+RUNNER_TEST(TED_1300_rsa_label, EncEnv)
+{
+    RUNNER_IGNORED_MSG("RSA-OAEP labels are not supported in openssl");
+    encryptionWithCustomData(RSA_OAEP_1024, CKMC_PARAM_ED_LABEL);
+    encryptionWithCustomData(RSA_OAEP_2048, CKMC_PARAM_ED_LABEL);
+    encryptionWithCustomData(RSA_OAEP_4096, CKMC_PARAM_ED_LABEL);
+}
+
+RUNNER_TEST(TED_1330_rsa_longest_data, EncEnv)
+{
+    testRsaLongestData(RSA_OAEP_1024, 86);
+    testRsaLongestData(RSA_OAEP_2048, 214);
+    testRsaLongestData(RSA_OAEP_4096, 470);
+}
+
+RUNNER_TEST(TED_1350_rsa_data_too_long, EncEnv)
+{
+    testRsaDataTooLong(RSA_OAEP_1024, 87);
+    testRsaDataTooLong(RSA_OAEP_2048, 215);
+    testRsaDataTooLong(RSA_OAEP_4096, 471);
+}