Improve argument checking 21/318821/7 tizen
authorJakub Wlostowski <j.wlostowski@samsung.com>
Wed, 9 Oct 2024 08:33:04 +0000 (10:33 +0200)
committerJakub Wlostowski <j.wlostowski@samsung.com>
Wed, 23 Oct 2024 09:29:10 +0000 (11:29 +0200)
Change-Id: I0a33791f77795985a1402ed32270a920a39d2144

src/manager/crypto/generic-backend/algo-validation.h
src/manager/crypto/sw-backend/internals.cpp
src/manager/crypto/tz-backend/internals.cpp
src/manager/crypto/tz-backend/obj.cpp
src/manager/service/ckm-logic.cpp
src/manager/service/encryption-logic.cpp
unit-tests/test_sw-backend.cpp

index 8946a35..dd0939e 100644 (file)
@@ -26,6 +26,7 @@
 #include <utility>
 
 #include <ckm/ckm-type.h>
+#include <generic-backend/crypto-params.h>
 
 #include <exception.h>
 
@@ -185,7 +186,7 @@ struct ParamCheckBase {
        virtual void Check(const CryptoAlgorithm &ca) const = 0;
 };
 
-typedef std::unique_ptr<const ParamCheckBase> ParamCheckBasePtr;
+typedef std::shared_ptr<const ParamCheckBase> ParamCheckBasePtr;
 
 typedef std::vector<ParamCheckBasePtr> ValidatorVector;
 
@@ -281,5 +282,190 @@ struct ParamCheck : public ParamCheckBase {
        }
 };
 
+// sign / verify
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               false,
+               Type<AlgoType>::Equals<AlgoType::RSA_SV,
+               AlgoType::DSA_SV,
+               AlgoType::ECDSA_SV>> IsSignVerify;
+
+typedef ParamCheck<ParamName::SV_HASH_ALGO,
+               HashAlgorithm,
+               false,
+               Type<HashAlgorithm>::Equals<HashAlgorithm::NONE,
+               HashAlgorithm::SHA1,
+               HashAlgorithm::SHA256,
+               HashAlgorithm::SHA384,
+               HashAlgorithm::SHA512>> HashAlgoCheck;
+
+typedef ParamCheck<ParamName::SV_RSA_PADDING,
+               RSAPaddingAlgorithm,
+               false,
+               Type<RSAPaddingAlgorithm>::Equals<RSAPaddingAlgorithm::NONE,
+               RSAPaddingAlgorithm::PKCS1,
+               RSAPaddingAlgorithm::X931>> RsaPaddingCheck;
+
+// key generation
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::RSA_GEN,
+               AlgoType::DSA_GEN,
+               AlgoType::ECDSA_GEN,
+               AlgoType::KEM_GEN>> IsAsymGeneration;
+
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::AES_GEN>> IsSymGeneration;
+
+typedef ParamCheck<ParamName::GEN_KEY_LEN,
+               int,
+               true,
+               Type<int>::Equals<1024, 2048, 3072, 4096>> RsaKeyLenCheck;
+
+typedef ParamCheck<ParamName::GEN_KEY_LEN,
+               int,
+               true,
+               Type<int>::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck;
+
+typedef ParamCheck<ParamName::GEN_KEY_LEN,
+               int,
+               true,
+               Type<int>::Equals<128, 192, 256>> AesKeyLenCheck;
+
+typedef ParamCheck<ParamName::GEN_EC,
+               ElipticCurve,
+               true,
+               Type<ElipticCurve>::Equals<ElipticCurve::prime192v1,
+               ElipticCurve::prime256v1,
+               ElipticCurve::secp384r1>> EcdsaEcCheck;
+
+typedef ParamCheck<ParamName::GEN_KEM_TYPE,
+               KemType,
+               true,
+               Type<KemType>::Equals<KemType::ML_KEM_768,
+               KemType::ML_KEM_1024>> KemTypeCheck;
+
+// encryption / decryption
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::AES_CTR,
+               AlgoType::AES_CBC,
+               AlgoType::AES_GCM,
+               AlgoType::AES_CFB>> IsSymEncryption;
+
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
+
+typedef ParamCheck<ParamName::ED_IV,
+               RawBuffer,
+               true,
+               Type<size_t>::Equals<Params::DEFAULT_AES_IV_LEN>,
+               BufferSizeGetter> IvSizeCheck;
+
+typedef ParamCheck<ParamName::ED_CTR_LEN,
+               int,
+               false,
+               Type<int>::Equals<128>> CtrLenCheck;
+
+typedef ParamCheck<ParamName::ED_IV,
+               RawBuffer,
+               true,
+               GreaterOrEqual<size_t, 1>,
+               BufferSizeGetter> GcmIvCheck;
+
+typedef ParamCheck<ParamName::ED_TAG_LEN,
+               int,
+               false,
+               Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
+
+typedef ParamCheck<ParamName::ED_LABEL,
+               RawBuffer,
+               false,
+               Unsupported<RawBuffer>> RsaLabelCheck;
+
+typedef ParamCheck<ParamName::ED_OAEP_HASH,
+               HashAlgorithm,
+               false,
+               Type<HashAlgorithm>::Equals<HashAlgorithm::SHA1,
+                                                                       HashAlgorithm::SHA256,
+                                                                       HashAlgorithm::SHA384,
+                                                                       HashAlgorithm::SHA512>> OaepHashAlgoCheck;
+
+// key derivation
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::ECDH>> IsEcdh;
+
+typedef ParamCheck<ParamName::ECDH_PUBKEY,
+               RawBuffer,
+               true,
+               DefaultValidator<RawBuffer>> EcdhPubKeyCheck;
+
+typedef ParamCheck<ParamName::ALGO_TYPE,
+               AlgoType,
+               true,
+               Type<AlgoType>::Equals<AlgoType::KBKDF>> IsKbkdf;
+
+typedef ParamCheck<ParamName::KDF_PRF,
+               KdfPrf,
+               true,
+               Type<KdfPrf>::Equals<KdfPrf::HMAC_SHA256,
+                                                        KdfPrf::HMAC_SHA384,
+                                                        KdfPrf::HMAC_SHA512>> KdfPrfCheck;
+
+typedef ParamCheck<ParamName::KBKDF_MODE,
+               KbkdfMode,
+               true,
+               Type<KbkdfMode>::Equals<KbkdfMode::COUNTER>> KbkdfModeCheck;
+
+typedef ParamCheck<ParamName::KDF_LEN,
+               int,
+               true,
+               Type<int>::Equals<16, 24, 32>> KdfLenCheck;
+
+typedef ParamCheck<ParamName::KBKDF_COUNTER_LOCATION,
+               KbkdfCounterLocation,
+               true,
+               Type<KbkdfCounterLocation>::Equals<KbkdfCounterLocation::BEFORE_FIXED,
+                                                                                  KbkdfCounterLocation::AFTER_FIXED,
+                                                                                  KbkdfCounterLocation::MIDDLE_FIXED>> KbkdfCounterLocationCheck;
+
+typedef ParamCheck<ParamName::KBKDF_RLEN,
+               int,
+               false,
+               Type<int>::Equals<8, 16, 24, 32>> KbkdfRlenCheck;
+
+typedef ParamCheck<ParamName::KBKDF_LLEN,
+               int,
+               false,
+               Type<int>::Equals<0, 8, 16, 24, 32>> KbkdfLlenCheck;
+
+typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
+
+template <typename TypeCheck>
+void validateParams(const CryptoAlgorithm &ca, const ValidatorMap g_validators)
+{
+       // check algorithm type (Sign/Verify, Key generation)
+       TypeCheck tc;
+       tc.Check(ca);
+
+       AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
+
+       auto it = g_validators.find(at);
+
+       // TypeCheck should prevent it
+       assert(it != g_validators.end());
+
+       for (const auto &validator : it->second)
+               validator->Check(ca);
+}
+
 } // namespace Crypto
 } // namespace CKM
index 07edb4e..bb07aed 100644 (file)
@@ -89,171 +89,6 @@ RawBuffer i2d(I2D_CONV fun, const EVP_PKEY *pkey)
        return output;
 }
 
-// encryption / decryption
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::AES_CTR,
-               AlgoType::AES_CBC,
-               AlgoType::AES_GCM,
-               AlgoType::AES_CFB>> IsSymEncryption;
-
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
-
-typedef ParamCheck<ParamName::ED_IV,
-               RawBuffer,
-               true,
-               Type<size_t>::Equals<Params::DEFAULT_AES_IV_LEN>,
-               BufferSizeGetter> IvSizeCheck;
-
-typedef ParamCheck<ParamName::ED_CTR_LEN,
-               int,
-               false,
-               Type<int>::Equals<128>> CtrLenCheck;
-
-typedef ParamCheck<ParamName::ED_IV,
-               RawBuffer,
-               true,
-               GreaterOrEqual<size_t, 1>,
-               BufferSizeGetter> GcmIvCheck;
-
-typedef ParamCheck<ParamName::ED_TAG_LEN,
-               int,
-               false,
-               Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
-
-typedef ParamCheck<ParamName::ED_LABEL,
-               RawBuffer,
-               false,
-               Unsupported<RawBuffer>> RsaLabelCheck;
-
-// sign / verify
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               false,
-               Type<AlgoType>::Equals<AlgoType::RSA_SV,
-               AlgoType::DSA_SV,
-               AlgoType::ECDSA_SV>> IsSignVerify;
-
-typedef ParamCheck<ParamName::SV_HASH_ALGO,
-               HashAlgorithm,
-               false,
-               Type<HashAlgorithm>::Equals<HashAlgorithm::NONE,
-               HashAlgorithm::SHA1,
-               HashAlgorithm::SHA256,
-               HashAlgorithm::SHA384,
-               HashAlgorithm::SHA512>> HashAlgoCheck;
-
-typedef ParamCheck<ParamName::SV_RSA_PADDING,
-               RSAPaddingAlgorithm,
-               false,
-               Type<RSAPaddingAlgorithm>::Equals<RSAPaddingAlgorithm::NONE,
-               RSAPaddingAlgorithm::PKCS1,
-               RSAPaddingAlgorithm::X931>> RsaPaddingCheck;
-
-// key generation
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::RSA_GEN,
-               AlgoType::DSA_GEN,
-               AlgoType::ECDSA_GEN,
-               AlgoType::KEM_GEN>> IsAsymGeneration;
-
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::AES_GEN>> IsSymGeneration;
-
-typedef ParamCheck<ParamName::GEN_KEY_LEN,
-               int,
-               true,
-               Type<int>::Equals<1024, 2048, 3072, 4096>> RsaKeyLenCheck;
-
-typedef ParamCheck<ParamName::GEN_KEY_LEN,
-               int,
-               true,
-               Type<int>::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck;
-
-typedef ParamCheck<ParamName::GEN_KEY_LEN,
-               int,
-               true,
-               Type<int>::Equals<128, 192, 256>> AesKeyLenCheck;
-
-typedef ParamCheck<ParamName::GEN_EC,
-               ElipticCurve,
-               true,
-               Type<ElipticCurve>::Equals<ElipticCurve::prime192v1,
-               ElipticCurve::prime256v1,
-               ElipticCurve::secp384r1>> EcdsaEcCheck;
-
-typedef ParamCheck<ParamName::GEN_KEM_TYPE,
-               KemType,
-               true,
-               Type<KemType>::Equals<KemType::ML_KEM_768,
-               KemType::ML_KEM_1024>> KemTypeCheck;
-
-// key derivation
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::ECDH>> IsEcdh;
-
-typedef ParamCheck<ParamName::ECDH_PUBKEY,
-               RawBuffer,
-               true,
-               DefaultValidator<RawBuffer>> EcdhPubKeyCheck;
-
-typedef ParamCheck<ParamName::ALGO_TYPE,
-               AlgoType,
-               true,
-               Type<AlgoType>::Equals<AlgoType::KBKDF>> IsKbkdf;
-
-typedef ParamCheck<ParamName::KDF_PRF,
-               KdfPrf,
-               true,
-               Type<KdfPrf>::Equals<KdfPrf::HMAC_SHA256,
-                                                        KdfPrf::HMAC_SHA384,
-                                                        KdfPrf::HMAC_SHA512>> KdfPrfCheck;
-
-typedef ParamCheck<ParamName::KBKDF_MODE,
-               KbkdfMode,
-               true,
-               Type<KbkdfMode>::Equals<KbkdfMode::COUNTER>> KbkdfModeCheck;
-
-typedef ParamCheck<ParamName::KDF_LEN,
-               int,
-               true,
-               Type<int>::Equals<16, 24, 32>> KdfLenCheck;
-
-typedef ParamCheck<ParamName::KBKDF_COUNTER_LOCATION,
-               KbkdfCounterLocation,
-               true,
-               Type<KbkdfCounterLocation>::Equals<KbkdfCounterLocation::BEFORE_FIXED,
-                                                                                  KbkdfCounterLocation::AFTER_FIXED,
-                                                                                  KbkdfCounterLocation::MIDDLE_FIXED>> KbkdfCounterLocationCheck;
-
-typedef ParamCheck<ParamName::KBKDF_RLEN,
-               int,
-               false,
-               Type<int>::Equals<8, 16, 24, 32>> KbkdfRlenCheck;
-
-typedef ParamCheck<ParamName::KBKDF_LLEN,
-               int,
-               false,
-               Type<int>::Equals<0, 8, 16, 24, 32>> KbkdfLlenCheck;
-
-typedef ParamCheck<ParamName::ED_OAEP_HASH,
-               HashAlgorithm,
-               false,
-               Type<HashAlgorithm>::Equals<HashAlgorithm::SHA1,
-                                                                       HashAlgorithm::SHA256,
-                                                                       HashAlgorithm::SHA384,
-                                                                       HashAlgorithm::SHA512>> OaepHashAlgoCheck;
-
 typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
 ValidatorMap initValidators()
 {
@@ -261,46 +96,12 @@ ValidatorMap initValidators()
        validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
        validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
        validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
-       validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
-       validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
-       validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
-       validators.emplace(AlgoType::KEM_GEN, VBuilder<KemTypeCheck>::Build());
-       validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
-       validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
-       validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
-       validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
-       validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
-       validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck, OaepHashAlgoCheck>::Build());
-       validators.emplace(AlgoType::ECDH, VBuilder<EcdhPubKeyCheck>::Build());
-       validators.emplace(AlgoType::KBKDF, VBuilder<KdfPrfCheck,
-                                                                                                KbkdfModeCheck,
-                                                                                                KdfLenCheck,
-                                                                                                KbkdfCounterLocationCheck,
-                                                                                                KbkdfRlenCheck,
-                                                                                                KbkdfLlenCheck>::Build());
+
        return validators;
 };
 
 const ValidatorMap g_validators = initValidators();
 
-template <typename TypeCheck>
-void validateParams(const CryptoAlgorithm &ca)
-{
-       // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
-       TypeCheck tc;
-       tc.Check(ca);
-
-       AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
-
-       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::function<void(EvpCipherPtr &, const RawBuffer &key, const RawBuffer &iv)>
 InitCipherFn;
 
@@ -433,8 +234,6 @@ RawBuffer asymmetricHelper(
        int ret;
        size_t outlen;
 
-       validateParams<IsAsymEncryption>(alg);
-
        HashAlgorithm hash = HashAlgorithm::SHA1;
        alg.getParam(ParamName::ED_OAEP_HASH, hash);
 
@@ -793,8 +592,6 @@ OqsKemPtr createNewKem(const KemType type)
 
 DataPair generateAKey(const CryptoAlgorithm &algorithm)
 {
-       validateParams<IsAsymGeneration>(algorithm);
-
        AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
 
        if (keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN) {
@@ -815,8 +612,6 @@ DataPair generateAKey(const CryptoAlgorithm &algorithm)
 
 Data generateSKey(const CryptoAlgorithm &algorithm)
 {
-       validateParams<IsSymGeneration>(algorithm);
-
        int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
        return createKeyAES(keySizeBits);
 }
@@ -921,7 +716,6 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
                                                   const CryptoAlgorithm &alg,
                                                   const RawBuffer &data)
 {
-       validateParams<IsSymEncryption>(alg);
        AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
        if (algo == AlgoType::AES_GCM) {
@@ -944,7 +738,6 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                                                   const CryptoAlgorithm &alg,
                                                   const RawBuffer &data)
 {
-       validateParams<IsSymEncryption>(alg);
        AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
        if (algo == AlgoType::AES_GCM) {
@@ -965,7 +758,6 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
 
 EvpCipherPtr initCipher(const RawBuffer &key, const CryptoAlgorithm &alg, bool encrypt, int& tagLen)
 {
-       validateParams<IsSymEncryption>(alg);
        AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
        auto iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
        tagLen = 0;
@@ -1004,7 +796,7 @@ RawBuffer sign(EVP_PKEY *pkey,
                           const CryptoAlgorithm &alg,
                           const RawBuffer &message)
 {
-       validateParams<IsSignVerify>(alg);
+       validateParams<IsSignVerify>(alg, g_validators);
 
        HashAlgorithm hashTmp = HashAlgorithm::NONE;
        alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
@@ -1041,7 +833,7 @@ int verify(EVP_PKEY *pkey,
                   const RawBuffer &message,
                   const RawBuffer &signature)
 {
-       validateParams<IsSignVerify>(alg);
+       validateParams<IsSignVerify>(alg, g_validators);
 
        HashAlgorithm hashTmp = HashAlgorithm::NONE;
        alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
@@ -1076,8 +868,6 @@ int verify(EVP_PKEY *pkey,
 
 Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg)
 {
-       validateParams<IsEcdh>(alg);
-
        const EC_KEY *ecKey = getEcKey(pkey.get());
 
        // get private key curve name
@@ -1133,8 +923,6 @@ Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg)
 
 Data deriveKBKDF(const RawBuffer &secret, const CryptoAlgorithm &alg)
 {
-       validateParams<IsKbkdf>(alg);
-
        RawBuffer label, context, fixed;
        KbkdfCounterLocation counterLocation = KbkdfCounterLocation::BEFORE_FIXED;
        KdfPrf prf = KdfPrf::HMAC_SHA256;
index 2f7afe6..ec6cf9e 100644 (file)
@@ -166,6 +166,19 @@ namespace Internals {
 
 namespace {
 
+typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
+ValidatorMap initValidators()
+{
+       ValidatorMap validators;
+       validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
+       validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
+       validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
+
+       return validators;
+};
+
+const ValidatorMap g_validators = initValidators();
+
 tz_algo_type getGenSKeyType(AlgoType type)
 {
        switch (type)
@@ -865,6 +878,8 @@ RawBuffer sign(const RawBuffer &pkeyId,
                        const CryptoAlgorithm &alg,
                        const RawBuffer &message)
 {
+       validateParams<IsSignVerify>(alg, g_validators);
+
        AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
        HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
        if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
@@ -891,6 +906,8 @@ int verify(const RawBuffer &pkeyId,
                const RawBuffer &message,
                const RawBuffer &signature)
 {
+       validateParams<IsSignVerify>(alg, g_validators);
+
        AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
        HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
        if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
@@ -1001,17 +1018,6 @@ void deriveKBKDF(const RawBuffer &secretId,
        bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
        bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
 
-       if (counterLocation != KbkdfCounterLocation::BEFORE_FIXED &&
-               counterLocation != KbkdfCounterLocation::MIDDLE_FIXED &&
-               counterLocation != KbkdfCounterLocation::AFTER_FIXED)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid counter location");
-
-       if (mode != KbkdfMode::COUNTER)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid mode");
-
-       if (prf != KdfPrf::HMAC_SHA256 && prf != KdfPrf::HMAC_SHA384 && prf != KdfPrf::HMAC_SHA512)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid pseudo random function");
-
        RawBuffer key;
        if (hasFixed) {
                if (hasLabel || hasContext || noSeparator || hasLLen ||
@@ -1020,15 +1026,7 @@ void deriveKBKDF(const RawBuffer &secretId,
        } else {
                if (!hasLabel || !hasContext)
                        ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
-
-               if (llenBits != 0 && llenBits != 8 && llenBits != 16 && llenBits != 24 && llenBits != 32)
-                       ThrowErr(Exc::Crypto::InputParam, "Invalid llen value");
        }
-       if (length != 16 && length != 24 && length != 32)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid key length");
-
-       if (rlenBits != 8 && rlenBits != 16 && rlenBits != 24 && rlenBits != 32)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid rlen value");
 
        RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
 
@@ -1073,17 +1071,6 @@ void deriveHybridKBKDF(const RawBuffer &firstSecretId,
        bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
        bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
 
-       if (counterLocation != KbkdfCounterLocation::BEFORE_FIXED &&
-               counterLocation != KbkdfCounterLocation::MIDDLE_FIXED &&
-               counterLocation != KbkdfCounterLocation::AFTER_FIXED)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid counter location");
-
-       if (mode != KbkdfMode::COUNTER)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid mode");
-
-       if (prf != KdfPrf::HMAC_SHA256 && prf != KdfPrf::HMAC_SHA384 && prf != KdfPrf::HMAC_SHA512)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid pseudo random function");
-
        if (hasFixed) {
                if (hasLabel || hasContext || noSeparator || hasLLen ||
                        counterLocation == KbkdfCounterLocation::MIDDLE_FIXED)
@@ -1091,14 +1078,7 @@ void deriveHybridKBKDF(const RawBuffer &firstSecretId,
        } else {
                if (!hasLabel || !hasContext)
                        ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
-               if (llenBits != 0 && llenBits != 8 && llenBits != 16 && llenBits != 24 && llenBits != 32)
-                       ThrowErr(Exc::Crypto::InputParam, "Invalid llen value");
        }
-       if (length != 16 && length != 24 && length != 32)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid key length");
-
-       if (rlenBits != 8 && rlenBits != 16 && rlenBits != 24 && rlenBits != 32)
-               ThrowErr(Exc::Crypto::InputParam, "Invalid rlen value");
 
        RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
 
index 2d30c98..0f964b9 100644 (file)
@@ -135,10 +135,6 @@ Token BData::deriveHybrid(const CryptoAlgorithm &alg,
                                                  const Password &newKeyPass,
                                                  const RawBuffer &hash)
 {
-       auto algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
-       if (algo != AlgoType::KBKDF)
-               ThrowErr(Exc::Crypto::InputParam, "Wrong algorithm");
-
        RawBuffer newKeyIV;
        RawBuffer newKeyTag;
        if (!newKeyPass.empty()) {
index 899102f..08038da 100644 (file)
@@ -189,6 +189,37 @@ int readMultiRow(const Name &name,
 
 } // namespace
 
+namespace Crypto {
+
+typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
+ValidatorMap initValidators()
+{
+       ValidatorMap validators;
+       validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
+       validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
+       validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
+       validators.emplace(AlgoType::KEM_GEN, VBuilder<KemTypeCheck>::Build());
+       validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
+       validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
+       validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
+       validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck, OaepHashAlgoCheck>::Build());
+       validators.emplace(AlgoType::ECDH, VBuilder<EcdhPubKeyCheck>::Build());
+       validators.emplace(AlgoType::KBKDF, VBuilder<KdfPrfCheck,
+                                                                                                KbkdfModeCheck,
+                                                                                                KdfLenCheck,
+                                                                                                KbkdfCounterLocationCheck,
+                                                                                                KbkdfRlenCheck,
+                                                                                                KbkdfLlenCheck>::Build());
+
+       return validators;
+};
+
+} // Crypto
+
+const CKM::Crypto::ValidatorMap g_validators = CKM::Crypto::initValidators();
+
 const uid_t CKMLogic::SYSTEM_DB_UID = 0;
 const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
 
@@ -1192,6 +1223,8 @@ RawBuffer CKMLogic::createKeyPair(
                        ThrowErr(Exc::InputParam, "Error, key pair must be RSA or DSA or ECDSA or KEM.");
                }
 
+               Crypto::validateParams<Crypto::IsAsymGeneration>(keyGenParams, g_validators);
+
                TokenPair keys = m_decider.getStore(
                        dataTypeIt->second, policyPrv, policyPub, false).generateAKey(
                                keyGenParams,
@@ -1227,6 +1260,8 @@ RawBuffer CKMLogic::createKeyAES(
                        keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
                        keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
 
+                       Crypto::validateParams<Crypto::IsSymGeneration>(keyGenAlgorithm, g_validators);
+
                        auto& store = m_decider.getStore(DataType::KEY_AES, policy, false);
                        Token key = store.generateSKey(keyGenAlgorithm, policy.password, digest);
 
@@ -1571,7 +1606,15 @@ RawBuffer CKMLogic::deriveKey(
                        return ret;
 
                // ECDH (private key) -> binary secret, KBKDF -> symmetric key
-               DataType newKeyType = objType.isKeyPrivate() ? DataType::BINARY_DATA : DataType::KEY_AES;
+               DataType newKeyType;
+               if (objType.isKeyPrivate()) {
+                       CKM::Crypto::validateParams<CKM::Crypto::IsEcdh>(params, g_validators);
+                       newKeyType = DataType::BINARY_DATA;
+               } else {
+                       CKM::Crypto::validateParams<CKM::Crypto::IsKbkdf>(params, g_validators);
+                       newKeyType = DataType::KEY_AES;
+               }
+
                if (!m_decider.checkStore(obj->backendId(), newKeyType, newKeyPolicy, false)) {
                        LogDebug("Can't import the derived key to backend " <<
                                 static_cast<int>(obj->backendId()) << " with given policy");
@@ -1635,6 +1678,11 @@ RawBuffer CKMLogic::importWrappedKey(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               if (wrappingKeyType == DataType::KEY_RSA_PRIVATE)
+                       CKM::Crypto::validateParams<CKM::Crypto::IsAsymEncryption>(params, g_validators);
+               else
+                       CKM::Crypto::validateParams<CKM::Crypto::IsSymEncryption>(params, g_validators);
+
                Token token = wrappingKey->unwrap(params,
                                                                                  Crypto::Data(keyType, wrappedKey),
                                                                                  policy.password,
@@ -1663,8 +1711,9 @@ RawBuffer CKMLogic::exportWrappedKey(
        RawBuffer wrappedKey;
 
        auto retCode = tryRet([&] {
+               DataType wrappingKeyType;
                auto retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
-                                                                          wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+                                                                          wrappingKeyOwner, wrappingKeyPassword, wrappingKey, wrappingKeyType);
                if (retCode2 != CKM_API_SUCCESS)
                        return retCode2;
 
@@ -1684,6 +1733,11 @@ RawBuffer CKMLogic::exportWrappedKey(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               if (wrappingKeyType == DataType::KEY_RSA_PUBLIC || wrappingKeyType == DataType::KEY_RSA_PRIVATE)
+                       CKM::Crypto::validateParams<CKM::Crypto::IsAsymEncryption>(params, g_validators);
+               else
+                       CKM::Crypto::validateParams<CKM::Crypto::IsSymEncryption>(params, g_validators);
+
                wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, keyPassword);
 
                return retCode2;
@@ -1730,6 +1784,8 @@ RawBuffer CKMLogic::wrapConcatenatedData(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               CKM::Crypto::validateParams<CKM::Crypto::IsAsymEncryption>(params, g_validators);
+
                wrappedKey = wrappingKey->wrapConcatenated(params, keyRow, keyPassword, data);
 
                return retCode2;
@@ -1783,6 +1839,8 @@ RawBuffer CKMLogic::unwrapConcatenatedData(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               CKM::Crypto::validateParams<CKM::Crypto::IsAsymEncryption>(params, g_validators);
+
                std::tuple<Token, RawBuffer> tokenWithData =
                        wrappingKey->unwrapConcatenated(params,
                                                                                        Crypto::Data(DataType::KEY_AES, wrappedKey),
@@ -1837,6 +1895,10 @@ RawBuffer CKMLogic::encapsulateKey(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               CryptoAlgorithm keyGenAlgorithm(params);
+               keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::KEM_GEN);
+               Crypto::validateParams<Crypto::IsAsymGeneration>(keyGenAlgorithm, g_validators);
+
                std::tuple<Token, RawBuffer> tokenWithData =
                        key->encapsulateKey(params, publicKeyRow, publicKeyPassword, sharedSecretPassword, digest);
 
@@ -1887,6 +1949,10 @@ RawBuffer CKMLogic::decapsulateKey(
                        return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               CryptoAlgorithm keyGenAlgorithm(params);
+               keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::KEM_GEN);
+               Crypto::validateParams<Crypto::IsAsymGeneration>(keyGenAlgorithm, g_validators);
+
                Token token = key->decapsulateKey(params, privateKeyRow, privateKeyPassword,
                                                                                  sharedSecretPassword, ciphertext, digest);
 
@@ -1953,6 +2019,8 @@ RawBuffer CKMLogic::deriveHybrid(
                                return CKM_API_ERROR_INPUT_PARAM;
                }
 
+               CKM::Crypto::validateParams<CKM::Crypto::IsKbkdf>(params, g_validators);
+
                Token newKey = obj->deriveHybrid(params, firstKeyRow, firstSecretPassword, secondKeyRow,
                                                                                 secondSecretPassword, newKeyPolicy.password, digest);
 
index 3038e90..561e0b8 100644 (file)
@@ -23,6 +23,7 @@
 #include <ckm/ckm-error.h>
 #include <dpl/log/log.h>
 #include <generic-backend/gctx.h>
+#include <generic-backend/algo-validation.h>
 
 namespace CKM {
 
@@ -30,6 +31,25 @@ namespace {
 constexpr unsigned NO_ID = 0;
 }
 
+namespace Crypto {
+
+typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
+ValidatorMap initCryptoValidators()
+{
+       ValidatorMap validators;
+       validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
+       validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
+       validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck, OaepHashAlgoCheck>::Build());
+
+       return validators;
+};
+
+} // Crypto
+
+const CKM::Crypto::ValidatorMap g_validators = CKM::Crypto::initCryptoValidators();
+
 void EncryptionLogic::BumpCounter()
 {
        m_counter++;
@@ -185,6 +205,13 @@ void EncryptionLogic::KeyRetrieved(MsgKeyResponse response)
        // encrypt/decrypt
        try {
                RawBuffer output;
+               AlgoType algo;
+               CryptoAlgorithm params = req.cas;
+               params.getParam(ParamName::ALGO_TYPE, algo);
+               if (algo == AlgoType::RSA_OAEP)
+                       CKM::Crypto::validateParams<CKM::Crypto::IsAsymEncryption>(params, g_validators);
+               else
+                       CKM::Crypto::validateParams<CKM::Crypto::IsSymEncryption>(params, g_validators);
 
                switch (req.command) {
                case EncryptionCommand::ENCRYPT:
index c1747d2..a76e179 100644 (file)
@@ -32,6 +32,7 @@
 #include <ckm/ckm-type.h>
 #include <crypto-logic.h>
 #include <generic-backend/crypto-params.h>
+#include <generic-backend/algo-validation.h>
 
 using namespace CKM;
 using namespace CKM::Crypto;
@@ -229,6 +230,33 @@ struct CertHelper : public Cert {
        using Cert::getEvpShPtr;
 };
 
+typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
+ValidatorMap initValidators()
+{
+       ValidatorMap validators;
+       validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
+       validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
+       validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
+       validators.emplace(AlgoType::KEM_GEN, VBuilder<KemTypeCheck>::Build());
+       validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
+       validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
+       validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
+       validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
+       validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck, OaepHashAlgoCheck>::Build());
+       validators.emplace(AlgoType::ECDH, VBuilder<EcdhPubKeyCheck>::Build());
+       validators.emplace(AlgoType::KBKDF, VBuilder<KdfPrfCheck,
+                                                                                                KbkdfModeCheck,
+                                                                                                KdfLenCheck,
+                                                                                                KbkdfCounterLocationCheck,
+                                                                                                KbkdfRlenCheck,
+                                                                                                KbkdfLlenCheck>::Build());
+
+       return validators;
+};
+
+const ValidatorMap g_validators = initValidators();
+
 const std::optional<RawBuffer> NO_BUF;
 const std::optional<size_t> NO_SIZE;
 const std::optional<KdfPrf> NO_PRF;
@@ -270,9 +298,10 @@ public:
                        const std::optional<RawBuffer>& fixed,
                        const std::optional<size_t>& rlen,
                        const std::optional<size_t>& llen,
+                       bool validateValues = false,
                        bool noSeparator = false)
        {
-               return Test(true, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+               return Test(true, len, prf, mode, location, context, label, fixed, rlen, llen, validateValues, noSeparator);
        }
 
        void Fail(const std::optional<size_t>& len,
@@ -284,10 +313,11 @@ public:
                          const std::optional<RawBuffer>& fixed,
                          const std::optional<size_t>& rlen,
                          const std::optional<size_t>& llen,
+                         bool validateValues = false,
                          bool noSeparator = false)
        {
                return Test(
-                       false, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+                       false, len, prf, mode, location, context, label, fixed, rlen, llen, validateValues, noSeparator);
        }
 private:
        void Test(bool ok,
@@ -300,6 +330,7 @@ private:
                          const std::optional<RawBuffer>& fixed,
                          const std::optional<size_t>& rlen,
                          const std::optional<size_t>& llen,
+                         bool validateValues = false,
                          bool noSeparator = false)
        {
                CryptoAlgorithm derive;
@@ -337,7 +368,10 @@ private:
 
                        BOOST_REQUIRE(key->getBinary().size() == *len);
                } else {
-                       BOOST_REQUIRE_THROW(secret->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+                       if (validateValues)
+                               BOOST_REQUIRE_THROW(validateParams<IsKbkdf>(derive, g_validators), Exc::Crypto::InputParam);
+                       else
+                               BOOST_REQUIRE_THROW(secret->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
                }
        }
 
@@ -414,51 +448,50 @@ POSITIVE_TEST_CASE(generateAKey)
 
 NEGATIVE_TEST_CASE(generateAKey)
 {
-       std::unique_ptr<CryptoAlgorithm> ca(new CryptoAlgorithm());
-
-       auto invalidGen = [&]
+       auto invalidGenParams = [&] (CryptoAlgorithm ca)
        {
-               const auto [digestPub, digestPriv] = makePubPrivTestDigest();
-               BOOST_REQUIRE_THROW(STORE.generateAKey(*ca, "", "", digestPriv, digestPub), Exc::Crypto::InputParam);
+               BOOST_REQUIRE_THROW(validateParams<IsAsymGeneration>(ca, g_validators), Exc::Crypto::InputParam);
        };
 
-       invalidGen();
+       CryptoAlgorithm ca;
+
+       invalidGenParams(ca);
 
-       ca->setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
-       invalidGen();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
+       invalidGenParams(ca);
 
        for (int keyLen : { 0, 512, 1023, 1025, 3073, 4097, 8192 }) {
-               ca->setParam(ParamName::GEN_KEY_LEN, keyLen);
-               invalidGen();
+               ca.setParam(ParamName::GEN_KEY_LEN, keyLen);
+               invalidGenParams(ca);
        }
 
-       ca->setParam(ParamName::ALGO_TYPE, AlgoType::DSA_GEN);
+       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::GEN_KEY_LEN, keyLen);
+               invalidGenParams(ca);
        }
 
-       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();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
+       invalidGenParams(ca);
+       ca.setParam(ParamName::GEN_EC, static_cast<ElipticCurve>(-1));
+       invalidGenParams(ca);
+       ca.setParam(ParamName::GEN_EC, static_cast<ElipticCurve>(3));
+       invalidGenParams(ca);
+
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       ca.setParam(ParamName::GEN_KEY_LEN, 128);
+       invalidGenParams(ca);
+       ca.setParam(ParamName::GEN_KEY_LEN, 1024);
+       invalidGenParams(ca);
+
+       CryptoAlgorithm ca2;
+
+       ca2.setParam(ParamName::GEN_KEY_LEN, 1024);
+       ca2.setParam(ParamName::GEN_EC, ElipticCurve::prime192v1);
+       invalidGenParams(ca2);
+       ca2.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       invalidGenParams(ca2);
 }
 
 POSITIVE_TEST_CASE(generateSKey)
@@ -485,33 +518,28 @@ POSITIVE_TEST_CASE(generateSKey)
 
 NEGATIVE_TEST_CASE(generateSKey)
 {
-       std::unique_ptr<CryptoAlgorithm> ca(new CryptoAlgorithm());
-
-       auto invalidGen = [&]
+       auto invalidGenParams = [&] (CryptoAlgorithm ca)
        {
-               const auto digest = makeTestDigest();
-               BOOST_REQUIRE_THROW(STORE.generateSKey(*ca, "", digest), Exc::Crypto::InputParam);
+               BOOST_REQUIRE_THROW(validateParams<IsSymGeneration>(ca, g_validators), Exc::Crypto::InputParam);
        };
 
-       invalidGen();
+       CryptoAlgorithm ca;
+
+       invalidGenParams(ca);
 
-       ca->setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
-       invalidGen();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
+       invalidGenParams(ca);
 
        for (int keyLen : { 0, 64, 127, 129, 257, 512 }) {
-               ca->setParam(ParamName::GEN_KEY_LEN, keyLen);
-               invalidGen();
+               ca.setParam(ParamName::GEN_KEY_LEN, keyLen);
+               invalidGenParams(ca);
        }
 
-       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();
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
+       ca.setParam(ParamName::GEN_KEY_LEN, 128);
+       invalidGenParams(ca);
+       ca.setParam(ParamName::GEN_KEY_LEN, 1024);
+       invalidGenParams(ca);
 }
 
 POSITIVE_TEST_CASE(symmetricEncryptDecrypt)
@@ -554,49 +582,46 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecrypt)
        const auto key = generateAes(128);
        const auto data = createRandom(128);
        const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
+
+       auto invalidEncParams = [&] (CryptoAlgorithm ca)
+       {
+               BOOST_REQUIRE_THROW(validateParams<IsSymEncryption>(ca, g_validators), Exc::Crypto::InputParam);
+       };
+
        CryptoAlgorithm ca;
 
        // no algo
-       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       invalidEncParams(ca);
 
        // 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);
+       invalidEncParams(ca);
        ca.setParam(ParamName::ALGO_TYPE, static_cast<AlgoType>(0));
-       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       invalidEncParams(ca);
 
        for (auto algo : { AlgoType::AES_CTR, AlgoType::AES_CBC, AlgoType::AES_CFB }) {
-               CryptoAlgorithm ca2;
+        CryptoAlgorithm ca2;
                ca2.setParam(ParamName::ALGO_TYPE, algo);
 
                // no iv
-               BOOST_REQUIRE_THROW(key->encrypt(ca2, data), Exc::Crypto::InputParam);
+               invalidEncParams(ca2);
 
                // 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);
+               invalidEncParams(ca2);
 
                // short key
                SKey shortKey(CryptoBackend::OpenSSL, createRandom(128/8 - 1), DataType::KEY_AES);
                BOOST_REQUIRE_THROW(shortKey.encrypt(ca2, data), Exc::Crypto::InternalError);
 
-               // proper encrypt
+        // proper encrypt
+               ca2.setParam(ParamName::ED_IV, iv);
                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
@@ -610,13 +635,18 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecryptGcm)
        const auto data = createRandom(128);
        const auto iv = createRandom(Params::DEFAULT_AES_IV_LEN);
        const auto aad = createRandom(42);
+
+       auto invalidEncParams = [&] (CryptoAlgorithm ca)
+       {
+               BOOST_REQUIRE_THROW(validateParams<IsSymEncryption>(ca, g_validators), Exc::Crypto::InputParam);
+       };
+
        CryptoAlgorithm ca;
 
        ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
 
        // no iv
-       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
-
+       invalidEncParams(ca);
        ca.setParam(ParamName::ED_IV, iv);
 
        // short key
@@ -626,7 +656,7 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecryptGcm)
        // 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);
+               invalidEncParams(ca);
        }
        ca.setParam(ParamName::ED_TAG_LEN, 128);
 
@@ -637,12 +667,12 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecryptGcm)
        CryptoAlgorithm ca2;
 
        // no algo
-       BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
+       invalidEncParams(ca2);
        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);
+       invalidEncParams(ca2);
 
        ca2.setParam(ParamName::ED_IV, iv);
 
@@ -688,49 +718,17 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecryptGcm)
        BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
 }
 
-POSITIVE_TEST_CASE(gcmIvLengthScrewUpWorkaround)
+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;
-       RawBuffer encrypted, decrypted;
-       auto shortIv = iv;
-       shortIv.resize(Params::DEFAULT_AES_GCM_IV_LEN);
-
-       ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
-       ca.setParam(ParamName::ED_IV, shortIv);
-       ca.setParam(ParamName::ED_TAG_LEN, 128);
-
-       // encrypt with 12B IV
-       BOOST_REQUIRE_NO_THROW(encrypted = key->encrypt(ca, data));
-
-       // decrypt with 12B IV
-       BOOST_REQUIRE_NO_THROW(decrypted = key->decrypt(ca, encrypted));
-       BOOST_REQUIRE(decrypted == data);
-
-       // decrypt with 16B IV should also succeed (workaround)
-       ca.setParam(ParamName::ED_IV, iv);
-       BOOST_REQUIRE_NO_THROW(decrypted = key->decrypt(ca, encrypted));
-       BOOST_REQUIRE(decrypted == data);
-
-       // encrypt with 16B IV
-       BOOST_REQUIRE_NO_THROW(encrypted = key->encrypt(ca, data));
-
-       // decrypt with 16B IV
-       BOOST_REQUIRE_NO_THROW(decrypted = key->decrypt(ca, encrypted));
-       BOOST_REQUIRE(decrypted == data);
 
-       // decrypt with 12B IV should fail
-       ca.setParam(ParamName::ED_IV, shortIv);
-       BOOST_REQUIRE_THROW(key->decrypt(ca, encrypted), Exc::Crypto::InputParam);
-}
+       auto invalidEncParams = [&] (CryptoAlgorithm ca)
+       {
+               BOOST_REQUIRE_THROW(validateParams<IsSymEncryption>(ca, g_validators), 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);
@@ -738,22 +736,11 @@ NEGATIVE_TEST_CASE(symmetricEncryptDecryptCtr)
 
        // wrong ctr len
        ca.setParam(ParamName::ED_CTR_LEN, 0);
-       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       invalidEncParams(ca);
        ca.setParam(ParamName::ED_CTR_LEN, 127);
-       BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
+       invalidEncParams(ca);
        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);
+       invalidEncParams(ca);
 }
 
 NEGATIVE_TEST_CASE(symmetricEncryptDecryptCbc)
@@ -828,6 +815,11 @@ NEGATIVE_TEST_CASE(asymmetricEncryptDecrypt)
        auto longData = data;
        longData.push_back(0);
 
+       auto invalidEncParams = [&] (CryptoAlgorithm ca)
+       {
+               BOOST_REQUIRE_THROW(validateParams<IsAsymEncryption>(ca, g_validators), Exc::Crypto::InputParam);
+       };
+
        CryptoAlgorithm enc;
        enc.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
        BOOST_REQUIRE_THROW(Internals::asymmetricEncrypt(EvpShPtr(), enc, data),
@@ -837,23 +829,23 @@ NEGATIVE_TEST_CASE(asymmetricEncryptDecrypt)
 
        CryptoAlgorithm enc2;
        enc2.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_SV);
-       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc2, data), Exc::Crypto::InputParam);
+       invalidEncParams(enc2);
 
        CryptoAlgorithm enc3;
        enc3.setParam(ParamName::ALGO_TYPE, AlgoType::AES_CBC);
-       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc3, data), Exc::Crypto::InputParam);
+       invalidEncParams(enc3);
 
        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);
+       invalidEncParams(enc4);
 
        CryptoAlgorithm enc5;
        enc5.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
        enc5.setParam(ParamName::ED_OAEP_HASH, HashAlgorithm::NONE);
-       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc5, data), Exc::Crypto::InputParam);
+       invalidEncParams(enc5);
        enc5.setParam(ParamName::ED_OAEP_HASH, static_cast<HashAlgorithm>(-1));
-       BOOST_REQUIRE_THROW(rsaKeys.pub->encrypt(enc5, data), Exc::Crypto::InputParam);
+       invalidEncParams(enc5);
 
        RawBuffer encrypted;
        BOOST_REQUIRE_NO_THROW(encrypted = rsaKeys.pub->encrypt(enc, data));
@@ -869,10 +861,6 @@ NEGATIVE_TEST_CASE(asymmetricEncryptDecrypt)
        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)
@@ -1269,32 +1257,37 @@ NEGATIVE_TEST_CASE(deriveECDH)
        GObjUPtr oursPrivate;
        BOOST_REQUIRE_NO_THROW(oursPrivate = STORE.getObject(ours.first, ""));
 
-       CryptoAlgorithm derive;
+       auto invalidEcdhParams = [&] (CryptoAlgorithm ca)
+       {
+               BOOST_REQUIRE_THROW(validateParams<IsEcdh>(ca, g_validators), Exc::Crypto::InputParam);
+       };
+
+       CryptoAlgorithm ca;
 
        // no algorithm
-       BOOST_REQUIRE_THROW(oursPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       invalidEcdhParams(ca);
 
        // wrong algorithm
-       derive.setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
-       BOOST_REQUIRE_THROW(oursPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN);
+       invalidEcdhParams(ca);
 
        // no pubkey
-       derive.setParam(ParamName::ALGO_TYPE, AlgoType::ECDH);
-       BOOST_REQUIRE_THROW(oursPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ALGO_TYPE, AlgoType::ECDH);
+       invalidEcdhParams(ca);
 
        // empty pubkey
-       derive.setParam(ParamName::ECDH_PUBKEY, RawBuffer());
-       BOOST_REQUIRE_THROW(oursPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ECDH_PUBKEY, RawBuffer());
+       BOOST_REQUIRE_THROW(oursPrivate->derive(ca, "", RawBuffer()), Exc::Crypto::InputParam);
 
        // private key instead of public
-       derive.setParam(ParamName::ECDH_PUBKEY, oursPrivate->getBinary());
-       BOOST_REQUIRE_THROW(oursPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ECDH_PUBKEY, oursPrivate->getBinary());
+       BOOST_REQUIRE_THROW(oursPrivate->derive(ca, "", RawBuffer()), Exc::Crypto::InputParam);
 
        // public key instead of private key
        GObjUPtr oursPublic;
        BOOST_REQUIRE_NO_THROW(oursPublic = STORE.getObject(ours.second, ""));
-       derive.setParam(ParamName::ECDH_PUBKEY, oursPublic->getBinary());
-       BOOST_REQUIRE_THROW(oursPublic->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       ca.setParam(ParamName::ECDH_PUBKEY, oursPublic->getBinary());
+       BOOST_REQUIRE_THROW(oursPublic->derive(ca, "", RawBuffer()), Exc::Crypto::InputParam);
 
        // RSA key instead of EC
        gen.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN);
@@ -1302,7 +1295,7 @@ NEGATIVE_TEST_CASE(deriveECDH)
        auto rsa = STORE.generateAKey(gen, "", "", RawBuffer(), RawBuffer());
        GObjUPtr rsaPrivate;
        BOOST_REQUIRE_NO_THROW(rsaPrivate = STORE.getObject(rsa.first, ""));
-       BOOST_REQUIRE_THROW(rsaPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam);
+       BOOST_REQUIRE_THROW(rsaPrivate->derive(ca, "", RawBuffer()), Exc::Crypto::InputParam);
 }
 
 POSITIVE_TEST_CASE(deriveKBKDFHMAC)
@@ -1371,12 +1364,11 @@ NEGATIVE_TEST_CASE(deriveKBKDFHMACwrongAlgo)
 NEGATIVE_TEST_CASE(deriveKBKDFHMACwrongParams)
 {
        KbkdfParamTester test;
-
        // missing parameters
-       test.Fail(NO_SIZE, HMAC256, COUNTER, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32,      NO_PRF,  COUNTER, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32,      HMAC256, NO_MODE, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32,      HMAC256, COUNTER, NO_LOC, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE);
+       test.Fail(NO_SIZE, HMAC256, COUNTER, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32,      NO_PRF,  COUNTER, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32,      HMAC256, NO_MODE, BEFORE, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32,      HMAC256, COUNTER, NO_LOC, CTX,    LAB,    NO_BUF, NO_SIZE, NO_SIZE, true);
        test.Fail(32,      HMAC256, COUNTER, BEFORE, NO_BUF, LAB,    NO_BUF, NO_SIZE, NO_SIZE);
        test.Fail(32,      HMAC256, COUNTER, BEFORE, CTX,    NO_BUF, NO_BUF, NO_SIZE, NO_SIZE);
 
@@ -1387,33 +1379,33 @@ NEGATIVE_TEST_CASE(deriveKBKDFHMACwrongParams)
        test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE);
        test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, 32);
        test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, 0);
-       test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE, true);
+       test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE, false, true);
 
        // invalid values
-       test.Fail(0,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(1,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(8,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(64, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
+       test.Fail(0,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(1,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(8,  HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(64, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
 
-       test.Fail(32, static_cast<KdfPrf>(0), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32, static_cast<KdfPrf>(4), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
+       test.Fail(32, static_cast<KdfPrf>(0), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32, static_cast<KdfPrf>(4), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
 
-       test.Fail(32, HMAC256, static_cast<KbkdfMode>(0), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32, HMAC256, static_cast<KbkdfMode>(2), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
+       test.Fail(32, HMAC256, static_cast<KbkdfMode>(0), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32, HMAC256, static_cast<KbkdfMode>(2), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
 
        auto wrongLocation1 = static_cast<KbkdfCounterLocation>(0);
        auto wrongLocation2 = static_cast<KbkdfCounterLocation>(4);
-       test.Fail(32, HMAC256, COUNTER, wrongLocation1, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
-       test.Fail(32, HMAC256, COUNTER, wrongLocation2, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE);
+       test.Fail(32, HMAC256, COUNTER, wrongLocation1, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
+       test.Fail(32, HMAC256, COUNTER, wrongLocation2, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true);
 
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 0,  NO_SIZE);
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 1,  NO_SIZE);
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 7,  NO_SIZE);
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 64, NO_SIZE);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 0,  NO_SIZE, true);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 1,  NO_SIZE, true);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 7,  NO_SIZE, true);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 64, NO_SIZE, true);
 
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 1);
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 7);
-       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 64);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 1, true);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 7, true);
+       test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 64, true);
 }
 
 NEGATIVE_TEST_CASE(cipherAPI)