Add algorithm param validation 16/42116/8
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 19 Jun 2015 08:08:31 +0000 (10:08 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 1 Jul 2015 11:40:12 +0000 (13:40 +0200)
[Problem] Algorithm param validation is quite complicated. We need a generic
mechanism for parameter constraints definition. Aes key generation algorithm is
missing. There's no validation of encryption params.
[Solution] Created generic parameter validation framework. Defined constraints
for all algorithms. Aes key algorithm added. Algorithm parameter validation
refactored.

[Verification] run ckm-tests --output=text

Change-Id: Ia1df8a3f4bcda835a736d5fe1e4fbc7157d1a26c

src/include/ckm/ckm-type.h
src/include/ckmc/ckmc-type.h
src/manager/common/data-type.cpp
src/manager/crypto/generic-backend/algo-validation.h [new file with mode: 0644]
src/manager/crypto/sw-backend/internals.cpp
src/manager/crypto/sw-backend/internals.h
src/manager/crypto/sw-backend/key.cpp
src/manager/crypto/sw-backend/store.cpp
src/manager/service/ckm-logic.cpp

index 281f351..5ce89b6 100644 (file)
@@ -148,6 +148,7 @@ enum class AlgoType : int {
     RSA_GEN,
     DSA_GEN,
     ECDSA_GEN,
+    AES_GEN,
 };
 
 // cryptographic algorithm description
index 611808e..a450b86 100644 (file)
@@ -228,13 +228,13 @@ typedef enum __ckmc_param_name {
 
     // encryption & decryption
     CKMC_PARAM_ED_IV = 101,         /**< 16B buffer (up to 2^64-1 bytes long in case of AES GCM) */
-    CKMC_PARAM_ED_CTR_LEN,          /**< integer */
+    CKMC_PARAM_ED_CTR_LEN,          /**< integer - ctr length in bits*/
     CKMC_PARAM_ED_AAD,              /**< buffer */
-    CKMC_PARAM_ED_TAG_LEN,          /**< integer */
+    CKMC_PARAM_ED_TAG_LEN,          /**< integer - tag length in bits */
     CKMC_PARAM_ED_LABEL,            /**< buffer */
 
     // key generation
-    CKMC_PARAM_GEN_KEY_LEN = 201,   /**< integer */
+    CKMC_PARAM_GEN_KEY_LEN = 201,   /**< integer - key length in bits */
     CKMC_PARAM_GEN_EC,              /**< integer - elliptic curve (ckmc_ec_type_e) */
 
     // sign & verify
@@ -307,10 +307,15 @@ typedef enum __ckmc_algo_type {
                                   - CKMC_PARAM_ALGO_TYPE,
                                   - CKMC_PARAM_GEN_KEY_LEN */
 
-    CKMC_ALGO_ECDSA_GEN,     /**< ECDA algorithm used for key generation
+    CKMC_ALGO_ECDSA_GEN,     /**< ECDSA algorithm used for key generation
                                   Supported parameters:
                                   - CKMC_PARAM_ALGO_TYPE,
                                   - CKMC_PARAM_GEN_EC */
+
+    CKMC_ALGO_AES_GEN,       /**< AES key generation
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_GEN_KEY_LEN */
 } ckmc_algo_type_e;
 
 /**
index e8cfb84..a7fcf63 100644 (file)
@@ -32,7 +32,8 @@ DataType::DataType(Type data)
   : m_dataType(data)
 {
     if (!isInRange(data))
-        ThrowMsg(Exception::OutOfRange, "Invalid conversion from DataType to DBDataType");
+        ThrowMsg(Exception::OutOfRange,
+                 "Invalid conversion from DataType=" << static_cast<int>(data) << " to DBDataType");
 }
 
 DataType::DataType(KeyType key) {
@@ -45,7 +46,8 @@ DataType::DataType(KeyType key) {
     case KeyType::KEY_ECDSA_PRIVATE: m_dataType = DataType::KEY_ECDSA_PRIVATE; break;
     case KeyType::KEY_AES:           m_dataType = DataType::KEY_AES;           break;
     default:
-        ThrowMsg(Exception::OutOfRange, "Invalid conversion from KeyType to DBDataType");
+        ThrowMsg(Exception::OutOfRange,
+                 "Invalid conversion from KeyType=" << static_cast<int>(key) << " to DBDataType");
     }
 }
 
@@ -54,12 +56,19 @@ DataType::DataType(AlgoType algorithmType) {
     case AlgoType::AES_CTR:
     case AlgoType::AES_CBC:
     case AlgoType::AES_GCM:
-    case AlgoType::AES_CFB:         m_dataType = DataType::KEY_AES;             break;
+    case AlgoType::AES_CFB:
+    case AlgoType::AES_GEN:         m_dataType = DataType::KEY_AES;             break;
+    case AlgoType::RSA_SV:
+    case AlgoType::RSA_OAEP:
     case AlgoType::RSA_GEN:         m_dataType = DataType::KEY_RSA_PUBLIC;      break;
+    case AlgoType::DSA_SV:
     case AlgoType::DSA_GEN:         m_dataType = DataType::KEY_DSA_PUBLIC;      break;
+    case AlgoType::ECDSA_SV:
     case AlgoType::ECDSA_GEN:       m_dataType = DataType::KEY_ECDSA_PUBLIC;    break;
     default:
-        ThrowMsg(Exception::OutOfRange, "Invalid conversion from AlgoType to DBDataType");
+        ThrowMsg(Exception::OutOfRange,
+                 "Invalid conversion from AlgoType=" << static_cast<int>(algorithmType) <<
+                 " to DBDataType");
     }
 }
 
@@ -67,7 +76,7 @@ DataType::DataType(int data)
   : m_dataType(static_cast<Type>(data))
 {
     if (!isInRange(data))
-        ThrowMsg(Exception::OutOfRange, "Invalid conversion from int to DBDataType");
+        ThrowMsg(Exception::OutOfRange, "Invalid conversion from int=" << data << " to DBDataType");
 }
 
 DataType::operator int () const {
@@ -84,7 +93,9 @@ DataType::operator KeyType () const {
     case DataType::KEY_ECDSA_PUBLIC: return KeyType::KEY_ECDSA_PUBLIC;
     case DataType::KEY_AES: return KeyType::KEY_AES;
     default:
-        ThrowMsg(Exception::OutOfRange, "Invalid conversion from DBDataType to KeyType");
+        ThrowMsg(Exception::OutOfRange,
+                 "Invalid conversion from DBDataType=" << static_cast<int>(m_dataType) <<
+                 " to KeyType" );
     }
 }
 
diff --git a/src/manager/crypto/generic-backend/algo-validation.h b/src/manager/crypto/generic-backend/algo-validation.h
new file mode 100644 (file)
index 0000000..c8abc72
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       algo-validation.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include <ckm/ckm-type.h>
+
+#include <exception.h>
+
+namespace CKM {
+namespace Crypto {
+
+template<typename T>
+T unpack(
+    const CryptoAlgorithm &alg,
+    ParamName paramName)
+{
+    T result;
+    if (!alg.getParam(paramName, result)) {
+        ThrowErr(Exc::Crypto::InputParam, "Wrong input param");
+    }
+    return result;
+}
+
+
+////////// Validators //////////////
+
+// Always validates as true. Useful for checking parameter existence only
+template <typename T>
+struct DefaultValidator {
+    static bool Check(const T&) { return true; }
+    static void Why(std::ostringstream& os) { os << "is ok"; }
+};
+
+// Validates as true if parameter value is equal to one of Args
+template <typename T>
+struct Type {
+    template <T ...Args>
+    struct Equals;
+
+    template <T First>
+    struct Equals<First> {
+    public:
+        static bool Check(const T& value) {
+            return First == value;
+        }
+        static void Why(std::ostringstream& os) {
+            os << "doesn't match " << static_cast<int>(First);
+        }
+    };
+
+    template <T First, T ...Args>
+    struct Equals<First, Args...> : public Equals<First>, public Equals<Args...> {
+    public:
+        static bool Check(const T& value) {
+            return Equals<First>::Check(value) || Equals<Args...>::Check(value);
+        }
+        static void Why(std::ostringstream& os) {
+            Equals<First>::Why(os);
+            os << ", ";
+            Equals<Args...>::Why(os);
+        }
+    };
+};
+
+
+////////// Getters //////////////
+
+// simply returns parameter value
+template <typename T>
+struct DefaultGetter {
+    static T Get(const T& value) { return value; }
+    static void What(std::ostringstream& os) { os << "value"; }
+};
+
+// returns buffer param size
+struct BufferSizeGetter {
+    static size_t Get(const RawBuffer& buffer) { return buffer.size(); }
+    static void What(std::ostringstream& os) { os << "buffer size"; }
+};
+
+
+////////// ErrorHandlers //////////////
+
+struct ThrowingHandler {
+    static void Handle(std::string message) {
+        ThrowErr(Exc::Crypto::InputParam, message);
+    }
+};
+
+
+// base class for parameter check
+struct ParamCheckBase {
+    virtual ~ParamCheckBase() {}
+    virtual void Check(const CryptoAlgorithm& ca) const = 0;
+};
+
+typedef std::unique_ptr<const ParamCheckBase> ParamCheckBasePtr;
+
+typedef std::vector<ParamCheckBasePtr> ValidatorVector;
+
+
+// ValidatorVector builder. Creates a vector of ParamCheckBasePtr's specified as Args
+template <typename ...Args>
+struct VBuilder;
+
+template <typename First>
+struct VBuilder<First> {
+static ValidatorVector Build() {
+        ValidatorVector validators;
+        Add(validators);
+        return validators;
+    }
+protected:
+    static void Add(ValidatorVector& validators) {
+        validators.emplace_back(new First);
+    }
+};
+
+template <typename First, typename ...Args>
+struct VBuilder<First, Args...> : public VBuilder<First>, public VBuilder<Args...> {
+    static ValidatorVector Build() {
+        ValidatorVector validators;
+        Add(validators);
+        return validators;
+    }
+protected:
+    static void Add(ValidatorVector& validators) {
+        VBuilder<First>::Add(validators);
+        VBuilder<Args...>::Add(validators);
+    }
+};
+
+/*
+ * Generic struct responsible for checking a single constraint on given algorithm parameter
+ *
+ * Name - name of param to check
+ * Type - type of param value
+ * Mandatory - true if param is mandatory
+ * Validator - class providing validation function bool Check(const CryptoAlgorithm&)
+ * Getter - gets the value used for validation (param value itself or a buffer size for example)
+ * ErrorHandler - class providing method for error handling void Handle(std::string)
+ */
+
+template <ParamName Name,
+          typename Type,
+          bool Mandatory,
+          typename Validator = DefaultValidator<Type>,
+          typename Getter = DefaultGetter<Type>,
+          typename ErrorHandler = ThrowingHandler>
+struct ParamCheck : public ParamCheckBase {
+    void Check(const CryptoAlgorithm& ca) const {
+        Type value;
+        std::ostringstream os;
+
+        // check existence
+        if(!ca.getParam(Name,value)) {
+            if (Mandatory) {
+                os << "Mandatory parameter " << static_cast<int>(Name) << " doesn't exist";
+                ErrorHandler::Handle(os.str());
+            }
+            return;
+        }
+        // validate
+        if(!Validator::Check(Getter::Get(value))) {
+            os << "The ";
+            Getter::What(os);
+            os << " of param '" << static_cast<int>(Name) << "'=" <<
+                  static_cast<int>(Getter::Get(value)) << " ";
+            Validator::Why(os);
+            ErrorHandler::Handle(os.str());
+        }
+    }
+};
+
+} // namespace Crypto
+} // namespace CKM
index 89c131f..8612631 100644 (file)
@@ -21,6 +21,7 @@
 #include <exception>
 #include <fstream>
 #include <utility>
+#include <algorithm>
 
 #include <openssl/evp.h>
 #include <openssl/obj_mac.h>
@@ -39,6 +40,7 @@
 #include <dpl/log/log.h>
 
 #include <generic-backend/exception.h>
+#include <generic-backend/algo-validation.h>
 #include <sw-backend/internals.h>
 #include <sw-backend/crypto.h>
 
 #define DEV_HW_RANDOM_FILE    "/dev/hwrng"
 #define DEV_URANDOM_FILE    "/dev/urandom"
 
+namespace CKM {
+namespace Crypto {
+namespace SW {
+namespace Internals {
+
 namespace {
 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
@@ -54,52 +61,162 @@ typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
 
 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
-CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
+
+const size_t DEFAULT_AES_GCM_TAG_LEN = 128; // tag length in bits according to W3C Crypto API
+const size_t DEFAULT_AES_IV_LEN = 16; // default iv size in bytes for AES
+
+RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
 
     if (NULL == pkey) {
-        ThrowErr(CKM::Exc::Crypto::InternalError, "attempt to parse an empty key!");
+        ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!");
     }
 
     if (NULL == bio.get()) {
-        ThrowErr(CKM::Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
+        ThrowErr(Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
     }
 
     if (1 != fun(bio.get(), pkey)) {
-        ThrowErr(CKM::Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
+        ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
     }
 
-    CKM::RawBuffer output(8196);
+    RawBuffer output(8196);
 
     int size = BIO_read(bio.get(), output.data(), output.size());
 
     if (size <= 0) {
-        ThrowErr(CKM::Exc::Crypto::InternalError, "Error in BIO_read: ", size);
+        ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size);
     }
 
     output.resize(size);
     return output;
 }
 
-template<typename T>
-T unpack(
-    const CKM::CryptoAlgorithm &alg,
-    CKM::ParamName paramName)
+// encryption / decryption
+typedef ParamCheck<ParamName::ALGO_TYPE,
+                   AlgoType,
+                   true,
+                   Type<AlgoType>::Equals<AlgoType::AES_CTR,
+                                          AlgoType::AES_CBC,
+                                          AlgoType::AES_GCM,
+                                          AlgoType::AES_CFB,
+                                          AlgoType::RSA_OAEP>> IsEncryption;
+
+typedef ParamCheck<ParamName::ED_IV,
+                   RawBuffer,
+                   true,
+                   Type<size_t>::Equals<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,
+                   DefaultValidator<size_t>,
+                   BufferSizeGetter> GcmIvCheck;
+
+typedef ParamCheck<ParamName::ED_TAG_LEN,
+                   int,
+                   false,
+                   Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
+
+// 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>> 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, 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 std::map<AlgoType, ValidatorVector> ValidatorMap;
+ValidatorMap initValidators() {
+    ValidatorMap validators;
+    validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
+    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::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());
+    return validators;
+};
+ValidatorMap g_validators = initValidators();
+
+template <typename TypeCheck>
+void validateParams(const CryptoAlgorithm& ca)
 {
-    T result;
-    if (!alg.getParam(paramName, result)) {
-        ThrowErr(CKM::Exc::Crypto::InputParam, "Wrong input param");
+    // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
+    TypeCheck tc;
+    tc.Check(ca);
+
+    AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
+    for(const auto& validator : g_validators.at(at)) {
+        validator->Check(ca);
     }
-    return result;
 }
 
 } // anonymous namespace
 
-namespace CKM {
-namespace Crypto {
-namespace SW {
-namespace Internals {
-
 int initialize() {
     int hw_rand_ret = 0;
     int u_rand_ret = 0;
@@ -332,6 +449,34 @@ Token createKeyAES(CryptoBackend backendId, const int sizeBits)
     return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
 }
 
+TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+{
+    validateParams<IsAsymGeneration>(algorithm);
+
+    AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
+    if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN)
+    {
+        int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
+        if(keyType == AlgoType::RSA_GEN)
+            return createKeyPairRSA(backendId, keyLength);
+        else
+            return createKeyPairDSA(backendId, keyLength);
+    }
+    else // AlgoType::ECDSA_GEN
+    {
+        ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
+        return createKeyPairECDSA(backendId, ecType);
+    }
+}
+
+Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+{
+    validateParams<IsSymGeneration>(algorithm);
+
+    int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
+    return createKeyAES(backendId, keySizeBits);
+}
+
 RawBuffer encryptDataAesCbc(
     const RawBuffer &key,
     const RawBuffer &data,
@@ -423,6 +568,7 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &data)
 {
+    validateParams<IsEncryption>(alg);
     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
     switch(keyType)
@@ -430,8 +576,14 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
         case AlgoType::AES_CBC:
             return encryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
         case AlgoType::AES_GCM:
-            return encryptDataAesGcmPacked(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV),
-              unpack<int>(alg, ParamName::ED_TAG_LEN));
+        {
+            int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
+            alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
+            return encryptDataAesGcmPacked(key,
+                                           data,
+                                           unpack<RawBuffer>(alg, ParamName::ED_IV),
+                                           tagLenBits/8);
+        }
         default:
             break;
     }
@@ -443,6 +595,7 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &data)
 {
+    validateParams<IsEncryption>(alg);
     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
 
     switch(keyType)
@@ -450,8 +603,14 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
         case AlgoType::AES_CBC:
             return decryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
         case AlgoType::AES_GCM:
-            return decryptDataAesGcmPacked(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV),
-                unpack<int>(alg, ParamName::ED_TAG_LEN));
+        {
+            int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
+            alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
+            return decryptDataAesGcmPacked(key,
+                                           data,
+                                           unpack<RawBuffer>(alg, ParamName::ED_IV),
+                                           tagLenBits/8);
+        }
         default:
             break;
     }
@@ -462,6 +621,8 @@ RawBuffer sign(EVP_PKEY *pkey,
     const CryptoAlgorithm &alg,
     const RawBuffer &message)
 {
+    validateParams<IsSignVerify>(alg);
+
     int rsa_padding = NOT_DEFINED;
     const EVP_MD *md_algo = NULL;
 
@@ -600,6 +761,8 @@ int verify(EVP_PKEY *pkey,
     const RawBuffer &message,
     const RawBuffer &signature)
 {
+    validateParams<IsSignVerify>(alg);
+
     int rsa_padding = NOT_DEFINED;
     const EVP_MD *md_algo = NULL;
 
index 833c88a..d9869b5 100644 (file)
@@ -50,6 +50,9 @@ TokenPair createKeyPairDSA(CryptoBackend backendId, const int size);
 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type1);
 Token     createKeyAES(CryptoBackend backendId, const int sizeBits);
 
+TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm);
+Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm);
+
 RawBuffer symmetricEncrypt(const RawBuffer &key,
                            const CryptoAlgorithm &alg,
                            const RawBuffer &data);
@@ -60,7 +63,7 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(const RawBuffer &key,
     const RawBuffer &data,
     const RawBuffer &iv,
-    int tagSize);
+    int tagSizeBits);
 
 RawBuffer decryptDataAesGcm(const RawBuffer &key,
     const RawBuffer &data,
index 1e81a3b..7ff0ebb 100644 (file)
@@ -37,6 +37,26 @@ namespace CKM {
 namespace Crypto {
 namespace SW {
 
+namespace {
+
+AlgoType key2algo(DataType type) {
+    switch(static_cast<int>(type)) {
+    case DataType::Type::KEY_RSA_PRIVATE:
+    case DataType::Type::KEY_RSA_PUBLIC:
+        return AlgoType::RSA_SV;
+    case DataType::Type::KEY_DSA_PRIVATE:
+    case DataType::Type::KEY_DSA_PUBLIC:
+        return AlgoType::DSA_SV;
+    case DataType::Type::KEY_ECDSA_PRIVATE:
+    case DataType::Type::KEY_ECDSA_PUBLIC:
+        return AlgoType::ECDSA_SV;
+    default:
+        ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
+    }
+}
+
+} // namespace anonymous
+
 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
 
 RawBuffer SKey::getBinary() const {
@@ -56,7 +76,9 @@ RawBuffer AKey::sign(
     const CryptoAlgorithm &alg,
     const RawBuffer &message)
 {
-    return Internals::sign(getEvpShPtr().get(), alg, message);
+    CryptoAlgorithm algWithType(alg);
+    algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
+    return Internals::sign(getEvpShPtr().get(), algWithType, message);
 }
 
 RawBuffer AKey::getBinary() const {
@@ -64,7 +86,26 @@ RawBuffer AKey::getBinary() const {
 }
 
 int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message, const RawBuffer &sign) {
-    return Internals::verify(getEvpShPtr().get(), alg, message, sign);
+    CryptoAlgorithm algWithType(alg);
+    EVP_PKEY* evp = getEvpShPtr().get();
+    AlgoType type;
+
+    // setup algorithm type basing on evp key type if it doesn't exist
+    if(!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
+        int subType = EVP_PKEY_type(evp->type);
+        switch(subType) {
+        case EVP_PKEY_RSA:
+            type = AlgoType::RSA_SV; break;
+        case EVP_PKEY_DSA:
+            type = AlgoType::DSA_SV; break;
+        case EVP_PKEY_EC:
+            type = AlgoType::ECDSA_SV; break;
+        default:
+            ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
+        }
+        algWithType.setParam(ParamName::ALGO_TYPE, type);
+    }
+    return Internals::verify(evp, algWithType, message, sign);
 }
 
 EvpShPtr AKey::getEvpShPtr() {
index 8888ea9..4d6b1bf 100644 (file)
@@ -68,38 +68,12 @@ GKeyUPtr Store::getKey(const Token &token) {
 
 TokenPair Store::generateAKey(const CryptoAlgorithm &algorithm)
 {
-    AlgoType keyType = AlgoType::RSA_GEN;
-    algorithm.getParam(ParamName::ALGO_TYPE, keyType);
-
-    if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN)
-    {
-        int keyLength = 0;
-        if(!algorithm.getParam(ParamName::GEN_KEY_LEN, keyLength))
-            ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_KEY_LEN not found.");
-
-        if(keyType == AlgoType::RSA_GEN)
-            return Internals::createKeyPairRSA(m_backendId, keyLength);
-        else
-            return Internals::createKeyPairDSA(m_backendId, keyLength);
-    }
-    else if(keyType == AlgoType::ECDSA_GEN)
-    {
-        int ecType = 0;
-        if(!algorithm.getParam(ParamName::GEN_EC, ecType))
-            ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_EC not found.");
-
-        return Internals::createKeyPairECDSA(m_backendId, static_cast<ElipticCurve>(ecType));
-    }
-    ThrowErr(Exc::Crypto::InputParam, "wrong key type");
+    return Internals::generateAKey(m_backendId, algorithm);
 }
 
 Token Store::generateSKey(const CryptoAlgorithm &algorithm)
 {
-    int keyLength = 0;
-    if(!algorithm.getParam(ParamName::GEN_KEY_LEN, keyLength))
-        ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_KEY_LEN not found.");
-
-    return Internals::createKeyAES(m_backendId, keyLength);
+    return Internals::generateSKey(m_backendId, algorithm);
 }
 
 Token Store::import(DataType dataType, const RawBuffer &buffer) {
index a173cd7..0a6893f 100644 (file)
@@ -1145,6 +1145,7 @@ int CKMLogic::createKeyAESHelper(
     const PolicySerializable &policy)
 {
     CryptoAlgorithm keyGenAlgorithm;
+    keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
     keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
     Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm);