Use new classes to sign and verify messages.
[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
24 #include <openssl/x509_vfy.h>
25 #include <openssl/evp.h>
26 #include <openssl/obj_mac.h>
27 #include <openssl/ec.h>
28 #include <openssl/dsa.h>
29 #include <openssl/dh.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
38 #include <ckm/ckm-error.h>
39 #include <ckm/ckm-type.h>
40 #include <key-impl.h>
41 #include <assert.h>
42 #include <dpl/log/log.h>
43
44 #include <generic-backend/exception.h>
45 #include <sw-backend/internals.h>
46
47 #define OPENSSL_SUCCESS 1       // DO NOTCHANGE THIS VALUE
48 #define OPENSSL_FAIL    0       // DO NOTCHANGE THIS VALUE
49 #define DEV_HW_RANDOM_FILE    "/dev/hwrng"
50 #define DEV_URANDOM_FILE    "/dev/urandom"
51
52 namespace {
53 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
54 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
55 } // anonymous namespace
56
57 namespace CKM {
58 namespace Crypto {
59 namespace SW {
60 namespace Internals {
61
62 int initialize() {
63     int hw_rand_ret = 0;
64     int u_rand_ret = 0;
65
66     // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
67     ERR_load_crypto_strings();
68     OpenSSL_add_all_algorithms();
69
70     // initialize entropy
71     std::ifstream ifile(DEV_HW_RANDOM_FILE);
72     if(ifile.is_open()) {
73         u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
74     }
75     if(u_rand_ret != 32 ){
76         LogError("Error in HW_RAND file load");
77         hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
78
79         if(hw_rand_ret != 32) {
80             LogError("Error in U_RAND_file_load");
81             ThrowMsg(Crypto::Exception::InternalError, "Error in U_RAND_file_load");
82         }
83     }
84
85     return CKM_CRYPTO_INIT_SUCCESS;
86 }
87
88 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
89     const EVP_MD *md_algo=NULL;
90     switch(hashAlgo) {
91     case HashAlgorithm::NONE:
92         md_algo = NULL;
93         break;
94     case HashAlgorithm::SHA1:
95         md_algo = EVP_sha1();
96          break;
97     case HashAlgorithm::SHA256:
98          md_algo = EVP_sha256();
99          break;
100     case HashAlgorithm::SHA384:
101          md_algo = EVP_sha384();
102          break;
103     case HashAlgorithm::SHA512:
104          md_algo = EVP_sha512();
105          break;
106     default:
107         LogError("Error in hashAlgorithm value");
108         ThrowMsg(Crypto::Exception::InternalError, "Error in hashAlgorithm value");
109     }
110     return md_algo;
111 }
112
113 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
114     int rsa_padding = -1;
115     switch(padAlgo) {
116     case RSAPaddingAlgorithm::NONE:
117         rsa_padding = RSA_NO_PADDING;
118         break;
119     case RSAPaddingAlgorithm::PKCS1:
120         rsa_padding = RSA_PKCS1_PADDING;
121         break;
122     case RSAPaddingAlgorithm::X931:
123         rsa_padding = RSA_X931_PADDING;
124         break;
125     default:
126         LogError("Error in RSAPaddingAlgorithm value");
127         ThrowMsg(Crypto::Exception::InternalError, "Error in RSAPaddingAlgorithm value");
128     }
129     return rsa_padding;
130 }
131
132 void createKeyPairRSA(const int size, // size in bits [1024, 2048, 4096]
133         KeyImpl &createdPrivateKey,  // returned value
134         KeyImpl &createdPublicKey)  // returned value
135 {
136     EVP_PKEY_CTX *ctx = NULL;
137     EVP_PKEY *pkey = NULL;
138     EVP_PKEY *pparam = NULL;
139
140     // check the parameters of functions
141     if(size != 1024 && size !=2048 && size != 4096) {
142         LogError("Error in RSA input size");
143         ThrowMsg(Crypto::Exception::InternalError, "Error in RSA input size");
144     }
145
146     // check the parameters of functions
147     if(&createdPrivateKey == NULL) {
148         LogError("Error in createdPrivateKey value");
149         ThrowMsg(Crypto::Exception::InternalError, "Error in createdPrivateKey value");
150     }
151
152     // check the parameters of functions
153     if(&createdPublicKey == NULL) {
154         LogError("Error in createdPrivateKey value");
155         ThrowMsg(Crypto::Exception::InternalError, "Error in createdPublicKey value");
156     }
157
158     Try {
159         if(!(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL))) {
160             LogError("Error in EVP_PKEY_CTX_new_id function !!");
161             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
162         }
163
164         if(EVP_PKEY_keygen_init(ctx) <= 0) {
165             LogError("Error in EVP_PKEY_keygen_init function !!");
166             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function !!");
167         }
168
169         if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx,size) <= 0) {
170             LogError("Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
171             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
172         }
173
174         if(!EVP_PKEY_keygen(ctx, &pkey)) {
175             LogError("Error in EVP_PKEY_keygen function !!");
176             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function !!");
177         }
178     } Catch(Crypto::Exception::InternalError) {
179         if(pkey) {
180             EVP_PKEY_free(pkey);
181         }
182
183         if(pparam) {
184             EVP_PKEY_free(pparam);
185         }
186
187         if(ctx) {
188             EVP_PKEY_CTX_free(ctx);
189         }
190
191         ReThrowMsg(Crypto::Exception::InternalError,"Error in opensslError function !!");
192     }
193
194     KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
195
196     createdPrivateKey = KeyImpl(ptr, KeyType::KEY_RSA_PRIVATE);
197     createdPublicKey = KeyImpl(ptr, KeyType::KEY_RSA_PUBLIC);
198
199     if(pparam) {
200         EVP_PKEY_free(pparam);
201     }
202
203     if(ctx) {
204         EVP_PKEY_CTX_free(ctx);
205     }
206 }
207
208
209 void createKeyPairDSA(const int size, // size in bits [1024, 2048, 3072, 4096]
210         KeyImpl &createdPrivateKey,  // returned value
211         KeyImpl &createdPublicKey)  // returned value
212 {
213         EVP_PKEY_CTX *pctx = NULL;
214         EVP_PKEY_CTX *kctx = NULL;
215         EVP_PKEY *pkey = NULL;
216         EVP_PKEY *pparam = NULL;
217
218         // check the parameters of functions
219         if(size != 1024 && size !=2048 && size !=3072 && size != 4096) {
220                 LogError("Error in DSA input size");
221                 ThrowMsg(Exception::InternalError, "Error in DSA input size");
222         }
223
224         // check the parameters of functions
225         if(&createdPrivateKey == NULL) {
226                 LogError("Error in createdPrivateKey value");
227                 ThrowMsg(Exception::InternalError, "Error in createdPrivateKey value");
228         }
229
230         // check the parameters of functions
231         if(&createdPublicKey == NULL) {
232                 LogError("Error in createdPrivateKey value");
233                 ThrowMsg(Exception::InternalError, "Error in createdPublicKey value");
234         }
235
236         Try {
237                 /* Create the context for generating the parameters */
238                 if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL))) {
239                         LogError("Error in EVP_PKEY_CTX_new_id function");
240                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function");
241                 }
242
243                 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx)) {
244                         LogError("Error in EVP_PKEY_paramgen_init function");
245                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen_init function");
246                 }
247
248                 if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, size)) {
249                         LogError("Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(" << size << ") function");
250                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(" << size << ") function");
251                 }
252
253                 /* Generate parameters */
254                 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx, &pparam)) {
255                         LogError("Error in EVP_PKEY_paramgen function");
256                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen function");
257                 }
258
259                 // Start to generate key
260                 if(!(kctx = EVP_PKEY_CTX_new(pparam, NULL))) {
261                         LogError("Error in EVP_PKEY_CTX_new function");
262                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
263                 }
264
265                 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx)) {
266                         LogError("Error in EVP_PKEY_keygen_init function");
267                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function");
268                 }
269
270                 /* Generate the key */
271                 if(EVP_SUCCESS != EVP_PKEY_keygen(kctx, &pkey)) {
272                         LogError("Error in EVP_PKEY_keygen function");
273                         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
274                 }
275         }
276         Catch(Crypto::Exception::InternalError)
277         {
278                 if(pkey) {
279                         EVP_PKEY_free(pkey);
280                 }
281
282                 if(pparam) {
283                         EVP_PKEY_free(pparam);
284                 }
285
286                 if(pctx) {
287                         EVP_PKEY_CTX_free(pctx);
288                 }
289
290                 if(kctx) {
291                         EVP_PKEY_CTX_free(kctx);
292                 }
293
294                 ReThrowMsg(Crypto::Exception::InternalError,"Error in openssl function !!");
295         }
296
297         KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
298
299         createdPrivateKey = KeyImpl(ptr, KeyType::KEY_DSA_PRIVATE);
300         createdPublicKey = KeyImpl(ptr, KeyType::KEY_DSA_PUBLIC);
301
302         if(pparam) {
303                 EVP_PKEY_free(pparam);
304         }
305
306         if(pctx) {
307                 EVP_PKEY_CTX_free(pctx);
308         }
309
310         if(kctx) {
311                 EVP_PKEY_CTX_free(kctx);
312         }
313 }
314
315 void createKeyPairECDSA(ElipticCurve type,
316         KeyImpl &createdPrivateKey,  // returned value
317         KeyImpl &createdPublicKey)  // returned value
318 {
319     int ecCurve = NOT_DEFINED;
320     EVP_PKEY_CTX *pctx = NULL;
321     EVP_PKEY_CTX *kctx = NULL;
322     EVP_PKEY *pkey = NULL;
323     EVP_PKEY *pparam = NULL;
324
325     switch(type) {
326     case ElipticCurve::prime192v1:
327         ecCurve = NID_X9_62_prime192v1;
328         break;
329     case ElipticCurve::prime256v1:
330         ecCurve = NID_X9_62_prime256v1;
331         break;
332     case ElipticCurve::secp384r1:
333         ecCurve = NID_secp384r1;
334         break;
335     default:
336         LogError("Error in EC type");
337         ThrowMsg(Exception::InternalError, "Error in EC type");
338     }
339
340     // check the parameters of functions
341     if(&createdPrivateKey == NULL) {
342         LogError("Error in createdPrivateKey value");
343         ThrowMsg(Exception::InternalError, "Error in createdPrivateKey value");
344     }
345
346     // check the parameters of functions
347     if(&createdPublicKey == NULL) {
348         LogError("Error in createdPrivateKey value");
349         ThrowMsg(Exception::InternalError, "Error in createdPublicKey value");
350     }
351
352     Try {
353         /* Create the context for generating the parameters */
354         if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
355             LogError("Error in EVP_PKEY_CTX_new_id function");
356             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new_id function");
357         }
358
359         if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx)) {
360             LogError("Error in EVP_PKEY_paramgen_init function");
361             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen_init function");
362         }
363
364         if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecCurve)) {
365             LogError("Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
366             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
367         }
368
369         /* Generate parameters */
370         if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx, &pparam)) {
371             LogError("Error in EVP_PKEY_paramgen function");
372             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_paramgen function");
373         }
374
375         // Start to generate key
376         if(!(kctx = EVP_PKEY_CTX_new(pparam, NULL))) {
377             LogError("Error in EVP_PKEY_CTX_new function");
378             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
379         }
380
381         if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx)) {
382             LogError("Error in EVP_PKEY_keygen_init function");
383             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen_init function");
384         }
385
386         /* Generate the key */
387         if(EVP_SUCCESS != EVP_PKEY_keygen(kctx, &pkey)) {
388             LogError("Error in EVP_PKEY_keygen function");
389             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
390         }
391     } Catch(Crypto::Exception::InternalError) {
392         if(pkey) {
393             EVP_PKEY_free(pkey);
394         }
395
396         if(pparam) {
397             EVP_PKEY_free(pparam);
398         }
399
400         if(pctx) {
401             EVP_PKEY_CTX_free(pctx);
402         }
403
404         if(kctx) {
405             EVP_PKEY_CTX_free(kctx);
406         }
407
408         ReThrowMsg(Crypto::Exception::InternalError,"Error in openssl function !!");
409     }
410
411     KeyImpl::EvpShPtr ptr(pkey, EVP_PKEY_free); // shared ptr will free pkey
412
413     createdPrivateKey = KeyImpl(ptr, KeyType::KEY_ECDSA_PRIVATE);
414     createdPublicKey = KeyImpl(ptr, KeyType::KEY_ECDSA_PUBLIC);
415
416     if(pparam) {
417         EVP_PKEY_free(pparam);
418     }
419
420     if(pctx) {
421         EVP_PKEY_CTX_free(pctx);
422     }
423
424     if(kctx) {
425         EVP_PKEY_CTX_free(kctx);
426     }
427 }
428
429 RawBuffer sign(EVP_PKEY *pkey,
430     const CryptoAlgorithm &alg,
431     const RawBuffer &message)
432 {
433     int rsa_padding = NOT_DEFINED;
434     const EVP_MD *md_algo = NULL;
435
436     HashAlgorithm hashTmp = HashAlgorithm::NONE;
437     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
438     md_algo = getMdAlgo(hashTmp);
439
440     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
441     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
442     rsa_padding = getRsaPadding(rsaPad);
443
444 //
445 //    if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
446 //       (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
447 //       (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
448 //    {
449 //        LogError("Error in private key type");
450 //        ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
451 //    }
452 //
453 //    if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
454 //        rsa_padding = getRsaPadding(padAlgo);
455 //    }
456
457     if (NULL == pkey) {
458         LogError("Error in EVP_PKEY_keygen function");
459         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
460     }
461
462     if(md_algo == NULL) {
463         return signMessage(pkey, message, rsa_padding);
464     }
465
466     return digestSignMessage(pkey,message, md_algo, rsa_padding);
467 }
468
469 RawBuffer signMessage(EVP_PKEY *privKey,
470         const RawBuffer &message,
471         const int rsa_padding)
472 {
473     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
474  
475     if(!pctx.get()) {
476         LogError("Error in EVP_PKEY_CTX_new function");
477         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
478     }
479
480     if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
481         LogError("Error in EVP_PKEY_sign_init function");
482         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign_init function");
483     }
484
485     /* Set padding algorithm */
486     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
487         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
488             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
489             ThrowMsg(Crypto::Exception::InternalError,
490                      "Error in EVP_PKEY_CTX_set_rsa_padding function");
491         }
492     }
493
494     /* Finalize the Sign operation */
495     /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
496      * signature. Length is returned in slen */
497     size_t slen;
498     if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
499         LogError("Error in EVP_PKEY_sign function");
500         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign function");
501     }
502
503     /* Allocate memory for the signature based on size in slen */
504     RawBuffer sig(slen);
505
506     if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
507                                     sig.data(),
508                                     &slen,
509                                     message.data(),
510                                     message.size()))
511     {
512         // Set value to return RawData
513         sig.resize(slen);
514         return sig;
515     }
516
517     LogError("Error in EVP_PKEY_sign function. Input param error.");
518     ThrowMsg(Crypto::Exception::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
519 }
520
521 RawBuffer digestSignMessage(EVP_PKEY *privKey,
522         const RawBuffer &message,
523         const EVP_MD *md_algo,
524         const int rsa_padding)
525 {
526     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
527  
528     EVP_PKEY_CTX *pctx = NULL;
529
530     // Create the Message Digest Context
531     if(!mdctx.get()) {
532         LogError("Error in EVP_MD_CTX_create function");
533         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
534     }
535
536     if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
537         LogError("Error in EVP_DigestSignInit function");
538         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignInit function");
539     }
540
541     /* Set padding algorithm */
542     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
543         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
544             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
545             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
546         }
547     }
548
549     /* Call update with the message */
550     if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
551         LogError("Error in EVP_DigestSignUpdate function");
552         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignUpdate function");
553     }
554
555     /* Finalize the DigestSign operation */
556     /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
557      * signature. Length is returned in slen */
558     size_t slen;
559     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
560         LogError("Error in EVP_DigestSignFinal function");
561         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
562     }
563
564     /* Allocate memory for the signature based on size in slen */
565     RawBuffer sig(slen);
566
567     /* Obtain the signature */
568     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
569         LogError("Error in EVP_DigestSignFinal function");
570         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
571     }
572
573     // Set value to return RawData
574     sig.resize(slen);
575     return sig;
576 }
577
578 int verify(EVP_PKEY *pkey,
579     const CryptoAlgorithm &alg,
580     const RawBuffer &message,
581     const RawBuffer &signature)
582 {
583     int rsa_padding = NOT_DEFINED;
584     const EVP_MD *md_algo = NULL;
585
586     HashAlgorithm hashTmp = HashAlgorithm::NONE;
587     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
588     md_algo = getMdAlgo(hashTmp);
589
590     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
591     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
592     rsa_padding = getRsaPadding(rsaPad);
593
594 //
595 //    if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
596 //       (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
597 //       (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
598 //    {
599 //        LogError("Error in private key type");
600 //        ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
601 //    }
602 //
603 //    if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
604 //        rsa_padding = getRsaPadding(padAlgo);
605 //    }
606
607 //    auto shrPKey = publicKey.getEvpShPtr();
608     if (NULL == pkey) {
609         LogError("Error in getEvpShPtr function");
610         ThrowMsg(Crypto::Exception::InternalError, "Error in getEvpShPtr function");
611     }
612
613     if (md_algo == NULL) {
614         return verifyMessage(pkey, message, signature, rsa_padding);
615     }
616
617     return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
618 }
619
620 int verifyMessage(EVP_PKEY *pubKey,
621         const RawBuffer &message,
622         const RawBuffer &signature,
623         const int rsa_padding)
624 {
625     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
626
627     if(!pctx.get()) {
628         LogError("Error in EVP_PKEY_CTX_new function");
629         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
630     }
631
632     if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
633         LogError("Error in EVP_PKEY_verify_init function");
634         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_verify_init function");
635     }
636
637     /* Set padding algorithm  */
638     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
639         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
640             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
641             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
642         }
643     }
644
645     if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
646         return CKM_API_SUCCESS;
647     } 
648
649     LogError("EVP_PKEY_verify Failed");
650     return CKM_API_ERROR_VERIFICATION_FAILED;
651 }
652
653 int digestVerifyMessage(EVP_PKEY *pubKey,
654         const RawBuffer &message,
655         const RawBuffer &signature,
656         const EVP_MD *md_algo,
657         const int rsa_padding)
658 {
659     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
660     EVP_PKEY_CTX *pctx = NULL;
661
662     /* Create the Message Digest Context */
663     if(!mdctx.get()) {
664         LogError("Error in EVP_MD_CTX_create function");
665         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
666     }
667
668     if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
669         LogError("Error in EVP_DigestVerifyInit function");
670         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyInit function");
671     }
672
673     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
674         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
675             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
676             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
677         }
678     }
679
680     if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
681         LogError("Error in EVP_DigestVerifyUpdate function");
682         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyUpdate function");
683     }
684
685     if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
686         return CKM_API_SUCCESS;
687     }
688
689     LogError("EVP_PKEY_verify Failed");
690     return CKM_API_ERROR_VERIFICATION_FAILED;
691 }
692
693 } // namespace Internals
694 } // namespace SW
695 } // namespace Crypto
696 } // namespace CKM