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