*/
#include <exception>
#include <fstream>
+#include <utility>
+#include <algorithm>
-#include <openssl/x509_vfy.h>
#include <openssl/evp.h>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <openssl/dsa.h>
-#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/obj_mac.h>
#include <ckm/ckm-error.h>
-#include <ckm/ckm-type.h>
-#include <key-impl.h>
#include <assert.h>
#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 OPENSSL_SUCCESS 1 // DO NOTCHANGE THIS VALUE
#define OPENSSL_FAIL 0 // DO NOTCHANGE THIS VALUE
#define DEV_HW_RANDOM_FILE "/dev/hwrng"
#define DEV_URANDOM_FILE "/dev/urandom"
-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;
-} // anonymous namespace
-
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;
+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*);
+
+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(Exc::Crypto::InternalError, "attempt to parse an empty key!");
+ }
+
+ if (NULL == bio.get()) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
+ }
+
+ if (1 != fun(bio.get(), pkey)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
+ }
+
+ RawBuffer output(8196);
+
+ int size = BIO_read(bio.get(), output.data(), output.size());
+
+ if (size <= 0) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size);
+ }
+
+ output.resize(size);
+ 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,
+ 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)
+{
+ // 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);
+ }
+}
+
+} // anonymous namespace
+
int initialize() {
int hw_rand_ret = 0;
int u_rand_ret = 0;
hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
if(hw_rand_ret != 32) {
- LogError("Error in U_RAND_file_load");
- ThrowMsg(Crypto::Exception::InternalError, "Error in U_RAND_file_load");
+ ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
}
}
md_algo = EVP_sha512();
break;
default:
- LogError("Error in hashAlgorithm value");
- ThrowMsg(Crypto::Exception::InternalError, "Error in hashAlgorithm value");
+ ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
}
return md_algo;
}
rsa_padding = RSA_X931_PADDING;
break;
default:
- LogError("Error in RSAPaddingAlgorithm value");
- ThrowMsg(Crypto::Exception::InternalError, "Error in RSAPaddingAlgorithm value");
+ ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
}
return rsa_padding;
}
-void createKeyPairRSA(const int size, // size in bits [1024, 2048, 4096]
- KeyImpl &createdPrivateKey, // returned value
- KeyImpl &createdPublicKey) // returned value
+TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
{
- EVP_PKEY_CTX *ctx = NULL;
- EVP_PKEY *pkey = NULL;
- EVP_PKEY *pparam = NULL;
+ EvpPkeyUPtr pkey;
// check the parameters of functions
- if(size != 1024 && size !=2048 && size != 4096) {
- LogError("Error in RSA input size");
- ThrowMsg(Crypto::Exception::InternalError, "Error in RSA input size");
+ if(size!=1024 && size!=2048 && size!=4096) {
+ ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
}
- // check the parameters of functions
- if(&createdPrivateKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Crypto::Exception::InternalError, "Error in createdPrivateKey value");
+ EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
+ if(!ctx) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
}
- // check the parameters of functions
- if(&createdPublicKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Crypto::Exception::InternalError, "Error in createdPublicKey value");
+ if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
}
- Try {
- if(!(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL))) {
- LogError("Error in EVP_PKEY_CTX_new_id function !!");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
- }
+ if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
+ }
- if(EVP_PKEY_keygen_init(ctx) <= 0) {
- LogError("Error in EVP_PKEY_keygen_init function !!");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function !!");
- }
+ EVP_PKEY *pkeyTmp = NULL;
+ if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
+ }
+ pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
- if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx,size) <= 0) {
- LogError("Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
- }
+ return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
+ Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
+}
- if(!EVP_PKEY_keygen(ctx, &pkey)) {
- LogError("Error in EVP_PKEY_keygen function !!");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function !!");
- }
- } Catch(Crypto::Exception::InternalError) {
- if(pkey) {
- EVP_PKEY_free(pkey);
- }
- if(pparam) {
- EVP_PKEY_free(pparam);
- }
+TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
+{
+ EvpPkeyUPtr pkey;
+ EvpPkeyUPtr pparam;
- if(ctx) {
- EVP_PKEY_CTX_free(ctx);
- }
+ // check the parameters of functions
+ if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
+ ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
+ }
- ReThrowMsg(Crypto::Exception::InternalError,"Error in opensslError function !!");
+ /* Create the context for generating the parameters */
+ EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
+ if(!pctx) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
}
- KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
+ if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
+ }
- createdPrivateKey = KeyImpl(ptr, KeyType::KEY_RSA_PRIVATE);
- createdPublicKey = KeyImpl(ptr, KeyType::KEY_RSA_PUBLIC);
+ if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
+ }
- if(pparam) {
- EVP_PKEY_free(pparam);
+ /* Generate parameters */
+ EVP_PKEY *pparamTmp = NULL;
+ if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
}
+ pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
- if(ctx) {
- EVP_PKEY_CTX_free(ctx);
+ // Start to generate key
+ EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
+ if(!kctx) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
+ }
+
+ if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
}
-}
+ /* Generate the key */
+ EVP_PKEY *pkeyTmp = NULL;
+ if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
+ }
+ pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
-void createKeyPairDSA(const int size, // size in bits [1024, 2048, 3072, 4096]
- KeyImpl &createdPrivateKey, // returned value
- KeyImpl &createdPublicKey) // returned value
-{
- EVP_PKEY_CTX *pctx = NULL;
- EVP_PKEY_CTX *kctx = NULL;
- EVP_PKEY *pkey = NULL;
- EVP_PKEY *pparam = NULL;
-
- // check the parameters of functions
- if(size != 1024 && size !=2048 && size !=3072 && size != 4096) {
- LogError("Error in DSA input size");
- ThrowMsg(Exception::InternalError, "Error in DSA input size");
- }
-
- // check the parameters of functions
- if(&createdPrivateKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Exception::InternalError, "Error in createdPrivateKey value");
- }
-
- // check the parameters of functions
- if(&createdPublicKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Exception::InternalError, "Error in createdPublicKey value");
- }
-
- Try {
- /* Create the context for generating the parameters */
- if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL))) {
- LogError("Error in EVP_PKEY_CTX_new_id function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function");
- }
-
- if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx)) {
- LogError("Error in EVP_PKEY_paramgen_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen_init function");
- }
-
- if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, size)) {
- LogError("Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(" << size << ") function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(" << size << ") function");
- }
-
- /* Generate parameters */
- if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx, &pparam)) {
- LogError("Error in EVP_PKEY_paramgen function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen function");
- }
-
- // Start to generate key
- if(!(kctx = EVP_PKEY_CTX_new(pparam, NULL))) {
- LogError("Error in EVP_PKEY_CTX_new function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
- }
-
- if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx)) {
- LogError("Error in EVP_PKEY_keygen_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function");
- }
-
- /* Generate the key */
- if(EVP_SUCCESS != EVP_PKEY_keygen(kctx, &pkey)) {
- LogError("Error in EVP_PKEY_keygen function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
- }
- }
- Catch(Crypto::Exception::InternalError)
- {
- if(pkey) {
- EVP_PKEY_free(pkey);
- }
-
- if(pparam) {
- EVP_PKEY_free(pparam);
- }
-
- if(pctx) {
- EVP_PKEY_CTX_free(pctx);
- }
-
- if(kctx) {
- EVP_PKEY_CTX_free(kctx);
- }
-
- ReThrowMsg(Crypto::Exception::InternalError,"Error in openssl function !!");
- }
-
- KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
-
- createdPrivateKey = KeyImpl(ptr, KeyType::KEY_DSA_PRIVATE);
- createdPublicKey = KeyImpl(ptr, KeyType::KEY_DSA_PUBLIC);
-
- if(pparam) {
- EVP_PKEY_free(pparam);
- }
-
- if(pctx) {
- EVP_PKEY_CTX_free(pctx);
- }
-
- if(kctx) {
- EVP_PKEY_CTX_free(kctx);
- }
+ return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
+ Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
}
-void createKeyPairECDSA(ElipticCurve type,
- KeyImpl &createdPrivateKey, // returned value
- KeyImpl &createdPublicKey) // returned value
+TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
{
int ecCurve = NOT_DEFINED;
- EVP_PKEY_CTX *pctx = NULL;
- EVP_PKEY_CTX *kctx = NULL;
- EVP_PKEY *pkey = NULL;
- EVP_PKEY *pparam = NULL;
+ EvpPkeyUPtr pkey;
+ EvpPkeyUPtr pparam;
switch(type) {
case ElipticCurve::prime192v1:
ecCurve = NID_secp384r1;
break;
default:
- LogError("Error in EC type");
- ThrowMsg(Exception::InternalError, "Error in EC type");
+ ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
}
- // check the parameters of functions
- if(&createdPrivateKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Exception::InternalError, "Error in createdPrivateKey value");
+ /* Create the context for generating the parameters */
+ EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
+ if(!pctx) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
}
- // check the parameters of functions
- if(&createdPublicKey == NULL) {
- LogError("Error in createdPrivateKey value");
- ThrowMsg(Exception::InternalError, "Error in createdPublicKey value");
+ if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
}
- Try {
- /* Create the context for generating the parameters */
- if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
- LogError("Error in EVP_PKEY_CTX_new_id function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function");
- }
+ if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
+ }
- if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx)) {
- LogError("Error in EVP_PKEY_paramgen_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen_init function");
- }
+ /* Generate parameters */
+ EVP_PKEY *pparamTmp = NULL;
+ if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
+ }
+ pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
- if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecCurve)) {
- LogError("Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
- }
+ // Start to generate key
+ EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
+ if(!kctx) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
+ }
- /* Generate parameters */
- if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx, &pparam)) {
- LogError("Error in EVP_PKEY_paramgen function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen function");
- }
+ if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
+ }
- // Start to generate key
- if(!(kctx = EVP_PKEY_CTX_new(pparam, NULL))) {
- LogError("Error in EVP_PKEY_CTX_new function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
- }
+ /* Generate the key */
+ EVP_PKEY *pkeyTmp = NULL;
+ if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
+ }
+ pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
- if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx)) {
- LogError("Error in EVP_PKEY_keygen_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function");
- }
+ return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
+ Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
+}
- /* Generate the key */
- if(EVP_SUCCESS != EVP_PKEY_keygen(kctx, &pkey)) {
- LogError("Error in EVP_PKEY_keygen function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
- }
- } Catch(Crypto::Exception::InternalError) {
- if(pkey) {
- EVP_PKEY_free(pkey);
- }
+Token createKeyAES(CryptoBackend backendId, const int sizeBits)
+{
+ // check the parameters of functions
+ if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
+ LogError("Error in AES input size");
+ ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
+ }
- if(pparam) {
- EVP_PKEY_free(pparam);
- }
+ uint8_t key[32];
+ int sizeBytes = sizeBits/8;
+ if (!RAND_bytes(key, sizeBytes)) {
+ LogError("Error in AES key generation");
+ ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
+ }
- if(pctx) {
- EVP_PKEY_CTX_free(pctx);
- }
+ return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
+}
- if(kctx) {
- EVP_PKEY_CTX_free(kctx);
- }
+TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+{
+ validateParams<IsAsymGeneration>(algorithm);
- ReThrowMsg(Crypto::Exception::InternalError,"Error in openssl function !!");
+ 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);
}
+}
- KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
+Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
+{
+ validateParams<IsSymGeneration>(algorithm);
- createdPrivateKey = KeyImpl(ptr, KeyType::KEY_ECDSA_PRIVATE);
- createdPublicKey = KeyImpl(ptr, KeyType::KEY_ECDSA_PUBLIC);
+ int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
+ return createKeyAES(backendId, keySizeBits);
+}
- if(pparam) {
- EVP_PKEY_free(pparam);
- }
+RawBuffer encryptDataAesCbc(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv)
+{
+ Crypto::SW::Cipher::AesCbcEncryption enc(key, iv);
+ RawBuffer result = enc.Append(data);
+ RawBuffer tmp = enc.Finalize();
+ std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
+ return result;
+}
+
+std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv,
+ int tagSize)
+{
+ RawBuffer tag(tagSize);
+ Crypto::SW::Cipher::AesGcmEncryption enc(key, iv);
+ RawBuffer result = enc.Append(data);
+ RawBuffer tmp = enc.Finalize();
+ std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
+ if (0 == enc.Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) {
+ ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Get tag failed.");
+ }
+ return std::make_pair(result, tag);
+}
+
+RawBuffer encryptDataAesGcmPacked(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv,
+ int tagSize)
+{
+ auto pair = encryptDataAesGcm(key, data, iv, tagSize);
+ std::copy(pair.second.begin(), pair.second.end(), std::back_inserter(pair.first));
+ return pair.first;
+}
+
+RawBuffer decryptDataAesCbc(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv)
+{
+ Crypto::SW::Cipher::AesCbcDecryption dec(key, iv);
+ RawBuffer result = dec.Append(data);
+ RawBuffer tmp = dec.Finalize();
+ std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
+ return result;
+}
+
+RawBuffer decryptDataAesGcm(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv,
+ const RawBuffer &tag)
+{
+ Crypto::SW::Cipher::AesGcmDecryption dec(key, iv);
+ void *ptr = (void*)tag.data();
+ if (0 == dec.Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) {
+ ThrowErr(Exc::Crypto::InternalError,
+ "Error in AES control function. Set tag failed.");
+ }
+ RawBuffer result = dec.Append(data);
+ RawBuffer tmp = dec.Finalize();
+ std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
+ return result;
+}
- if(pctx) {
- EVP_PKEY_CTX_free(pctx);
+RawBuffer decryptDataAesGcmPacked(
+ const RawBuffer &key,
+ const RawBuffer &data,
+ const RawBuffer &iv,
+ int tagSize)
+{
+ 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()));
+}
+
+RawBuffer symmetricEncrypt(const RawBuffer &key,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
+{
+ validateParams<IsEncryption>(alg);
+ AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+
+ switch(keyType)
+ {
+ case AlgoType::AES_CBC:
+ return encryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
+ case AlgoType::AES_GCM:
+ {
+ 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;
}
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "symmetric enc error: algorithm not recognized");
+}
+
+RawBuffer symmetricDecrypt(const RawBuffer &key,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
+{
+ validateParams<IsEncryption>(alg);
+ AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
- if(kctx) {
- EVP_PKEY_CTX_free(kctx);
+ switch(keyType)
+ {
+ case AlgoType::AES_CBC:
+ return decryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
+ case AlgoType::AES_GCM:
+ {
+ 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;
}
+ ThrowErr(Exc::Crypto::InputParam, "symmetric dec error: algorithm not recognized");
}
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;
// (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
// {
// LogError("Error in private key type");
-// ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
+// ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
// }
//
// if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
// }
if (NULL == pkey) {
- LogError("Error in EVP_PKEY_keygen function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
}
if(md_algo == NULL) {
EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
if(!pctx.get()) {
- LogError("Error in EVP_PKEY_CTX_new function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
}
if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
- LogError("Error in EVP_PKEY_sign_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign_init function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
}
/* Set padding algorithm */
if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
- LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
- ThrowMsg(Crypto::Exception::InternalError,
+ ThrowErr(Exc::Crypto::InternalError,
"Error in EVP_PKEY_CTX_set_rsa_padding function");
}
}
* signature. Length is returned in slen */
size_t slen;
if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
- LogError("Error in EVP_PKEY_sign function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
}
/* Allocate memory for the signature based on size in slen */
return sig;
}
- LogError("Error in EVP_PKEY_sign function. Input param error.");
- ThrowMsg(Crypto::Exception::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
+ ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
}
RawBuffer digestSignMessage(EVP_PKEY *privKey,
// Create the Message Digest Context
if(!mdctx.get()) {
- LogError("Error in EVP_MD_CTX_create function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
}
if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
- LogError("Error in EVP_DigestSignInit function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignInit function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
}
/* Set padding algorithm */
if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
- LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
}
}
/* Call update with the message */
if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
- LogError("Error in EVP_DigestSignUpdate function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignUpdate function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
}
/* Finalize the DigestSign operation */
* signature. Length is returned in slen */
size_t slen;
if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
- LogError("Error in EVP_DigestSignFinal function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
}
/* Allocate memory for the signature based on size in slen */
/* Obtain the signature */
if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
- LogError("Error in EVP_DigestSignFinal function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
}
// Set value to return RawData
const RawBuffer &message,
const RawBuffer &signature)
{
+ validateParams<IsSignVerify>(alg);
+
int rsa_padding = NOT_DEFINED;
const EVP_MD *md_algo = NULL;
// (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
// {
// LogError("Error in private key type");
-// ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
+// ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
// }
//
// if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
// auto shrPKey = publicKey.getEvpShPtr();
if (NULL == pkey) {
- LogError("Error in getEvpShPtr function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in getEvpShPtr function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
}
if (md_algo == NULL) {
EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
if(!pctx.get()) {
- LogError("Error in EVP_PKEY_CTX_new function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
}
if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
- LogError("Error in EVP_PKEY_verify_init function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_verify_init function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
}
/* Set padding algorithm */
if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
- LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
}
}
/* Create the Message Digest Context */
if(!mdctx.get()) {
- LogError("Error in EVP_MD_CTX_create function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
}
if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
- LogError("Error in EVP_DigestVerifyInit function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyInit function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
}
if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
- LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
}
}
if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
- LogError("Error in EVP_DigestVerifyUpdate function");
- ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyUpdate function");
+ ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
}
if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {