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 <sw-backend/internals.h>
43 #include <sw-backend/crypto.h>
45 #define OPENSSL_SUCCESS 1 // DO NOTCHANGE THIS VALUE
46 #define OPENSSL_FAIL 0 // DO NOTCHANGE THIS VALUE
47 #define DEV_HW_RANDOM_FILE "/dev/hwrng"
48 #define DEV_URANDOM_FILE "/dev/urandom"
51 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
52 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
53 typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
55 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
56 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
57 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
58 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
61 ThrowErr(CKM::Exc::Crypto::InternalError, "attempt to parse an empty key!");
64 if (NULL == bio.get()) {
65 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
68 if (1 != fun(bio.get(), pkey)) {
69 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
72 CKM::RawBuffer output(8196);
74 int size = BIO_read(bio.get(), output.data(), output.size());
77 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in BIO_read: ", size);
86 const CKM::CryptoAlgorithm &alg,
87 CKM::ParamName paramName)
90 if (!alg.getParam(paramName, result)) {
91 ThrowErr(CKM::Exc::Crypto::InputParam, "Wrong input param");
96 } // anonymous namespace
101 namespace Internals {
107 // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
108 ERR_load_crypto_strings();
109 OpenSSL_add_all_algorithms();
111 // initialize entropy
112 std::ifstream ifile(DEV_HW_RANDOM_FILE);
113 if(ifile.is_open()) {
114 u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
116 if(u_rand_ret != 32 ){
117 LogError("Error in HW_RAND file load");
118 hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
120 if(hw_rand_ret != 32) {
121 ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
125 return CKM_CRYPTO_INIT_SUCCESS;
128 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
129 const EVP_MD *md_algo=NULL;
131 case HashAlgorithm::NONE:
134 case HashAlgorithm::SHA1:
135 md_algo = EVP_sha1();
137 case HashAlgorithm::SHA256:
138 md_algo = EVP_sha256();
140 case HashAlgorithm::SHA384:
141 md_algo = EVP_sha384();
143 case HashAlgorithm::SHA512:
144 md_algo = EVP_sha512();
147 ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
152 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
153 int rsa_padding = -1;
155 case RSAPaddingAlgorithm::NONE:
156 rsa_padding = RSA_NO_PADDING;
158 case RSAPaddingAlgorithm::PKCS1:
159 rsa_padding = RSA_PKCS1_PADDING;
161 case RSAPaddingAlgorithm::X931:
162 rsa_padding = RSA_X931_PADDING;
165 ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
170 TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
174 // check the parameters of functions
175 if(size!=1024 && size!=2048 && size!=4096) {
176 ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
179 EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
181 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
184 if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
185 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
188 if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
189 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
192 EVP_PKEY *pkeyTmp = NULL;
193 if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
194 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
196 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
198 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
199 Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
203 TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
208 // check the parameters of functions
209 if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
210 ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
213 /* Create the context for generating the parameters */
214 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
216 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
219 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
220 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
223 if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
224 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
227 /* Generate parameters */
228 EVP_PKEY *pparamTmp = NULL;
229 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
230 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
232 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
234 // Start to generate key
235 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
237 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
240 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
241 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
244 /* Generate the key */
245 EVP_PKEY *pkeyTmp = NULL;
246 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
247 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
249 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
251 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
252 Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
255 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
257 int ecCurve = NOT_DEFINED;
262 case ElipticCurve::prime192v1:
263 ecCurve = NID_X9_62_prime192v1;
265 case ElipticCurve::prime256v1:
266 ecCurve = NID_X9_62_prime256v1;
268 case ElipticCurve::secp384r1:
269 ecCurve = NID_secp384r1;
272 ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
275 /* Create the context for generating the parameters */
276 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
278 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
281 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
282 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
285 if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
286 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
289 /* Generate parameters */
290 EVP_PKEY *pparamTmp = NULL;
291 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
292 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
294 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
296 // Start to generate key
297 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
299 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
302 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
303 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
306 /* Generate the key */
307 EVP_PKEY *pkeyTmp = NULL;
308 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
309 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
311 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
313 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
314 Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
317 Token createKeyAES(CryptoBackend backendId, const int sizeBits)
319 // check the parameters of functions
320 if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
321 LogError("Error in AES input size");
322 ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
326 int sizeBytes = sizeBits/8;
327 if (!RAND_bytes(key, sizeBytes)) {
328 LogError("Error in AES key generation");
329 ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
332 return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
335 RawBuffer encryptDataAesCbc(
336 const RawBuffer &key,
337 const RawBuffer &data,
340 Crypto::SW::Cipher::AesCbcEncryption enc(key, iv);
341 RawBuffer result = enc.Append(data);
342 RawBuffer tmp = enc.Finalize();
343 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
347 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
348 const RawBuffer &key,
349 const RawBuffer &data,
353 RawBuffer tag(tagSize);
354 Crypto::SW::Cipher::AesGcmEncryption enc(key, iv);
355 RawBuffer result = enc.Append(data);
356 RawBuffer tmp = enc.Finalize();
357 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
358 if (0 == enc.Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) {
359 ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Get tag failed.");
361 return std::make_pair(result, tag);
364 RawBuffer encryptDataAesGcmPacked(
365 const RawBuffer &key,
366 const RawBuffer &data,
370 auto pair = encryptDataAesGcm(key, data, iv, tagSize);
371 std::copy(pair.second.begin(), pair.second.end(), std::back_inserter(pair.first));
375 RawBuffer decryptDataAesCbc(
376 const RawBuffer &key,
377 const RawBuffer &data,
380 Crypto::SW::Cipher::AesCbcDecryption dec(key, iv);
381 RawBuffer result = dec.Append(data);
382 RawBuffer tmp = dec.Finalize();
383 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
387 RawBuffer decryptDataAesGcm(
388 const RawBuffer &key,
389 const RawBuffer &data,
391 const RawBuffer &tag)
393 Crypto::SW::Cipher::AesGcmDecryption dec(key, iv);
394 void *ptr = (void*)tag.data();
395 if (0 == dec.Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) {
396 ThrowErr(Exc::Crypto::InternalError,
397 "Error in AES control function. Set tag failed.");
399 RawBuffer result = dec.Append(data);
400 RawBuffer tmp = dec.Finalize();
401 std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
405 RawBuffer decryptDataAesGcmPacked(
406 const RawBuffer &key,
407 const RawBuffer &data,
411 if (tagSize > static_cast<int>(data.size()))
412 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
414 auto tagPos = data.data() + data.size() - tagSize;
415 return decryptDataAesGcm(
417 RawBuffer(data.data(), tagPos),
419 RawBuffer(tagPos, data.data() + data.size()));
422 RawBuffer symmetricEncrypt(const RawBuffer &key,
423 const CryptoAlgorithm &alg,
424 const RawBuffer &data)
426 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
430 case AlgoType::AES_CBC:
431 return encryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
432 case AlgoType::AES_GCM:
433 return encryptDataAesGcmPacked(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV),
434 unpack<int>(alg, ParamName::ED_TAG_LEN));
438 ThrowErr(Exc::Crypto::OperationNotSupported,
439 "symmetric enc error: algorithm not recognized");
442 RawBuffer symmetricDecrypt(const RawBuffer &key,
443 const CryptoAlgorithm &alg,
444 const RawBuffer &data)
446 AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
450 case AlgoType::AES_CBC:
451 return decryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
452 case AlgoType::AES_GCM:
453 return decryptDataAesGcmPacked(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV),
454 unpack<int>(alg, ParamName::ED_TAG_LEN));
458 ThrowErr(Exc::Crypto::InputParam, "symmetric dec error: algorithm not recognized");
461 RawBuffer sign(EVP_PKEY *pkey,
462 const CryptoAlgorithm &alg,
463 const RawBuffer &message)
465 int rsa_padding = NOT_DEFINED;
466 const EVP_MD *md_algo = NULL;
468 HashAlgorithm hashTmp = HashAlgorithm::NONE;
469 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
470 md_algo = getMdAlgo(hashTmp);
472 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
473 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
474 rsa_padding = getRsaPadding(rsaPad);
477 // if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
478 // (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
479 // (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
481 // LogError("Error in private key type");
482 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
485 // if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
486 // rsa_padding = getRsaPadding(padAlgo);
490 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
493 if(md_algo == NULL) {
494 return signMessage(pkey, message, rsa_padding);
497 return digestSignMessage(pkey,message, md_algo, rsa_padding);
500 RawBuffer signMessage(EVP_PKEY *privKey,
501 const RawBuffer &message,
502 const int rsa_padding)
504 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
507 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
510 if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
511 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
514 /* Set padding algorithm */
515 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
516 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
517 ThrowErr(Exc::Crypto::InternalError,
518 "Error in EVP_PKEY_CTX_set_rsa_padding function");
522 /* Finalize the Sign operation */
523 /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
524 * signature. Length is returned in slen */
526 if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
527 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
530 /* Allocate memory for the signature based on size in slen */
533 if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
539 // Set value to return RawData
544 ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
547 RawBuffer digestSignMessage(EVP_PKEY *privKey,
548 const RawBuffer &message,
549 const EVP_MD *md_algo,
550 const int rsa_padding)
552 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
554 EVP_PKEY_CTX *pctx = NULL;
556 // Create the Message Digest Context
558 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
561 if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
562 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
565 /* Set padding algorithm */
566 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
567 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
568 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
572 /* Call update with the message */
573 if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
574 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
577 /* Finalize the DigestSign operation */
578 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
579 * signature. Length is returned in slen */
581 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
582 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
585 /* Allocate memory for the signature based on size in slen */
588 /* Obtain the signature */
589 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
590 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
593 // Set value to return RawData
598 int verify(EVP_PKEY *pkey,
599 const CryptoAlgorithm &alg,
600 const RawBuffer &message,
601 const RawBuffer &signature)
603 int rsa_padding = NOT_DEFINED;
604 const EVP_MD *md_algo = NULL;
606 HashAlgorithm hashTmp = HashAlgorithm::NONE;
607 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
608 md_algo = getMdAlgo(hashTmp);
610 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
611 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
612 rsa_padding = getRsaPadding(rsaPad);
615 // if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
616 // (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
617 // (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
619 // LogError("Error in private key type");
620 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
623 // if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
624 // rsa_padding = getRsaPadding(padAlgo);
627 // auto shrPKey = publicKey.getEvpShPtr();
629 ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
632 if (md_algo == NULL) {
633 return verifyMessage(pkey, message, signature, rsa_padding);
636 return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
639 int verifyMessage(EVP_PKEY *pubKey,
640 const RawBuffer &message,
641 const RawBuffer &signature,
642 const int rsa_padding)
644 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
647 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
650 if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
651 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
654 /* Set padding algorithm */
655 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
656 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
657 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
661 if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
662 return CKM_API_SUCCESS;
665 LogError("EVP_PKEY_verify Failed");
666 return CKM_API_ERROR_VERIFICATION_FAILED;
669 int digestVerifyMessage(EVP_PKEY *pubKey,
670 const RawBuffer &message,
671 const RawBuffer &signature,
672 const EVP_MD *md_algo,
673 const int rsa_padding)
675 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
676 EVP_PKEY_CTX *pctx = NULL;
678 /* Create the Message Digest Context */
680 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
683 if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
684 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
687 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
688 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
689 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
693 if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
694 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
697 if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
698 return CKM_API_SUCCESS;
701 LogError("EVP_PKEY_verify Failed");
702 return CKM_API_ERROR_VERIFICATION_FAILED;
705 } // namespace Internals
707 } // namespace Crypto