2 * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
26 #include <openssl/evp.h>
27 #include <openssl/obj_mac.h>
28 #include <openssl/ec.h>
29 #include <openssl/dsa.h>
30 #include <openssl/rsa.h>
31 #include <openssl/bio.h>
32 #include <openssl/rand.h>
33 #include <openssl/crypto.h>
34 #include <openssl/err.h>
35 #include <openssl/x509v3.h>
36 #include <openssl/obj_mac.h>
37 #include <openssl/kdf.h>
39 #include <ckm/ckm-error.h>
41 #include <dpl/log/log.h>
44 #include <generic-backend/exception.h>
45 #include <generic-backend/algo-validation.h>
46 #include <generic-backend/crypto-params.h>
47 #include <sw-backend/internals.h>
48 #include <openssl-error-handler.h>
51 #define OPENSSL_SUCCESS 1 // DO NOT CHANGE THIS VALUE
52 #define OPENSSL_FAIL 0 // DO NOT CHANGE THIS VALUE
60 typedef Uptr<EVP_PKEY_CTX_free, EVP_PKEY_CTX> EvpPkeyCtxUPtr;
62 typedef int(*I2D_CONV)(BIO *, EVP_PKEY *);
65 RawBuffer i2d(I2D_CONV fun, EVP_PKEY *pkey)
67 auto bio = uptr<BIO_free_all>(BIO_new(BIO_s_mem()));
70 ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!");
72 if (NULL == bio.get())
73 ThrowErr(Exc::Crypto::InternalError,
74 "Error in memory allocation! Function: BIO_new.");
76 if (1 != fun(bio.get(), pkey))
77 ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
79 RawBuffer output(8196);
81 int size = BIO_read(bio.get(), output.data(), output.size());
84 ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size);
90 // encryption / decryption
91 typedef ParamCheck<ParamName::ALGO_TYPE,
94 Type<AlgoType>::Equals<AlgoType::AES_CTR,
97 AlgoType::AES_CFB>> IsSymEncryption;
99 typedef ParamCheck<ParamName::ALGO_TYPE,
102 Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
104 typedef ParamCheck<ParamName::ED_IV,
107 Type<size_t>::Equals<Params::DEFAULT_AES_IV_LEN>,
108 BufferSizeGetter> IvSizeCheck;
110 typedef ParamCheck<ParamName::ED_CTR_LEN,
113 Type<int>::Equals<128>> CtrLenCheck;
115 typedef ParamCheck<ParamName::ED_IV,
118 DefaultValidator<RawBuffer>> GcmIvCheck;
120 typedef ParamCheck<ParamName::ED_TAG_LEN,
123 Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
125 typedef ParamCheck<ParamName::ED_LABEL,
128 Unsupported<RawBuffer>> RsaLabelCheck;
131 typedef ParamCheck<ParamName::ALGO_TYPE,
134 Type<AlgoType>::Equals<AlgoType::RSA_SV,
136 AlgoType::ECDSA_SV>> IsSignVerify;
138 typedef ParamCheck<ParamName::SV_HASH_ALGO,
141 Type<HashAlgorithm>::Equals<HashAlgorithm::NONE,
143 HashAlgorithm::SHA256,
144 HashAlgorithm::SHA384,
145 HashAlgorithm::SHA512>> HashAlgoCheck;
147 typedef ParamCheck<ParamName::SV_RSA_PADDING,
150 Type<RSAPaddingAlgorithm>::Equals<RSAPaddingAlgorithm::NONE,
151 RSAPaddingAlgorithm::PKCS1,
152 RSAPaddingAlgorithm::X931>> RsaPaddingCheck;
155 typedef ParamCheck<ParamName::ALGO_TYPE,
158 Type<AlgoType>::Equals<AlgoType::RSA_GEN,
160 AlgoType::ECDSA_GEN>> IsAsymGeneration;
162 typedef ParamCheck<ParamName::ALGO_TYPE,
165 Type<AlgoType>::Equals<AlgoType::AES_GEN>> IsSymGeneration;
167 typedef ParamCheck<ParamName::GEN_KEY_LEN,
170 Type<int>::Equals<1024, 2048, 4096>> RsaKeyLenCheck;
172 typedef ParamCheck<ParamName::GEN_KEY_LEN,
175 Type<int>::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck;
177 typedef ParamCheck<ParamName::GEN_KEY_LEN,
180 Type<int>::Equals<128, 192, 256>> AesKeyLenCheck;
182 typedef ParamCheck<ParamName::GEN_EC,
185 Type<ElipticCurve>::Equals<ElipticCurve::prime192v1,
186 ElipticCurve::prime256v1,
187 ElipticCurve::secp384r1>> EcdsaEcCheck;
190 typedef ParamCheck<ParamName::ALGO_TYPE,
193 Type<AlgoType>::Equals<AlgoType::ECDH>> IsEcdh;
195 typedef ParamCheck<ParamName::ECDH_PUBKEY,
198 DefaultValidator<RawBuffer>> EcdhPubKeyCheck;
200 typedef ParamCheck<ParamName::ALGO_TYPE,
203 Type<AlgoType>::Equals<AlgoType::KBKDF>> IsKbkdf;
205 typedef ParamCheck<ParamName::KDF_PRF,
208 Type<KdfPrf>::Equals<KdfPrf::HMAC_SHA256,
210 KdfPrf::HMAC_SHA512>> KdfPrfCheck;
212 typedef ParamCheck<ParamName::KBKDF_MODE,
215 Type<KbkdfMode>::Equals<KbkdfMode::COUNTER>> KbkdfModeCheck;
217 typedef ParamCheck<ParamName::KDF_LEN,
220 Type<int>::Equals<16, 24, 32>> KdfLenCheck;
222 typedef ParamCheck<ParamName::KBKDF_COUNTER_LOCATION,
223 KbkdfCounterLocation,
225 Type<KbkdfCounterLocation>::Equals<KbkdfCounterLocation::BEFORE_FIXED,
226 KbkdfCounterLocation::AFTER_FIXED,
227 KbkdfCounterLocation::MIDDLE_FIXED>> KbkdfCounterLocationCheck;
229 typedef ParamCheck<ParamName::KBKDF_RLEN,
232 Type<int>::Equals<8, 16, 24, 32>> KbkdfRlenCheck;
234 typedef ParamCheck<ParamName::KBKDF_LLEN,
237 Type<int>::Equals<0, 8, 16, 24, 32>> KbkdfLlenCheck;
240 typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
241 ValidatorMap initValidators()
243 ValidatorMap validators;
244 validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
245 validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
246 validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
247 validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
248 validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
249 validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
250 validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
251 validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
252 validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
253 validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
254 validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
255 validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck>::Build());
256 validators.emplace(AlgoType::ECDH, VBuilder<EcdhPubKeyCheck>::Build());
257 validators.emplace(AlgoType::KBKDF, VBuilder<KdfPrfCheck,
260 KbkdfCounterLocationCheck,
262 KbkdfLlenCheck>::Build());
266 const ValidatorMap g_validators = initValidators();
268 template <typename TypeCheck>
269 void validateParams(const CryptoAlgorithm &ca)
271 // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
275 AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
277 auto it = g_validators.find(at);
279 // TypeCheck should prevent it
280 assert(it != g_validators.end());
282 for (const auto &validator : it->second)
283 validator->Check(ca);
286 typedef std::function<void(EvpCipherPtr &, const RawBuffer &key, const RawBuffer &iv)>
289 // aes mode, key length in bits, encryption
290 typedef std::map<AlgoType, std::map<size_t, std::map<bool, InitCipherFn>>>
293 template <typename T>
294 void initCipher(EvpCipherPtr &ptr, const RawBuffer &key, const RawBuffer &iv)
296 ptr.reset(new T(key, iv));
299 CipherTree initializeCipherTree()
302 tree[AlgoType::AES_CBC][128][true] = initCipher<Cipher::AesCbcEncryption128>;
303 tree[AlgoType::AES_CBC][192][true] = initCipher<Cipher::AesCbcEncryption192>;
304 tree[AlgoType::AES_CBC][256][true] = initCipher<Cipher::AesCbcEncryption256>;
306 tree[AlgoType::AES_CBC][128][false] = initCipher<Cipher::AesCbcDecryption128>;
307 tree[AlgoType::AES_CBC][192][false] = initCipher<Cipher::AesCbcDecryption192>;
308 tree[AlgoType::AES_CBC][256][false] = initCipher<Cipher::AesCbcDecryption256>;
310 tree[AlgoType::AES_GCM][128][true] = initCipher<Cipher::AesGcmEncryption128>;
311 tree[AlgoType::AES_GCM][192][true] = initCipher<Cipher::AesGcmEncryption192>;
312 tree[AlgoType::AES_GCM][256][true] = initCipher<Cipher::AesGcmEncryption256>;
314 tree[AlgoType::AES_GCM][128][false] = initCipher<Cipher::AesGcmDecryption128>;
315 tree[AlgoType::AES_GCM][192][false] = initCipher<Cipher::AesGcmDecryption192>;
316 tree[AlgoType::AES_GCM][256][false] = initCipher<Cipher::AesGcmDecryption256>;
318 tree[AlgoType::AES_CTR][128][true] = initCipher<Cipher::AesCtrEncryption128>;
319 tree[AlgoType::AES_CTR][192][true] = initCipher<Cipher::AesCtrEncryption192>;
320 tree[AlgoType::AES_CTR][256][true] = initCipher<Cipher::AesCtrEncryption256>;
322 tree[AlgoType::AES_CTR][128][false] = initCipher<Cipher::AesCtrDecryption128>;
323 tree[AlgoType::AES_CTR][192][false] = initCipher<Cipher::AesCtrDecryption192>;
324 tree[AlgoType::AES_CTR][256][false] = initCipher<Cipher::AesCtrDecryption256>;
326 tree[AlgoType::AES_CFB][128][true] = initCipher<Cipher::AesCfbEncryption128>;
327 tree[AlgoType::AES_CFB][192][true] = initCipher<Cipher::AesCfbEncryption192>;
328 tree[AlgoType::AES_CFB][256][true] = initCipher<Cipher::AesCfbEncryption256>;
330 tree[AlgoType::AES_CFB][128][false] = initCipher<Cipher::AesCfbDecryption128>;
331 tree[AlgoType::AES_CFB][192][false] = initCipher<Cipher::AesCfbDecryption192>;
332 tree[AlgoType::AES_CFB][256][false] = initCipher<Cipher::AesCfbDecryption256>;
337 CipherTree g_cipherTree = initializeCipherTree();
339 // key length in bytes
340 InitCipherFn selectCipher(AlgoType type, size_t key_len = 32,
341 bool encryption = true)
344 return g_cipherTree.at(type).at(key_len * 8).at(encryption);
345 } catch (const std::out_of_range &) {
346 ThrowErr(Exc::Crypto::InternalError,
347 "Unsupported cipher: ",
348 static_cast<int>(type), ", ",
355 RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char *,
356 unsigned char *, RSA *, int),
357 const std::string &logPrefix,
358 const EvpShPtr &pkey,
359 const CryptoAlgorithm &alg,
360 const RawBuffer &data)
362 validateParams<IsAsymEncryption>(alg);
365 ThrowErr(Exc::Crypto::InputParam, logPrefix, "no key");
367 RSA *rsa = EVP_PKEY_get1_RSA(pkey.get());
370 ThrowErr(Exc::Crypto::InputParam, logPrefix, "invalid key");
373 * RSA_padding_add_PKCS1_OAEP supports custom label but RSA_public_encrypt calls it with NULL
374 * value so for now label is not supported. Alternative is to rewrite the openssl implementation
375 * to support it: openssl-fips/crypto/rsa/rsa_eay.c
378 output.resize(RSA_size(rsa));
382 ret = cryptoFn(data.size(),
386 RSA_PKCS1_OAEP_PADDING);
388 errorHandle(__FILE__, __LINE__, __func__, ret);
398 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo)
402 // validateParams<IsSignVerify> should prevent it
403 assert(hashAlgo == HashAlgorithm::NONE);
406 case HashAlgorithm::SHA1:
409 case HashAlgorithm::SHA256:
412 case HashAlgorithm::SHA384:
415 case HashAlgorithm::SHA512:
420 int getRsaPadding(const RSAPaddingAlgorithm padAlgo)
424 // validateParams<IsSignVerify> should prevent it
425 assert(padAlgo == RSAPaddingAlgorithm::NONE);
426 return RSA_NO_PADDING;
428 case RSAPaddingAlgorithm::PKCS1:
429 return RSA_PKCS1_PADDING;
431 case RSAPaddingAlgorithm::X931:
432 return RSA_X931_PADDING;
436 EvpPkeyCtxUPtr newCtx(int id)
438 if (auto ctx = EVP_PKEY_CTX_new_id(id, NULL))
439 return EvpPkeyCtxUPtr(ctx);
441 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
444 EvpPkeyCtxUPtr newCtx(EVP_PKEY *pkey)
446 if (auto ctx = EVP_PKEY_CTX_new(pkey, NULL))
447 return EvpPkeyCtxUPtr(ctx);
449 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
452 DataPair keyPair(const EvpPkeyCtxUPtr &ctx, KeyType prv, KeyType pub)
454 EVP_PKEY *pkeyTmp = NULL;
456 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen(ctx.get(), &pkeyTmp));
458 auto pkey = uptr<EVP_PKEY_free>(pkeyTmp);
460 return std::make_pair<Data, Data>(
461 {DataType(prv), i2d(i2d_PrivateKey_bio, pkey.get())},
462 {DataType(pub), i2d(i2d_PUBKEY_bio, pkey.get())});
465 DataPair createKeyPairRSA(const int size)
467 // validateParams<IsAsymGeneration> should prevent it
468 assert(size == 1024 || size == 2048 || size == 4096);
470 auto ctx = newCtx(EVP_PKEY_RSA);
472 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen_init(ctx.get()));
474 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size));
476 return keyPair(ctx, KeyType::KEY_RSA_PRIVATE, KeyType::KEY_RSA_PUBLIC);
479 DataPair paramgenKeyPair(const EvpPkeyCtxUPtr &pctx, KeyType prv, KeyType pub)
481 /* Generate parameters */
482 EVP_PKEY *pparamTmp = NULL;
483 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen(pctx.get(), &pparamTmp));
485 auto pparam = uptr<EVP_PKEY_free>(pparamTmp);
487 // Start to generate key
488 auto kctx = newCtx(pparam.get());
490 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen_init(kctx.get()));
492 return keyPair(kctx, prv, pub);
495 DataPair createKeyPairDSA(const int size)
497 // validateParams<IsAsymGeneration> should prevent it
498 assert(size == 1024 || size == 2048 || size == 3072 || size == 4096);
500 /* Create the context for generating the parameters */
501 auto pctx = newCtx(EVP_PKEY_DSA);
503 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen_init(pctx.get()));
505 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size));
507 return paramgenKeyPair(pctx, KeyType::KEY_DSA_PRIVATE, KeyType::KEY_DSA_PUBLIC);
510 DataPair createKeyPairECDSA(ElipticCurve type)
516 // validateParams<IsAsymGeneration> should prevent it
517 assert(type == ElipticCurve::prime192v1);
518 ecCurve = NID_X9_62_prime192v1;
521 case ElipticCurve::prime256v1:
522 ecCurve = NID_X9_62_prime256v1;
525 case ElipticCurve::secp384r1:
526 ecCurve = NID_secp384r1;
530 /* Create the context for generating the parameters */
531 auto pctx = newCtx(EVP_PKEY_EC);
533 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen_init(pctx.get()));
535 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve));
537 return paramgenKeyPair(pctx, KeyType::KEY_ECDSA_PRIVATE, KeyType::KEY_ECDSA_PUBLIC);
540 Data createKeyAES(const int sizeBits)
542 // validateParams<IsSymGeneration> should prevent it
543 assert(sizeBits == 128 || sizeBits == 192 || sizeBits == 256);
546 int sizeBytes = sizeBits / 8;
548 if (!RAND_bytes(key, sizeBytes)) {
549 ThrowErr(Exc::Crypto::InternalError, "Error in AES key generation");
552 return { DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key + sizeBytes)};
555 RawBuffer signMessage(EVP_PKEY *privKey,
556 const RawBuffer &message,
557 const int rsa_padding)
559 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) != EVP_PKEY_RSA)
560 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
562 auto pctx = newCtx(privKey);
564 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign_init(pctx.get()));
566 /* Set padding algorithm */
567 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
568 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
570 /* Finalize the Sign operation */
571 /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
572 * signature. Length is returned in slen */
575 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size()));
577 /* Allocate memory for the signature based on size in slen */
580 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), sig.data(), &slen, message.data(), message.size()));
582 // Set value to return RawData
587 RawBuffer digestSignMessage(EVP_PKEY *privKey,
588 const RawBuffer &message,
589 const EVP_MD *md_algo,
590 const int rsa_padding)
592 EVP_PKEY_CTX *pctx = NULL;
594 // Create the Message Digest Context
595 auto mdctx = uptr<EVP_MD_CTX_free>(EVP_MD_CTX_new());
597 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
599 OPENSSL_ERROR_HANDLE(EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey));
601 /* Set padding algorithm */
602 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
603 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
605 /* Call update with the message */
606 OPENSSL_ERROR_HANDLE(EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size()));
608 /* Finalize the DigestSign operation */
609 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
610 * signature. Length is returned in slen */
613 OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), NULL, &slen));
615 /* Allocate memory for the signature based on size in slen */
618 /* Obtain the signature */
619 OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen));
621 // Set value to return RawData
626 int verifyMessage(EVP_PKEY *pubKey,
627 const RawBuffer &message,
628 const RawBuffer &signature,
629 const int rsa_padding)
631 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) != EVP_PKEY_RSA)
632 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
634 auto pctx = newCtx(pubKey);
636 OPENSSL_ERROR_HANDLE(EVP_PKEY_verify_init(pctx.get()));
638 /* Set padding algorithm */
639 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
640 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
642 if (OPENSSL_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(),
643 signature.size(), message.data(), message.size()))
644 return CKM_API_SUCCESS;
646 LogError("EVP_PKEY_verify Failed");
647 return CKM_API_ERROR_VERIFICATION_FAILED;
650 int digestVerifyMessage(EVP_PKEY *pubKey,
651 const RawBuffer &message,
652 const RawBuffer &signature,
653 const EVP_MD *md_algo,
654 const int rsa_padding)
656 EVP_PKEY_CTX *pctx = NULL;
658 // Create the Message Digest Context
659 auto mdctx = uptr<EVP_MD_CTX_free>(EVP_MD_CTX_new());
661 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
663 OPENSSL_ERROR_HANDLE(EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey));
665 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
666 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
668 OPENSSL_ERROR_HANDLE(EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()));
670 if (OPENSSL_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(),
671 const_cast<unsigned char *>(signature.data()), signature.size()))
672 return CKM_API_SUCCESS;
674 LogError("EVP_PKEY_verify Failed");
675 return CKM_API_ERROR_VERIFICATION_FAILED;
678 RawBuffer encryptDataAesGcmPacked(
679 const RawBuffer &key,
680 const RawBuffer &data,
683 const RawBuffer &aad)
685 auto pair = encryptDataAesGcm(key, data, iv, tagSize, aad);
686 std::copy(pair.second.begin(), pair.second.end(),
687 std::back_inserter(pair.first));
692 RawBuffer decryptDataAesGcmPacked(
693 const RawBuffer &key,
694 const RawBuffer &data,
697 const RawBuffer &aad)
699 if (tagSize > static_cast<int>(data.size()))
700 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
702 auto tagPos = data.data() + data.size() - tagSize;
703 return decryptDataAesGcm(
705 RawBuffer(data.data(), tagPos),
707 RawBuffer(tagPos, data.data() + data.size()),
711 EC_KEY* getEcKey(EVP_PKEY* evpKey)
713 int subType = EVP_PKEY_type(EVP_PKEY_id(evpKey));
714 if (subType != EVP_PKEY_EC)
715 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
717 EC_KEY *ecKey = EVP_PKEY_get0_EC_KEY(evpKey);
719 ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
724 int getCurve(const EC_KEY* ecKey)
726 return EC_GROUP_get_curve_name(EC_KEY_get0_group(ecKey));
732 DataPair generateAKey(const CryptoAlgorithm &algorithm)
734 validateParams<IsAsymGeneration>(algorithm);
736 AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
738 if (keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN) {
739 int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
741 if (keyType == AlgoType::RSA_GEN)
742 return createKeyPairRSA(keyLength);
744 return createKeyPairDSA(keyLength);
745 } else { // AlgoType::ECDSA_GEN
746 ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
747 return createKeyPairECDSA(ecType);
751 Data generateSKey(const CryptoAlgorithm &algorithm)
753 validateParams<IsSymGeneration>(algorithm);
755 int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
756 return createKeyAES(keySizeBits);
759 RawBuffer encryptDataAes(
761 const RawBuffer &key,
762 const RawBuffer &data,
766 selectCipher(type, key.size())(enc, key, iv);
767 RawBuffer result = enc->Append(data);
768 RawBuffer tmp = enc->Finalize();
769 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
773 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
774 const RawBuffer &key,
775 const RawBuffer &data,
778 const RawBuffer &aad)
780 RawBuffer tag(tagSize);
782 selectCipher(AlgoType::AES_GCM, key.size())(enc, key, iv);
787 RawBuffer result = enc->Append(data);
788 RawBuffer tmp = enc->Finalize();
789 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
791 enc->Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data());
793 return std::make_pair(result, tag);
796 RawBuffer decryptDataAes(
798 const RawBuffer &key,
799 const RawBuffer &data,
803 selectCipher(type, key.size(), false)(dec, key, iv);
804 RawBuffer result = dec->Append(data);
807 tmp = dec->Finalize();
808 } catch (const Exc::Exception &e) {
809 ThrowErr(Exc::InputParam, "Authentication failed in AES finalize function (wrong key/data was used).");
811 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
815 RawBuffer decryptDataAesGcm(
816 const RawBuffer &key,
817 const RawBuffer &data,
819 const RawBuffer &tag,
820 const RawBuffer &aad)
823 selectCipher(AlgoType::AES_GCM, key.size(), false)(dec, key, iv);
824 void *ptr = (void *)tag.data();
826 dec->Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr);
831 RawBuffer result = dec->Append(data);
834 tmp = dec->Finalize();
835 } catch (const Exc::Exception &e) {
836 ThrowErr(Exc::InputParam, "Tag authentication failed in AES finalize function (the tag doesn't match).");
838 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
842 RawBuffer symmetricEncrypt(const RawBuffer &key,
843 const CryptoAlgorithm &alg,
844 const RawBuffer &data)
846 validateParams<IsSymEncryption>(alg);
847 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
849 if (algo == AlgoType::AES_GCM) {
850 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
851 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
853 alg.getParam(ParamName::ED_AAD, aad);
854 return encryptDataAesGcmPacked(key,
856 unpack<RawBuffer>(alg, ParamName::ED_IV),
860 // validateParams<IsSymEncryption> should prevent it
861 assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
862 return encryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
865 RawBuffer symmetricDecrypt(const RawBuffer &key,
866 const CryptoAlgorithm &alg,
867 const RawBuffer &data)
869 validateParams<IsSymEncryption>(alg);
870 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
872 if (algo == AlgoType::AES_GCM) {
873 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
874 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
876 alg.getParam(ParamName::ED_AAD, aad);
877 return decryptDataAesGcmPacked(key,
879 unpack<RawBuffer>(alg, ParamName::ED_IV),
883 // validateParams<IsSymEncryption> should prevent it
884 assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
885 return decryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
888 EvpCipherPtr initCipher(const RawBuffer &key, const CryptoAlgorithm &alg, bool encrypt, int& tagLen)
890 validateParams<IsSymEncryption>(alg);
891 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
892 auto iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
896 selectCipher(algo, key.size(), encrypt)(cipher, key, iv);
898 if (algo == AlgoType::AES_GCM) {
899 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
900 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
901 tagLen = tagLenBits / 8;
904 alg.getParam(ParamName::ED_AAD, aad);
906 cipher->AppendAAD(aad);
911 RawBuffer asymmetricEncrypt(const EvpShPtr &pkey,
912 const CryptoAlgorithm &alg,
913 const RawBuffer &data)
915 return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey, alg, data);
918 RawBuffer asymmetricDecrypt(const EvpShPtr &pkey,
919 const CryptoAlgorithm &alg,
920 const RawBuffer &data)
922 return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey, alg, data);
925 RawBuffer sign(EVP_PKEY *pkey,
926 const CryptoAlgorithm &alg,
927 const RawBuffer &message)
929 validateParams<IsSignVerify>(alg);
931 HashAlgorithm hashTmp = HashAlgorithm::NONE;
932 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
933 const EVP_MD *md_algo = getMdAlgo(hashTmp);
935 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
936 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
937 int rsa_padding = getRsaPadding(rsaPad);
940 // if ((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
941 // (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
942 // (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
944 // LogError("Error in private key type");
945 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
948 // if (privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
949 // rsa_padding = getRsaPadding(padAlgo);
953 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
956 return signMessage(pkey, message, rsa_padding);
958 return digestSignMessage(pkey, message, md_algo, rsa_padding);
961 int verify(EVP_PKEY *pkey,
962 const CryptoAlgorithm &alg,
963 const RawBuffer &message,
964 const RawBuffer &signature)
966 validateParams<IsSignVerify>(alg);
968 HashAlgorithm hashTmp = HashAlgorithm::NONE;
969 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
970 const EVP_MD *md_algo = getMdAlgo(hashTmp);
972 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
973 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
974 int rsa_padding = getRsaPadding(rsaPad);
977 // if ((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
978 // (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
979 // (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
981 // LogError("Error in private key type");
982 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
985 // if (publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
986 // rsa_padding = getRsaPadding(padAlgo);
989 // auto shrPKey = publicKey.getEvpShPtr();
991 ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
994 return verifyMessage(pkey, message, signature, rsa_padding);
996 return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
999 Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg)
1001 validateParams<IsEcdh>(alg);
1003 EC_KEY *ecKey = getEcKey(pkey.get());
1005 // get private key curve name
1006 int prvCurve = getCurve(ecKey);
1008 auto prv = EC_KEY_get0_private_key(ecKey);
1010 ThrowErr(Exc::Crypto::InputParam, "ECDH requires own private EC key");
1012 // Create the context for the shared secret derivation
1013 auto ctx = newCtx(pkey.get());
1015 ThrowErr(Exc::Crypto::InternalError, "Key context creation failed");
1017 // import peer's public key from buffer
1018 RawBuffer pubKeyBuffer;
1019 [[maybe_unused]] bool hasPubKey = alg.getParam(ParamName::ECDH_PUBKEY, pubKeyBuffer);
1021 auto peerKey = std::make_shared<KeyImpl>(pubKeyBuffer);
1022 if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
1023 ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
1024 auto peerEvp = peerKey->getEvpShPtr().get();
1027 int pubCurve = getCurve(getEcKey(peerEvp));
1029 if (pubCurve != prvCurve)
1030 ThrowErr(Exc::Crypto::InputParam, "Private and public key use different ECs");
1033 if (1 != EVP_PKEY_derive_init(ctx.get()))
1034 ThrowErr(Exc::Crypto::InternalError, "EVP_PKEY_derive_init failed");
1036 // provide the peer public key
1037 if (1 != EVP_PKEY_derive_set_peer(ctx.get(), peerEvp))
1038 ThrowErr(Exc::Crypto::InternalError, "EVP_PKEY_derive_set_peer failed");
1040 // determine buffer length for shared secret
1042 if(1 != EVP_PKEY_derive(ctx.get(), nullptr, &secretLen))
1043 ThrowErr(Exc::Crypto::InternalError, "Failed to determine ECDH secret length");
1045 RawBuffer secret(secretLen);
1047 // derive the shared secret
1048 if (1 != (EVP_PKEY_derive(ctx.get(), secret.data(), &secretLen)))
1049 ThrowErr(Exc::Crypto::InternalError, "ECDH failed");
1051 // Never use a derived secret directly. Typically it is passed
1052 // through some hash function to produce a key
1053 return { DataType::BINARY_DATA, std::move(secret)};
1056 Data deriveKBKDF(const RawBuffer &secret, const CryptoAlgorithm &alg)
1058 validateParams<IsKbkdf>(alg);
1060 RawBuffer label, context, fixed;
1061 KbkdfCounterLocation counterLocation;
1063 size_t length, rlenBits = 32, llenBits = 32, tmp;
1064 bool hasLabel = alg.getParam(ParamName::KBKDF_LABEL, label);
1065 bool hasContext = alg.getParam(ParamName::KBKDF_CONTEXT, context);
1066 bool hasFixed = alg.getParam(ParamName::KBKDF_FIXED_INPUT, fixed);
1067 alg.getParam(ParamName::KBKDF_COUNTER_LOCATION, counterLocation);
1068 alg.getParam(ParamName::KDF_PRF, prf);
1069 alg.getParam(ParamName::KDF_LEN, length);
1070 alg.getParam(ParamName::KBKDF_RLEN, rlenBits);
1071 bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
1072 bool useSeparator = !alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
1074 const EVP_MD* md = nullptr;
1076 case KdfPrf::HMAC_SHA256:
1079 case KdfPrf::HMAC_SHA384:
1082 case KdfPrf::HMAC_SHA512:
1086 assert(false); // prf is checked in validateParams above
1091 if (hasLabel || hasContext || !useSeparator || hasLLen ||
1092 counterLocation == KbkdfCounterLocation::MIDDLE_FIXED)
1093 ThrowErr(Exc::Crypto::InputParam, "Unexpected parameters for fixed input mode.");
1095 key = deriveKbkdfHmac(secret, length * 8, md, counterLocation, rlenBits, fixed);
1097 if (!hasLabel || !hasContext)
1098 ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
1100 key = deriveKbkdfHmac(secret,
1111 return { DataType::KEY_AES, std::move(key)};
1114 } // namespace Internals
1116 } // namespace Crypto