5b8ad1e6c500b480a2842d554f4c23ae8664acf8
[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_DSA_PUBLIC:    return TYPE_AKEY_PUBLIC_DSA;
99         case CKM::DataType::KEY_RSA_PUBLIC:    return TYPE_AKEY_PUBLIC_RSA;
100         default:
101                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
102                         "Data type could not be imported by tz-backend");
103         }
104 }
105
106 tz_ec toTzEc(CKM::ElipticCurve ec)
107 {
108         switch(ec) {
109         case CKM::ElipticCurve::prime192v1: return EC_NIST_P192;
110         case CKM::ElipticCurve::prime256v1: return EC_NIST_P256;
111         case CKM::ElipticCurve::secp384r1: return EC_NIST_P384;
112         default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "EC not supported by tz-backend");
113         }
114 }
115
116 tz_prf toTzPrf(CKM::KdfPrf prf)
117 {
118         switch(prf) {
119         case CKM::KdfPrf::HMAC_SHA256: return PRF_HMAC_SHA256;
120         case CKM::KdfPrf::HMAC_SHA384: return PRF_HMAC_SHA384;
121         case CKM::KdfPrf::HMAC_SHA512: return PRF_HMAC_SHA512;
122         default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "PRF not supported by tz-backend");
123         }
124 }
125
126 tz_kbkdf_mode toTzKbkdfMode(CKM::KbkdfMode mode)
127 {
128         switch(mode) {
129         case CKM::KbkdfMode::COUNTER: return KBKDF_MODE_COUNTER;
130         default:
131                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "KBKDF mode not supported by tz-backend");
132         }
133 }
134
135 tz_kbkdf_ctr_loc toTzCtrLoc(CKM::KbkdfCounterLocation loc)
136 {
137         switch(loc) {
138         case CKM::KbkdfCounterLocation::BEFORE_FIXED: return KBKDF_LOC_BEFORE_FIXED;
139         case CKM::KbkdfCounterLocation::AFTER_FIXED: return KBKDF_LOC_AFTER_FIXED;
140         case CKM::KbkdfCounterLocation::MIDDLE_FIXED: return KBKDF_LOC_MIDDLE_FIXED;
141         default:
142                 ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported,
143                         "KBKDF counter location not supported by tz-backend");
144         }
145 }
146
147 } // namespace
148
149 namespace CKM {
150 namespace Crypto {
151 namespace TZ {
152 namespace Internals {
153
154 tz_algo_type getGenSKeyType(AlgoType type)
155 {
156         switch (type)
157         {
158         case AlgoType::AES_GEN: return ALGO_AES_GEN;
159         default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
160         }
161 }
162
163 tz_algo_type getAlgType(AlgoType type)
164 {
165         switch (type)
166         {
167         case AlgoType::AES_CBC: return ALGO_AES_CBC;
168         case AlgoType::AES_CTR: return ALGO_AES_CTR;
169         case AlgoType::AES_CFB: return ALGO_AES_CFB;
170         case AlgoType::AES_GCM: return ALGO_AES_GCM;
171         case AlgoType::RSA_OAEP: return ALGO_RSA;
172         case AlgoType::RSA_SV: return ALGO_RSA_SV;
173         case AlgoType::DSA_SV: return ALGO_DSA_SV;
174         case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
175         default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
176         };
177 }
178
179 tz_hash_type getHashType(HashAlgorithm hash)
180 {
181         switch (hash)
182         {
183         case HashAlgorithm::SHA1: return HASH_SHA1;
184         case HashAlgorithm::SHA256: return HASH_SHA256;
185         case HashAlgorithm::SHA384: return HASH_SHA384;
186         case HashAlgorithm::SHA512: return HASH_SHA512;
187         default:
188                 ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
189         }
190 }
191
192 RawBuffer generateIV()
193 {
194         RawBuffer result;
195         TrustZoneContext::Instance().generateIV(result);
196         return result;
197 }
198
199 void generateSKey(const CryptoAlgorithm &alg,
200                                 const Password &pwd,
201                                 const RawBuffer &iv,
202                                 RawBuffer &tag,
203                                 const RawBuffer &hash)
204 {
205         AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
206         int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
207
208         if (!pwd.empty()) {
209                 if (iv.empty()) {
210                         ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
211                 }
212
213                 RawBuffer pwdBuf(pwd.begin(), pwd.end());
214                 TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
215                                                                                                         pwdBuf, iv, keyBits,
216                                                                                                         tag, hash);
217         } else {
218                 TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
219                                                                                                 hash);
220         }
221
222 }
223
224 AlgoType generateAKey(const CryptoAlgorithm &alg,
225                                         const Password &pubPwd,
226                                         const Password &privPwd,
227                                         const RawBuffer &pubPwdIv,
228                                         const RawBuffer &privPwdIv,
229                                         RawBuffer &pubTag,
230                                         RawBuffer &privTag,
231                                         const RawBuffer &hashPriv,
232                                         const RawBuffer &hashPub)
233 {
234         AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
235
236         RawBuffer pubPwdBuf;
237         if (!pubPwd.empty())
238                 pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
239
240         RawBuffer privPwdBuf;
241         if (!privPwd.empty())
242                 privPwdBuf.assign(privPwd.begin(), privPwd.end());
243
244         switch (keyType) {
245         case AlgoType::RSA_GEN: {
246                 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
247                 TrustZoneContext::Instance().generateRSAKey(keyBits,
248                                                                                                         pubPwdBuf,
249                                                                                                         pubPwdIv,
250                                                                                                         privPwdBuf,
251                                                                                                         privPwdIv,
252                                                                                                         pubTag,
253                                                                                                         privTag,
254                                                                                                         hashPriv,
255                                                                                                         hashPub);
256                 break;
257         }
258         case AlgoType::DSA_GEN: {
259                 int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
260                 RawBuffer prime;
261                 RawBuffer subprime;
262                 RawBuffer base;
263                 generateDSAParams(keyBits, prime, subprime, base);
264                 TrustZoneContext::Instance().generateDSAKey(keyBits,
265                                                                                                         prime,
266                                                                                                         subprime,
267                                                                                                         base,
268                                                                                                         pubPwdBuf,
269                                                                                                         pubPwdIv,
270                                                                                                         privPwdBuf,
271                                                                                                         privPwdIv,
272                                                                                                         pubTag,
273                                                                                                         privTag,
274                                                                                                         hashPriv,
275                                                                                                         hashPub);
276                 break;
277         }
278         case AlgoType::ECDSA_GEN: {
279                 CKM::ElipticCurve ec = unpack<CKM::ElipticCurve>(alg, ParamName::GEN_EC);
280                 TrustZoneContext::Instance().generateECKey(toTzEc(ec),
281                                                                                                    pubPwdBuf,
282                                                                                                    pubPwdIv,
283                                                                                                    privPwdBuf,
284                                                                                                    privPwdIv,
285                                                                                                    pubTag,
286                                                                                                    privTag,
287                                                                                                    hashPriv,
288                                                                                                    hashPub);
289                 break;
290         }
291         default: {
292                 ThrowErr(Exc::Crypto::InputParam,
293                         "Invalid algo type provided for generateAKey function");
294         }
295         }
296
297         return keyType;
298 }
299
300 void destroyKey(const RawBuffer &key)
301 {
302         TrustZoneContext::Instance().executeDestroy(key);
303 }
304
305 void importData(const Data &data,
306                                          const EncryptionParams &encData,
307                                          const Password &pwd,
308                                          const RawBuffer &pwdIV,
309                                          RawBuffer &tag,
310                                          const RawBuffer &hash)
311 {
312
313         const auto dataType = toTzDataType(data.type);
314
315         RawBuffer pwdBuf(pwd.begin(), pwd.end());
316         uint32_t keySizeBits = data.data.size() * 8;
317         TrustZoneContext::Instance().importData(dataType,
318                                                                                 data.data,
319                                                                                 encData,
320                                                                                 pwdBuf,
321                                                                                 pwdIV,
322                                                                                 keySizeBits,
323                                                                                 tag,
324                                                                                 hash);
325 }
326
327 RawBuffer getData(const RawBuffer &dataId,
328                                   const Pwd &pwd)
329 {
330         RawBuffer result;
331         TrustZoneContext::Instance().getData(dataId,
332                                  pwd,
333                                  result);
334         return result;
335 }
336
337 void destroyData(const RawBuffer &dataId)
338 {
339         TrustZoneContext::Instance().destroyData(dataId);
340 }
341
342 BufferPair encryptDataAesGcm(const RawBuffer &key,
343                                                         const Pwd &pwd,
344                                                         const RawBuffer &iv,
345                                                         int tagSize,
346                                                         const RawBuffer &data,
347                                                         const RawBuffer &aad)
348 {
349         RawBuffer result;
350         RawBuffer tag;
351
352         TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
353                                                                                                 aad, data, result, tag);
354
355         return std::make_pair(result, tag);
356 }
357
358 RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
359                                                                 const Pwd &pwd,
360                                                                 const RawBuffer &iv,
361                                                                 int tagSize,
362                                                                 const RawBuffer &data,
363                                                                 const RawBuffer &aad)
364 {
365         auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
366         std::copy(pair.second.begin(), pair.second.end(),
367                         std::back_inserter(pair.first));
368         return pair.first;
369 }
370
371 RawBuffer decryptDataAesGcm(const RawBuffer &key,
372                                                         const Pwd &pwd,
373                                                         const RawBuffer &iv,
374                                                         int tagSizeBits,
375                                                         const RawBuffer &tag,
376                                                         const RawBuffer &data,
377                                                         const RawBuffer &aad)
378 {
379         RawBuffer result;
380
381         TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
382                                                                                                 tag, aad, data, result);
383
384         return result;
385 }
386
387 RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
388                                                                 const Pwd &pwd,
389                                                                 const RawBuffer &iv,
390                                                                 int tagSizeBits,
391                                                                 const RawBuffer &data,
392                                                                 const RawBuffer &aad)
393 {
394         int tagSizeBytes = tagSizeBits / 8;
395         if (tagSizeBytes > static_cast<int>(data.size()))
396                 ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
397
398         auto tagPos = data.data() + data.size() - tagSizeBytes;
399         return decryptDataAesGcm(key,
400                                                         pwd,
401                                                         iv,
402                                                         tagSizeBits,
403                                                         RawBuffer(tagPos, data.data() + data.size()),
404                                                         RawBuffer(data.data(), tagPos),
405                                                         aad);
406 }
407
408
409 RawBuffer symmetricEncrypt(const RawBuffer &key,
410                                                 const Pwd &pwd,
411                                                 const CryptoAlgorithm &alg,
412                                                 const RawBuffer &data)
413 {
414         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
415         uint64_t ctrLen = 0;
416
417         switch (algo) {
418                 case AlgoType::AES_CTR: {
419                         ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
420                         // counter length is in bits
421                         if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
422                                 LogError("CTR length invalid: " << std::to_string(ctrLen));
423                                 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
424                         }
425                         // no break here, we still need to slide down to executeCrypt
426                         fallthru;
427                 }
428                 case AlgoType::AES_CBC:
429                 case AlgoType::AES_CFB: {
430                         RawBuffer result;
431                         TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
432                                                                                                         getAlgType(algo),
433                                                                                                         key,
434                                                                                                         pwd,
435                                                                                                         unpack<RawBuffer>(alg, ParamName::ED_IV),
436                                                                                                         data,
437                                                                                                         result);
438                         return result;
439                 }
440                 case AlgoType::AES_GCM: {
441                         int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
442                         alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
443                         RawBuffer aad;
444                         alg.getParam(ParamName::ED_AAD, aad);
445                         return encryptDataAesGcmPacked(key,
446                                                                                 pwd,
447                                                                                 unpack<RawBuffer>(alg, ParamName::ED_IV),
448                                                                                 tagLenBits,
449                                                                                 data,
450                                                                                 aad);
451                 }
452                 default:
453                         break;
454         }
455
456         ThrowErr(Exc::Crypto::OperationNotSupported,
457                                 "Incorrect algorithm provided for symmetric crypto operation");
458 }
459
460 RawBuffer symmetricDecrypt(const RawBuffer &key,
461                                                 const Pwd &pwd,
462                                                 const CryptoAlgorithm &alg,
463                                                 const RawBuffer &data)
464 {
465         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
466         uint64_t ctrLen = 0;
467
468         switch (algo) {
469                 case AlgoType::AES_CTR: {
470                         ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
471                         // counter length is in bits
472                         if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
473                                 LogError("CTR length invalid: " << std::to_string(ctrLen));
474                                 ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
475                         }
476                         // no break here, we still need to slide down to executeCrypt
477                         fallthru;
478                 }
479                 case AlgoType::AES_CBC:
480                 case AlgoType::AES_CFB: {
481                         RawBuffer result;
482                         TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
483                                                                                                         getAlgType(algo),
484                                                                                                         key,
485                                                                                                         pwd,
486                                                                                                         unpack<RawBuffer>(alg, ParamName::ED_IV),
487                                                                                                         data,
488                                                                                                         result);
489                         return result;
490                 }
491                 case AlgoType::AES_GCM: {
492                         int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
493                         alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
494                         RawBuffer aad;
495                         alg.getParam(ParamName::ED_AAD, aad);
496                         return decryptDataAesGcmPacked(key,
497                                                                                 pwd,
498                                                                                 unpack<RawBuffer>(alg, ParamName::ED_IV),
499                                                                                 tagSizeBits,
500                                                                                 data,
501                                                                                 aad);
502                 }
503                 default:
504                         break;
505         }
506
507         ThrowErr(Exc::Crypto::OperationNotSupported,
508                                 "Incorrect algorithm provided for symmetric crypto operation");
509 }
510
511 RawBuffer asymmetricEncrypt(const RawBuffer &key,
512                                                         const Pwd &pwd,
513                                                         const CryptoAlgorithm &alg,
514                                                         const RawBuffer &data)
515 {
516         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
517         RawBuffer result;
518
519         switch (algo)
520         {
521         case AlgoType::RSA_OAEP: {
522                 TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
523                                                                                                 getAlgType(algo),
524                                                                                                 key,
525                                                                                                 pwd,
526                                                                                                 result, // unused dummy
527                                                                                                 data,
528                                                                                                 result);
529                 return result;
530         }
531         default:
532                 break;
533         }
534
535         ThrowErr(Exc::Crypto::OperationNotSupported,
536                                 "Incorrect algorithm provided for asymmetric crypto operation");
537 }
538
539 RawBuffer asymmetricDecrypt(const RawBuffer &key,
540                                                         const Pwd &pwd,
541                                                         const CryptoAlgorithm &alg,
542                                                         const RawBuffer &cipher)
543 {
544         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
545         RawBuffer result;
546
547         switch (algo)
548         {
549         case AlgoType::RSA_OAEP: {
550                 TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
551                                                                                                 getAlgType(algo),
552                                                                                                 key,
553                                                                                                 pwd,
554                                                                                                 result, // unused dummy
555                                                                                                 cipher,
556                                                                                                 result);
557                 return result;
558         }
559         default:
560                 break;
561         }
562
563         ThrowErr(Exc::Crypto::OperationNotSupported,
564                                 "Incorrect algorithm provided for asymmetric crypto operation");
565 }
566
567 RawBuffer sign(const RawBuffer &pkey,
568                         const Pwd &pwd,
569                         const CryptoAlgorithm &alg,
570                         const RawBuffer &message)
571 {
572         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
573         HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
574         if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
575                 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
576
577         RawBuffer signature;
578         TrustZoneContext::Instance().executeSign(getAlgType(algo),
579                                                                                         getHashType(hash),
580                                                                                         pkey,
581                                                                                         pwd,
582                                                                                         message,
583                                                                                         signature);
584         return signature;
585 }
586
587 int verify(const RawBuffer &pkey,
588                 const Pwd &pwd,
589                 const CryptoAlgorithm &alg,
590                 const RawBuffer &message,
591                 const RawBuffer &signature)
592 {
593         AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
594         HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
595         if (algo != AlgoType::RSA_SV && hash == HashAlgorithm::NONE)
596                 ThrowErr(Exc::Crypto::InputParam, "Only RSA supports no hash option");
597
598         return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
599                                                                                                         getHashType(hash),
600                                                                                                         pkey,
601                                                                                                         pwd,
602                                                                                                         message,
603                                                                                                         signature);
604 }
605
606 void deriveECDH(const RawBuffer &prvKey,
607                                 const Pwd &prvKeyPwd,
608                                 const RawBuffer &pubKey,
609                                 const Password &secretPwd,
610                                 const RawBuffer &secretPwdIV,
611                                 RawBuffer &secretTag,
612                                 const RawBuffer &secretHash)
613 {
614         auto peerKey = std::make_shared<KeyImpl>(pubKey);
615         if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC)
616                 ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key");
617         auto peerEvp = peerKey->getEvpShPtr().get();
618         assert(peerEvp);
619
620         int subType = EVP_PKEY_type(EVP_PKEY_id(peerEvp));
621         if (subType != EVP_PKEY_EC)
622                 ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType);
623
624         auto ecKey = EVP_PKEY_get0_EC_KEY(peerEvp);
625         if (!ecKey)
626                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC key");
627
628         auto ecPoint = EC_KEY_get0_public_key(ecKey);
629         if (!ecPoint)
630                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC public key");
631
632         auto ecGroup = EC_KEY_get0_group(ecKey);
633         if (!ecGroup)
634                 ThrowErr(Exc::Crypto::InternalError, "Can't get EC group");
635
636         BIGNUM *x = BN_new();
637         BIGNUM *y = BN_new();
638         if (!EC_POINT_get_affine_coordinates(ecGroup, ecPoint, x, y, NULL))
639                 ThrowErr(Exc::Crypto::InternalError, "Failed to get EC pub key coordinates");
640
641         auto xBuf = extractBignumData(x);
642         auto yBuf = extractBignumData(y);
643
644         RawBuffer secretPwdBuf(secretPwd.begin(), secretPwd.end());
645
646         TrustZoneContext::Instance().executeEcdh(prvKey,
647                                                                                          prvKeyPwd,
648                                                                                          xBuf,
649                                                                                          yBuf,
650                                                                                          secretPwdBuf,
651                                                                                          secretPwdIV,
652                                                                                          secretTag,
653                                                                                          secretHash);
654 }
655
656 void deriveKBKDF(const RawBuffer &secret,
657                                  const CryptoAlgorithm &alg,
658                                  const Password &keyPwd,
659                                  const RawBuffer &keyPwdIV,
660                                  RawBuffer &keyTag,
661                                  const RawBuffer &keyHash)
662 {
663         auto prf = unpack<KdfPrf>(alg, ParamName::KDF_PRF);
664         auto mode = unpack<KbkdfMode>(alg, ParamName::KBKDF_MODE);
665         auto location = unpack<KbkdfCounterLocation>(alg, ParamName::KBKDF_COUNTER_LOCATION);
666
667         size_t rlen = 32, llen = 32, dummy;
668         alg.getParam(ParamName::KBKDF_RLEN, rlen);
669         alg.getParam(ParamName::KBKDF_LLEN, llen);
670         bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, dummy);
671
672         RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end());
673
674         TrustZoneContext::Instance().executeKbkdf(secret,
675                                                                                           toTzPrf(prf),
676                                                                                           toTzKbkdfMode(mode),
677                                                                                           toTzCtrLoc(location),
678                                                                                           rlen,
679                                                                                           llen,
680                                                                                           noSeparator,
681                                                                                           keyPwdBuf,
682                                                                                           keyPwdIV,
683                                                                                           keyTag,
684                                                                                           keyHash);
685 }
686
687
688 } // namespace Internals
689 } // namespace TZ
690 } // namespace Crypto
691 } // namespace CKM