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