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