SW backend unit tests 78/235778/14
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 9 Jun 2020 16:27:23 +0000 (18:27 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 9 Jul 2020 16:20:28 +0000 (18:20 +0200)
Also:
* Hide SW::Internals functions unused outside and add few asserts.
* Add missing openssl errors.
* Properly handle rsa encryption output.
* Properly handle missing asymmetric key.
* Old partial tests replaced.
* Minor code cleanup.

Change-Id: I1f83f6dc6bcdc99708b2f1f081b4be6fef8a4b08

src/manager/common/openssl-error-handler.cpp
src/manager/crypto/sw-backend/internals.cpp
src/manager/crypto/sw-backend/internals.h
unit-tests/test_sw-backend.cpp

index c7c1263..60f5e45 100644 (file)
@@ -102,6 +102,8 @@ void errorHandle(const char *file, int line, const char *function, int openssl_r
        case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN):
 #endif /* OPENSSL_VERSION_NUMBER > 0x10100000L */
        case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL):
+       case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_MISSING_PRIVATE_KEY):
+       case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_MISSING_PRIVATE_KEY):
        case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED):
        case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET):
        case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION):
@@ -112,7 +114,9 @@ void errorHandle(const char *file, int line, const char *function, int openssl_r
        case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_WRONG_FINAL_BLOCK_LENGTH):
        case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS):
        case ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE):
+       case ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY):
        case ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE):
+       case ERR_PACK(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, DSA_R_MISSING_PRIVATE_KEY):
        case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG):
        case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG):
        case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG):
index 445a900..9a13c03 100644 (file)
@@ -21,6 +21,7 @@
 #include <exception>
 #include <utility>
 #include <algorithm>
+#include <cassert>
 
 #include <openssl/evp.h>
 #include <openssl/obj_mac.h>
@@ -207,7 +208,7 @@ ValidatorMap initValidators()
        return validators;
 };
 
-ValidatorMap g_validators = initValidators();
+const ValidatorMap g_validators = initValidators();
 
 template <typename TypeCheck>
 void validateParams(const CryptoAlgorithm &ca)
@@ -218,13 +219,13 @@ void validateParams(const CryptoAlgorithm &ca)
 
        AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
 
-       try {
-               for (const auto &validator : g_validators.at(at))
-                       validator->Check(ca);
-       } catch (const std::out_of_range &) {
-               ThrowErr(Exc::Crypto::InputParam, "Unsupported algorithm ",
-                                static_cast<int>(at));
-       }
+       auto it = g_validators.find(at);
+
+       // TypeCheck should prevent it
+       assert(it != g_validators.end());
+
+       for (const auto &validator : it->second)
+               validator->Check(ca);
 }
 
 typedef std::unique_ptr<Cipher::EvpCipherWrapper<RawBuffer>> EvpCipherPtr;
@@ -307,6 +308,9 @@ RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char *,
 {
        validateParams<IsAsymEncryption>(alg);
 
+       if (!pkey)
+               ThrowErr(Exc::Crypto::InputParam, logPrefix, "no key");
+
        RSA *rsa = EVP_PKEY_get1_RSA(pkey.get());
 
        if (!rsa)
@@ -321,11 +325,14 @@ RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char *,
        output.resize(RSA_size(rsa));
        int ret;
        try {
-               OPENSSL_ERROR_HANDLE(ret = cryptoFn(data.size(),
-                                    data.data(),
-                                    output.data(),
-                                    rsa,
-                                    RSA_PKCS1_OAEP_PADDING));
+               ERR_clear_error();
+               ret = cryptoFn(data.size(),
+                              data.data(),
+                              output.data(),
+                              rsa,
+                              RSA_PKCS1_OAEP_PADDING);
+               if (ret < 0)
+                       errorHandle(__FILE__, __LINE__, __func__, ret);
        } catch (...) {
                RSA_free(rsa);
                throw;
@@ -335,71 +342,50 @@ RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char *,
        return output;
 }
 
-} // anonymous namespace
-
 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo)
 {
-       const EVP_MD *md_algo = NULL;
-
        switch (hashAlgo) {
-       case HashAlgorithm::NONE:
-               md_algo = NULL;
-               break;
+       default:
+               // validateParams<IsSignVerify> should prevent it
+               assert(hashAlgo == HashAlgorithm::NONE);
+               return NULL;
 
        case HashAlgorithm::SHA1:
-               md_algo = EVP_sha1();
-               break;
+               return EVP_sha1();
 
        case HashAlgorithm::SHA256:
-               md_algo = EVP_sha256();
-               break;
+               return EVP_sha256();
 
        case HashAlgorithm::SHA384:
-               md_algo = EVP_sha384();
-               break;
+               return EVP_sha384();
 
        case HashAlgorithm::SHA512:
-               md_algo = EVP_sha512();
-               break;
-
-       default:
-               ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
+               return EVP_sha512();
        }
-
-       return md_algo;
 }
 
 int getRsaPadding(const RSAPaddingAlgorithm padAlgo)
 {
-       int rsa_padding = -1;
-
        switch (padAlgo) {
-       case RSAPaddingAlgorithm::NONE:
-               rsa_padding = RSA_NO_PADDING;
-               break;
+       default:
+               // validateParams<IsSignVerify> should prevent it
+               assert(padAlgo == RSAPaddingAlgorithm::NONE);
+               return RSA_NO_PADDING;
 
        case RSAPaddingAlgorithm::PKCS1:
-               rsa_padding = RSA_PKCS1_PADDING;
-               break;
+               return RSA_PKCS1_PADDING;
 
        case RSAPaddingAlgorithm::X931:
-               rsa_padding = RSA_X931_PADDING;
-               break;
-
-       default:
-               ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
+               return RSA_X931_PADDING;
        }
-
-       return rsa_padding;
 }
 
 DataPair createKeyPairRSA(const int size)
 {
        EvpPkeyUPtr pkey;
 
-       // check the parameters of functions
-       if (size != 1024 && size != 2048 && size != 4096)
-               ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
+       // validateParams<IsAsymGeneration> should prevent it
+       assert(size == 1024 || size == 2048 || size == 4096);
 
        EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
 
@@ -422,15 +408,13 @@ DataPair createKeyPairRSA(const int size)
        {DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())});
 }
 
-
 DataPair createKeyPairDSA(const int size)
 {
        EvpPkeyUPtr pkey;
        EvpPkeyUPtr pparam;
 
-       // check the parameters of functions
-       if (size != 1024 && size != 2048 && size != 3072 && size != 4096)
-               ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
+       // validateParams<IsAsymGeneration> should prevent it
+       assert(size == 1024 || size == 2048 || size == 3072 || size == 4096);
 
        /* Create the context for generating the parameters */
        EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
@@ -471,12 +455,14 @@ DataPair createKeyPairDSA(const int size)
 
 DataPair createKeyPairECDSA(ElipticCurve type)
 {
-       int ecCurve = NOT_DEFINED;
+       int ecCurve;
        EvpPkeyUPtr pkey;
        EvpPkeyUPtr pparam;
 
        switch (type) {
-       case ElipticCurve::prime192v1:
+       default:
+               // validateParams<IsAsymGeneration> should prevent it
+               assert(type == ElipticCurve::prime192v1);
                ecCurve = NID_X9_62_prime192v1;
                break;
 
@@ -487,9 +473,6 @@ DataPair createKeyPairECDSA(ElipticCurve type)
        case ElipticCurve::secp384r1:
                ecCurve = NID_secp384r1;
                break;
-
-       default:
-               ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
        }
 
        /* Create the context for generating the parameters */
@@ -531,10 +514,8 @@ DataPair createKeyPairECDSA(ElipticCurve type)
 
 Data createKeyAES(const int sizeBits)
 {
-       // check the parameters of functions
-       if (sizeBits != 128 && sizeBits != 192 && sizeBits != 256) {
-               ThrowErr(Exc::Crypto::InputParam, "Error in AES input size");
-       }
+       // validateParams<IsSymGeneration> should prevent it
+       assert(sizeBits == 128 || sizeBits == 192 || sizeBits == 256);
 
        uint8_t key[32];
        int sizeBytes = sizeBits / 8;
@@ -546,6 +527,183 @@ Data createKeyAES(const int sizeBits)
        return { DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key + sizeBytes)};
 }
 
+RawBuffer signMessage(EVP_PKEY *privKey,
+                                         const RawBuffer &message,
+                                         const int rsa_padding)
+{
+       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) != EVP_PKEY_RSA)
+               ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
+
+       EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
+
+       if (!pctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
+
+       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign_init(pctx.get()));
+
+       /* Set padding algorithm */
+       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
+               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
+
+       /* Finalize the Sign operation */
+       /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
+        * signature. Length is returned in slen */
+       size_t slen;
+
+       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size()));
+
+       /* Allocate memory for the signature based on size in slen */
+       RawBuffer sig(slen);
+
+       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), sig.data(), &slen, message.data(), message.size()));
+
+       // Set value to return RawData
+       sig.resize(slen);
+       return sig;
+}
+
+RawBuffer digestSignMessage(EVP_PKEY *privKey,
+                                                       const RawBuffer &message,
+                                                       const EVP_MD *md_algo,
+                                                       const int rsa_padding)
+{
+       EVP_PKEY_CTX *pctx = NULL;
+
+       // Create the Message Digest Context
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+       EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
+       if (!mdctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
+#else
+       EvpMdCtxUPtr mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
+       if (!mdctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
+#endif
+
+       OPENSSL_ERROR_HANDLE(EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey));
+
+       /* Set padding algorithm */
+       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
+               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
+
+       /* Call update with the message */
+       OPENSSL_ERROR_HANDLE(EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size()));
+
+       /* Finalize the DigestSign operation */
+       /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
+        * signature. Length is returned in slen */
+       size_t slen;
+
+       OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), NULL, &slen));
+
+       /* Allocate memory for the signature based on size in slen */
+       RawBuffer sig(slen);
+
+       /* Obtain the signature */
+       OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen));
+
+       // Set value to return RawData
+       sig.resize(slen);
+       return sig;
+}
+
+int verifyMessage(EVP_PKEY *pubKey,
+                                 const RawBuffer &message,
+                                 const RawBuffer &signature,
+                                 const int rsa_padding)
+{
+       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) != EVP_PKEY_RSA)
+               ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
+
+       EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
+
+       if (!pctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
+
+       OPENSSL_ERROR_HANDLE(EVP_PKEY_verify_init(pctx.get()));
+
+       /* Set padding algorithm */
+       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
+               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
+
+       if (OPENSSL_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(),
+                                                                          signature.size(), message.data(), message.size()))
+               return CKM_API_SUCCESS;
+
+       LogError("EVP_PKEY_verify Failed");
+       return CKM_API_ERROR_VERIFICATION_FAILED;
+}
+
+int digestVerifyMessage(EVP_PKEY *pubKey,
+                                               const RawBuffer &message,
+                                               const RawBuffer &signature,
+                                               const EVP_MD *md_algo,
+                                               const int rsa_padding)
+{
+       EVP_PKEY_CTX *pctx = NULL;
+
+       // Create the Message Digest Context
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+       EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
+       if (!mdctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
+#else
+       EvpMdCtxUPtr mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
+       if (!mdctx.get())
+               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
+#endif
+
+       OPENSSL_ERROR_HANDLE(EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey));
+
+       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
+               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
+
+       OPENSSL_ERROR_HANDLE(EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()));
+
+       if (OPENSSL_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(),
+                       const_cast<unsigned char *>(signature.data()), signature.size()))
+               return CKM_API_SUCCESS;
+
+       LogError("EVP_PKEY_verify Failed");
+       return CKM_API_ERROR_VERIFICATION_FAILED;
+}
+
+RawBuffer encryptDataAesGcmPacked(
+       const RawBuffer &key,
+       const RawBuffer &data,
+       const RawBuffer &iv,
+       int tagSize,
+       const RawBuffer &aad)
+{
+       auto pair = encryptDataAesGcm(key, data, iv, tagSize, aad);
+       std::copy(pair.second.begin(), pair.second.end(),
+                         std::back_inserter(pair.first));
+       return pair.first;
+}
+
+
+RawBuffer decryptDataAesGcmPacked(
+       const RawBuffer &key,
+       const RawBuffer &data,
+       const RawBuffer &iv,
+       int tagSize,
+       const RawBuffer &aad)
+{
+       if (tagSize > static_cast<int>(data.size()))
+               ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
+
+       auto tagPos = data.data() + data.size() - tagSize;
+       return decryptDataAesGcm(
+                          key,
+                          RawBuffer(data.data(), tagPos),
+                          iv,
+                          RawBuffer(tagPos, data.data() + data.size()),
+                          aad);
+}
+
+} // namespace
+
+
 DataPair generateAKey(const CryptoAlgorithm &algorithm)
 {
        validateParams<IsAsymGeneration>(algorithm);
@@ -610,19 +768,6 @@ std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
        return std::make_pair(result, tag);
 }
 
-RawBuffer encryptDataAesGcmPacked(
-       const RawBuffer &key,
-       const RawBuffer &data,
-       const RawBuffer &iv,
-       int tagSize,
-       const RawBuffer &aad)
-{
-       auto pair = encryptDataAesGcm(key, data, iv, tagSize, aad);
-       std::copy(pair.second.begin(), pair.second.end(),
-                         std::back_inserter(pair.first));
-       return pair.first;
-}
-
 RawBuffer decryptDataAes(
        AlgoType type,
        const RawBuffer &key,
@@ -669,40 +814,14 @@ RawBuffer decryptDataAesGcm(
        return result;
 }
 
-RawBuffer decryptDataAesGcmPacked(
-       const RawBuffer &key,
-       const RawBuffer &data,
-       const RawBuffer &iv,
-       int tagSize,
-       const RawBuffer &aad)
-{
-       if (tagSize > static_cast<int>(data.size()))
-               ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
-
-       auto tagPos = data.data() + data.size() - tagSize;
-       return decryptDataAesGcm(
-                          key,
-                          RawBuffer(data.data(), tagPos),
-                          iv,
-                          RawBuffer(tagPos, data.data() + data.size()),
-                          aad);
-}
-
 RawBuffer symmetricEncrypt(const RawBuffer &key,
                                                   const CryptoAlgorithm &alg,
                                                   const RawBuffer &data)
 {
        validateParams<IsSymEncryption>(alg);
-       AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
-
-       switch (keyType) {
-       case AlgoType::AES_CBC:
-       case AlgoType::AES_CTR:
-       case AlgoType::AES_CFB:
-               return encryptDataAes(keyType, key, data, unpack<RawBuffer>(alg,
-                                                         ParamName::ED_IV));
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
-       case AlgoType::AES_GCM: {
+       if (algo == AlgoType::AES_GCM) {
                int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
                alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
                RawBuffer aad;
@@ -713,13 +832,9 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
                                                                           tagLenBits / 8,
                                                                           aad);
        }
-
-       default:
-               break;
-       }
-
-       ThrowErr(Exc::Crypto::OperationNotSupported,
-                        "symmetric enc: algorithm not recognized");
+       // validateParams<IsSymEncryption> should prevent it
+       assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
+       return encryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
 }
 
 RawBuffer symmetricDecrypt(const RawBuffer &key,
@@ -727,16 +842,9 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                                                   const RawBuffer &data)
 {
        validateParams<IsSymEncryption>(alg);
-       AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
-
-       switch (keyType) {
-       case AlgoType::AES_CBC:
-       case AlgoType::AES_CTR:
-       case AlgoType::AES_CFB:
-               return decryptDataAes(keyType, key, data, unpack<RawBuffer>(alg,
-                                                         ParamName::ED_IV));
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
-       case AlgoType::AES_GCM: {
+       if (algo == AlgoType::AES_GCM) {
                int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
                alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
                RawBuffer aad;
@@ -747,28 +855,23 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                                                                           tagLenBits / 8,
                                                                           aad);
        }
-
-       default:
-               break;
-       }
-
-       ThrowErr(Exc::Crypto::InputParam, "symmetric dec: algorithm not recognized");
+       // validateParams<IsSymEncryption> should prevent it
+       assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
+       return decryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
 }
 
 RawBuffer asymmetricEncrypt(const EvpShPtr &pkey,
                                                        const CryptoAlgorithm &alg,
                                                        const RawBuffer &data)
 {
-       return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey,
-                                                       alg, data);
+       return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey, alg, data);
 }
 
 RawBuffer asymmetricDecrypt(const EvpShPtr &pkey,
                                                        const CryptoAlgorithm &alg,
                                                        const RawBuffer &data)
 {
-       return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey,
-                                                       alg, data);
+       return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey, alg, data);
 }
 
 RawBuffer sign(EVP_PKEY *pkey,
@@ -807,86 +910,6 @@ RawBuffer sign(EVP_PKEY *pkey,
        return digestSignMessage(pkey, message, md_algo, rsa_padding);
 }
 
-RawBuffer signMessage(EVP_PKEY *privKey,
-                                         const RawBuffer &message,
-                                         const int rsa_padding)
-{
-       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) != EVP_PKEY_RSA)
-               ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
-
-       EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
-
-       if (!pctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
-
-       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign_init(pctx.get()));
-
-       /* Set padding algorithm */
-       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
-               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
-
-       /* Finalize the Sign operation */
-       /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
-        * signature. Length is returned in slen */
-       size_t slen;
-
-       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size()));
-
-       /* Allocate memory for the signature based on size in slen */
-       RawBuffer sig(slen);
-
-       OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), sig.data(), &slen, message.data(), message.size()));
-
-       // Set value to return RawData
-       sig.resize(slen);
-       return sig;
-}
-
-RawBuffer digestSignMessage(EVP_PKEY *privKey,
-                                                       const RawBuffer &message,
-                                                       const EVP_MD *md_algo,
-                                                       const int rsa_padding)
-{
-       EVP_PKEY_CTX *pctx = NULL;
-
-       // Create the Message Digest Context
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-       EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
-       if (!mdctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
-#else
-       EvpMdCtxUPtr mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
-       if (!mdctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
-#endif
-
-       OPENSSL_ERROR_HANDLE(EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey));
-
-       /* Set padding algorithm */
-       if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
-               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
-
-       /* Call update with the message */
-       OPENSSL_ERROR_HANDLE(EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size()));
-
-       /* Finalize the DigestSign operation */
-       /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
-        * signature. Length is returned in slen */
-       size_t slen;
-
-       OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), NULL, &slen));
-
-       /* Allocate memory for the signature based on size in slen */
-       RawBuffer sig(slen);
-
-       /* Obtain the signature */
-       OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen));
-
-       // Set value to return RawData
-       sig.resize(slen);
-       return sig;
-}
-
 int verify(EVP_PKEY *pkey,
                   const CryptoAlgorithm &alg,
                   const RawBuffer &message,
@@ -894,16 +917,13 @@ int verify(EVP_PKEY *pkey,
 {
        validateParams<IsSignVerify>(alg);
 
-       int rsa_padding = NOT_DEFINED;
-       const EVP_MD *md_algo = NULL;
-
        HashAlgorithm hashTmp = HashAlgorithm::NONE;
        alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
-       md_algo = getMdAlgo(hashTmp);
+       const EVP_MD *md_algo = getMdAlgo(hashTmp);
 
        RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
        alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
-       rsa_padding = getRsaPadding(rsaPad);
+       int rsa_padding = getRsaPadding(rsaPad);
 
        //
        //    if ((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
@@ -928,135 +948,6 @@ int verify(EVP_PKEY *pkey,
        return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
 }
 
-int verifyMessage(EVP_PKEY *pubKey,
-                                 const RawBuffer &message,
-                                 const RawBuffer &signature,
-                                 const int rsa_padding)
-{
-       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) != EVP_PKEY_RSA)
-               ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
-
-       EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
-
-       if (!pctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
-
-       OPENSSL_ERROR_HANDLE(EVP_PKEY_verify_init(pctx.get()));
-
-       /* Set padding algorithm */
-       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
-               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
-
-       if (OPENSSL_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(),
-                                                                          signature.size(), message.data(), message.size()))
-               return CKM_API_SUCCESS;
-
-       LogError("EVP_PKEY_verify Failed");
-       return CKM_API_ERROR_VERIFICATION_FAILED;
-}
-
-int digestVerifyMessage(EVP_PKEY *pubKey,
-                                               const RawBuffer &message,
-                                               const RawBuffer &signature,
-                                               const EVP_MD *md_algo,
-                                               const int rsa_padding)
-{
-       EVP_PKEY_CTX *pctx = NULL;
-
-       // Create the Message Digest Context
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-       EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
-       if (!mdctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
-#else
-       EvpMdCtxUPtr mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
-       if (!mdctx.get())
-               ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
-#endif
-
-       OPENSSL_ERROR_HANDLE(EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey));
-
-       if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
-               OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
-
-       OPENSSL_ERROR_HANDLE(EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()));
-
-       if (OPENSSL_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(),
-                       const_cast<unsigned char *>(signature.data()), signature.size()))
-               return CKM_API_SUCCESS;
-
-       LogError("EVP_PKEY_verify Failed");
-       return CKM_API_ERROR_VERIFICATION_FAILED;
-}
-
-bool verifyBinaryData(DataType dataType, const RawBuffer &buffer)
-{
-       if (dataType.isSKey()) {
-               switch (buffer.size()) {
-               case 128:
-               case 192:
-               case 256:
-                       LogDebug("AES key verified.");
-                       return true;
-
-               default:
-                       LogError("AES key have wrong size.");
-                       return false;
-               }
-       }
-
-       if (dataType.isKeyPublic()) {
-               BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
-
-               BIO_write(bio.get(), buffer.data(), buffer.size());
-               EVP_PKEY *pkey = d2i_PUBKEY_bio(bio.get(), NULL);
-
-               if (pkey) {
-                       EVP_PKEY_free(pkey);
-                       LogDebug("Verified with d2i_PUBKEY_bio.");
-                       return true;
-               }
-
-               LogError("Key was not verified. Unsupported format.");
-               return false;
-       }
-
-       if (dataType.isKeyPrivate()) {
-               BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
-
-               BIO_write(bio.get(), buffer.data(), buffer.size());
-               EVP_PKEY *pkey = d2i_PrivateKey_bio(bio.get(), NULL);
-
-               if (pkey) {
-                       EVP_PKEY_free(pkey);
-                       LogDebug("Key verified with d2i_PrivateKey_bio." << (void *)pkey);
-                       return true;
-               }
-
-               LogError("Key was not verified. Unsupported format.");
-               return false;
-       }
-
-       if (dataType.isCertificate() || dataType.isChainCert()) {
-               const unsigned char *ptr = reinterpret_cast<const unsigned char *>
-                                                                  (buffer.data());
-               int size = static_cast<int>(buffer.size());
-               X509 *x509 = d2i_X509(NULL, &ptr, size);
-
-               if (x509) {
-                       LogDebug("Cerificate verified with d2i_X509");
-                       X509_free(x509);
-                       return true;
-               }
-
-               LogError("Certificate was not verified. Unsupported format.");
-               return false;
-       }
-
-       LogDebug("Importing binary data...");
-       return true;
-}
-
 } // namespace Internals
 } // namespace SW
 } // namespace Crypto
index 0c984c6..fa8bd93 100644 (file)
 #include <openssl/evp.h>
 #include <sw-backend/obj.h>
 
-#define CKM_CRYPTO_INIT_SUCCESS 1
-#define CKM_CRYPTO_CREATEKEY_SUCCESS 2
-#define CKM_VERIFY_CHAIN_SUCCESS 5
-#define NOT_DEFINED -1
-
 namespace CKM {
 namespace Crypto {
 namespace SW {
@@ -42,11 +37,6 @@ struct Data {
 
 typedef std::pair<Data, Data> DataPair;
 
-DataPair createKeyPairRSA(const int size);
-DataPair createKeyPairDSA(const int size);
-DataPair createKeyPairECDSA(ElipticCurve type1);
-Data     createKeyAES(const int sizeBits);
-
 DataPair generateAKey(const CryptoAlgorithm &algorithm);
 Data generateSKey(const CryptoAlgorithm &algorithm);
 
@@ -100,32 +90,7 @@ int verify(EVP_PKEY *pkey,
                   const RawBuffer &message,
                   const RawBuffer &signature);
 
-const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo);
-int getRsaPadding(const RSAPaddingAlgorithm padAlgo);
-
-RawBuffer signMessage(EVP_PKEY *privKey,
-                                         const RawBuffer &message,
-                                         const int rsa_padding);
-
-RawBuffer digestSignMessage(EVP_PKEY *privKey,
-                                                       const RawBuffer &message,
-                                                       const EVP_MD *md_algo,
-                                                       const int rsa_padding);
-
-int verifyMessage(EVP_PKEY *pubKey,
-                                 const RawBuffer &message,
-                                 const RawBuffer &signature,
-                                 const int rsa_padding);
-
-int digestVerifyMessage(EVP_PKEY *pubKey,
-                                               const RawBuffer &message,
-                                               const RawBuffer &signature,
-                                               const EVP_MD *md_algo,
-                                               const int rsa_padding);
-
-bool verifyBinaryData(DataType dataType, const RawBuffer &buffer);
-
 } // namespace Internals
 } // namespace SW
 } // namespace Crypto
-} // namespace CKM
\ No newline at end of file
+} // namespace CKM
index 2de262c..c740e9a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2020 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.
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
-#include <sw-backend/crypto.h>
+
+#include <unordered_map>
+#include <utility>
+#include <memory>
+#include <exception>
 
 #include <boost_macros_wrapper.h>
+#include <test_common.h>
 
-#include "test_common.h"
+#include <sw-backend/internals.h>
+#include <sw-backend/store.h>
+#include <sw-backend/crypto.h>
+#include <sw-backend/obj.h>
+#include <data-type.h>
+#include <ckm/ckm-key.h>
+#include <ckm/ckm-type.h>
+#include <generic-backend/crypto-params.h>
 
 using namespace CKM;
-using namespace CKM::Crypto::SW::Cipher;
+using namespace CKM::Crypto;
+using namespace CKM::Crypto::SW;
+
+namespace {
+
+Store STORE(CryptoBackend::OpenSSL);
+
+void checkKey(const Token& token, KeyType keyType, const Password& pass)
+{
+       DataType dataType(keyType);
+       BOOST_REQUIRE(token.dataType == dataType);
+
+       GObjUPtr obj;
+       BOOST_REQUIRE_NO_THROW(obj = STORE.getObject(token, pass));
+       BOOST_REQUIRE(obj);
+
+       RawBuffer data = obj->getBinary();
+       BOOST_REQUIRE(!data.empty());
+
+       KeyShPtr key;
+       if (dataType.isSKey())
+               key = Key::createAES(data);
+       else
+               key = Key::create(data);
+
+       BOOST_REQUIRE(key);
+       BOOST_REQUIRE(!key->empty());
+       BOOST_REQUIRE(!key->getDER().empty());
+       BOOST_REQUIRE(key->getType() == keyType);
+}
+
+struct GObjUPtrPair {
+       GObjUPtr prv;
+       GObjUPtr pub;
+};
+
+const GObjUPtrPair& generateObjUPtrPair(AlgoType algo, int param)
+{
+       static std::unordered_map<AlgoType, std::unordered_map<int, GObjUPtrPair>> keyMap;
+
+       auto& algoMap = keyMap[algo];
+       auto it = algoMap.find(param);
+       if (it != algoMap.end())
+               return it->second;
+
+       CryptoAlgorithm gen;
+       gen.setParam(ParamName::ALGO_TYPE, algo);
+       if (algo == AlgoType::ECDSA_GEN)
+               gen.setParam(ParamName::GEN_EC, param);
+       else
+               gen.setParam(ParamName::GEN_KEY_LEN, param);
+       auto keyPair = STORE.generateAKey(gen, "", "");
+
+       GObjUPtrPair pair;
+       BOOST_REQUIRE_NO_THROW(pair.prv = STORE.getObject(keyPair.first, ""));
+       BOOST_REQUIRE_NO_THROW(pair.pub = STORE.getObject(keyPair.second, ""));
+       BOOST_REQUIRE(pair.prv);
+       BOOST_REQUIRE(pair.pub);
+       return algoMap.emplace(param, std::move(pair)).first->second;
+}
+
+struct EvpPtrPair {
+       EvpShPtr prv;
+       EvpShPtr pub;
+};
+
+EvpPtrPair generateEvpPair(AlgoType algo, int param)
+{
+       class AKeyHelper : public AKey {
+       private:
+               using AKey::AKey;
+
+       public:
+               static EvpPtrPair getEvps(const GObjUPtrPair& objPair, DataType prvType, DataType pubType)
+               {
+                       AKeyHelper prv(objPair.prv->getBinary(), prvType);
+                       AKeyHelper pub(objPair.pub->getBinary(), pubType);
+                       return { prv.getEvpShPtr(), pub.getEvpShPtr() };
+               }
+       };
+
+       auto& objs = generateObjUPtrPair(algo, param);
+
+       switch (algo) {
+       default:
+               BOOST_REQUIRE_MESSAGE(algo == AlgoType::RSA_GEN, "Invalid algorithm. Fix the test.");
+               return AKeyHelper::getEvps(objs, DataType::KEY_RSA_PRIVATE, DataType::KEY_RSA_PUBLIC);
+       case AlgoType::DSA_GEN:
+               return AKeyHelper::getEvps(objs, DataType::KEY_DSA_PRIVATE, DataType::KEY_DSA_PUBLIC);
+       case AlgoType::ECDSA_GEN:
+               return AKeyHelper::getEvps(objs, DataType::KEY_ECDSA_PRIVATE, DataType::KEY_ECDSA_PUBLIC);
+       }
+}
+
+GObjUPtr generateAes(int len)
+{
+       CryptoAlgorithm ca;
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       ca.setParam(ParamName::GEN_KEY_LEN, len);
+
+       Token token;
+       BOOST_REQUIRE_NO_THROW(token = STORE.generateSKey(ca, ""));
+
+       GObjUPtr obj;
+       BOOST_REQUIRE_NO_THROW(obj = STORE.getObject(token, ""));
+       BOOST_REQUIRE(obj);
+       return obj;
+}
+
+const RawBuffer X509_CERT = {
+       0x30, 0x82, 0x02, 0xf6, 0x30, 0x82, 0x02, 0x5f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x69,
+       0x63, 0x3b, 0x0d, 0x5c, 0xbf, 0x7a, 0xfb, 0xec, 0xac, 0xac, 0xfc, 0x82, 0x4c, 0xf7, 0xa9, 0x66,
+       0x4a, 0xc3, 0xb1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+       0x05, 0x00, 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+       0x50, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0b, 0x4d, 0x61, 0x7a,
+       0x6f, 0x77, 0x69, 0x65, 0x63, 0x6b, 0x69, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+       0x07, 0x0c, 0x08, 0x57, 0x61, 0x72, 0x73, 0x7a, 0x61, 0x77, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06,
+       0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x31, 0x0b, 0x30,
+       0x09, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x02, 0x49, 0x54, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
+       0x55, 0x04, 0x03, 0x0c, 0x0b, 0x73, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d,
+       0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+       0x10, 0x6e, 0x6f, 0x6e, 0x65, 0x40, 0x73, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x2e, 0x63, 0x6f,
+       0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x34, 0x30, 0x39, 0x31, 0x37, 0x35, 0x33, 0x30,
+       0x39, 0x5a, 0x17, 0x0d, 0x32, 0x35, 0x30, 0x34, 0x30, 0x38, 0x31, 0x37, 0x35, 0x33, 0x30, 0x39,
+       0x5a, 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x50,
+       0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0b, 0x4d, 0x61, 0x7a, 0x6f,
+       0x77, 0x69, 0x65, 0x63, 0x6b, 0x69, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
+       0x0c, 0x08, 0x57, 0x61, 0x72, 0x73, 0x7a, 0x61, 0x77, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+       0x55, 0x04, 0x0a, 0x0c, 0x07, 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x31, 0x0b, 0x30, 0x09,
+       0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x02, 0x49, 0x54, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
+       0x04, 0x03, 0x0c, 0x0b, 0x73, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d, 0x31,
+       0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10,
+       0x6e, 0x6f, 0x6e, 0x65, 0x40, 0x73, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d,
+       0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+       0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xca, 0xf1, 0xe1,
+       0x57, 0x5c, 0x04, 0x45, 0x92, 0x5d, 0xd3, 0x9a, 0xee, 0x72, 0x6b, 0xe9, 0x58, 0x79, 0xdd, 0x30,
+       0xdf, 0x9e, 0xa8, 0x60, 0x38, 0x64, 0x54, 0x0b, 0xc7, 0x3e, 0x90, 0x65, 0x2e, 0xe3, 0x90, 0xa9,
+       0x85, 0xc1, 0x94, 0xee, 0xae, 0x38, 0xcd, 0xfa, 0xaf, 0x11, 0xd8, 0x24, 0x54, 0x12, 0xbe, 0x63,
+       0xa1, 0x81, 0x32, 0xb6, 0xc1, 0xd1, 0x30, 0x0b, 0xa3, 0x6c, 0xca, 0xe1, 0x15, 0x43, 0x22, 0x04,
+       0xdc, 0xf1, 0x4b, 0x24, 0x6e, 0x20, 0x63, 0x88, 0xfe, 0x1c, 0x1c, 0x1f, 0x99, 0x97, 0x8e, 0xb4,
+       0x91, 0x4f, 0xf4, 0xbc, 0xa6, 0x4f, 0x5a, 0xde, 0xf2, 0x5a, 0xaf, 0x60, 0xf3, 0xb9, 0x69, 0xa4,
+       0x4a, 0xff, 0x7f, 0x44, 0x53, 0x1a, 0xb2, 0xa4, 0x91, 0xc5, 0x5a, 0x74, 0x2c, 0x66, 0x28, 0x82,
+       0xeb, 0xe1, 0x9b, 0x52, 0xf7, 0x9e, 0xb7, 0xc5, 0x71, 0xfe, 0x90, 0xa0, 0x25, 0x02, 0x03, 0x01,
+       0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+       0x14, 0x01, 0xae, 0x82, 0xb1, 0x4a, 0x2f, 0xa5, 0xe9, 0x1a, 0x8e, 0x0f, 0x98, 0xd0, 0x19, 0x16,
+       0x32, 0xa0, 0xcd, 0x08, 0xd6, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+       0x80, 0x14, 0x01, 0xae, 0x82, 0xb1, 0x4a, 0x2f, 0xa5, 0xe9, 0x1a, 0x8e, 0x0f, 0x98, 0xd0, 0x19,
+       0x16, 0x32, 0xa0, 0xcd, 0x08, 0xd6, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+       0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+       0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x2d, 0x5f, 0xfa, 0x7e, 0x25, 0xcb,
+       0xce, 0xfa, 0x9d, 0x35, 0xcc, 0x8d, 0xd2, 0x0d, 0x1f, 0xca, 0xa6, 0xc6, 0xb1, 0xce, 0x1f, 0x9e,
+       0x6f, 0xb7, 0xbb, 0xf5, 0x29, 0x85, 0xaa, 0x09, 0x51, 0x52, 0x25, 0xba, 0xad, 0x40, 0xc9, 0x53,
+       0x13, 0xdf, 0x9b, 0xa9, 0x11, 0x8d, 0xd8, 0xba, 0x73, 0x30, 0x19, 0x03, 0x74, 0xd9, 0x06, 0x4a,
+       0xb0, 0x9e, 0xb0, 0x8d, 0x65, 0xfc, 0x55, 0x12, 0xb6, 0x3a, 0x9d, 0xa4, 0x11, 0x8c, 0x8b, 0x57,
+       0xea, 0x14, 0x33, 0x43, 0xc8, 0x15, 0xe4, 0x2c, 0x90, 0xc7, 0xe4, 0x70, 0x0c, 0x47, 0x77, 0xa2,
+       0x85, 0xa8, 0xc7, 0x21, 0xab, 0x1d, 0x19, 0x67, 0x00, 0x7e, 0x3f, 0x82, 0xca, 0xe9, 0x35, 0x29,
+       0xc4, 0xc8, 0x12, 0x40, 0x5f, 0x75, 0x84, 0x7a, 0x6b, 0xc0, 0xb8, 0x83, 0x4e, 0x15, 0x6e, 0x0e,
+       0x8c, 0xd2, 0xa1, 0x23, 0x16, 0x5e, 0x54, 0x4c, 0xcc, 0x26
+};
+
+struct CertHelper : public Cert {
+       using Cert::Cert;
+       using Cert::getEvpShPtr;
+};
+
+} // namespace
+
+BOOST_AUTO_TEST_SUITE(SW_TEST)
+
+POSITIVE_TEST_CASE(generateAKey)
+{
+       static const std::unordered_map<AlgoType, std::pair<KeyType, KeyType>> algo2types = {
+               { AlgoType::RSA_GEN, { KeyType::KEY_RSA_PRIVATE, KeyType::KEY_RSA_PUBLIC } },
+               { AlgoType::DSA_GEN, { KeyType::KEY_DSA_PRIVATE, KeyType::KEY_DSA_PUBLIC } },
+               { AlgoType::ECDSA_GEN, { KeyType::KEY_ECDSA_PRIVATE, KeyType::KEY_ECDSA_PUBLIC } }
+       };
+
+       CryptoAlgorithm ca;
+
+       auto testAKey = [&](const Password& prvPass = "", const Password& pubPass = "")
+       {
+               AlgoType algo;
+               ca.getParam(ParamName::ALGO_TYPE, algo);
+               auto& types = algo2types.at(algo);
+
+               TokenPair tokenPair;
+               BOOST_REQUIRE_NO_THROW(tokenPair = STORE.generateAKey(ca, prvPass, pubPass));
+               checkKey(tokenPair.first, types.first, prvPass);
+               checkKey(tokenPair.second, types.second, pubPass);
+       };
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
+       ca.setParam(ParamName::GEN_KEY_LEN, 1024);
+       testAKey();
+       testAKey("prvpass");
+       testAKey("", "pubpass");
+       testAKey("prvpass", "pubpass");
+       ca.setParam(ParamName::GEN_KEY_LEN, 2048);
+       testAKey();
+       ca.setParam(ParamName::GEN_KEY_LEN, 4096);
+       testAKey();
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::DSA_GEN);
+       for (int keyLen : { 1024, 2048, 3072, 4096 }) {
+               ca.setParam(ParamName::GEN_KEY_LEN, keyLen);
+               testAKey();
+       }
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
+       ca.setParam(ParamName::GEN_EC, ElipticCurve::prime192v1);
+       testAKey();
+       ca.setParam(ParamName::GEN_EC, ElipticCurve::prime256v1);
+       testAKey();
+       ca.setParam(ParamName::GEN_EC, ElipticCurve::secp384r1);
+       testAKey();
+}
+
+NEGATIVE_TEST_CASE(generateAKey)
+{
+       std::unique_ptr<CryptoAlgorithm> ca(new CryptoAlgorithm());
+
+       auto invalidGen = [&]
+       {
+               BOOST_REQUIRE_THROW(STORE.generateAKey(*ca, "", ""), Exc::Crypto::InputParam);
+       };
+
+       invalidGen();
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
+       invalidGen();
+
+       for (int keyLen : { 0, 512, 1023, 1025, 3072, 4097, 8192 }) {
+               ca->setParam(ParamName::GEN_KEY_LEN, keyLen);
+               invalidGen();
+       }
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::DSA_GEN);
+
+       for (int keyLen : { 0, 512, 1023, 1025, 4097, 8192 }) {
+               ca->setParam(ParamName::GEN_KEY_LEN, keyLen);
+               invalidGen();
+       }
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
+       invalidGen();
+       ca->setParam(ParamName::GEN_EC, static_cast<ElipticCurve>(-1));
+       invalidGen();
+       ca->setParam(ParamName::GEN_EC, static_cast<ElipticCurve>(3));
+       invalidGen();
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       ca->setParam(ParamName::GEN_KEY_LEN, 128);
+       invalidGen();
+       ca->setParam(ParamName::GEN_KEY_LEN, 1024);
+       invalidGen();
+
+
+       ca.reset(new CryptoAlgorithm());
+       ca->setParam(ParamName::GEN_KEY_LEN, 1024);
+       ca->setParam(ParamName::GEN_EC, ElipticCurve::prime192v1);
+       invalidGen();
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       invalidGen();
+}
+
+POSITIVE_TEST_CASE(generateSKey)
+{
+       CryptoAlgorithm ca;
+
+       auto testSKey = [&](const Password& pass = "")
+       {
+               Token token;
+               BOOST_REQUIRE_NO_THROW(token = STORE.generateSKey(ca, pass));
+               checkKey(token, KeyType::KEY_AES, pass);
+       };
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       ca.setParam(ParamName::GEN_KEY_LEN, 128);
+       testSKey();
+       testSKey("pass");
+       ca.setParam(ParamName::GEN_KEY_LEN, 192);
+       testSKey();
+       ca.setParam(ParamName::GEN_KEY_LEN, 256);
+       testSKey();
+}
+
+NEGATIVE_TEST_CASE(generateSKey)
+{
+       std::unique_ptr<CryptoAlgorithm> ca(new CryptoAlgorithm());
+
+       auto invalidGen = [&]
+       {
+               BOOST_REQUIRE_THROW(STORE.generateSKey(*ca, ""), Exc::Crypto::InputParam);
+       };
+
+       invalidGen();
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       invalidGen();
+
+       for (int keyLen : { 0, 64, 127, 129, 257, 512 }) {
+               ca->setParam(ParamName::GEN_KEY_LEN, keyLen);
+               invalidGen();
+       }
+
+       ca->setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
+       ca->setParam(ParamName::GEN_KEY_LEN, 128);
+       invalidGen();
+       ca->setParam(ParamName::GEN_KEY_LEN, 1024);
+       invalidGen();
+
+       ca.reset(new CryptoAlgorithm());
+       ca->setParam(ParamName::GEN_KEY_LEN, 128);
+       invalidGen();
+}
+
+POSITIVE_TEST_CASE(symmetricEncryptDecrypt)
+{
+       const GObjUPtr keys[] = { generateAes(128), generateAes(192), generateAes(256) };
+       const auto data = createRandom(128);
+       CryptoAlgorithm ca;
+
+       auto encryptDecrypt = [&]
+       {
+               for (const auto& key : keys) {
+                       RawBuffer encrypted, decrypted;
+                       BOOST_REQUIRE_NO_THROW(encrypted = key->encrypt(ca, data));
+                       BOOST_REQUIRE(encrypted.size() >= data.size());
+                       BOOST_REQUIRE_NO_THROW(decrypted = key->decrypt(ca, encrypted));
+                       BOOST_REQUIRE(decrypted == data);
+               }
+       };
+
+       ca.setParam(ParamName::ED_IV, createRandom(Params::DEFAULT_AES_IV_LEN));
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CTR);
+       encryptDecrypt();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CBC);
+       encryptDecrypt();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CFB);
+       encryptDecrypt();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
+       ca.setParam(ParamName::ED_AAD, createRandom(42));
+       encryptDecrypt();
+}
+
+NEGATIVE_TEST_CASE(symmetricEncryptDecrypt)
+{
+       const auto key = generateAes(128);
+       const auto data = createRandom(128);
+       const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
+       CryptoAlgorithm ca;
+
+       // no algo
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+
+       // wrong algo
+       ca.setParam(ParamName::ED_IV, iv);
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ALGO_TYPE, static_cast<AlgoType>(0));
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+
+       for (auto algo : { AlgoType::AES_CTR, AlgoType::AES_CBC, AlgoType::AES_CFB }) {
+               CryptoAlgorithm ca2;
+               ca2.setParam(ParamName::ALGO_TYPE, algo);
+
+               // no iv
+               BOOST_REQUIRE_THROW(key->encrypt(ca2, data), Exc::Crypto::InputParam);
+
+               // short iv
+               ca2.setParam(ParamName::ED_IV, RawBuffer(1));
+               BOOST_REQUIRE_THROW(key->encrypt(ca2, data), Exc::Crypto::InputParam);
+               ca2.setParam(ParamName::ED_IV, iv);
+
+               // short key
+               SKey shortKey(createRandom(128/8 - 1), DataType::KEY_AES);
+               BOOST_REQUIRE_THROW(shortKey.encrypt(ca2, data), Exc::Crypto::InternalError);
+
+               // proper encrypt
+               auto encrypted = key->encrypt(ca2, data);
+
+               CryptoAlgorithm ca3;
+
+               // no algo
+               BOOST_REQUIRE_THROW(key->decrypt(ca3, encrypted), Exc::Crypto::InputParam);
+               ca3.setParam(ParamName::ALGO_TYPE, algo);
+
+               // no iv
+               BOOST_REQUIRE_THROW(key->decrypt(ca3, encrypted), Exc::Crypto::InputParam);
+
+               // short iv
+               ca3.setParam(ParamName::ED_IV, RawBuffer(15));
+               BOOST_REQUIRE_THROW(key->decrypt(ca3, encrypted), Exc::Crypto::InputParam);
+               ca3.setParam(ParamName::ED_IV, iv);
+
+               // short key
+               BOOST_REQUIRE_THROW(shortKey.decrypt(ca3, encrypted), Exc::Crypto::InternalError);
+       }
+}
+
+NEGATIVE_TEST_CASE(symmetricEncryptDecryptGcm)
+{
+       const auto key = generateAes(128);
+       const auto data = createRandom(128);
+       const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
+       const auto aad = createRandom(42);
+       CryptoAlgorithm ca;
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
+
+       // no iv
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+
+       // short iv
+       ca.setParam(ParamName::ED_IV, RawBuffer(1));
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InternalError);
+       ca.setParam(ParamName::ED_IV, iv);
 
-BOOST_AUTO_TEST_SUITE(SW_BACKEND_TEST)
+       // short key
+       SKey shortKey(createRandom(15), DataType::KEY_AES);
+       BOOST_REQUIRE_THROW(shortKey.encrypt(ca, data), Exc::Crypto::InternalError);
 
-BOOST_AUTO_TEST_SUITE(CRYPTO)
+       // wrong tag length
+       for (int tagLen : { 0, 16, 31, 48, 127, 256, 129 }) {
+               ca.setParam(ParamName::ED_TAG_LEN, tagLen);
+               BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       }
+       ca.setParam(ParamName::ED_TAG_LEN, 128);
 
-POSITIVE_TEST_CASE(constructs)
+       // proper encrypt
+       ca.setParam(ParamName::ED_AAD, aad);
+       auto encrypted = key->encrypt(ca, data);
+
+       CryptoAlgorithm ca2;
+
+       // no algo
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+       ca2.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
+       ca2.setParam(ParamName::ED_AAD, aad);
+
+       // no iv
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+
+       // short iv
+       ca2.setParam(ParamName::ED_IV, RawBuffer(1));
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InternalError);
+       ca2.setParam(ParamName::ED_IV, iv);
+
+       // short key
+       BOOST_REQUIRE_THROW(shortKey.decrypt(ca2, encrypted), Exc::Crypto::InternalError);
+
+       // wrong key
+       auto wrongBuffer = key->getBinary();
+       wrongBuffer[0] ^= 0x1;
+       SKey wrongKey(std::move(wrongBuffer), DataType::KEY_AES);
+
+       BOOST_REQUIRE_THROW(wrongKey.decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+
+       // wrong iv
+       auto wrongIv = iv;
+       wrongIv[0] ^= 0x1;
+       ca2.setParam(ParamName::ED_IV, wrongIv);
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+       ca2.setParam(ParamName::ED_IV, iv);
+
+       // wrong ciphertext
+       auto wrongCiphertext = encrypted;
+       wrongCiphertext[0] ^= 0x1;
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, wrongCiphertext), Exc::Crypto::InputParam);
+
+       // wrong tag (tag is appended to ciphertext)
+       wrongCiphertext = encrypted;
+       wrongCiphertext.back() ^= 0x1;
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, wrongCiphertext), Exc::Crypto::InputParam);
+
+       // wrong aad
+       auto wrongAad = aad;
+       wrongAad[0] ^= 0x1;
+       ca2.setParam(ParamName::ED_AAD, wrongAad);
+       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+}
+
+NEGATIVE_TEST_CASE(symmetricEncryptDecryptCtr)
+{
+       const auto key = generateAes(128);
+       const auto data = createRandom(128);
+       const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
+       CryptoAlgorithm ca;
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CTR);
+       ca.setParam(ParamName::ED_IV, iv);
+
+       // wrong ctr len
+       ca.setParam(ParamName::ED_CTR_LEN, 0);
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ED_CTR_LEN, 127);
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ED_CTR_LEN, 129);
+       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+
+       ca.setParam(ParamName::ED_CTR_LEN, 128);
+       auto encrypted = key->encrypt(ca, data);
+
+       // wrong ctr len
+       ca.setParam(ParamName::ED_CTR_LEN, 0);
+       BOOST_REQUIRE_THROW(key->decrypt(ca, encrypted), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ED_CTR_LEN, 127);
+       BOOST_REQUIRE_THROW(key->decrypt(ca, encrypted), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ED_CTR_LEN, 129);
+       BOOST_REQUIRE_THROW(key->decrypt(ca, encrypted), Exc::Crypto::InputParam);
+}
+
+NEGATIVE_TEST_CASE(symmetricEncryptDecryptCbc)
+{
+       const auto key = generateAes(128);
+       const auto data = createRandom(128);
+       const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
+       CryptoAlgorithm ca;
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CBC);
+       ca.setParam(ParamName::ED_IV, iv);
+
+       auto encrypted = key->encrypt(ca, data);
+
+       // broken padding
+       encrypted.back() ^= 0x1;
+       BOOST_REQUIRE_THROW(key->decrypt(ca, encrypted), Exc::Crypto::InputParam);
+}
+
+POSITIVE_TEST_CASE(asymmetricEncryptDecrypt)
+{
+       constexpr int KEY_BIT_LEN = 1024;
+       auto& rsaKeys = generateObjUPtrPair(AlgoType::RSA_GEN, KEY_BIT_LEN);
+
+       CryptoAlgorithm enc;
+       enc.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+
+       RawBuffer encrypted;
+       RawBuffer decrypted;
+
+       auto encryptDecrypt = [&](const RawBuffer& input)
+       {
+               BOOST_REQUIRE_NO_THROW(encrypted = rsaKeys.pub->encrypt(enc, input));
+               BOOST_REQUIRE(encrypted.size() == KEY_BIT_LEN / 8);
+
+               BOOST_REQUIRE_NO_THROW(decrypted = rsaKeys.prv->decrypt(enc, encrypted));
+               BOOST_REQUIRE(decrypted == input);
+       };
+
+       encryptDecrypt(createRandom(KEY_BIT_LEN / 8 - 42));
+       encryptDecrypt(createRandom(KEY_BIT_LEN / 8 - 42 - 1));
+       encryptDecrypt(RawBuffer());
+}
+
+NEGATIVE_TEST_CASE(asymmetricEncryptDecrypt)
+{
+       constexpr int KEY_BIT_LEN = 1024;
+       auto& rsaKeys = generateObjUPtrPair(AlgoType::RSA_GEN, KEY_BIT_LEN);
+       auto& dsaKeys = generateObjUPtrPair(AlgoType::DSA_GEN, KEY_BIT_LEN);
+       const auto data = createRandom(KEY_BIT_LEN / 8 - 42);
+       auto longData = data;
+       longData.push_back(0);
+
+       CryptoAlgorithm enc;
+       enc.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+       BOOST_REQUIRE_THROW(Internals::asymmetricEncrypt(EvpShPtr(), enc, data),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(dsaKeys.pub->encrypt(enc, data), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc, longData), Exc::Crypto::InputParam);
+
+       CryptoAlgorithm enc2;
+       enc2.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_SV);
+       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc2, data), Exc::Crypto::InputParam);
+
+       CryptoAlgorithm enc3;
+       enc3.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CBC);
+       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc3, data), Exc::Crypto::InputParam);
+
+       CryptoAlgorithm enc4;
+       enc4.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+       enc4.setParam(ParamName::ED_LABEL, RawBuffer(64));
+       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc4, data), Exc::Crypto::InputParam);
+
+       RawBuffer encrypted;
+       BOOST_REQUIRE_NO_THROW(encrypted = rsaKeys.pub->encrypt(enc, data));
+       RawBuffer shortEncrypted = encrypted;
+       shortEncrypted.pop_back();
+       RawBuffer longEncrypted = encrypted;
+       longEncrypted.push_back(0);
+
+       BOOST_REQUIRE_THROW(Internals::asymmetricDecrypt(EvpShPtr(), enc, encrypted),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaKeys.pub->decrypt(enc, encrypted), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(dsaKeys.prv->decrypt(enc, encrypted), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaKeys.prv->decrypt(enc, RawBuffer()), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaKeys.prv->decrypt(enc, shortEncrypted), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaKeys.prv->decrypt(enc, longEncrypted), Exc::Crypto::InputParam);
+
+       BOOST_REQUIRE_THROW(rsaKeys.prv->decrypt(enc2, encrypted), Exc::Crypto::InputParam);
+
+       BOOST_REQUIRE_THROW(rsaKeys.prv->decrypt(enc3, encrypted), Exc::Crypto::InputParam);
+}
+
+POSITIVE_TEST_CASE(sign)
+{
+       auto message = createRandom(1234);
+       RawBuffer signature;
+
+       auto signVerify = [&](AlgoType keyType,
+                             auto keyParam,
+                             HashAlgorithm hash,
+                             RSAPaddingAlgorithm padding = RSAPaddingAlgorithm::NONE)
+       {
+               CryptoAlgorithm algo;
+               algo.setParam(ParamName::SV_HASH_ALGO, hash);
+               if (keyType == AlgoType::RSA_GEN)
+                       algo.setParam(ParamName::SV_RSA_PADDING, padding);
+
+               auto& keys = generateObjUPtrPair(keyType, static_cast<int>(keyParam));
+               BOOST_REQUIRE_NO_THROW(signature = keys.prv->sign(algo, message));
+               if (keyType == AlgoType::RSA_GEN) {
+                       BOOST_REQUIRE(signature.size() * 8 == static_cast<size_t>(keyParam));
+               } else {
+                       BOOST_REQUIRE(!signature.empty());
+               }
+
+               int ret = keys.pub->verify(algo, message, signature);
+               BOOST_REQUIRE(CKM_API_SUCCESS == ret);
+       };
+
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::SHA1, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::SHA1, RSAPaddingAlgorithm::X931);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::SHA256, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::SHA384, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::SHA512, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 2048, HashAlgorithm::SHA1, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 4096, HashAlgorithm::SHA1, RSAPaddingAlgorithm::PKCS1);
+
+       signVerify(AlgoType::DSA_GEN, 1024, HashAlgorithm::SHA1);
+       signVerify(AlgoType::DSA_GEN, 1024, HashAlgorithm::SHA256);
+       signVerify(AlgoType::DSA_GEN, 1024, HashAlgorithm::SHA384);
+       signVerify(AlgoType::DSA_GEN, 1024, HashAlgorithm::SHA512);
+       signVerify(AlgoType::DSA_GEN, 2048, HashAlgorithm::SHA1);
+       signVerify(AlgoType::DSA_GEN, 3072, HashAlgorithm::SHA1);
+       signVerify(AlgoType::DSA_GEN, 4096, HashAlgorithm::SHA1);
+
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::prime192v1, HashAlgorithm::SHA1);
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::prime192v1, HashAlgorithm::SHA256);
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::prime192v1, HashAlgorithm::SHA384);
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::prime192v1, HashAlgorithm::SHA512);
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::prime256v1, HashAlgorithm::SHA1);
+       signVerify(AlgoType::ECDSA_GEN, ElipticCurve::secp384r1, HashAlgorithm::SHA1);
+
+       // no hash + no padding
+       message[0] = 0; // make sure it's smaller than the modulus
+       message.resize(4096/8);
+       signVerify(AlgoType::RSA_GEN, 4096, HashAlgorithm::NONE);
+       message.resize(2048/8);
+       signVerify(AlgoType::RSA_GEN, 2048, HashAlgorithm::NONE);
+       message.resize(1024/8);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::NONE);
+
+       // no hash + padding
+       message.resize(512/8);
+       signVerify(AlgoType::RSA_GEN, 4096, HashAlgorithm::NONE, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 2048, HashAlgorithm::NONE, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::NONE, RSAPaddingAlgorithm::PKCS1);
+       signVerify(AlgoType::RSA_GEN, 1024, HashAlgorithm::NONE, RSAPaddingAlgorithm::X931);
+}
+
+NEGATIVE_TEST_CASE(sign)
+{
+       auto keysRsa = generateEvpPair(AlgoType::RSA_GEN, 1024);
+       auto keysDsa = generateEvpPair(AlgoType::DSA_GEN, 1024);
+       auto keysEcdsa = generateEvpPair(AlgoType::ECDSA_GEN,
+                                        static_cast<int>(ElipticCurve::prime192v1));
+
+       const auto longMsg = createRandom(1234);
+       auto equalMsg = longMsg;
+       equalMsg.resize(1024/8);
+       auto shortMsg = longMsg;
+       shortMsg.resize(1024/8 - 1); // padding requires 2/11 bytes
+       auto paddingMsg = longMsg;
+       paddingMsg.resize(1024/8 - 11);
+
+       CryptoAlgorithm signRsa;
+       signRsa.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_SV);
+       signRsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA1);
+       signRsa.setParam(ParamName::SV_RSA_PADDING, RSAPaddingAlgorithm::PKCS1);
+
+       CryptoAlgorithm signDsa;
+       signDsa.setParam(ParamName::ALGO_TYPE, AlgoType::DSA_SV);
+       signDsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA1);
+
+       CryptoAlgorithm signEcdsa;
+       signEcdsa.setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_SV);
+       signEcdsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA1);
+
+       // wrong key
+       BOOST_REQUIRE_THROW(Internals::sign(nullptr, signRsa, longMsg), Exc::Crypto::InternalError);
+       BOOST_REQUIRE_THROW(Internals::sign(keysRsa.pub.get(), signRsa, longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysDsa.pub.get(), signDsa, longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysEcdsa.pub.get(), signEcdsa, longMsg),
+                           Exc::Crypto::InputParam);
+
+       // empty crypto
+       BOOST_REQUIRE_THROW(Internals::sign(keysRsa.prv.get(), CryptoAlgorithm(), longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysDsa.prv.get(), CryptoAlgorithm(), longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysEcdsa.prv.get(), CryptoAlgorithm(), longMsg),
+                           Exc::Crypto::InputParam);
+
+       // wrong crypto
+       CryptoAlgorithm encrypt;
+       encrypt.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
+       BOOST_REQUIRE_THROW(Internals::sign(keysRsa.prv.get(), encrypt, longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysRsa.pub.get(), encrypt, longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysDsa.prv.get(), encrypt, longMsg),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::sign(keysEcdsa.prv.get(), encrypt, longMsg),
+                           Exc::Crypto::InputParam);
+
+       // Obj API with wrong key type
+       AKey wrongKey(createRandom(16), DataType::KEY_AES);
+       BOOST_REQUIRE_THROW(wrongKey.sign(signRsa, shortMsg), Exc::Crypto::InputParam);
+
+       auto invalidSign = [&](const RawBuffer& msg,
+                              AlgoType signAlgo,
+                              HashAlgorithm hash,
+                              RSAPaddingAlgorithm padding = RSAPaddingAlgorithm::NONE)
+       {
+               EvpPtrPair keys;
+               switch (signAlgo) {
+               case AlgoType::RSA_SV:
+                       keys = keysRsa;
+                       break;
+               case AlgoType::DSA_SV:
+                       keys = keysDsa;
+                       break;
+               case AlgoType::ECDSA_SV:
+                       keys = keysEcdsa;
+                       break;
+               default:
+                       BOOST_FAIL("Invalid algorithm. Fix the test.");
+               }
+
+               CryptoAlgorithm ca;
+               ca.setParam(ParamName::ALGO_TYPE, signAlgo);
+               ca.setParam(ParamName::SV_HASH_ALGO, hash);
+               if (padding != RSAPaddingAlgorithm::NONE)
+                       ca.setParam(ParamName::SV_RSA_PADDING, padding);
+
+               BOOST_REQUIRE_THROW(Internals::sign(keys.prv.get(), ca, msg), Exc::Crypto::InputParam);
+       };
+
+       HashAlgorithm wrongHash = static_cast<HashAlgorithm>(-1);
+
+       // out of range hash
+       invalidSign(paddingMsg, AlgoType::RSA_SV, wrongHash, RSAPaddingAlgorithm::PKCS1);
+       invalidSign(shortMsg, AlgoType::DSA_SV, wrongHash);
+       invalidSign(shortMsg, AlgoType::ECDSA_SV, wrongHash);
+
+       // out of range padding
+       invalidSign(shortMsg,
+                   AlgoType::RSA_SV,
+                   HashAlgorithm::SHA1,
+                   static_cast<RSAPaddingAlgorithm>(-1));
+
+       // no hash + padding + too long message
+       invalidSign(longMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::PKCS1);
+       invalidSign(longMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::X931);
+       invalidSign(shortMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::PKCS1);
+       invalidSign(shortMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::X931);
+
+       // no hash forbidden
+       invalidSign(shortMsg, AlgoType::DSA_SV, HashAlgorithm::NONE);
+       invalidSign(shortMsg, AlgoType::ECDSA_SV, HashAlgorithm::NONE);
+
+       // non-none hash + no padding forbidden
+       invalidSign(equalMsg, AlgoType::RSA_SV, HashAlgorithm::SHA256, RSAPaddingAlgorithm::NONE);
+
+       // no hash + no padding + invalid msg length
+       invalidSign(paddingMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::NONE);
+       invalidSign(shortMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::NONE);
+       invalidSign(longMsg, AlgoType::RSA_SV, HashAlgorithm::NONE, RSAPaddingAlgorithm::NONE);
+
+       auto signature = Internals::sign(keysRsa.prv.get(), signRsa, longMsg);
+
+       BOOST_REQUIRE_THROW(Internals::verify(nullptr, signRsa, longMsg, signature),
+                           Exc::Crypto::InternalError);
+
+       // wrong crypto
+       BOOST_REQUIRE_THROW(Internals::verify(keysRsa.pub.get(), CryptoAlgorithm(), longMsg, signature),
+                           Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(Internals::verify(keysRsa.pub.get(), encrypt, longMsg, signature),
+                           Exc::Crypto::InputParam);
+
+       CryptoAlgorithm verifyAlgo;
+       verifyAlgo.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_SV);
+       auto invalidVerify = [&](HashAlgorithm hash, RSAPaddingAlgorithm padding)
+       {
+               verifyAlgo.setParam(ParamName::SV_HASH_ALGO, hash);
+               verifyAlgo.setParam(ParamName::SV_RSA_PADDING, padding);
+
+               BOOST_REQUIRE_THROW(Internals::verify(keysRsa.prv.get(), verifyAlgo, longMsg, signature),
+                                   Exc::Crypto::InputParam);
+       };
+
+       // out of range hash
+       invalidVerify(wrongHash, RSAPaddingAlgorithm::PKCS1);
+
+       // out of range padding
+       invalidVerify(HashAlgorithm::SHA1, static_cast<RSAPaddingAlgorithm>(-1));
+
+       // non-none hash + no padding forbidden
+       invalidVerify(HashAlgorithm::SHA1, RSAPaddingAlgorithm::NONE);
+
+       auto verificationFailed = [&](EVP_PKEY* key,
+                                     const CryptoAlgorithm& algo,
+                                     const RawBuffer& msg,
+                                     const RawBuffer& sgn)
+       {
+               int ret = Internals::verify(key, algo, msg, sgn);
+               BOOST_REQUIRE(ret == CKM_API_ERROR_VERIFICATION_FAILED);
+       };
+
+       auto wrongSignature = signature;
+       wrongSignature.pop_back();
+       verificationFailed(keysDsa.pub.get(), signDsa, longMsg, signature);
+       verificationFailed(keysEcdsa.pub.get(), signEcdsa, longMsg, signature);
+       verificationFailed(keysRsa.pub.get(), signRsa, longMsg, wrongSignature);
+       verificationFailed(keysRsa.pub.get(), signRsa, equalMsg, signature);
+
+       // different padding
+       signRsa.setParam(ParamName::SV_RSA_PADDING, RSAPaddingAlgorithm::X931);
+       verificationFailed(keysRsa.pub.get(), signRsa, longMsg, signature);
+       signRsa.setParam(ParamName::SV_RSA_PADDING, RSAPaddingAlgorithm::NONE);
+       signRsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::NONE);
+       verificationFailed(keysRsa.pub.get(), signRsa, equalMsg, signature);
+       signRsa.setParam(ParamName::SV_RSA_PADDING, RSAPaddingAlgorithm::PKCS1);
+
+       // different hash
+       signRsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA256);
+       verificationFailed(keysRsa.pub.get(), signRsa, longMsg, signature);
+       signRsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA384);
+       verificationFailed(keysRsa.pub.get(), signRsa, longMsg, signature);
+       signRsa.setParam(ParamName::SV_HASH_ALGO, HashAlgorithm::SHA512);
+       verificationFailed(keysRsa.pub.get(), signRsa, longMsg, signature);
+}
+
+POSITIVE_TEST_CASE(importGetObjectDestroy)
 {
-       BOOST_REQUIRE_NO_THROW(AesCbcEncryption128(createRandom(16), createRandom(16)));
+       const auto buffer = createRandom(16);
+       Data data(DataType::BINARY_DATA, buffer);
+       EncryptionParams ep;
+       Token token;
+       BOOST_REQUIRE_NO_THROW(token = STORE.import(data, "pass", ep));
+       BOOST_REQUIRE(token.backendId == CryptoBackend::OpenSSL);
+       BOOST_REQUIRE(token.dataType == data.type);
+       BOOST_REQUIRE(!token.data.empty());
+
+       GObjUPtr obj;
+       BOOST_REQUIRE_NO_THROW(obj = STORE.getObject(token, "pass"));
+       BOOST_REQUIRE(obj);
+       BOOST_REQUIRE(obj->getBinary() == buffer);
+
+       BOOST_REQUIRE_NO_THROW(STORE.destroy(token));
 }
 
-NEGATIVE_TEST_CASE(constructs)
+NEGATIVE_TEST_CASE(import)
 {
-       BOOST_REQUIRE_THROW(AesCbcEncryption128(createRandom(16), createRandom(5)),
-                                               Exc::Crypto::InternalError);
-       BOOST_REQUIRE_THROW(AesCbcEncryption128(createRandom(17), createRandom(16)),
-                                               Exc::Crypto::InternalError);
+       Data data(DataType::BINARY_DATA, createRandom(16));
+       EncryptionParams ep;
+       ep.iv = createRandom(16);
+       BOOST_REQUIRE_THROW(STORE.import(data, "pass", ep), Exc::Crypto::OperationNotSupported);
 }
 
-POSITIVE_TEST_CASE(encryption_cbc)
+NEGATIVE_TEST_CASE(getObject)
 {
-       AesCbcEncryption128 cipher(createRandom(16), createRandom(16));
+       Data data(DataType::BINARY_DATA, createRandom(16));
+       EncryptionParams ep;
+       Token token;
+       BOOST_REQUIRE_NO_THROW(token = STORE.import(data, "pass", ep));
+
+       BOOST_REQUIRE_THROW(STORE.getObject(token, "wrongpass"), Exc::Crypto::AuthenticationFailed);
 
-       BOOST_REQUIRE_NO_THROW(cipher.Append(createRandom(10)));
-       BOOST_REQUIRE_NO_THROW(cipher.Finalize());
+       token.backendId = CryptoBackend::TrustZone;
+       BOOST_REQUIRE_THROW(STORE.getObject(token, "pass"), Exc::Crypto::WrongBackend);
 }
 
-POSITIVE_TEST_CASE(encryption_gcm)
+POSITIVE_TEST_CASE(certImportGetObject)
 {
-       AesGcmEncryption128 cipher(createRandom(16), createRandom(16));
+       CertHelper cert(X509_CERT, DataType::CERTIFICATE);
+       EvpShPtr evp, evp2;
+       BOOST_REQUIRE_NO_THROW(evp = cert.getEvpShPtr());
+       BOOST_REQUIRE(evp);
+       BOOST_REQUIRE_NO_THROW(evp2 = cert.getEvpShPtr());
+       BOOST_REQUIRE(evp2.get() == evp.get());
+
+       EncryptionParams ep;
+       Data data(DataType::CERTIFICATE, cert.getBinary());
+       Token token;
+       BOOST_REQUIRE_NO_THROW(token = STORE.import(data, "", ep));
+       BOOST_REQUIRE(token.dataType == DataType::CERTIFICATE);
 
-       BOOST_REQUIRE_NO_THROW(cipher.AppendAAD(createRandom(10)));
-       BOOST_REQUIRE_NO_THROW(cipher.Append(createRandom(10)));
-       BOOST_REQUIRE_NO_THROW(cipher.Finalize());
+       GObjUPtr obj;
+       BOOST_REQUIRE_NO_THROW(obj = STORE.getObject(token, ""));
+       BOOST_REQUIRE(obj);
 }
 
-BOOST_AUTO_TEST_SUITE_END() // CRYPTO
+NEGATIVE_TEST_CASE(cert)
+{
+       RawBuffer wrongX509 = X509_CERT;
+       wrongX509.pop_back();
+       CertHelper cert(wrongX509, DataType::CERTIFICATE);
+
+       BOOST_REQUIRE_THROW(cert.getEvpShPtr(), Exc::Crypto::InternalError);
+}
 
-BOOST_AUTO_TEST_SUITE_END() // SW_BACKEND_TEST
+BOOST_AUTO_TEST_SUITE_END()