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 <sw-backend/crypto.h>
49 #include <openssl-error-handler.h>
52 #define OPENSSL_SUCCESS 1 // DO NOT CHANGE THIS VALUE
53 #define OPENSSL_FAIL 0 // DO NOT CHANGE THIS VALUE
61 typedef Uptr<EVP_PKEY_CTX_free, EVP_PKEY_CTX> EvpPkeyCtxUPtr;
63 typedef int(*I2D_CONV)(BIO *, EVP_PKEY *);
66 RawBuffer i2d(I2D_CONV fun, EVP_PKEY *pkey)
68 auto bio = uptr<BIO_free_all>(BIO_new(BIO_s_mem()));
71 ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!");
73 if (NULL == bio.get())
74 ThrowErr(Exc::Crypto::InternalError,
75 "Error in memory allocation! Function: BIO_new.");
77 if (1 != fun(bio.get(), pkey))
78 ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
80 RawBuffer output(8196);
82 int size = BIO_read(bio.get(), output.data(), output.size());
85 ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size);
91 // encryption / decryption
92 typedef ParamCheck<ParamName::ALGO_TYPE,
95 Type<AlgoType>::Equals<AlgoType::AES_CTR,
98 AlgoType::AES_CFB>> IsSymEncryption;
100 typedef ParamCheck<ParamName::ALGO_TYPE,
103 Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
105 typedef ParamCheck<ParamName::ED_IV,
108 Type<size_t>::Equals<Params::DEFAULT_AES_IV_LEN>,
109 BufferSizeGetter> IvSizeCheck;
111 typedef ParamCheck<ParamName::ED_CTR_LEN,
114 Type<int>::Equals<128>> CtrLenCheck;
116 typedef ParamCheck<ParamName::ED_IV,
119 GreaterOrEqual<size_t, 1>,
120 BufferSizeGetter> GcmIvCheck;
122 typedef ParamCheck<ParamName::ED_TAG_LEN,
125 Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
127 typedef ParamCheck<ParamName::ED_LABEL,
130 Unsupported<RawBuffer>> RsaLabelCheck;
133 typedef ParamCheck<ParamName::ALGO_TYPE,
136 Type<AlgoType>::Equals<AlgoType::RSA_SV,
138 AlgoType::ECDSA_SV>> IsSignVerify;
140 typedef ParamCheck<ParamName::SV_HASH_ALGO,
143 Type<HashAlgorithm>::Equals<HashAlgorithm::NONE,
145 HashAlgorithm::SHA256,
146 HashAlgorithm::SHA384,
147 HashAlgorithm::SHA512>> HashAlgoCheck;
149 typedef ParamCheck<ParamName::SV_RSA_PADDING,
152 Type<RSAPaddingAlgorithm>::Equals<RSAPaddingAlgorithm::NONE,
153 RSAPaddingAlgorithm::PKCS1,
154 RSAPaddingAlgorithm::X931>> RsaPaddingCheck;
157 typedef ParamCheck<ParamName::ALGO_TYPE,
160 Type<AlgoType>::Equals<AlgoType::RSA_GEN,
162 AlgoType::ECDSA_GEN>> IsAsymGeneration;
164 typedef ParamCheck<ParamName::ALGO_TYPE,
167 Type<AlgoType>::Equals<AlgoType::AES_GEN>> IsSymGeneration;
169 typedef ParamCheck<ParamName::GEN_KEY_LEN,
172 Type<int>::Equals<1024, 2048, 4096>> RsaKeyLenCheck;
174 typedef ParamCheck<ParamName::GEN_KEY_LEN,
177 Type<int>::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck;
179 typedef ParamCheck<ParamName::GEN_KEY_LEN,
182 Type<int>::Equals<128, 192, 256>> AesKeyLenCheck;
184 typedef ParamCheck<ParamName::GEN_EC,
187 Type<ElipticCurve>::Equals<ElipticCurve::prime192v1,
188 ElipticCurve::prime256v1,
189 ElipticCurve::secp384r1>> EcdsaEcCheck;
192 typedef ParamCheck<ParamName::ALGO_TYPE,
195 Type<AlgoType>::Equals<AlgoType::ECDH>> IsEcdh;
197 typedef ParamCheck<ParamName::ECDH_PUBKEY,
200 DefaultValidator<RawBuffer>> EcdhPubKeyCheck;
202 typedef ParamCheck<ParamName::ALGO_TYPE,
205 Type<AlgoType>::Equals<AlgoType::KBKDF>> IsKbkdf;
207 typedef ParamCheck<ParamName::KDF_PRF,
210 Type<KdfPrf>::Equals<KdfPrf::HMAC_SHA256,
212 KdfPrf::HMAC_SHA512>> KdfPrfCheck;
214 typedef ParamCheck<ParamName::KBKDF_MODE,
217 Type<KbkdfMode>::Equals<KbkdfMode::COUNTER>> KbkdfModeCheck;
219 typedef ParamCheck<ParamName::KDF_LEN,
222 Type<int>::Equals<16, 24, 32>> KdfLenCheck;
224 typedef ParamCheck<ParamName::KBKDF_COUNTER_LOCATION,
225 KbkdfCounterLocation,
227 Type<KbkdfCounterLocation>::Equals<KbkdfCounterLocation::BEFORE_FIXED,
228 KbkdfCounterLocation::AFTER_FIXED,
229 KbkdfCounterLocation::MIDDLE_FIXED>> KbkdfCounterLocationCheck;
231 typedef ParamCheck<ParamName::KBKDF_RLEN,
234 Type<int>::Equals<8, 16, 24, 32>> KbkdfRlenCheck;
236 typedef ParamCheck<ParamName::KBKDF_LLEN,
239 Type<int>::Equals<0, 8, 16, 24, 32>> KbkdfLlenCheck;
242 typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
243 ValidatorMap initValidators()
245 ValidatorMap validators;
246 validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
247 validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
248 validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
249 validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
250 validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
251 validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
252 validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
253 validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
254 validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
255 validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
256 validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
257 validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck>::Build());
258 validators.emplace(AlgoType::ECDH, VBuilder<EcdhPubKeyCheck>::Build());
259 validators.emplace(AlgoType::KBKDF, VBuilder<KdfPrfCheck,
262 KbkdfCounterLocationCheck,
264 KbkdfLlenCheck>::Build());
268 const ValidatorMap g_validators = initValidators();
270 template <typename TypeCheck>
271 void validateParams(const CryptoAlgorithm &ca)
273 // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
277 AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
279 auto it = g_validators.find(at);
281 // TypeCheck should prevent it
282 assert(it != g_validators.end());
284 for (const auto &validator : it->second)
285 validator->Check(ca);
288 typedef std::unique_ptr<Cipher::EvpCipherWrapper<RawBuffer>> EvpCipherPtr;
290 typedef std::function<void(EvpCipherPtr &, const RawBuffer &key, const RawBuffer &iv)>
293 // aes mode, key length in bits, encryption
294 typedef std::map<AlgoType, std::map<size_t, std::map<bool, InitCipherFn>>>
297 template <typename T>
298 void initCipher(EvpCipherPtr &ptr, const RawBuffer &key, const RawBuffer &iv)
300 ptr.reset(new T(key, iv));
303 CipherTree initializeCipherTree()
306 tree[AlgoType::AES_CBC][128][true] = initCipher<Cipher::AesCbcEncryption128>;
307 tree[AlgoType::AES_CBC][192][true] = initCipher<Cipher::AesCbcEncryption192>;
308 tree[AlgoType::AES_CBC][256][true] = initCipher<Cipher::AesCbcEncryption256>;
310 tree[AlgoType::AES_CBC][128][false] = initCipher<Cipher::AesCbcDecryption128>;
311 tree[AlgoType::AES_CBC][192][false] = initCipher<Cipher::AesCbcDecryption192>;
312 tree[AlgoType::AES_CBC][256][false] = initCipher<Cipher::AesCbcDecryption256>;
314 tree[AlgoType::AES_GCM][128][true] = initCipher<Cipher::AesGcmEncryption128>;
315 tree[AlgoType::AES_GCM][192][true] = initCipher<Cipher::AesGcmEncryption192>;
316 tree[AlgoType::AES_GCM][256][true] = initCipher<Cipher::AesGcmEncryption256>;
318 tree[AlgoType::AES_GCM][128][false] = initCipher<Cipher::AesGcmDecryption128>;
319 tree[AlgoType::AES_GCM][192][false] = initCipher<Cipher::AesGcmDecryption192>;
320 tree[AlgoType::AES_GCM][256][false] = initCipher<Cipher::AesGcmDecryption256>;
322 tree[AlgoType::AES_CTR][128][true] = initCipher<Cipher::AesCtrEncryption128>;
323 tree[AlgoType::AES_CTR][192][true] = initCipher<Cipher::AesCtrEncryption192>;
324 tree[AlgoType::AES_CTR][256][true] = initCipher<Cipher::AesCtrEncryption256>;
326 tree[AlgoType::AES_CTR][128][false] = initCipher<Cipher::AesCtrDecryption128>;
327 tree[AlgoType::AES_CTR][192][false] = initCipher<Cipher::AesCtrDecryption192>;
328 tree[AlgoType::AES_CTR][256][false] = initCipher<Cipher::AesCtrDecryption256>;
330 tree[AlgoType::AES_CFB][128][true] = initCipher<Cipher::AesCfbEncryption128>;
331 tree[AlgoType::AES_CFB][192][true] = initCipher<Cipher::AesCfbEncryption192>;
332 tree[AlgoType::AES_CFB][256][true] = initCipher<Cipher::AesCfbEncryption256>;
334 tree[AlgoType::AES_CFB][128][false] = initCipher<Cipher::AesCfbDecryption128>;
335 tree[AlgoType::AES_CFB][192][false] = initCipher<Cipher::AesCfbDecryption192>;
336 tree[AlgoType::AES_CFB][256][false] = initCipher<Cipher::AesCfbDecryption256>;
341 CipherTree g_cipherTree = initializeCipherTree();
343 // key length in bytes
344 InitCipherFn selectCipher(AlgoType type, size_t key_len = 32,
345 bool encryption = true)
348 return g_cipherTree.at(type).at(key_len * 8).at(encryption);
349 } catch (const std::out_of_range &) {
350 ThrowErr(Exc::Crypto::InternalError,
351 "Unsupported cipher: ",
352 static_cast<int>(type), ", ",
359 RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char *,
360 unsigned char *, RSA *, int),
361 const std::string &logPrefix,
362 const EvpShPtr &pkey,
363 const CryptoAlgorithm &alg,
364 const RawBuffer &data)
366 validateParams<IsAsymEncryption>(alg);
369 ThrowErr(Exc::Crypto::InputParam, logPrefix, "no key");
371 RSA *rsa = EVP_PKEY_get1_RSA(pkey.get());
374 ThrowErr(Exc::Crypto::InputParam, logPrefix, "invalid key");
377 * RSA_padding_add_PKCS1_OAEP supports custom label but RSA_public_encrypt calls it with NULL
378 * value so for now label is not supported. Alternative is to rewrite the openssl implementation
379 * to support it: openssl-fips/crypto/rsa/rsa_eay.c
382 output.resize(RSA_size(rsa));
386 ret = cryptoFn(data.size(),
390 RSA_PKCS1_OAEP_PADDING);
392 errorHandle(__FILE__, __LINE__, __func__, ret);
402 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo)
406 // validateParams<IsSignVerify> should prevent it
407 assert(hashAlgo == HashAlgorithm::NONE);
410 case HashAlgorithm::SHA1:
413 case HashAlgorithm::SHA256:
416 case HashAlgorithm::SHA384:
419 case HashAlgorithm::SHA512:
424 int getRsaPadding(const RSAPaddingAlgorithm padAlgo)
428 // validateParams<IsSignVerify> should prevent it
429 assert(padAlgo == RSAPaddingAlgorithm::NONE);
430 return RSA_NO_PADDING;
432 case RSAPaddingAlgorithm::PKCS1:
433 return RSA_PKCS1_PADDING;
435 case RSAPaddingAlgorithm::X931:
436 return RSA_X931_PADDING;
440 EvpPkeyCtxUPtr newCtx(int id)
442 if (auto ctx = EVP_PKEY_CTX_new_id(id, NULL))
443 return EvpPkeyCtxUPtr(ctx);
445 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
448 EvpPkeyCtxUPtr newCtx(EVP_PKEY *pkey)
450 if (auto ctx = EVP_PKEY_CTX_new(pkey, NULL))
451 return EvpPkeyCtxUPtr(ctx);
453 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
456 DataPair keyPair(const EvpPkeyCtxUPtr &ctx, KeyType prv, KeyType pub)
458 EVP_PKEY *pkeyTmp = NULL;
460 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen(ctx.get(), &pkeyTmp));
462 auto pkey = uptr<EVP_PKEY_free>(pkeyTmp);
464 return std::make_pair<Data, Data>(
465 {DataType(prv), i2d(i2d_PrivateKey_bio, pkey.get())},
466 {DataType(pub), i2d(i2d_PUBKEY_bio, pkey.get())});
469 DataPair createKeyPairRSA(const int size)
471 // validateParams<IsAsymGeneration> should prevent it
472 assert(size == 1024 || size == 2048 || size == 4096);
474 auto ctx = newCtx(EVP_PKEY_RSA);
476 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen_init(ctx.get()));
478 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size));
480 return keyPair(ctx, KeyType::KEY_RSA_PRIVATE, KeyType::KEY_RSA_PUBLIC);
483 DataPair paramgenKeyPair(const EvpPkeyCtxUPtr &pctx, KeyType prv, KeyType pub)
485 /* Generate parameters */
486 EVP_PKEY *pparamTmp = NULL;
487 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen(pctx.get(), &pparamTmp));
489 auto pparam = uptr<EVP_PKEY_free>(pparamTmp);
491 // Start to generate key
492 auto kctx = newCtx(pparam.get());
494 OPENSSL_ERROR_HANDLE(EVP_PKEY_keygen_init(kctx.get()));
496 return keyPair(kctx, prv, pub);
499 DataPair createKeyPairDSA(const int size)
501 // validateParams<IsAsymGeneration> should prevent it
502 assert(size == 1024 || size == 2048 || size == 3072 || size == 4096);
504 /* Create the context for generating the parameters */
505 auto pctx = newCtx(EVP_PKEY_DSA);
507 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen_init(pctx.get()));
509 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size));
511 return paramgenKeyPair(pctx, KeyType::KEY_DSA_PRIVATE, KeyType::KEY_DSA_PUBLIC);
514 DataPair createKeyPairECDSA(ElipticCurve type)
520 // validateParams<IsAsymGeneration> should prevent it
521 assert(type == ElipticCurve::prime192v1);
522 ecCurve = NID_X9_62_prime192v1;
525 case ElipticCurve::prime256v1:
526 ecCurve = NID_X9_62_prime256v1;
529 case ElipticCurve::secp384r1:
530 ecCurve = NID_secp384r1;
534 /* Create the context for generating the parameters */
535 auto pctx = newCtx(EVP_PKEY_EC);
537 OPENSSL_ERROR_HANDLE(EVP_PKEY_paramgen_init(pctx.get()));
539 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve));
541 return paramgenKeyPair(pctx, KeyType::KEY_ECDSA_PRIVATE, KeyType::KEY_ECDSA_PUBLIC);
544 Data createKeyAES(const int sizeBits)
546 // validateParams<IsSymGeneration> should prevent it
547 assert(sizeBits == 128 || sizeBits == 192 || sizeBits == 256);
550 int sizeBytes = sizeBits / 8;
552 if (!RAND_bytes(key, sizeBytes)) {
553 ThrowErr(Exc::Crypto::InternalError, "Error in AES key generation");
556 return { DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key + sizeBytes)};
559 RawBuffer signMessage(EVP_PKEY *privKey,
560 const RawBuffer &message,
561 const int rsa_padding)
563 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) != EVP_PKEY_RSA)
564 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
566 auto pctx = newCtx(privKey);
568 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign_init(pctx.get()));
570 /* Set padding algorithm */
571 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
572 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
574 /* Finalize the Sign operation */
575 /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
576 * signature. Length is returned in slen */
579 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size()));
581 /* Allocate memory for the signature based on size in slen */
584 OPENSSL_ERROR_HANDLE(EVP_PKEY_sign(pctx.get(), sig.data(), &slen, message.data(), message.size()));
586 // Set value to return RawData
591 RawBuffer digestSignMessage(EVP_PKEY *privKey,
592 const RawBuffer &message,
593 const EVP_MD *md_algo,
594 const int rsa_padding)
596 EVP_PKEY_CTX *pctx = NULL;
598 // Create the Message Digest Context
599 auto mdctx = uptr<EVP_MD_CTX_free>(EVP_MD_CTX_new());
601 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
603 OPENSSL_ERROR_HANDLE(EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey));
605 /* Set padding algorithm */
606 if (EVP_PKEY_type(EVP_PKEY_id(privKey)) == EVP_PKEY_RSA)
607 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
609 /* Call update with the message */
610 OPENSSL_ERROR_HANDLE(EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size()));
612 /* Finalize the DigestSign operation */
613 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
614 * signature. Length is returned in slen */
617 OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), NULL, &slen));
619 /* Allocate memory for the signature based on size in slen */
622 /* Obtain the signature */
623 OPENSSL_ERROR_HANDLE(EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen));
625 // Set value to return RawData
630 int verifyMessage(EVP_PKEY *pubKey,
631 const RawBuffer &message,
632 const RawBuffer &signature,
633 const int rsa_padding)
635 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) != EVP_PKEY_RSA)
636 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
638 auto pctx = newCtx(pubKey);
640 OPENSSL_ERROR_HANDLE(EVP_PKEY_verify_init(pctx.get()));
642 /* Set padding algorithm */
643 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
644 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding));
646 if (OPENSSL_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(),
647 signature.size(), message.data(), message.size()))
648 return CKM_API_SUCCESS;
650 LogError("EVP_PKEY_verify Failed");
651 return CKM_API_ERROR_VERIFICATION_FAILED;
654 int digestVerifyMessage(EVP_PKEY *pubKey,
655 const RawBuffer &message,
656 const RawBuffer &signature,
657 const EVP_MD *md_algo,
658 const int rsa_padding)
660 EVP_PKEY_CTX *pctx = NULL;
662 // Create the Message Digest Context
663 auto mdctx = uptr<EVP_MD_CTX_free>(EVP_MD_CTX_new());
665 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_new function");
667 OPENSSL_ERROR_HANDLE(EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey));
669 if (EVP_PKEY_type(EVP_PKEY_id(pubKey)) == EVP_PKEY_RSA)
670 OPENSSL_ERROR_HANDLE(EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding));
672 OPENSSL_ERROR_HANDLE(EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()));
674 if (OPENSSL_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(),
675 const_cast<unsigned char *>(signature.data()), signature.size()))
676 return CKM_API_SUCCESS;
678 LogError("EVP_PKEY_verify Failed");
679 return CKM_API_ERROR_VERIFICATION_FAILED;
682 RawBuffer encryptDataAesGcmPacked(
683 const RawBuffer &key,
684 const RawBuffer &data,
687 const RawBuffer &aad)
689 auto pair = encryptDataAesGcm(key, data, iv, tagSize, aad);
690 std::copy(pair.second.begin(), pair.second.end(),
691 std::back_inserter(pair.first));
696 RawBuffer decryptDataAesGcmPacked(
697 const RawBuffer &key,
698 const RawBuffer &data,
701 const RawBuffer &aad)
703 if (tagSize > static_cast<int>(data.size()))
704 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
706 auto tagPos = data.data() + data.size() - tagSize;
707 return decryptDataAesGcm(
709 RawBuffer(data.data(), tagPos),
711 RawBuffer(tagPos, data.data() + data.size()),
715 EC_KEY* getEcKey(EVP_PKEY* evpKey)
717 int subType = EVP_PKEY_type(EVP_PKEY_id(evpKey));
718 if (subType != EVP_PKEY_EC)
719 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
721 EC_KEY *ecKey = EVP_PKEY_get0_EC_KEY(evpKey);
723 ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
728 int getCurve(const EC_KEY* ecKey)
730 return EC_GROUP_get_curve_name(EC_KEY_get0_group(ecKey));
736 DataPair generateAKey(const CryptoAlgorithm &algorithm)
738 validateParams<IsAsymGeneration>(algorithm);
740 AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
742 if (keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN) {
743 int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
745 if (keyType == AlgoType::RSA_GEN)
746 return createKeyPairRSA(keyLength);
748 return createKeyPairDSA(keyLength);
749 } else { // AlgoType::ECDSA_GEN
750 ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
751 return createKeyPairECDSA(ecType);
755 Data generateSKey(const CryptoAlgorithm &algorithm)
757 validateParams<IsSymGeneration>(algorithm);
759 int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
760 return createKeyAES(keySizeBits);
763 RawBuffer encryptDataAes(
765 const RawBuffer &key,
766 const RawBuffer &data,
770 selectCipher(type, key.size())(enc, key, iv);
771 RawBuffer result = enc->Append(data);
772 RawBuffer tmp = enc->Finalize();
773 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
777 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
778 const RawBuffer &key,
779 const RawBuffer &data,
782 const RawBuffer &aad)
784 RawBuffer tag(tagSize);
786 selectCipher(AlgoType::AES_GCM, key.size())(enc, key, iv);
791 RawBuffer result = enc->Append(data);
792 RawBuffer tmp = enc->Finalize();
793 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
795 enc->Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data());
797 return std::make_pair(result, tag);
800 RawBuffer decryptDataAes(
802 const RawBuffer &key,
803 const RawBuffer &data,
807 selectCipher(type, key.size(), false)(dec, key, iv);
808 RawBuffer result = dec->Append(data);
811 tmp = dec->Finalize();
812 } catch (const Exc::Exception &e) {
813 ThrowErr(Exc::InputParam, "Authentication failed in AES finalize function (wrong key/data was used).");
815 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
819 RawBuffer decryptDataAesGcm(
820 const RawBuffer &key,
821 const RawBuffer &data,
823 const RawBuffer &tag,
824 const RawBuffer &aad)
827 selectCipher(AlgoType::AES_GCM, key.size(), false)(dec, key, iv);
828 void *ptr = (void *)tag.data();
830 dec->Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr);
835 RawBuffer result = dec->Append(data);
838 tmp = dec->Finalize();
839 } catch (const Exc::Exception &e) {
840 ThrowErr(Exc::InputParam, "Tag authentication failed in AES finalize function (the tag doesn't match).");
842 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
846 RawBuffer symmetricEncrypt(const RawBuffer &key,
847 const CryptoAlgorithm &alg,
848 const RawBuffer &data)
850 validateParams<IsSymEncryption>(alg);
851 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
853 if (algo == AlgoType::AES_GCM) {
854 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
855 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
857 alg.getParam(ParamName::ED_AAD, aad);
858 return encryptDataAesGcmPacked(key,
860 unpack<RawBuffer>(alg, ParamName::ED_IV),
864 // validateParams<IsSymEncryption> should prevent it
865 assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
866 return encryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
869 RawBuffer symmetricDecrypt(const RawBuffer &key,
870 const CryptoAlgorithm &alg,
871 const RawBuffer &data)
873 validateParams<IsSymEncryption>(alg);
874 AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
876 if (algo == AlgoType::AES_GCM) {
877 int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
878 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
880 alg.getParam(ParamName::ED_AAD, aad);
881 return decryptDataAesGcmPacked(key,
883 unpack<RawBuffer>(alg, ParamName::ED_IV),
887 // validateParams<IsSymEncryption> should prevent it
888 assert(algo == AlgoType::AES_CBC || algo == AlgoType::AES_CTR || algo == AlgoType::AES_CFB);
889 return decryptDataAes(algo, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
892 RawBuffer asymmetricEncrypt(const EvpShPtr &pkey,
893 const CryptoAlgorithm &alg,
894 const RawBuffer &data)
896 return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey, alg, data);
899 RawBuffer asymmetricDecrypt(const EvpShPtr &pkey,
900 const CryptoAlgorithm &alg,
901 const RawBuffer &data)
903 return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey, alg, data);
906 RawBuffer sign(EVP_PKEY *pkey,
907 const CryptoAlgorithm &alg,
908 const RawBuffer &message)
910 validateParams<IsSignVerify>(alg);
912 HashAlgorithm hashTmp = HashAlgorithm::NONE;
913 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
914 const EVP_MD *md_algo = getMdAlgo(hashTmp);
916 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
917 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
918 int rsa_padding = getRsaPadding(rsaPad);
921 // if ((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
922 // (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
923 // (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
925 // LogError("Error in private key type");
926 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
929 // if (privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
930 // rsa_padding = getRsaPadding(padAlgo);
934 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
937 return signMessage(pkey, message, rsa_padding);
939 return digestSignMessage(pkey, message, md_algo, rsa_padding);
942 int verify(EVP_PKEY *pkey,
943 const CryptoAlgorithm &alg,
944 const RawBuffer &message,
945 const RawBuffer &signature)
947 validateParams<IsSignVerify>(alg);
949 HashAlgorithm hashTmp = HashAlgorithm::NONE;
950 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
951 const EVP_MD *md_algo = getMdAlgo(hashTmp);
953 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
954 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
955 int rsa_padding = getRsaPadding(rsaPad);
958 // if ((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
959 // (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
960 // (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
962 // LogError("Error in private key type");
963 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
966 // if (publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
967 // rsa_padding = getRsaPadding(padAlgo);
970 // auto shrPKey = publicKey.getEvpShPtr();
972 ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
975 return verifyMessage(pkey, message, signature, rsa_padding);
977 return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
980 Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg)
982 validateParams<IsEcdh>(alg);
984 EC_KEY *ecKey = getEcKey(pkey.get());
986 // get private key curve name
987 int prvCurve = getCurve(ecKey);
989 auto prv = EC_KEY_get0_private_key(ecKey);
991 ThrowErr(Exc::Crypto::InputParam, "ECDH requires own private EC key");
993 // Create the context for the shared secret derivation
994 auto ctx = newCtx(pkey.get());
996 ThrowErr(Exc::Crypto::InternalError, "Key context creation failed");
998 // import peer's public key from buffer
999 RawBuffer pubKeyBuffer;
1000 [[maybe_unused]] bool hasPubKey = alg.getParam(ParamName::ECDH_PUBKEY, pubKeyBuffer);
1002 auto peerKey = std::make_shared<KeyImpl>(pubKeyBuffer);
1003 if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
1004 ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
1005 auto peerEvp = peerKey->getEvpShPtr().get();
1008 int pubCurve = getCurve(getEcKey(peerEvp));
1010 if (pubCurve != prvCurve)
1011 ThrowErr(Exc::Crypto::InputParam, "Private and public key use different ECs");
1014 if (1 != EVP_PKEY_derive_init(ctx.get()))
1015 ThrowErr(Exc::Crypto::InternalError, "EVP_PKEY_derive_init failed");
1017 // provide the peer public key
1018 if (1 != EVP_PKEY_derive_set_peer(ctx.get(), peerEvp))
1019 ThrowErr(Exc::Crypto::InternalError, "EVP_PKEY_derive_set_peer failed");
1021 // determine buffer length for shared secret
1023 if(1 != EVP_PKEY_derive(ctx.get(), nullptr, &secretLen))
1024 ThrowErr(Exc::Crypto::InternalError, "Failed to determine ECDH secret length");
1026 RawBuffer secret(secretLen);
1028 // derive the shared secret
1029 if (1 != (EVP_PKEY_derive(ctx.get(), secret.data(), &secretLen)))
1030 ThrowErr(Exc::Crypto::InternalError, "ECDH failed");
1032 // Never use a derived secret directly. Typically it is passed
1033 // through some hash function to produce a key
1034 return { DataType::BINARY_DATA, std::move(secret)};
1037 Data deriveKBKDF(const RawBuffer &secret, const CryptoAlgorithm &alg)
1039 validateParams<IsKbkdf>(alg);
1041 RawBuffer label, context, fixed;
1042 KbkdfCounterLocation counterLocation;
1044 size_t length, rlenBits = 32, llenBits = 32, tmp;
1045 bool hasLabel = alg.getParam(ParamName::KBKDF_LABEL, label);
1046 bool hasContext = alg.getParam(ParamName::KBKDF_CONTEXT, context);
1047 bool hasFixed = alg.getParam(ParamName::KBKDF_FIXED_INPUT, fixed);
1048 alg.getParam(ParamName::KBKDF_COUNTER_LOCATION, counterLocation);
1049 alg.getParam(ParamName::KDF_PRF, prf);
1050 alg.getParam(ParamName::KDF_LEN, length);
1051 alg.getParam(ParamName::KBKDF_RLEN, rlenBits);
1052 bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
1053 bool useSeparator = !alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
1055 const EVP_MD* md = nullptr;
1057 case KdfPrf::HMAC_SHA256:
1060 case KdfPrf::HMAC_SHA384:
1063 case KdfPrf::HMAC_SHA512:
1067 assert(false); // prf is checked in validateParams above
1072 if (hasLabel || hasContext || !useSeparator || hasLLen ||
1073 counterLocation == KbkdfCounterLocation::MIDDLE_FIXED)
1074 ThrowErr(Exc::Crypto::InputParam, "Unexpected parameters for fixed input mode.");
1076 key = deriveKbkdfHmac(secret, length * 8, md, counterLocation, rlenBits, fixed);
1078 if (!hasLabel || !hasContext)
1079 ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
1081 key = deriveKbkdfHmac(secret,
1092 return { DataType::KEY_AES, std::move(key)};
1095 } // namespace Internals
1097 } // namespace Crypto