2 * Copyright (c) 2000 - 2015 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
25 #include <openssl/evp.h>
26 #include <openssl/obj_mac.h>
27 #include <openssl/ec.h>
28 #include <openssl/dsa.h>
29 #include <openssl/rsa.h>
30 #include <openssl/bio.h>
31 #include <openssl/rand.h>
32 #include <openssl/crypto.h>
33 #include <openssl/err.h>
34 #include <openssl/x509v3.h>
35 #include <openssl/obj_mac.h>
37 #include <ckm/ckm-error.h>
39 #include <dpl/log/log.h>
41 #include <generic-backend/exception.h>
42 #include <generic-backend/algo-validation.h>
43 #include <sw-backend/internals.h>
44 #include <sw-backend/crypto.h>
46 #define OPENSSL_SUCCESS 1 // DO NOTCHANGE THIS VALUE
47 #define OPENSSL_FAIL 0 // DO NOTCHANGE THIS VALUE
55 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
56 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
57 typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
59 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
60 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
62 const size_t DEFAULT_AES_GCM_TAG_LEN = 128; // tag length in bits according to W3C Crypto API
63 const size_t DEFAULT_AES_IV_LEN = 16; // default iv size in bytes for AES
65 RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
66 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
69 ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!");
72 if (NULL == bio.get()) {
73 ThrowErr(Exc::Crypto::InternalError, "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");
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);
92 // encryption / decryption
93 typedef ParamCheck<ParamName::ALGO_TYPE,
96 Type<AlgoType>::Equals<AlgoType::AES_CTR,
99 AlgoType::AES_CFB>> IsSymEncryption;
101 typedef ParamCheck<ParamName::ALGO_TYPE,
104 Type<AlgoType>::Equals<AlgoType::RSA_OAEP>> IsAsymEncryption;
106 typedef ParamCheck<ParamName::ED_IV,
109 Type<size_t>::Equals<DEFAULT_AES_IV_LEN>,
110 BufferSizeGetter> IvSizeCheck;
112 typedef ParamCheck<ParamName::ED_CTR_LEN,
115 Type<int>::Equals<128>> CtrLenCheck;
117 typedef ParamCheck<ParamName::ED_IV,
120 DefaultValidator<RawBuffer>> 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;
191 typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
192 ValidatorMap initValidators() {
193 ValidatorMap validators;
194 validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
195 validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
196 validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
197 validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
198 validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
199 validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
200 validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
201 validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
202 validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
203 validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
204 validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
205 validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
206 validators.emplace(AlgoType::RSA_OAEP, VBuilder<RsaLabelCheck>::Build());
209 ValidatorMap g_validators = initValidators();
211 template <typename TypeCheck>
212 void validateParams(const CryptoAlgorithm& ca)
214 // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
218 AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
220 for(const auto& validator : g_validators.at(at))
221 validator->Check(ca);
222 } catch(const std::out_of_range&) {
223 ThrowErr(Exc::Crypto::InputParam, "Unsupported algorithm ", static_cast<int>(at));
227 typedef std::unique_ptr<Cipher::EvpCipherWrapper<RawBuffer>> EvpCipherPtr;
229 typedef std::function<void(EvpCipherPtr&, const RawBuffer& key, const RawBuffer& iv)> InitCipherFn;
231 // aes mode, key length in bits, encryption
232 typedef std::map<AlgoType, std::map<size_t, std::map<bool, InitCipherFn>>> CipherTree;
234 template <typename T>
235 void initCipher(EvpCipherPtr& ptr, const RawBuffer& key, const RawBuffer& iv)
237 ptr.reset(new T(key, iv));
240 CipherTree initializeCipherTree()
243 tree[AlgoType::AES_CBC][128][true] = initCipher<Cipher::AesCbcEncryption128>;
244 tree[AlgoType::AES_CBC][192][true] = initCipher<Cipher::AesCbcEncryption192>;
245 tree[AlgoType::AES_CBC][256][true] = initCipher<Cipher::AesCbcEncryption256>;
247 tree[AlgoType::AES_CBC][128][false] = initCipher<Cipher::AesCbcDecryption128>;
248 tree[AlgoType::AES_CBC][192][false] = initCipher<Cipher::AesCbcDecryption192>;
249 tree[AlgoType::AES_CBC][256][false] = initCipher<Cipher::AesCbcDecryption256>;
251 tree[AlgoType::AES_GCM][128][true] = initCipher<Cipher::AesGcmEncryption128>;
252 tree[AlgoType::AES_GCM][192][true] = initCipher<Cipher::AesGcmEncryption192>;
253 tree[AlgoType::AES_GCM][256][true] = initCipher<Cipher::AesGcmEncryption256>;
255 tree[AlgoType::AES_GCM][128][false] = initCipher<Cipher::AesGcmDecryption128>;
256 tree[AlgoType::AES_GCM][192][false] = initCipher<Cipher::AesGcmDecryption192>;
257 tree[AlgoType::AES_GCM][256][false] = initCipher<Cipher::AesGcmDecryption256>;
259 tree[AlgoType::AES_CTR][128][true] = initCipher<Cipher::AesCtrEncryption128>;
260 tree[AlgoType::AES_CTR][192][true] = initCipher<Cipher::AesCtrEncryption192>;
261 tree[AlgoType::AES_CTR][256][true] = initCipher<Cipher::AesCtrEncryption256>;
263 tree[AlgoType::AES_CTR][128][false] = initCipher<Cipher::AesCtrDecryption128>;
264 tree[AlgoType::AES_CTR][192][false] = initCipher<Cipher::AesCtrDecryption192>;
265 tree[AlgoType::AES_CTR][256][false] = initCipher<Cipher::AesCtrDecryption256>;
267 tree[AlgoType::AES_CFB][128][true] = initCipher<Cipher::AesCfbEncryption128>;
268 tree[AlgoType::AES_CFB][192][true] = initCipher<Cipher::AesCfbEncryption192>;
269 tree[AlgoType::AES_CFB][256][true] = initCipher<Cipher::AesCfbEncryption256>;
271 tree[AlgoType::AES_CFB][128][false] = initCipher<Cipher::AesCfbDecryption128>;
272 tree[AlgoType::AES_CFB][192][false] = initCipher<Cipher::AesCfbDecryption192>;
273 tree[AlgoType::AES_CFB][256][false] = initCipher<Cipher::AesCfbDecryption256>;
278 CipherTree g_cipherTree = initializeCipherTree();
280 // key length in bytes
281 InitCipherFn selectCipher(AlgoType type, size_t key_len = 32, bool encryption = true)
284 return g_cipherTree.at(type).at(key_len*8).at(encryption);
285 } catch (const std::out_of_range&) {
286 ThrowErr(Exc::Crypto::InternalError,
287 "Unsupported cipher: ",
288 static_cast<int>(type), ", ",
295 RawBuffer asymmetricHelper(int (*cryptoFn)(int, const unsigned char*, unsigned char*, RSA*, int),
296 const std::string logPrefix,
297 const EvpShPtr &pkey,
298 const CryptoAlgorithm &alg,
299 const RawBuffer &data)
301 validateParams<IsAsymEncryption>(alg);
303 RSA* rsa = EVP_PKEY_get1_RSA(pkey.get());
305 ThrowErr(Exc::Crypto::InputParam, logPrefix, "invalid key");
308 * RSA_padding_add_PKCS1_OAEP supports custom label but RSA_public_encrypt calls it with NULL
309 * value so for now label is not supported. Alternative is to rewrite the openssl implementation
310 * to support it: openssl-fips/crypto/rsa/rsa_eay.c
313 output.resize(RSA_size(rsa));
314 int ret = cryptoFn(data.size(),
318 RSA_PKCS1_OAEP_PADDING);
321 ThrowErr(Exc::Crypto::InternalError, logPrefix, "failed");
327 } // anonymous namespace
329 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
330 const EVP_MD *md_algo=NULL;
332 case HashAlgorithm::NONE:
335 case HashAlgorithm::SHA1:
336 md_algo = EVP_sha1();
338 case HashAlgorithm::SHA256:
339 md_algo = EVP_sha256();
341 case HashAlgorithm::SHA384:
342 md_algo = EVP_sha384();
344 case HashAlgorithm::SHA512:
345 md_algo = EVP_sha512();
348 ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
353 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
354 int rsa_padding = -1;
356 case RSAPaddingAlgorithm::NONE:
357 rsa_padding = RSA_NO_PADDING;
359 case RSAPaddingAlgorithm::PKCS1:
360 rsa_padding = RSA_PKCS1_PADDING;
362 case RSAPaddingAlgorithm::X931:
363 rsa_padding = RSA_X931_PADDING;
366 ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
371 TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
375 // check the parameters of functions
376 if(size!=1024 && size!=2048 && size!=4096) {
377 ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
380 EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
382 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
385 if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
386 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
389 if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
390 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
393 EVP_PKEY *pkeyTmp = NULL;
394 if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
395 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
397 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
399 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
400 Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
404 TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
409 // check the parameters of functions
410 if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
411 ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
414 /* Create the context for generating the parameters */
415 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
417 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
420 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
421 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
424 if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
425 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
428 /* Generate parameters */
429 EVP_PKEY *pparamTmp = NULL;
430 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
431 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
433 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
435 // Start to generate key
436 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
438 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
441 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
442 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
445 /* Generate the key */
446 EVP_PKEY *pkeyTmp = NULL;
447 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
448 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
450 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
452 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
453 Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
456 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
458 int ecCurve = NOT_DEFINED;
463 case ElipticCurve::prime192v1:
464 ecCurve = NID_X9_62_prime192v1;
466 case ElipticCurve::prime256v1:
467 ecCurve = NID_X9_62_prime256v1;
469 case ElipticCurve::secp384r1:
470 ecCurve = NID_secp384r1;
473 ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
476 /* Create the context for generating the parameters */
477 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
479 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
482 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
483 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
486 if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
487 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
490 /* Generate parameters */
491 EVP_PKEY *pparamTmp = NULL;
492 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
493 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
495 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
497 // Start to generate key
498 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
500 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
503 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
504 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
507 /* Generate the key */
508 EVP_PKEY *pkeyTmp = NULL;
509 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
510 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
512 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
514 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
515 Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
518 Token createKeyAES(CryptoBackend backendId, const int sizeBits)
520 // check the parameters of functions
521 if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
522 LogError("Error in AES input size");
523 ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
527 int sizeBytes = sizeBits/8;
528 if (!RAND_bytes(key, sizeBytes)) {
529 LogError("Error in AES key generation");
530 ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
533 return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
536 TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
538 validateParams<IsAsymGeneration>(algorithm);
540 AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
541 if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN)
543 int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
544 if(keyType == AlgoType::RSA_GEN)
545 return createKeyPairRSA(backendId, keyLength);
547 return createKeyPairDSA(backendId, keyLength);
549 else // AlgoType::ECDSA_GEN
551 ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
552 return createKeyPairECDSA(backendId, ecType);
556 Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
558 validateParams<IsSymGeneration>(algorithm);
560 int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
561 return createKeyAES(backendId, keySizeBits);
564 RawBuffer encryptDataAes(
566 const RawBuffer &key,
567 const RawBuffer &data,
571 selectCipher(type, key.size())(enc, key, iv);
572 RawBuffer result = enc->Append(data);
573 RawBuffer tmp = enc->Finalize();
574 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
578 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
579 const RawBuffer &key,
580 const RawBuffer &data,
583 const RawBuffer &aad)
585 RawBuffer tag(tagSize);
587 selectCipher(AlgoType::AES_GCM, key.size())(enc, key, iv);
592 RawBuffer result = enc->Append(data);
593 RawBuffer tmp = enc->Finalize();
594 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
595 if (0 == enc->Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) {
596 ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Get tag failed.");
598 return std::make_pair(result, tag);
601 RawBuffer encryptDataAesGcmPacked(
602 const RawBuffer &key,
603 const RawBuffer &data,
606 const RawBuffer &aad)
608 auto pair = encryptDataAesGcm(key, data, iv, tagSize, aad);
609 std::copy(pair.second.begin(), pair.second.end(), std::back_inserter(pair.first));
613 RawBuffer decryptDataAes(
615 const RawBuffer &key,
616 const RawBuffer &data,
620 selectCipher(type, key.size(), false)(dec, key, iv);
621 RawBuffer result = dec->Append(data);
622 RawBuffer tmp = dec->Finalize();
623 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
627 RawBuffer decryptDataAesGcm(
628 const RawBuffer &key,
629 const RawBuffer &data,
631 const RawBuffer &tag,
632 const RawBuffer &aad)
635 selectCipher(AlgoType::AES_GCM, key.size(), false)(dec, key, iv);
636 void *ptr = (void*)tag.data();
637 if (0 == dec->Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) {
638 ThrowErr(Exc::Crypto::InternalError,
639 "Error in AES control function. Set tag failed.");
644 RawBuffer result = dec->Append(data);
645 RawBuffer tmp = dec->Finalize();
646 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
650 RawBuffer decryptDataAesGcmPacked(
651 const RawBuffer &key,
652 const RawBuffer &data,
655 const RawBuffer &aad)
657 if (tagSize > static_cast<int>(data.size()))
658 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
660 auto tagPos = data.data() + data.size() - tagSize;
661 return decryptDataAesGcm(
663 RawBuffer(data.data(), tagPos),
665 RawBuffer(tagPos, data.data() + data.size()),
669 RawBuffer symmetricEncrypt(const RawBuffer &key,
670 const CryptoAlgorithm &alg,
671 const RawBuffer &data)
673 validateParams<IsSymEncryption>(alg);
674 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
678 case AlgoType::AES_CBC:
679 case AlgoType::AES_CTR:
680 case AlgoType::AES_CFB:
681 return encryptDataAes(keyType, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
682 case AlgoType::AES_GCM:
684 int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
685 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
687 alg.getParam(ParamName::ED_AAD, aad);
688 return encryptDataAesGcmPacked(key,
690 unpack<RawBuffer>(alg, ParamName::ED_IV),
697 ThrowErr(Exc::Crypto::OperationNotSupported, "symmetric enc: algorithm not recognized");
700 RawBuffer symmetricDecrypt(const RawBuffer &key,
701 const CryptoAlgorithm &alg,
702 const RawBuffer &data)
704 validateParams<IsSymEncryption>(alg);
705 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
709 case AlgoType::AES_CBC:
710 case AlgoType::AES_CTR:
711 case AlgoType::AES_CFB:
712 return decryptDataAes(keyType, key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
713 case AlgoType::AES_GCM:
715 int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
716 alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
718 alg.getParam(ParamName::ED_AAD, aad);
719 return decryptDataAesGcmPacked(key,
721 unpack<RawBuffer>(alg, ParamName::ED_IV),
728 ThrowErr(Exc::Crypto::InputParam, "symmetric dec: algorithm not recognized");
731 RawBuffer asymmetricEncrypt(const EvpShPtr &pkey,
732 const CryptoAlgorithm &alg,
733 const RawBuffer &data)
735 return asymmetricHelper(RSA_public_encrypt, "Asymmetric encryption: ", pkey, alg, data);
738 RawBuffer asymmetricDecrypt(const EvpShPtr &pkey,
739 const CryptoAlgorithm &alg,
740 const RawBuffer &data)
742 return asymmetricHelper(RSA_private_decrypt, "Asymmetric decryption: ", pkey, alg, data);
745 RawBuffer sign(EVP_PKEY *pkey,
746 const CryptoAlgorithm &alg,
747 const RawBuffer &message)
749 validateParams<IsSignVerify>(alg);
751 int rsa_padding = NOT_DEFINED;
752 const EVP_MD *md_algo = NULL;
754 HashAlgorithm hashTmp = HashAlgorithm::NONE;
755 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
756 md_algo = getMdAlgo(hashTmp);
758 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
759 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
760 rsa_padding = getRsaPadding(rsaPad);
763 // if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
764 // (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
765 // (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
767 // LogError("Error in private key type");
768 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
771 // if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
772 // rsa_padding = getRsaPadding(padAlgo);
776 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
779 if(md_algo == NULL) {
780 return signMessage(pkey, message, rsa_padding);
783 return digestSignMessage(pkey,message, md_algo, rsa_padding);
786 RawBuffer signMessage(EVP_PKEY *privKey,
787 const RawBuffer &message,
788 const int rsa_padding)
790 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
793 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
796 if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
797 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
800 /* Set padding algorithm */
801 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
802 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
803 ThrowErr(Exc::Crypto::InternalError,
804 "Error in EVP_PKEY_CTX_set_rsa_padding function");
808 /* Finalize the Sign operation */
809 /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
810 * signature. Length is returned in slen */
812 if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
813 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
816 /* Allocate memory for the signature based on size in slen */
819 if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
825 // Set value to return RawData
830 ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
833 RawBuffer digestSignMessage(EVP_PKEY *privKey,
834 const RawBuffer &message,
835 const EVP_MD *md_algo,
836 const int rsa_padding)
838 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
840 EVP_PKEY_CTX *pctx = NULL;
842 // Create the Message Digest Context
844 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
847 if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
848 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
851 /* Set padding algorithm */
852 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
853 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
854 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
858 /* Call update with the message */
859 if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
860 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
863 /* Finalize the DigestSign operation */
864 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
865 * signature. Length is returned in slen */
867 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
868 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
871 /* Allocate memory for the signature based on size in slen */
874 /* Obtain the signature */
875 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
876 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
879 // Set value to return RawData
884 int verify(EVP_PKEY *pkey,
885 const CryptoAlgorithm &alg,
886 const RawBuffer &message,
887 const RawBuffer &signature)
889 validateParams<IsSignVerify>(alg);
891 int rsa_padding = NOT_DEFINED;
892 const EVP_MD *md_algo = NULL;
894 HashAlgorithm hashTmp = HashAlgorithm::NONE;
895 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
896 md_algo = getMdAlgo(hashTmp);
898 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
899 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
900 rsa_padding = getRsaPadding(rsaPad);
903 // if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
904 // (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
905 // (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
907 // LogError("Error in private key type");
908 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
911 // if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
912 // rsa_padding = getRsaPadding(padAlgo);
915 // auto shrPKey = publicKey.getEvpShPtr();
917 ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
920 if (md_algo == NULL) {
921 return verifyMessage(pkey, message, signature, rsa_padding);
924 return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
927 int verifyMessage(EVP_PKEY *pubKey,
928 const RawBuffer &message,
929 const RawBuffer &signature,
930 const int rsa_padding)
932 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
935 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
938 if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
939 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
942 /* Set padding algorithm */
943 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
944 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
945 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
949 if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
950 return CKM_API_SUCCESS;
953 LogError("EVP_PKEY_verify Failed");
954 return CKM_API_ERROR_VERIFICATION_FAILED;
957 int digestVerifyMessage(EVP_PKEY *pubKey,
958 const RawBuffer &message,
959 const RawBuffer &signature,
960 const EVP_MD *md_algo,
961 const int rsa_padding)
963 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
964 EVP_PKEY_CTX *pctx = NULL;
966 /* Create the Message Digest Context */
968 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
971 if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
972 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
975 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
976 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
977 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
981 if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
982 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
985 if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
986 return CKM_API_SUCCESS;
989 LogError("EVP_PKEY_verify Failed");
990 return CKM_API_ERROR_VERIFICATION_FAILED;
993 } // namespace Internals
995 } // namespace Crypto