Add algorithm param validation
[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 #include <algorithm>
25
26 #include <openssl/evp.h>
27 #include <openssl/obj_mac.h>
28 #include <openssl/ec.h>
29 #include <openssl/dsa.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 <assert.h>
40 #include <dpl/log/log.h>
41
42 #include <generic-backend/exception.h>
43 #include <generic-backend/algo-validation.h>
44 #include <sw-backend/internals.h>
45 #include <sw-backend/crypto.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 CKM {
53 namespace Crypto {
54 namespace SW {
55 namespace Internals {
56
57 namespace {
58 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
59 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
60 typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
61
62 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
63 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
64
65 const size_t DEFAULT_AES_GCM_TAG_LEN = 128; // tag length in bits according to W3C Crypto API
66 const size_t DEFAULT_AES_IV_LEN = 16; // default iv size in bytes for AES
67
68 RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
69     BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
70
71     if (NULL == pkey) {
72         ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!");
73     }
74
75     if (NULL == bio.get()) {
76         ThrowErr(Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
77     }
78
79     if (1 != fun(bio.get(), pkey)) {
80         ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
81     }
82
83     RawBuffer output(8196);
84
85     int size = BIO_read(bio.get(), output.data(), output.size());
86
87     if (size <= 0) {
88         ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size);
89     }
90
91     output.resize(size);
92     return output;
93 }
94
95 // encryption / decryption
96 typedef ParamCheck<ParamName::ALGO_TYPE,
97                    AlgoType,
98                    true,
99                    Type<AlgoType>::Equals<AlgoType::AES_CTR,
100                                           AlgoType::AES_CBC,
101                                           AlgoType::AES_GCM,
102                                           AlgoType::AES_CFB,
103                                           AlgoType::RSA_OAEP>> IsEncryption;
104
105 typedef ParamCheck<ParamName::ED_IV,
106                    RawBuffer,
107                    true,
108                    Type<size_t>::Equals<DEFAULT_AES_IV_LEN>,
109                    BufferSizeGetter> IvSizeCheck;
110
111 typedef ParamCheck<ParamName::ED_CTR_LEN,
112                    int,
113                    false,
114                    Type<int>::Equals<128>> CtrLenCheck;
115
116 typedef ParamCheck<ParamName::ED_IV,
117                    RawBuffer,
118                    true,
119                    DefaultValidator<size_t>,
120                    BufferSizeGetter> GcmIvCheck;
121
122 typedef ParamCheck<ParamName::ED_TAG_LEN,
123                    int,
124                    false,
125                    Type<int>::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck;
126
127 // sign / verify
128 typedef ParamCheck<ParamName::ALGO_TYPE,
129                    AlgoType,
130                    false,
131                    Type<AlgoType>::Equals<AlgoType::RSA_SV,
132                                           AlgoType::DSA_SV,
133                                           AlgoType::ECDSA_SV>> IsSignVerify;
134
135 typedef ParamCheck<ParamName::SV_HASH_ALGO,
136                    HashAlgorithm,
137                    false,
138                    Type<HashAlgorithm>::Equals<HashAlgorithm::NONE,
139                                                HashAlgorithm::SHA1,
140                                                HashAlgorithm::SHA256,
141                                                HashAlgorithm::SHA384,
142                                                HashAlgorithm::SHA512>> HashAlgoCheck;
143
144 typedef ParamCheck<ParamName::SV_RSA_PADDING,
145                    RSAPaddingAlgorithm,
146                    false,
147                    Type<RSAPaddingAlgorithm>::Equals<RSAPaddingAlgorithm::NONE,
148                                                      RSAPaddingAlgorithm::PKCS1,
149                                                      RSAPaddingAlgorithm::X931>> RsaPaddingCheck;
150
151 // key generation
152 typedef ParamCheck<ParamName::ALGO_TYPE,
153                    AlgoType,
154                    true,
155                    Type<AlgoType>::Equals<AlgoType::RSA_GEN,
156                                           AlgoType::DSA_GEN,
157                                           AlgoType::ECDSA_GEN>> IsAsymGeneration;
158
159 typedef ParamCheck<ParamName::ALGO_TYPE,
160                    AlgoType,
161                    true,
162                    Type<AlgoType>::Equals<AlgoType::AES_GEN>> IsSymGeneration;
163
164 typedef ParamCheck<ParamName::GEN_KEY_LEN,
165                    int,
166                    true,
167                    Type<int>::Equals<1024, 2048, 4096>> RsaKeyLenCheck;
168
169 typedef ParamCheck<ParamName::GEN_KEY_LEN,
170                    int,
171                    true,
172                    Type<int>::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck;
173
174 typedef ParamCheck<ParamName::GEN_KEY_LEN,
175                    int,
176                    true,
177                    Type<int>::Equals<128, 192, 256>> AesKeyLenCheck;
178
179 typedef ParamCheck<ParamName::GEN_EC,
180                    ElipticCurve,
181                    true,
182                    Type<ElipticCurve>::Equals<ElipticCurve::prime192v1,
183                                               ElipticCurve::prime256v1,
184                                               ElipticCurve::secp384r1>> EcdsaEcCheck;
185
186 typedef std::map<AlgoType, ValidatorVector> ValidatorMap;
187 ValidatorMap initValidators() {
188     ValidatorMap validators;
189     validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
190     validators.emplace(AlgoType::RSA_SV, VBuilder<HashAlgoCheck, RsaPaddingCheck>::Build());
191     validators.emplace(AlgoType::DSA_SV, VBuilder<HashAlgoCheck>::Build());
192     validators.emplace(AlgoType::ECDSA_SV, VBuilder<HashAlgoCheck>::Build());
193     validators.emplace(AlgoType::RSA_GEN, VBuilder<RsaKeyLenCheck>::Build());
194     validators.emplace(AlgoType::DSA_GEN, VBuilder<DsaKeyLenCheck>::Build());
195     validators.emplace(AlgoType::ECDSA_GEN, VBuilder<EcdsaEcCheck>::Build());
196     validators.emplace(AlgoType::AES_GEN, VBuilder<AesKeyLenCheck>::Build());
197     validators.emplace(AlgoType::AES_CTR, VBuilder<IvSizeCheck, CtrLenCheck>::Build());
198     validators.emplace(AlgoType::AES_CBC, VBuilder<IvSizeCheck>::Build());
199     validators.emplace(AlgoType::AES_CFB, VBuilder<IvSizeCheck>::Build());
200     validators.emplace(AlgoType::AES_GCM, VBuilder<GcmIvCheck, GcmTagCheck>::Build());
201     return validators;
202 };
203 ValidatorMap g_validators = initValidators();
204
205 template <typename TypeCheck>
206 void validateParams(const CryptoAlgorithm& ca)
207 {
208     // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation)
209     TypeCheck tc;
210     tc.Check(ca);
211
212     AlgoType at = unpack<AlgoType>(ca, ParamName::ALGO_TYPE);
213     for(const auto& validator : g_validators.at(at)) {
214         validator->Check(ca);
215     }
216 }
217
218 } // anonymous namespace
219
220 int initialize() {
221     int hw_rand_ret = 0;
222     int u_rand_ret = 0;
223
224     // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
225     ERR_load_crypto_strings();
226     OpenSSL_add_all_algorithms();
227
228     // initialize entropy
229     std::ifstream ifile(DEV_HW_RANDOM_FILE);
230     if(ifile.is_open()) {
231         u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
232     }
233     if(u_rand_ret != 32 ){
234         LogError("Error in HW_RAND file load");
235         hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
236
237         if(hw_rand_ret != 32) {
238             ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
239         }
240     }
241
242     return CKM_CRYPTO_INIT_SUCCESS;
243 }
244
245 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
246     const EVP_MD *md_algo=NULL;
247     switch(hashAlgo) {
248     case HashAlgorithm::NONE:
249         md_algo = NULL;
250         break;
251     case HashAlgorithm::SHA1:
252         md_algo = EVP_sha1();
253          break;
254     case HashAlgorithm::SHA256:
255          md_algo = EVP_sha256();
256          break;
257     case HashAlgorithm::SHA384:
258          md_algo = EVP_sha384();
259          break;
260     case HashAlgorithm::SHA512:
261          md_algo = EVP_sha512();
262          break;
263     default:
264         ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
265     }
266     return md_algo;
267 }
268
269 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
270     int rsa_padding = -1;
271     switch(padAlgo) {
272     case RSAPaddingAlgorithm::NONE:
273         rsa_padding = RSA_NO_PADDING;
274         break;
275     case RSAPaddingAlgorithm::PKCS1:
276         rsa_padding = RSA_PKCS1_PADDING;
277         break;
278     case RSAPaddingAlgorithm::X931:
279         rsa_padding = RSA_X931_PADDING;
280         break;
281     default:
282         ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
283     }
284     return rsa_padding;
285 }
286
287 TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
288 {
289     EvpPkeyUPtr pkey;
290
291     // check the parameters of functions
292     if(size!=1024 && size!=2048 && size!=4096) {
293         ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
294     }
295
296     EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
297     if(!ctx) {
298         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
299     }
300
301     if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
302         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
303     }
304
305     if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
306         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
307     }
308
309     EVP_PKEY *pkeyTmp = NULL;
310     if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
311         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
312     }
313     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
314
315     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
316                                         Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
317 }
318
319
320 TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
321 {
322     EvpPkeyUPtr pkey;
323     EvpPkeyUPtr pparam;
324
325     // check the parameters of functions
326     if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
327         ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
328     }
329
330     /* Create the context for generating the parameters */
331     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
332     if(!pctx) {
333         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
334     }
335
336     if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
337         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
338     }
339
340     if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
341         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
342     }
343
344     /* Generate parameters */
345     EVP_PKEY *pparamTmp = NULL;
346     if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
347         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
348     }
349     pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
350
351     // Start to generate key
352     EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
353     if(!kctx) {
354         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
355     }
356
357     if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
358         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
359     }
360
361     /* Generate the key */
362     EVP_PKEY *pkeyTmp = NULL;
363     if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
364         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
365     }
366     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
367
368     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
369                                         Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
370 }
371
372 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
373 {
374     int ecCurve = NOT_DEFINED;
375     EvpPkeyUPtr pkey;
376     EvpPkeyUPtr pparam;
377
378     switch(type) {
379     case ElipticCurve::prime192v1:
380         ecCurve = NID_X9_62_prime192v1;
381         break;
382     case ElipticCurve::prime256v1:
383         ecCurve = NID_X9_62_prime256v1;
384         break;
385     case ElipticCurve::secp384r1:
386         ecCurve = NID_secp384r1;
387         break;
388     default:
389         ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
390     }
391
392     /* Create the context for generating the parameters */
393     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
394     if(!pctx) {
395         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
396     }
397
398     if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
399         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
400     }
401
402     if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
403         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
404     }
405
406     /* Generate parameters */
407     EVP_PKEY *pparamTmp = NULL;
408     if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
409         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
410     }
411     pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
412
413     // Start to generate key
414     EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
415     if(!kctx) {
416         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
417     }
418
419     if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
420         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
421     }
422
423     /* Generate the key */
424     EVP_PKEY *pkeyTmp = NULL;
425     if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
426         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
427     }
428     pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
429
430     return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
431                                         Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
432 }
433
434 Token createKeyAES(CryptoBackend backendId, const int sizeBits)
435 {
436     // check the parameters of functions
437     if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
438         LogError("Error in AES input size");
439         ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
440     }
441
442     uint8_t key[32];
443     int sizeBytes = sizeBits/8;
444     if (!RAND_bytes(key, sizeBytes)) {
445         LogError("Error in AES key generation");
446         ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
447     }
448
449     return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
450 }
451
452 TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
453 {
454     validateParams<IsAsymGeneration>(algorithm);
455
456     AlgoType keyType = unpack<AlgoType>(algorithm, ParamName::ALGO_TYPE);
457     if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN)
458     {
459         int keyLength = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
460         if(keyType == AlgoType::RSA_GEN)
461             return createKeyPairRSA(backendId, keyLength);
462         else
463             return createKeyPairDSA(backendId, keyLength);
464     }
465     else // AlgoType::ECDSA_GEN
466     {
467         ElipticCurve ecType = unpack<ElipticCurve>(algorithm, ParamName::GEN_EC);
468         return createKeyPairECDSA(backendId, ecType);
469     }
470 }
471
472 Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm)
473 {
474     validateParams<IsSymGeneration>(algorithm);
475
476     int keySizeBits = unpack<int>(algorithm, ParamName::GEN_KEY_LEN);
477     return createKeyAES(backendId, keySizeBits);
478 }
479
480 RawBuffer encryptDataAesCbc(
481     const RawBuffer &key,
482     const RawBuffer &data,
483     const RawBuffer &iv)
484 {
485     Crypto::SW::Cipher::AesCbcEncryption enc(key, iv);
486     RawBuffer result = enc.Append(data);
487     RawBuffer tmp = enc.Finalize();
488     std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
489     return result;
490 }
491
492 std::pair<RawBuffer, RawBuffer> encryptDataAesGcm(
493     const RawBuffer &key,
494     const RawBuffer &data,
495     const RawBuffer &iv,
496     int tagSize)
497 {
498     RawBuffer tag(tagSize);
499     Crypto::SW::Cipher::AesGcmEncryption enc(key, iv);
500     RawBuffer result = enc.Append(data);
501     RawBuffer tmp = enc.Finalize();
502     std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
503     if (0 == enc.Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) {
504         ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Get tag failed.");
505     }
506     return std::make_pair(result, tag);
507 }
508
509 RawBuffer encryptDataAesGcmPacked(
510     const RawBuffer &key,
511     const RawBuffer &data,
512     const RawBuffer &iv,
513     int tagSize)
514 {
515     auto pair = encryptDataAesGcm(key, data, iv, tagSize);
516     std::copy(pair.second.begin(), pair.second.end(), std::back_inserter(pair.first));
517     return pair.first;
518 }
519
520 RawBuffer decryptDataAesCbc(
521     const RawBuffer &key,
522     const RawBuffer &data,
523     const RawBuffer &iv)
524 {
525     Crypto::SW::Cipher::AesCbcDecryption dec(key, iv);
526     RawBuffer result = dec.Append(data);
527     RawBuffer tmp = dec.Finalize();
528     std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
529     return result;
530 }
531
532 RawBuffer decryptDataAesGcm(
533     const RawBuffer &key,
534     const RawBuffer &data,
535     const RawBuffer &iv,
536     const RawBuffer &tag)
537 {
538     Crypto::SW::Cipher::AesGcmDecryption dec(key, iv);
539     void *ptr = (void*)tag.data();
540     if (0 == dec.Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) {
541         ThrowErr(Exc::Crypto::InternalError,
542             "Error in AES control function. Set tag failed.");
543     }
544     RawBuffer result = dec.Append(data);
545     RawBuffer tmp = dec.Finalize();
546     std::copy(tmp.begin(), tmp.end(), std::back_inserter(result));
547     return result;
548 }
549
550 RawBuffer decryptDataAesGcmPacked(
551     const RawBuffer &key,
552     const RawBuffer &data,
553     const RawBuffer &iv,
554     int tagSize)
555 {
556     if (tagSize > static_cast<int>(data.size()))
557         ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
558
559     auto tagPos = data.data() + data.size() - tagSize;
560     return decryptDataAesGcm(
561         key,
562         RawBuffer(data.data(), tagPos),
563         iv,
564         RawBuffer(tagPos, data.data() + data.size()));
565 }
566
567 RawBuffer symmetricEncrypt(const RawBuffer &key,
568                            const CryptoAlgorithm &alg,
569                            const RawBuffer &data)
570 {
571     validateParams<IsEncryption>(alg);
572     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
573
574     switch(keyType)
575     {
576         case AlgoType::AES_CBC:
577             return encryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
578         case AlgoType::AES_GCM:
579         {
580             int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
581             alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
582             return encryptDataAesGcmPacked(key,
583                                            data,
584                                            unpack<RawBuffer>(alg, ParamName::ED_IV),
585                                            tagLenBits/8);
586         }
587         default:
588             break;
589     }
590     ThrowErr(Exc::Crypto::OperationNotSupported,
591         "symmetric enc error: algorithm not recognized");
592 }
593
594 RawBuffer symmetricDecrypt(const RawBuffer &key,
595                            const CryptoAlgorithm &alg,
596                            const RawBuffer &data)
597 {
598     validateParams<IsEncryption>(alg);
599     AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
600
601     switch(keyType)
602     {
603         case AlgoType::AES_CBC:
604             return decryptDataAesCbc(key, data, unpack<RawBuffer>(alg, ParamName::ED_IV));
605         case AlgoType::AES_GCM:
606         {
607             int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
608             alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
609             return decryptDataAesGcmPacked(key,
610                                            data,
611                                            unpack<RawBuffer>(alg, ParamName::ED_IV),
612                                            tagLenBits/8);
613         }
614         default:
615             break;
616     }
617     ThrowErr(Exc::Crypto::InputParam, "symmetric dec error: algorithm not recognized");
618 }
619
620 RawBuffer sign(EVP_PKEY *pkey,
621     const CryptoAlgorithm &alg,
622     const RawBuffer &message)
623 {
624     validateParams<IsSignVerify>(alg);
625
626     int rsa_padding = NOT_DEFINED;
627     const EVP_MD *md_algo = NULL;
628
629     HashAlgorithm hashTmp = HashAlgorithm::NONE;
630     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
631     md_algo = getMdAlgo(hashTmp);
632
633     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
634     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
635     rsa_padding = getRsaPadding(rsaPad);
636
637 //
638 //    if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
639 //       (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
640 //       (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
641 //    {
642 //        LogError("Error in private key type");
643 //        ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
644 //    }
645 //
646 //    if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
647 //        rsa_padding = getRsaPadding(padAlgo);
648 //    }
649
650     if (NULL == pkey) {
651         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
652     }
653
654     if(md_algo == NULL) {
655         return signMessage(pkey, message, rsa_padding);
656     }
657
658     return digestSignMessage(pkey,message, md_algo, rsa_padding);
659 }
660
661 RawBuffer signMessage(EVP_PKEY *privKey,
662         const RawBuffer &message,
663         const int rsa_padding)
664 {
665     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
666  
667     if(!pctx.get()) {
668         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
669     }
670
671     if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
672         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
673     }
674
675     /* Set padding algorithm */
676     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
677         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
678             ThrowErr(Exc::Crypto::InternalError,
679                      "Error in EVP_PKEY_CTX_set_rsa_padding function");
680         }
681     }
682
683     /* Finalize the Sign operation */
684     /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
685      * signature. Length is returned in slen */
686     size_t slen;
687     if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
688         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
689     }
690
691     /* Allocate memory for the signature based on size in slen */
692     RawBuffer sig(slen);
693
694     if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
695                                     sig.data(),
696                                     &slen,
697                                     message.data(),
698                                     message.size()))
699     {
700         // Set value to return RawData
701         sig.resize(slen);
702         return sig;
703     }
704
705     ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
706 }
707
708 RawBuffer digestSignMessage(EVP_PKEY *privKey,
709         const RawBuffer &message,
710         const EVP_MD *md_algo,
711         const int rsa_padding)
712 {
713     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
714  
715     EVP_PKEY_CTX *pctx = NULL;
716
717     // Create the Message Digest Context
718     if(!mdctx.get()) {
719         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
720     }
721
722     if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
723         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
724     }
725
726     /* Set padding algorithm */
727     if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
728         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
729             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
730         }
731     }
732
733     /* Call update with the message */
734     if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
735         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
736     }
737
738     /* Finalize the DigestSign operation */
739     /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
740      * signature. Length is returned in slen */
741     size_t slen;
742     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
743         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
744     }
745
746     /* Allocate memory for the signature based on size in slen */
747     RawBuffer sig(slen);
748
749     /* Obtain the signature */
750     if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
751         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
752     }
753
754     // Set value to return RawData
755     sig.resize(slen);
756     return sig;
757 }
758
759 int verify(EVP_PKEY *pkey,
760     const CryptoAlgorithm &alg,
761     const RawBuffer &message,
762     const RawBuffer &signature)
763 {
764     validateParams<IsSignVerify>(alg);
765
766     int rsa_padding = NOT_DEFINED;
767     const EVP_MD *md_algo = NULL;
768
769     HashAlgorithm hashTmp = HashAlgorithm::NONE;
770     alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
771     md_algo = getMdAlgo(hashTmp);
772
773     RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
774     alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
775     rsa_padding = getRsaPadding(rsaPad);
776
777 //
778 //    if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
779 //       (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
780 //       (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
781 //    {
782 //        LogError("Error in private key type");
783 //        ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
784 //    }
785 //
786 //    if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
787 //        rsa_padding = getRsaPadding(padAlgo);
788 //    }
789
790 //    auto shrPKey = publicKey.getEvpShPtr();
791     if (NULL == pkey) {
792         ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
793     }
794
795     if (md_algo == NULL) {
796         return verifyMessage(pkey, message, signature, rsa_padding);
797     }
798
799     return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
800 }
801
802 int verifyMessage(EVP_PKEY *pubKey,
803         const RawBuffer &message,
804         const RawBuffer &signature,
805         const int rsa_padding)
806 {
807     EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
808
809     if(!pctx.get()) {
810         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
811     }
812
813     if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
814         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
815     }
816
817     /* Set padding algorithm  */
818     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
819         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
820             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
821         }
822     }
823
824     if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
825         return CKM_API_SUCCESS;
826     } 
827
828     LogError("EVP_PKEY_verify Failed");
829     return CKM_API_ERROR_VERIFICATION_FAILED;
830 }
831
832 int digestVerifyMessage(EVP_PKEY *pubKey,
833         const RawBuffer &message,
834         const RawBuffer &signature,
835         const EVP_MD *md_algo,
836         const int rsa_padding)
837 {
838     EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
839     EVP_PKEY_CTX *pctx = NULL;
840
841     /* Create the Message Digest Context */
842     if(!mdctx.get()) {
843         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
844     }
845
846     if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
847         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
848     }
849
850     if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
851         if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
852             ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
853         }
854     }
855
856     if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
857         ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
858     }
859
860     if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
861         return CKM_API_SUCCESS;
862     }
863
864     LogError("EVP_PKEY_verify Failed");
865     return CKM_API_ERROR_VERIFICATION_FAILED;
866 }
867
868 } // namespace Internals
869 } // namespace SW
870 } // namespace Crypto
871 } // namespace CKM