Add implementation for sign and verify operation.
[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     (void) alg;
437 //    md_algo = getMdAlgo(hashAlgo);
438 //
439 //    if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
440 //       (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
441 //       (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
442 //    {
443 //        LogError("Error in private key type");
444 //        ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
445 //    }
446 //
447 //    if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
448 //        rsa_padding = getRsaPadding(padAlgo);
449 //    }
450
451     if (NULL == pkey) {
452         LogError("Error in EVP_PKEY_keygen function");
453         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_keygen function");
454     }
455
456     if(md_algo == NULL) {
457         return signMessage(pkey, message, rsa_padding);
458     }
459
460     return digestSignMessage(pkey,message, md_algo, rsa_padding);
461 }
462
463 RawBuffer signMessage(EVP_PKEY *privKey,
464         const RawBuffer &message,
465         const int rsa_padding)
466 {
467     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
468  
469     if(!pctx.get()) {
470         LogError("Error in EVP_PKEY_CTX_new function");
471         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
472     }
473
474     if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
475         LogError("Error in EVP_PKEY_sign_init function");
476         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign_init function");
477     }
478
479     /* Set padding algorithm */
480     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
481         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
482             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
483             ThrowMsg(Crypto::Exception::InternalError,
484                      "Error in EVP_PKEY_CTX_set_rsa_padding function");
485         }
486     }
487
488     /* Finalize the Sign operation */
489     /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
490      * signature. Length is returned in slen */
491     size_t slen;
492     if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
493         LogError("Error in EVP_PKEY_sign function");
494         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign function");
495     }
496
497     /* Allocate memory for the signature based on size in slen */
498     RawBuffer sig(slen);
499
500     if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
501                                     sig.data(),
502                                     &slen,
503                                     message.data(),
504                                     message.size()))
505     {
506         // Set value to return RawData
507         sig.resize(slen);
508         return sig;
509     }
510
511     LogError("Error in EVP_PKEY_sign function");
512     ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_sign function");
513 }
514
515 RawBuffer digestSignMessage(EVP_PKEY *privKey,
516         const RawBuffer &message,
517         const EVP_MD *md_algo,
518         const int rsa_padding)
519 {
520     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
521  
522     EVP_PKEY_CTX *pctx = NULL;
523
524     // Create the Message Digest Context
525     if(!mdctx.get()) {
526         LogError("Error in EVP_MD_CTX_create function");
527         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
528     }
529
530     if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
531         LogError("Error in EVP_DigestSignInit function");
532         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignInit function");
533     }
534
535     /* Set padding algorithm */
536     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
537         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
538             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
539             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
540         }
541     }
542
543     /* Call update with the message */
544     if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
545         LogError("Error in EVP_DigestSignUpdate function");
546         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignUpdate function");
547     }
548
549     /* Finalize the DigestSign operation */
550     /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
551      * signature. Length is returned in slen */
552     size_t slen;
553     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
554         LogError("Error in EVP_DigestSignFinal function");
555         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
556     }
557
558     /* Allocate memory for the signature based on size in slen */
559     RawBuffer sig(slen);
560
561     /* Obtain the signature */
562     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
563         LogError("Error in EVP_DigestSignFinal function");
564         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestSignFinal function");
565     }
566
567     // Set value to return RawData
568     sig.resize(slen);
569     return sig;
570 }
571
572 int verify(EVP_PKEY *pkey,
573     const CryptoAlgorithm &alg,
574     const RawBuffer &message,
575     const RawBuffer &signature)
576 {
577     int rsa_padding = NOT_DEFINED;
578     const EVP_MD *md_algo = NULL;
579
580     (void)alg;
581 //    md_algo = getMdAlgo(hashAlgo);
582 //
583 //    if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
584 //       (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
585 //       (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
586 //    {
587 //        LogError("Error in private key type");
588 //        ThrowMsg(CryptoService::Exception::Crypto_internal, "Error in private key type");
589 //    }
590 //
591 //    if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
592 //        rsa_padding = getRsaPadding(padAlgo);
593 //    }
594
595 //    auto shrPKey = publicKey.getEvpShPtr();
596     if (NULL == pkey) {
597         LogError("Error in getEvpShPtr function");
598         ThrowMsg(Crypto::Exception::InternalError, "Error in getEvpShPtr function");
599     }
600
601     if (md_algo == NULL) {
602         return verifyMessage(pkey, message, signature, rsa_padding);
603     }
604
605     return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
606 }
607
608 int verifyMessage(EVP_PKEY *pubKey,
609         const RawBuffer &message,
610         const RawBuffer &signature,
611         const int rsa_padding)
612 {
613     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
614
615     if(!pctx.get()) {
616         LogError("Error in EVP_PKEY_CTX_new function");
617         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_new function");
618     }
619
620     if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
621         LogError("Error in EVP_PKEY_verify_init function");
622         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_verify_init function");
623     }
624
625     /* Set padding algorithm  */
626     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
627         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
628             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
629             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
630         }
631     }
632
633     if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
634         return CKM_API_SUCCESS;
635     } 
636
637     LogError("EVP_PKEY_verify Failed");
638     return CKM_API_ERROR_VERIFICATION_FAILED;
639 }
640
641 int digestVerifyMessage(EVP_PKEY *pubKey,
642         const RawBuffer &message,
643         const RawBuffer &signature,
644         const EVP_MD *md_algo,
645         const int rsa_padding)
646 {
647     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
648     EVP_PKEY_CTX *pctx = NULL;
649
650     /* Create the Message Digest Context */
651     if(!mdctx.get()) {
652         LogError("Error in EVP_MD_CTX_create function");
653         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_MD_CTX_create function");
654     }
655
656     if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
657         LogError("Error in EVP_DigestVerifyInit function");
658         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyInit function");
659     }
660
661     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
662         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
663             LogError("Error in EVP_PKEY_CTX_set_rsa_padding function");
664             ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
665         }
666     }
667
668     if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
669         LogError("Error in EVP_DigestVerifyUpdate function");
670         ThrowMsg(Crypto::Exception::InternalError, "Error in EVP_DigestVerifyUpdate function");
671     }
672
673     if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
674         return CKM_API_SUCCESS;
675     }
676
677     LogError("EVP_PKEY_verify Failed");
678     return CKM_API_ERROR_VERIFICATION_FAILED;
679 }
680
681 } // namespace Internals
682 } // namespace SW
683 } // namespace Crypto
684 } // namespace CKM