Introduce new (much simpler) Exception type.
[platform/core/security/key-manager.git] / src / manager / crypto / sw-backend / internals.cpp
1 /*
2  *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       internals.cpp
18  * @author
19  * @version    1.0
20  */
21 #include <exception>
22 #include <fstream>
23 #include <utility>
24
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>
36
37 #include <ckm/ckm-error.h>
38 #include <assert.h>
39 #include <dpl/log/log.h>
40
41 #include <generic-backend/exception.h>
42 #include <sw-backend/internals.h>
43
44 #define OPENSSL_SUCCESS 1       // DO NOTCHANGE THIS VALUE
45 #define OPENSSL_FAIL    0       // DO NOTCHANGE THIS VALUE
46 #define DEV_HW_RANDOM_FILE    "/dev/hwrng"
47 #define DEV_URANDOM_FILE    "/dev/urandom"
48
49 namespace {
50 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
51 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
52 typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
53
54 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
55 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
56 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
57     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
58
59     if (NULL == pkey) {
60         ThrowErr(CKM::Exc::Crypto::InternalError, "attempt to parse an empty key!");
61     }
62
63     if (NULL == bio.get()) {
64         ThrowErr(CKM::Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
65     }
66
67     if (1 != fun(bio.get(), pkey)) {
68         ThrowErr(CKM::Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
69     }
70
71     CKM::RawBuffer output(8196);
72
73     int size = BIO_read(bio.get(), output.data(), output.size());
74
75     if (size <= 0) {
76         ThrowErr(CKM::Exc::Crypto::InternalError, "Error in BIO_read: ", size);
77     }
78
79     output.resize(size);
80     return output;
81 }
82 } // anonymous namespace
83
84 namespace CKM {
85 namespace Crypto {
86 namespace SW {
87 namespace Internals {
88
89 int initialize() {
90     int hw_rand_ret = 0;
91     int u_rand_ret = 0;
92
93     // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
94     ERR_load_crypto_strings();
95     OpenSSL_add_all_algorithms();
96
97     // initialize entropy
98     std::ifstream ifile(DEV_HW_RANDOM_FILE);
99     if(ifile.is_open()) {
100         u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
101     }
102     if(u_rand_ret != 32 ){
103         LogError("Error in HW_RAND file load");
104         hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
105
106         if(hw_rand_ret != 32) {
107             ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
108         }
109     }
110
111     return CKM_CRYPTO_INIT_SUCCESS;
112 }
113
114 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
115     const EVP_MD *md_algo=NULL;
116     switch(hashAlgo) {
117     case HashAlgorithm::NONE:
118         md_algo = NULL;
119         break;
120     case HashAlgorithm::SHA1:
121         md_algo = EVP_sha1();
122          break;
123     case HashAlgorithm::SHA256:
124          md_algo = EVP_sha256();
125          break;
126     case HashAlgorithm::SHA384:
127          md_algo = EVP_sha384();
128          break;
129     case HashAlgorithm::SHA512:
130          md_algo = EVP_sha512();
131          break;
132     default:
133         ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
134     }
135     return md_algo;
136 }
137
138 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
139     int rsa_padding = -1;
140     switch(padAlgo) {
141     case RSAPaddingAlgorithm::NONE:
142         rsa_padding = RSA_NO_PADDING;
143         break;
144     case RSAPaddingAlgorithm::PKCS1:
145         rsa_padding = RSA_PKCS1_PADDING;
146         break;
147     case RSAPaddingAlgorithm::X931:
148         rsa_padding = RSA_X931_PADDING;
149         break;
150     default:
151         ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
152     }
153     return rsa_padding;
154 }
155
156 TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
157 {
158     EvpPkeyUPtr pkey;
159
160     // check the parameters of functions
161     if(size!=1024 && size!=2048 && size!=4096) {
162         ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
163     }
164
165     EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
166     if(!ctx) {
167         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
168     }
169
170     if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
171         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
172     }
173
174     if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
175         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
176     }
177
178     EVP_PKEY *pkeyTmp = NULL;
179     if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
180         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
181     }
182     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
183
184     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
185                                         Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
186 }
187
188
189 TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
190 {
191     EvpPkeyUPtr pkey;
192     EvpPkeyUPtr pparam;
193
194     // check the parameters of functions
195     if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
196         ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
197     }
198
199     /* Create the context for generating the parameters */
200     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
201     if(!pctx) {
202         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
203     }
204
205     if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
206         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
207     }
208
209     if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
210         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
211     }
212
213     /* Generate parameters */
214     EVP_PKEY *pparamTmp = NULL;
215     if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
216         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
217     }
218     pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
219
220     // Start to generate key
221     EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
222     if(!kctx) {
223         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
224     }
225
226     if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
227         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
228     }
229
230     /* Generate the key */
231     EVP_PKEY *pkeyTmp = NULL;
232     if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
233         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
234     }
235     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
236
237     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
238                                         Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
239 }
240
241 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
242 {
243     int ecCurve = NOT_DEFINED;
244     EvpPkeyUPtr pkey;
245     EvpPkeyUPtr pparam;
246
247     switch(type) {
248     case ElipticCurve::prime192v1:
249         ecCurve = NID_X9_62_prime192v1;
250         break;
251     case ElipticCurve::prime256v1:
252         ecCurve = NID_X9_62_prime256v1;
253         break;
254     case ElipticCurve::secp384r1:
255         ecCurve = NID_secp384r1;
256         break;
257     default:
258         ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
259     }
260
261     /* Create the context for generating the parameters */
262     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
263     if(!pctx) {
264         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
265     }
266
267     if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
268         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
269     }
270
271     if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
272         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
273     }
274
275     /* Generate parameters */
276     EVP_PKEY *pparamTmp = NULL;
277     if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
278         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
279     }
280     pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
281
282     // Start to generate key
283     EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
284     if(!kctx) {
285         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
286     }
287
288     if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
289         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
290     }
291
292     /* Generate the key */
293     EVP_PKEY *pkeyTmp = NULL;
294     if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
295         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
296     }
297     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
298
299     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
300                                         Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
301 }
302
303 Token createKeyAES(CryptoBackend backendId, const int sizeBits)
304 {
305     // check the parameters of functions
306     if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
307         LogError("Error in AES input size");
308         ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
309     }
310
311     uint8_t key[32];
312     int sizeBytes = sizeBits/8;
313     if (!RAND_bytes(key, sizeBytes)) {
314         LogError("Error in AES key generation");
315         ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
316     }
317
318     return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
319 }
320
321 RawBuffer sign(EVP_PKEY *pkey,
322     const CryptoAlgorithm &alg,
323     const RawBuffer &message)
324 {
325     int rsa_padding = NOT_DEFINED;
326     const EVP_MD *md_algo = NULL;
327
328     HashAlgorithm hashTmp = HashAlgorithm::NONE;
329     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
330     md_algo = getMdAlgo(hashTmp);
331
332     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
333     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
334     rsa_padding = getRsaPadding(rsaPad);
335
336 //
337 //    if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
338 //       (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
339 //       (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
340 //    {
341 //        LogError("Error in private key type");
342 //        ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
343 //    }
344 //
345 //    if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
346 //        rsa_padding = getRsaPadding(padAlgo);
347 //    }
348
349     if (NULL == pkey) {
350         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
351     }
352
353     if(md_algo == NULL) {
354         return signMessage(pkey, message, rsa_padding);
355     }
356
357     return digestSignMessage(pkey,message, md_algo, rsa_padding);
358 }
359
360 RawBuffer signMessage(EVP_PKEY *privKey,
361         const RawBuffer &message,
362         const int rsa_padding)
363 {
364     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
365  
366     if(!pctx.get()) {
367         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
368     }
369
370     if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
371         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
372     }
373
374     /* Set padding algorithm */
375     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
376         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
377             ThrowErr(Exc::Crypto::InternalError,
378                      "Error in EVP_PKEY_CTX_set_rsa_padding function");
379         }
380     }
381
382     /* Finalize the Sign operation */
383     /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
384      * signature. Length is returned in slen */
385     size_t slen;
386     if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
387         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
388     }
389
390     /* Allocate memory for the signature based on size in slen */
391     RawBuffer sig(slen);
392
393     if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
394                                     sig.data(),
395                                     &slen,
396                                     message.data(),
397                                     message.size()))
398     {
399         // Set value to return RawData
400         sig.resize(slen);
401         return sig;
402     }
403
404     ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
405 }
406
407 RawBuffer digestSignMessage(EVP_PKEY *privKey,
408         const RawBuffer &message,
409         const EVP_MD *md_algo,
410         const int rsa_padding)
411 {
412     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
413  
414     EVP_PKEY_CTX *pctx = NULL;
415
416     // Create the Message Digest Context
417     if(!mdctx.get()) {
418         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
419     }
420
421     if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
422         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
423     }
424
425     /* Set padding algorithm */
426     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
427         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
428             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
429         }
430     }
431
432     /* Call update with the message */
433     if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
434         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
435     }
436
437     /* Finalize the DigestSign operation */
438     /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
439      * signature. Length is returned in slen */
440     size_t slen;
441     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
442         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
443     }
444
445     /* Allocate memory for the signature based on size in slen */
446     RawBuffer sig(slen);
447
448     /* Obtain the signature */
449     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
450         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
451     }
452
453     // Set value to return RawData
454     sig.resize(slen);
455     return sig;
456 }
457
458 int verify(EVP_PKEY *pkey,
459     const CryptoAlgorithm &alg,
460     const RawBuffer &message,
461     const RawBuffer &signature)
462 {
463     int rsa_padding = NOT_DEFINED;
464     const EVP_MD *md_algo = NULL;
465
466     HashAlgorithm hashTmp = HashAlgorithm::NONE;
467     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
468     md_algo = getMdAlgo(hashTmp);
469
470     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
471     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
472     rsa_padding = getRsaPadding(rsaPad);
473
474 //
475 //    if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
476 //       (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
477 //       (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
478 //    {
479 //        LogError("Error in private key type");
480 //        ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
481 //    }
482 //
483 //    if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
484 //        rsa_padding = getRsaPadding(padAlgo);
485 //    }
486
487 //    auto shrPKey = publicKey.getEvpShPtr();
488     if (NULL == pkey) {
489         ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
490     }
491
492     if (md_algo == NULL) {
493         return verifyMessage(pkey, message, signature, rsa_padding);
494     }
495
496     return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
497 }
498
499 int verifyMessage(EVP_PKEY *pubKey,
500         const RawBuffer &message,
501         const RawBuffer &signature,
502         const int rsa_padding)
503 {
504     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
505
506     if(!pctx.get()) {
507         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
508     }
509
510     if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
511         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
512     }
513
514     /* Set padding algorithm  */
515     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
516         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
517             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
518         }
519     }
520
521     if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
522         return CKM_API_SUCCESS;
523     } 
524
525     LogError("EVP_PKEY_verify Failed");
526     return CKM_API_ERROR_VERIFICATION_FAILED;
527 }
528
529 int digestVerifyMessage(EVP_PKEY *pubKey,
530         const RawBuffer &message,
531         const RawBuffer &signature,
532         const EVP_MD *md_algo,
533         const int rsa_padding)
534 {
535     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
536     EVP_PKEY_CTX *pctx = NULL;
537
538     /* Create the Message Digest Context */
539     if(!mdctx.get()) {
540         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
541     }
542
543     if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
544         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
545     }
546
547     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
548         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
549             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
550         }
551     }
552
553     if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
554         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
555     }
556
557     if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
558         return CKM_API_SUCCESS;
559     }
560
561     LogError("EVP_PKEY_verify Failed");
562     return CKM_API_ERROR_VERIFICATION_FAILED;
563 }
564
565 } // namespace Internals
566 } // namespace SW
567 } // namespace Crypto
568 } // namespace CKM