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