Check KBKDF parameters on key-manager side
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / internals.cpp
1 /*
2  *  Copyright (c) 2017-2020 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.h
18  * @author     Krzysztof Dynowski (k.dynowski@samsung.com)
19  * @author     Lukasz Kostyra (l.kostyra@samsung.com)
20  * @version    1.0
21  */
22
23 #include <generic-backend/exception.h>
24 #include <generic-backend/algo-validation.h>
25 #include <generic-backend/crypto-params.h>
26 #include <dpl/log/log.h>
27 #include <utils.h>
28 #include <openssl/evp.h>
29 #include <openssl/dsa.h>
30 #include <openssl/ec.h>
31 #include <openssl/bio.h>
32 #include <openssl/bn.h>
33
34 #include <tz-backend/internals.h>
35 #include <tz-backend/tz-context.h>
36 #include <openssl-error-handler.h>
37 #include <km_ta_defines.h>
38 #include <key-impl.h>
39
40 #include <functional>
41
42 #ifndef __has_cpp_attribute
43 #define __has_cpp_attribute(_) 0
44 #endif
45
46 #if __has_cpp_attribute(fallthrough)
47 #define fallthru [[fallthrough]]
48 #else
49 #define fallthru ((void)0)
50 #endif
51
52 namespace {
53
54 CKM::RawBuffer extractBignumData(const BIGNUM* bn)
55 {
56         size_t size = static_cast<size_t>(BN_num_bytes(bn));
57
58         CKM::RawBuffer result(size);
59         int ret = BN_bn2bin(bn, result.data());
60         if (ret != static_cast<int>(size)) {
61                 ThrowErr(CKM::Exc::Crypto::InternalError,
62                         "Error while converting bignums - expected "
63                         + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
64         }
65
66         return result;
67 }
68
69 void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
70                                         CKM::RawBuffer &subprime, CKM::RawBuffer &base)
71 {
72         auto dsa = uptr<DSA_free>(DSA_new());
73         if (!dsa) {
74                 ThrowErr(CKM::Exc::Crypto::InternalError,
75                         "Failed to create DSA context for parameter gen");
76         }
77
78         if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
79                 ThrowErr(CKM::Exc::Crypto::InternalError,
80                         "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
81         }
82
83         // at this stage dsa->p, dsa->q & dsa->r should contain our params
84         // extract them into buffers
85         const BIGNUM *p, *q, *g;
86         DSA_get0_pqg(dsa.get(), &p, &q, &g);
87         prime = extractBignumData(p);
88         subprime = extractBignumData(q);
89         base = extractBignumData(g);
90 }
91
92 tz_data_type toTzDataType(const CKM::DataType dataType) {
93         switch (dataType) {
94         case CKM::DataType::BINARY_DATA:       return TYPE_GENERIC_SECRET;
95         case CKM::DataType::KEY_AES:           return TYPE_SKEY;
96         case CKM::DataType::KEY_DSA_PRIVATE:   return TYPE_AKEY_PRIVATE_DSA;
97         case CKM::DataType::KEY_RSA_PRIVATE:   return TYPE_AKEY_PRIVATE_RSA;
98         case CKM::DataType::KEY_ECDSA_PRIVATE: return TYPE_AKEY_PRIVATE_EC;
99         case CKM::DataType::KEY_DSA_PUBLIC:    return TYPE_AKEY_PUBLIC_DSA;
100         case CKM::DataType::KEY_RSA_PUBLIC:    return TYPE_AKEY_PUBLIC_RSA;
101         case CKM::DataType::KEY_ECDSA_PUBLIC:  return TYPE_AKEY_PUBLIC_EC;
102         default:
103                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
104                         "Data type could not be imported by tz-backend");
105         }
106 }
107
108 tz_ec toTzEc(CKM::ElipticCurve ec)
109 {
110         switch(ec) {
111         case CKM::ElipticCurve::prime192v1: return EC_NIST_P192;
112         case CKM::ElipticCurve::prime256v1: return EC_NIST_P256;
113         case CKM::ElipticCurve::secp384r1: return EC_NIST_P384;
114         default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "EC not supported by tz-backend");
115         }
116 }
117
118 tz_prf toTzPrf(CKM::KdfPrf prf)
119 {
120         switch(prf) {
121         case CKM::KdfPrf::HMAC_SHA256: return PRF_HMAC_SHA256;
122         case CKM::KdfPrf::HMAC_SHA384: return PRF_HMAC_SHA384;
123         case CKM::KdfPrf::HMAC_SHA512: return PRF_HMAC_SHA512;
124         default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "PRF not supported by tz-backend");
125         }
126 }
127
128 tz_kbkdf_mode toTzKbkdfMode(CKM::KbkdfMode mode)
129 {
130         switch(mode) {
131         case CKM::KbkdfMode::COUNTER: return KBKDF_MODE_COUNTER;
132         default:
133                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "KBKDF mode not supported by tz-backend");
134         }
135 }
136
137 tz_kbkdf_ctr_loc toTzCtrLoc(CKM::KbkdfCounterLocation loc)
138 {
139         switch(loc) {
140         case CKM::KbkdfCounterLocation::BEFORE_FIXED: return KBKDF_LOC_BEFORE_FIXED;
141         case CKM::KbkdfCounterLocation::AFTER_FIXED: return KBKDF_LOC_AFTER_FIXED;
142         case CKM::KbkdfCounterLocation::MIDDLE_FIXED: return KBKDF_LOC_MIDDLE_FIXED;
143         default:
144                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
145                         "KBKDF counter location not supported by tz-backend");
146         }
147 }
148
149 } // namespace
150
151 namespace CKM {
152 namespace Crypto {
153 namespace TZ {
154 namespace Internals {
155
156 namespace {
157
158 tz_algo_type getGenSKeyType(AlgoType type)
159 {
160         switch (type)
161         {
162         case AlgoType::AES_GEN: return ALGO_AES_GEN;
163         default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
164         }
165 }
166
167 tz_algo_type getAlgType(AlgoType type)
168 {
169         switch (type)
170         {
171         case AlgoType::AES_CBC: return ALGO_AES_CBC;
172         case AlgoType::AES_CTR: return ALGO_AES_CTR;
173         case AlgoType::AES_CFB: return ALGO_AES_CFB;
174         case AlgoType::AES_GCM: return ALGO_AES_GCM;
175         case AlgoType::RSA_OAEP: return ALGO_RSA;
176         case AlgoType::RSA_SV: return ALGO_RSA_SV;
177         case AlgoType::DSA_SV: return ALGO_DSA_SV;
178         case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
179         default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
180         };
181 }
182
183 tz_hash_type getHashType(HashAlgorithm hash)
184 {
185         switch (hash)
186         {
187         case HashAlgorithm::SHA1: return HASH_SHA1;
188         case HashAlgorithm::SHA256: return HASH_SHA256;
189         case HashAlgorithm::SHA384: return HASH_SHA384;
190         case HashAlgorithm::SHA512: return HASH_SHA512;
191         default:
192                 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
193         }
194 }
195
196 void decompose(const CryptoAlgorithm &alg,
197                            AlgoType &algo,
198                            uint32_t &ctrLenOrTagSizeBits,
199                            RawBuffer &iv,
200                            RawBuffer &aad)
201 {
202         algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
203         switch (algo) {
204                 case AlgoType::AES_CTR:
205                         iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
206                         ctrLenOrTagSizeBits = Params::DEFAULT_AES_IV_LEN * 8;
207                         alg.getParam(ParamName::ED_CTR_LEN, ctrLenOrTagSizeBits);
208                         // counter length is in bits
209                         if (ctrLenOrTagSizeBits != Params::DEFAULT_AES_IV_LEN * 8) {
210                                 LogError("CTR length invalid: " << std::to_string(ctrLenOrTagSizeBits));
211                                 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
212                         }
213                         break;
214                 case AlgoType::AES_CBC:
215                         iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
216                         break;
217                 case AlgoType::AES_CFB:
218                         iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
219                         break;
220                 case AlgoType::AES_GCM:
221                         iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
222                         ctrLenOrTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
223                         alg.getParam(ParamName::ED_TAG_LEN, ctrLenOrTagSizeBits);
224                         alg.getParam(ParamName::ED_AAD, aad);
225                         break;
226                 case AlgoType::RSA_OAEP:
227                         break;
228                 default:
229                         ThrowErr(Exc::Crypto::InputParam, "Invalid decryption algorithm");
230                         break;
231         }
232 }
233
234 } // namespace
235
236 RawBuffer generateIV()
237 {
238         RawBuffer result;
239         TrustZoneContext::Instance().generateIV(result);
240         return result;
241 }
242
243 void generateSKey(const CryptoAlgorithm &alg,
244                                 const Password &pwd,
245                                 const RawBuffer &iv,
246                                 RawBuffer &tag,
247                                 const RawBuffer &hash)
248 {
249         AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
250         int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
251
252         if (!pwd.empty()) {
253                 if (iv.empty()) {
254                         ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
255                 }
256
257                 RawBuffer pwdBuf(pwd.begin(), pwd.end());
258                 TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
259                                                                                                         pwdBuf, iv, keyBits,
260                                                                                                         tag, hash);
261         } else {
262                 TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
263                                                                                                 hash);
264         }
265
266 }
267
268 AlgoType generateAKey(const CryptoAlgorithm &alg,
269                                         const Password &pubPwd,
270                                         const Password &privPwd,
271                                         const RawBuffer &pubPwdIv,
272                                         const RawBuffer &privPwdIv,
273                                         RawBuffer &pubTag,
274                                         RawBuffer &privTag,
275                                         const RawBuffer &hashPriv,
276                                         const RawBuffer &hashPub)
277 {
278         AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
279
280         RawBuffer pubPwdBuf;
281         if (!pubPwd.empty())
282                 pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
283
284         RawBuffer privPwdBuf;
285         if (!privPwd.empty())
286                 privPwdBuf.assign(privPwd.begin(), privPwd.end());
287
288         switch (keyType) {
289         case AlgoType::RSA_GEN: {
290                 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
291                 TrustZoneContext::Instance().generateRSAKey(keyBits,
292                                                                                                         pubPwdBuf,
293                                                                                                         pubPwdIv,
294                                                                                                         privPwdBuf,
295                                                                                                         privPwdIv,
296                                                                                                         pubTag,
297                                                                                                         privTag,
298                                                                                                         hashPriv,
299                                                                                                         hashPub);
300                 break;
301         }
302         case AlgoType::DSA_GEN: {
303                 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
304                 RawBuffer prime;
305                 RawBuffer subprime;
306                 RawBuffer base;
307                 generateDSAParams(keyBits, prime, subprime, base);
308                 TrustZoneContext::Instance().generateDSAKey(keyBits,
309                                                                                                         prime,
310                                                                                                         subprime,
311                                                                                                         base,
312                                                                                                         pubPwdBuf,
313                                                                                                         pubPwdIv,
314                                                                                                         privPwdBuf,
315                                                                                                         privPwdIv,
316                                                                                                         pubTag,
317                                                                                                         privTag,
318                                                                                                         hashPriv,
319                                                                                                         hashPub);
320                 break;
321         }
322         case AlgoType::ECDSA_GEN: {
323                 CKM::ElipticCurve ec = unpack<CKM::ElipticCurve>(alg, ParamName::GEN_EC);
324                 TrustZoneContext::Instance().generateECKey(toTzEc(ec),
325                                                                                                    pubPwdBuf,
326                                                                                                    pubPwdIv,
327                                                                                                    privPwdBuf,
328                                                                                                    privPwdIv,
329                                                                                                    pubTag,
330                                                                                                    privTag,
331                                                                                                    hashPriv,
332                                                                                                    hashPub);
333                 break;
334         }
335         default: {
336                 ThrowErr(Exc::Crypto::InputParam,
337                         "Invalid algo type provided for generateAKey function");
338         }
339         }
340
341         return keyType;
342 }
343
344 void destroyKey(const RawBuffer &keyId)
345 {
346         TrustZoneContext::Instance().executeDestroy(keyId);
347 }
348
349 void importData(const Data &data,
350                                          const EncryptionParams &encData,
351                                          const Password &pwd,
352                                          const RawBuffer &pwdIV,
353                                          RawBuffer &tag,
354                                          const RawBuffer &hash)
355 {
356
357         const auto dataType = toTzDataType(data.type);
358
359         RawBuffer pwdBuf(pwd.begin(), pwd.end());
360         uint32_t keySizeBits = data.data.size() * 8;
361         TrustZoneContext::Instance().importData(dataType,
362                                                                                 data.data,
363                                                                                 encData,
364                                                                                 pwdBuf,
365                                                                                 pwdIV,
366                                                                                 keySizeBits,
367                                                                                 tag,
368                                                                                 hash);
369 }
370
371 void importWrappedKey(const RawBuffer &wrappingKeyId,
372                                           const Pwd &wrappingKeyPwd,
373                                           const CryptoAlgorithm &alg,
374                                           const Data &encryptedKey,
375                                           const Password &encryptedKeyPassword,
376                                           const RawBuffer &encryptedKeyIV,
377                                           RawBuffer &encryptedKeyTag,
378                                           const RawBuffer &encryptedKeyId)
379 {
380         RawBuffer encryptedKeyPwdBuf(encryptedKeyPassword.begin(), encryptedKeyPassword.end());
381
382         AlgoType algo;
383         uint32_t ctrLenOrTagSizeBits = 0;
384         RawBuffer iv;
385         RawBuffer aad;
386         decompose(alg, algo, ctrLenOrTagSizeBits, iv, aad);
387
388         // TODO it is awful!
389         TrustZoneContext::Instance().importWrappedKey(wrappingKeyId,
390                                                                                                   wrappingKeyPwd,
391                                                                                                   getAlgType(algo),
392                                                                                                   iv,
393                                                                                                   ctrLenOrTagSizeBits,
394                                                                                                   aad,
395                                                                                                   toTzDataType(encryptedKey.type),
396                                                                                                   encryptedKey.data,
397                                                                                                   encryptedKeyPwdBuf,
398                                                                                                   encryptedKeyIV,
399                                                                                                   encryptedKeyTag,
400                                                                                                   encryptedKeyId);
401 }
402
403 RawBuffer exportWrappedKey(const RawBuffer &wrappingKeyId,
404                                                    const Pwd &wrappingKeyPwd,
405                                                    const CryptoAlgorithm &alg,
406                                                    const RawBuffer &keyToWrapId,
407                                                    const Pwd &keyToWrapPwd,
408                                                    const DataType &keyToWrapType)
409 {
410         AlgoType algo;
411         uint32_t ctrLenOrTagSizeBits = 0;
412         RawBuffer iv;
413         RawBuffer aad;
414         decompose(alg, algo, ctrLenOrTagSizeBits, iv, aad);
415
416         // TODO it is awful!
417         return TrustZoneContext::Instance().exportWrappedKey(wrappingKeyId,
418                                                                                                                  wrappingKeyPwd,
419                                                                                                                  getAlgType(algo),
420                                                                                                                  iv,
421                                                                                                                  ctrLenOrTagSizeBits,
422                                                                                                                  aad,
423                                                                                                                  keyToWrapId,
424                                                                                                                  keyToWrapPwd,
425                                                                                                                  toTzDataType(keyToWrapType));
426 }
427
428 RawBuffer getData(const RawBuffer &dataId,
429                                   const Pwd &pwd,
430                                   const DataType &type)
431 {
432         RawBuffer result;
433         TrustZoneContext::Instance().getData(dataId,
434                                  pwd,
435                                  toTzDataType(type),
436                                  result);
437         return result;
438 }
439
440 void destroyData(const RawBuffer &dataId)
441 {
442         TrustZoneContext::Instance().destroyData(dataId);
443 }
444
445 BufferPair encryptDataAesGcm(const RawBuffer &keyId,
446                                                         const Pwd &pwd,
447                                                         const RawBuffer &iv,
448                                                         int tagSize,
449                                                         const RawBuffer &data,
450                                                         const RawBuffer &aad)
451 {
452         RawBuffer result;
453         RawBuffer tag;
454
455         TrustZoneContext::Instance().executeEncryptAE(keyId, pwd, iv, tagSize,
456                                                                                                 aad, data, result, tag);
457
458         return std::make_pair(result, tag);
459 }
460
461 RawBuffer encryptDataAesGcmPacked(const RawBuffer &keyId,
462                                                                 const Pwd &pwd,
463                                                                 const RawBuffer &iv,
464                                                                 int tagSize,
465                                                                 const RawBuffer &data,
466                                                                 const RawBuffer &aad)
467 {
468         auto pair = encryptDataAesGcm(keyId, pwd, iv, tagSize, data, aad);
469         std::copy(pair.second.begin(), pair.second.end(),
470                         std::back_inserter(pair.first));
471         return pair.first;
472 }
473
474 RawBuffer decryptDataAesGcm(const RawBuffer &keyId,
475                                                         const Pwd &pwd,
476                                                         const RawBuffer &iv,
477                                                         int tagSizeBits,
478                                                         const RawBuffer &tag,
479                                                         const RawBuffer &data,
480                                                         const RawBuffer &aad)
481 {
482         RawBuffer result;
483
484         TrustZoneContext::Instance().executeDecryptAE(keyId, pwd, iv, tagSizeBits,
485                                                                                                 tag, aad, data, result);
486
487         return result;
488 }
489
490 RawBuffer decryptDataAesGcmPacked(const RawBuffer &keyId,
491                                                                 const Pwd &pwd,
492                                                                 const RawBuffer &iv,
493                                                                 int tagSizeBits,
494                                                                 const RawBuffer &data,
495                                                                 const RawBuffer &aad)
496 {
497         int tagSizeBytes = tagSizeBits / 8;
498         if (tagSizeBytes > static_cast<int>(data.size()))
499                 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
500
501         auto tagPos = data.data() + data.size() - tagSizeBytes;
502         return decryptDataAesGcm(keyId,
503                                                         pwd,
504                                                         iv,
505                                                         tagSizeBits,
506                                                         RawBuffer(tagPos, data.data() + data.size()),
507                                                         RawBuffer(data.data(), tagPos),
508                                                         aad);
509 }
510
511
512 RawBuffer symmetricEncrypt(const RawBuffer &keyId,
513                                                 const Pwd &pwd,
514                                                 const CryptoAlgorithm &alg,
515                                                 const RawBuffer &data)
516 {
517         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
518         uint64_t ctrLen = Params::DEFAULT_AES_IV_LEN * 8;
519
520         switch (algo) {
521                 case AlgoType::AES_CTR: {
522                         alg.getParam(ParamName::ED_CTR_LEN, ctrLen);
523                         // counter length is in bits
524                         if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
525                                 LogError("CTR length invalid: " << std::to_string(ctrLen));
526                                 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
527                         }
528                         // no break here, we still need to slide down to executeCrypt
529                         fallthru;
530                 }
531                 case AlgoType::AES_CBC:
532                 case AlgoType::AES_CFB: {
533                         RawBuffer result;
534                         TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
535                                                                                                         getAlgType(algo),
536                                                                                                         keyId,
537                                                                                                         pwd,
538                                                                                                         unpack<RawBuffer>(alg, ParamName::ED_IV),
539                                                                                                         data,
540                                                                                                         result);
541                         return result;
542                 }
543                 case AlgoType::AES_GCM: {
544                         int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
545                         alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
546                         RawBuffer aad;
547                         alg.getParam(ParamName::ED_AAD, aad);
548                         return encryptDataAesGcmPacked(keyId,
549                                                                                 pwd,
550                                                                                 unpack<RawBuffer>(alg, ParamName::ED_IV),
551                                                                                 tagLenBits,
552                                                                                 data,
553                                                                                 aad);
554                 }
555                 default:
556                         break;
557         }
558
559         ThrowErr(Exc::Crypto::OperationNotSupported,
560                                 "Incorrect algorithm provided for symmetric crypto operation");
561 }
562
563 RawBuffer symmetricDecrypt(const RawBuffer &keyId,
564                                                 const Pwd &pwd,
565                                                 const CryptoAlgorithm &alg,
566                                                 const RawBuffer &data)
567 {
568         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
569         uint64_t ctrLen = Params::DEFAULT_AES_IV_LEN * 8;
570
571         switch (algo) {
572                 case AlgoType::AES_CTR: {
573                         alg.getParam(ParamName::ED_CTR_LEN, ctrLen);
574                         // counter length is in bits
575                         if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
576                                 LogError("CTR length invalid: " << std::to_string(ctrLen));
577                                 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
578                         }
579                         // no break here, we still need to slide down to executeCrypt
580                         fallthru;
581                 }
582                 case AlgoType::AES_CBC:
583                 case AlgoType::AES_CFB: {
584                         RawBuffer result;
585                         TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
586                                                                                                         getAlgType(algo),
587                                                                                                         keyId,
588                                                                                                         pwd,
589                                                                                                         unpack<RawBuffer>(alg, ParamName::ED_IV),
590                                                                                                         data,
591                                                                                                         result);
592                         return result;
593                 }
594                 case AlgoType::AES_GCM: {
595                         int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
596                         alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
597                         RawBuffer aad;
598                         alg.getParam(ParamName::ED_AAD, aad);
599                         return decryptDataAesGcmPacked(keyId,
600                                                                                 pwd,
601                                                                                 unpack<RawBuffer>(alg, ParamName::ED_IV),
602                                                                                 tagSizeBits,
603                                                                                 data,
604                                                                                 aad);
605                 }
606                 default:
607                         break;
608         }
609
610         ThrowErr(Exc::Crypto::OperationNotSupported,
611                                 "Incorrect algorithm provided for symmetric crypto operation");
612 }
613
614 RawBuffer asymmetricEncrypt(const RawBuffer &keyId,
615                                                         const Pwd &pwd,
616                                                         const CryptoAlgorithm &alg,
617                                                         const RawBuffer &data)
618 {
619         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
620         RawBuffer result;
621
622         switch (algo)
623         {
624         case AlgoType::RSA_OAEP: {
625                 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
626                                                                                                 getAlgType(algo),
627                                                                                                 keyId,
628                                                                                                 pwd,
629                                                                                                 result, // unused dummy
630                                                                                                 data,
631                                                                                                 result);
632                 return result;
633         }
634         default:
635                 break;
636         }
637
638         ThrowErr(Exc::Crypto::OperationNotSupported,
639                                 "Incorrect algorithm provided for asymmetric crypto operation");
640 }
641
642 RawBuffer asymmetricDecrypt(const RawBuffer &keyId,
643                                                         const Pwd &pwd,
644                                                         const CryptoAlgorithm &alg,
645                                                         const RawBuffer &cipher)
646 {
647         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
648         RawBuffer result;
649
650         switch (algo)
651         {
652         case AlgoType::RSA_OAEP: {
653                 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
654                                                                                                 getAlgType(algo),
655                                                                                                 keyId,
656                                                                                                 pwd,
657                                                                                                 result, // unused dummy
658                                                                                                 cipher,
659                                                                                                 result);
660                 return result;
661         }
662         default:
663                 break;
664         }
665
666         ThrowErr(Exc::Crypto::OperationNotSupported,
667                                 "Incorrect algorithm provided for asymmetric crypto operation");
668 }
669
670 uint32_t initCipher(const RawBuffer &keyId,
671                                         const Pwd &pwd,
672                                         const CryptoAlgorithm &alg,
673                                         bool encrypt)
674 {
675         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
676
677         switch (algo)
678         {
679         case AlgoType::AES_GCM: {
680                 int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
681                 alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
682                 RawBuffer aad;
683                 alg.getParam(ParamName::ED_AAD, aad);
684                 return TrustZoneContext::Instance().initGcmCipher(encrypt ? CIPHER_ENCRYPT : CIPHER_DECRYPT,
685                                                                                                                   keyId,
686                                                                                                                   pwd,
687                                                                                                                   unpack<RawBuffer>(alg, ParamName::ED_IV),
688                                                                                                                   tagSizeBits,
689                                                                                                                   aad);
690         }
691         case AlgoType::AES_CBC:
692         case AlgoType::AES_CTR:
693         case AlgoType::AES_CFB:
694                 // TODO optionally implement above modes as well
695         default:
696                 break;
697         };
698
699         ThrowErr(Exc::Crypto::OperationNotSupported,
700                          "Incorrect algorithm provided for symmetric crypto operation");
701 }
702
703 void addAAD(uint32_t opId,
704                         const RawBuffer &aad)
705 {
706         TrustZoneContext::Instance().addGcmAAD(opId, aad);
707 }
708
709 RawBuffer updateCipher(uint32_t opId,
710                                            const RawBuffer &data)
711 {
712         return TrustZoneContext::Instance().updateGcmCipher(opId, data);
713 }
714
715 RawBuffer finalizeCipher(uint32_t opId,
716                                                  const RawBuffer &data)
717 {
718         return TrustZoneContext::Instance().finalizeGcmCipher(opId, data);
719 }
720
721 void cleanupCipher(uint32_t opId)
722 {
723         return TrustZoneContext::Instance().cleanupCipher(opId);
724 }
725
726 RawBuffer sign(const RawBuffer &pkeyId,
727                         const Pwd &pwd,
728                         const CryptoAlgorithm &alg,
729                         const RawBuffer &message)
730 {
731         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
732         HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
733         if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
734                 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
735
736         RawBuffer signature;
737         TrustZoneContext::Instance().executeSign(getAlgType(algo),
738                                                                                         getHashType(hash),
739                                                                                         pkeyId,
740                                                                                         pwd,
741                                                                                         message,
742                                                                                         signature);
743         return signature;
744 }
745
746 int verify(const RawBuffer &pkeyId,
747                 const Pwd &pwd,
748                 const CryptoAlgorithm &alg,
749                 const RawBuffer &message,
750                 const RawBuffer &signature)
751 {
752         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
753         HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
754         if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
755                 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
756
757         return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
758                                                                                                         getHashType(hash),
759                                                                                                         pkeyId,
760                                                                                                         pwd,
761                                                                                                         message,
762                                                                                                         signature);
763 }
764
765 void deriveECDH(const RawBuffer &prvKeyId,
766                                 const Pwd &prvKeyPwd,
767                                 const RawBuffer &pubKey,
768                                 const Password &secretPwd,
769                                 const RawBuffer &secretPwdIV,
770                                 RawBuffer &secretTag,
771                                 const RawBuffer &secretHash)
772 {
773         auto peerKey = std::make_shared<KeyImpl>(pubKey);
774         if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
775                 ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
776         auto peerEvp = peerKey->getEvpShPtr().get();
777         assert(peerEvp);
778
779         int subType = EVP_PKEY_type(EVP_PKEY_id(peerEvp));
780         if (subType != EVP_PKEY_EC)
781                 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
782
783         auto ecKey = EVP_PKEY_get0_EC_KEY(peerEvp);
784         if (!ecKey)
785                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
786
787         auto ecPoint = EC_KEY_get0_public_key(ecKey);
788         if (!ecPoint)
789                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC public key");
790
791         auto ecGroup = EC_KEY_get0_group(ecKey);
792         if (!ecGroup)
793                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC group");
794
795         BIGNUM *x = BN_new();
796         BIGNUM *y = BN_new();
797         if (!EC_POINT_get_affine_coordinates(ecGroup, ecPoint, x, y, NULL))
798                 ThrowErr(Exc::Crypto::InternalError, "Failed to get EC pub key coordinates");
799
800         auto xBuf = extractBignumData(x);
801         auto yBuf = extractBignumData(y);
802
803         RawBuffer secretPwdBuf(secretPwd.begin(), secretPwd.end());
804
805         int pubCurve = EC_GROUP_get_curve_name(ecGroup);
806         tz_ec tzCurve;
807         switch (pubCurve)
808         {
809         case NID_X9_62_prime192v1:
810                 tzCurve = EC_NIST_P192;
811                 break;
812
813         case NID_X9_62_prime256v1:
814                 tzCurve = EC_NIST_P256;
815                 break;
816
817         case NID_secp384r1:
818                 tzCurve = EC_NIST_P384;
819                 break;
820
821         default:
822                 ThrowErr(Exc::Crypto::InputParam, "Unsupported public key EC");
823         }
824
825         TrustZoneContext::Instance().executeEcdh(prvKeyId,
826                                                                                          prvKeyPwd,
827                                                                                          tzCurve,
828                                                                                          xBuf,
829                                                                                          yBuf,
830                                                                                          secretPwdBuf,
831                                                                                          secretPwdIV,
832                                                                                          secretTag,
833                                                                                          secretHash);
834 }
835
836 void deriveKBKDF(const RawBuffer &secretId,
837                                  const Pwd &secretPwd,
838                                  const CryptoAlgorithm &alg,
839                                  const Password &keyPwd,
840                                  const RawBuffer &keyPwdIV,
841                                  RawBuffer &keyTag,
842                                  const RawBuffer &keyHash)
843 {
844         RawBuffer label, context, fixed;
845         KbkdfCounterLocation counterLocation;
846         KdfPrf prf;
847         KbkdfMode mode;
848         size_t length, rlenBits = 32, llenBits = 32, tmp;
849         bool hasLabel = alg.getParam(ParamName::KBKDF_LABEL, label);
850         bool hasContext = alg.getParam(ParamName::KBKDF_CONTEXT, context);
851         bool hasFixed = alg.getParam(ParamName::KBKDF_FIXED_INPUT, fixed);
852         alg.getParam(ParamName::KBKDF_COUNTER_LOCATION, counterLocation);
853         alg.getParam(ParamName::KBKDF_MODE, mode);
854         alg.getParam(ParamName::KDF_PRF, prf);
855         alg.getParam(ParamName::KDF_LEN, length);
856         alg.getParam(ParamName::KBKDF_RLEN, rlenBits);
857         bool hasLLen = alg.getParam(ParamName::KBKDF_LLEN, llenBits);
858         bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp);
859
860         RawBuffer key;
861         if (hasFixed) {
862                 if (hasLabel || hasContext || noSeparator || hasLLen ||
863                         counterLocation == KbkdfCounterLocation::MIDDLE_FIXED)
864                         ThrowErr(Exc::Crypto::InputParam, "Unexpected parameters for fixed input mode.");
865         } else {
866                 if (!hasLabel || !hasContext)
867                         ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context.");
868
869                 if (llenBits != 0 && llenBits != 8 && llenBits != 16 && llenBits != 24 && llenBits != 32)
870                         ThrowErr(Exc::Crypto::InputParam, "Invalid llen value");
871         }
872         if (length != 16 && length != 24 && length != 32)
873                 ThrowErr(Exc::Crypto::InputParam, "Invalid key length");
874
875         if (rlenBits != 8 && rlenBits != 16 && rlenBits != 24 && rlenBits != 32)
876                 ThrowErr(Exc::Crypto::InputParam, "Invalid rlen value");
877
878         RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
879
880         TrustZoneContext::Instance().executeKbkdf(secretId,
881                                                                                           secretPwd,
882                                                                                           length,
883                                                                                           label,
884                                                                                           context,
885                                                                                           fixed,
886                                                                                           toTzPrf(prf),
887                                                                                           toTzKbkdfMode(mode),
888                                                                                           toTzCtrLoc(counterLocation),
889                                                                                           rlenBits,
890                                                                                           llenBits,
891                                                                                           noSeparator,
892                                                                                           keyPwdBuf,
893                                                                                           keyPwdIV,
894                                                                                           keyTag,
895                                                                                           keyHash);
896 }
897
898 size_t maxChunkSize()
899 {
900         return TrustZoneContext::Instance().getMaxChunkSize();
901 }
902
903 } // namespace Internals
904 } // namespace TZ
905 } // namespace Crypto
906 } // namespace CKM