#include <exception>
#include <utility>
#include <algorithm>
+#include <cassert>
#include <openssl/evp.h>
#include <openssl/obj_mac.h>
return validators;
};
-ValidatorMap g_validators = initValidators();
+const ValidatorMap g_validators = initValidators();
template <typename TypeCheck>
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;
{
validateParams<IsAsymEncryption>(alg);
+ if (!pkey)
+ ThrowErr(Exc::Crypto::InputParam, logPrefix, "no key");
+
RSA *rsa = EVP_PKEY_get1_RSA(pkey.get());
if (!rsa)
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;
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);
{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);
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;
case ElipticCurve::secp384r1:
ecCurve = NID_secp384r1;
break;
-
- default:
- ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
}
/* Create the context for generating the parameters */
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;
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);
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,
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;
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,
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;
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,
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,
{
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) &&
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
/*
- * 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()