Be prepared for no data from TA
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / tz-context.cpp
1 /*
2  *  Copyright (c) 2017 - 2019 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       tz-context.cpp
18  * @author     Lukasz Kostyra (l.kostyra@samsung.com)
19  * @version    1.0
20  */
21
22 #include <tz-backend/tz-context.h>
23 #include <tz-backend/tz-memory.h>
24 #include <generic-backend/exception.h>
25 #include <generic-backend/crypto-params.h>
26 #include <generic-backend/encryption-params.h>
27 #include <dpl/log/log.h>
28
29 #include <km_serialization.h>
30 #include <km_ta_defines.h>
31
32 #include <cstdint>
33 #include <cstring>
34 #include <cassert>
35 #include <iomanip>
36 #include <sstream>
37 #include <unordered_map>
38
39 namespace CKM {
40 namespace Crypto {
41 namespace TZ {
42 namespace Internals {
43
44 namespace {
45
46 // A little bit of extra memory to add to output buffers.
47 //
48 // We need this extra memory to output for padding purposes - after encryption
49 // we can resize the result memory back to its proper size according to
50 // whatever TA will return us.
51 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
52
53 // Identifier of our TA
54 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
55
56 //raw to hex string conversion to print persistent storage data ID
57 static std::string rawToHexString(const RawBuffer &raw)
58 {
59         std::string dump;
60
61         for (auto &e : raw) {
62                 char buf[3];
63                 snprintf(buf, sizeof(buf), "%02x", (e & 0xff));
64                 dump.push_back(buf[0]);
65                 dump.push_back(buf[1]);
66         }
67
68         return dump;
69 }
70
71 /*
72  * Maximum size for given key type in bytes according to key-manager-ta implementation.
73  * Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
74  */
75 const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
76         { ALGO_RSA, 4096 / 8 },
77         { ALGO_RSA_SV, 4096 / 8 },
78         { ALGO_DSA_SV, 4096 / 8 }
79 };
80
81 void DeserializeKeyID(TrustZoneMemory &mem, RawBuffer &id)
82 {
83         LogDebug("Deserializing key ID");
84
85         KM_SymmetricInput* output = nullptr;
86         int ret = KM_ParamsDeserializationInit(mem.Get()->buffer, mem.Get()->size, &output);
87         if (ret) {
88                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize key ID data deserialization: ", ret);
89         }
90
91         KM_OutData* outData = nullptr;
92         ret = KM_ParamsDeserializeOutData(output, &outData);
93         if (ret) {
94                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key ID data: ", ret);
95         }
96
97         if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
98                 ThrowErr(Exc::Crypto::InternalError, "Deserialized invalid key ID");
99         }
100
101         // data_size should contain how much memory we actually took for our cipher operation
102         id.resize(outData->data_size);
103         memcpy(id.data(), outData->data, outData->data_size);
104 }
105
106 } // anonymous namespace
107
108 TrustZoneContext::TrustZoneContext()
109         : m_ContextInitialized(false)
110         , m_SessionInitialized(false)
111 {
112         Initialize();
113 }
114
115 TrustZoneContext::~TrustZoneContext()
116 {
117         Destroy();
118 }
119
120 TrustZoneContext& TrustZoneContext::Instance()
121 {
122         static TrustZoneContext instance;
123         return instance;
124 }
125
126 void TrustZoneContext::generateIV(RawBuffer& iv)
127 {
128         // command ID = CMD_GENERATE_IV
129         //
130         // TEEC_Operation layout:
131         // params:
132         //   [1].memref.buffer - output
133         //   [1].memref.size - output size
134         // output:
135         //   [0].value.a - return code
136
137         // IV generation is a simple call - no need to serialize data
138         // just provide the output buffer with size equal to iv.
139         uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
140         TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
141
142         TEEC_Operation op;
143         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
144                                                                         TEEC_NONE, TEEC_NONE);
145         op.params[1].memref.parent = ivMemory.Get();
146         op.params[1].memref.offset = 0;
147         op.params[1].memref.size = ivMemory.Get()->size;
148         Execute(CMD_GENERATE_IV, &op);
149
150         iv.resize(ivSize);
151         memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
152 }
153
154 void TrustZoneContext::generateSKey(tz_algo_type algo,
155                                                                         uint32_t keySizeBits,
156                                                                         RawBuffer &keyId)
157 {
158         // command ID = CMD_GENERATE_KEY
159         //
160         // TEEC_Operation layout:
161         // params:
162         //   [0].value.a - key type
163         //   [0].value.b - key bit size
164         // output:
165         //   [0].value.a - return code
166         //   [1].memref - serialized key reference
167
168         KM_BufferSizeDesc bufSize;
169
170         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
171         bufSize.out_size = KM_KEY_ID_SIZE;
172         uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
173         TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
174
175         TEEC_Operation op;
176         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
177                                                                         TEEC_NONE, TEEC_NONE);
178         op.params[0].value.a = algo;
179         op.params[0].value.b = keySizeBits;
180         op.params[1].memref.parent = keyMemory.Get();
181         op.params[1].memref.offset = 0;
182         op.params[1].memref.size = keyMemorySize;
183         Execute(CMD_GENERATE_KEY, &op);
184
185         DeserializeKeyID(keyMemory, keyId);
186 }
187
188 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
189                                                                         const RawBuffer &pwd,
190                                                                         const RawBuffer &iv,
191                                                                         const uint32_t keySizeBits,
192                                                                         RawBuffer &keyId,
193                                                                         RawBuffer &pwdTag)
194 {
195         // command ID = CMD_GENERATE_KEY_PWD
196         //
197         // TEEC_Operation layout:
198         // params:
199         //   [0].value.a - key type
200         //   [0].value.b - key size in bits
201         //   [1].memref  - input (seralized pwd/iv for pbkdf2)
202         // output:
203         //   [0].value.a - return code
204         //   [2].memref - serialized key reference ID
205
206         KM_BufferSizeDesc bufSize;
207
208         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
209         bufSize.with_pwd_data = true;
210         bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
211         bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
212         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
213         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
214
215         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
216         bufSize.out_size = KM_KEY_ID_SIZE;
217         bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
218         uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
219         TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
220
221         KM_SymmetricInput* input = nullptr;
222         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
223         if (ret) {
224                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
225         }
226
227         ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
228                                                                         nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
229                                                                         Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
230         if (ret) {
231                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
232         }
233
234         TEEC_Operation op;
235         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
236                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
237         op.params[0].value.a = algo;
238         op.params[0].value.b = keySizeBits;
239         op.params[1].memref.parent = inMemory.Get();
240         op.params[1].memref.offset = 0;
241         op.params[1].memref.size = inMemory.Get()->size;
242         op.params[2].memref.parent = keyMemory.Get();
243         op.params[2].memref.offset = 0;
244         op.params[2].memref.size = keyMemory.Get()->size;
245         Execute(CMD_GENERATE_KEY_PWD, &op);
246
247         DeserializeKeyID(keyMemory, keyId);
248
249         KM_SymmetricInput* output = nullptr;
250         ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
251         if (ret) {
252                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
253         }
254
255         KM_OutData* outData = nullptr;
256         ret = KM_ParamsDeserializeOutData(output, &outData);
257         if (ret) {
258                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
259         }
260
261         KM_TagData* tagData = nullptr;
262         ret = KM_ParamsDeserializeTagData(output, &tagData);
263         if (ret) {
264                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
265         }
266
267         if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
268                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
269         }
270
271         if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
272                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
273         }
274
275         keyId.resize(KM_KEY_ID_SIZE);
276         memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
277
278         pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
279         memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
280 }
281
282 void TrustZoneContext::GenerateAKey(tz_command commandId,
283                                     TZSerializer &sIn,
284                                     uint32_t keySizeBits,
285                                     const RawBuffer &pubPwd,
286                                     const RawBuffer &pubPwdIv,
287                                     const RawBuffer &privPwd,
288                                     const RawBuffer &privPwdIv,
289                                     RawBuffer &pubKeyId,
290                                     RawBuffer &pubKeyTag,
291                                     RawBuffer &privKeyId,
292                                     RawBuffer &privKeyTag)
293 {
294         uint32_t pubTagSize = 0;
295         uint32_t privTagSize = 0;
296
297         uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
298         sIn.Push(new TZSerializableFlag(pubPwdExists));
299         if (pubPwdExists) {
300                 sIn.Push(new TZSerializablePwdData(pubPwd, pubPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
301                 pubTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
302         }
303         uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
304         sIn.Push(new TZSerializableFlag(privPwdExists));
305         if (privPwdExists) {
306                 sIn.Push(new TZSerializablePwdData(privPwd, privPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
307                 privTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
308         }
309
310         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
311         sIn.Serialize(inMemory);
312
313         TZSerializer sOut;
314         sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
315         sOut.Push(new TZSerializableBinary(pubTagSize));
316         sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
317         sOut.Push(new TZSerializableBinary(privTagSize));
318
319         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
320
321         TEEC_Operation op;
322         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
323                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
324         op.params[0].value.b = keySizeBits;
325         op.params[1].memref.parent = inMemory.Get();
326         op.params[1].memref.offset = 0;
327         op.params[1].memref.size = inMemory.Get()->size;
328         op.params[2].memref.parent = outMemory.Get();
329         op.params[2].memref.offset = 0;
330         op.params[2].memref.size = outMemory.Get()->size;
331         Execute(commandId, &op);
332
333         sOut.Deserialize(outMemory);
334
335         sOut.Pull(pubKeyId);
336         if (pubKeyId.size() != KM_KEY_ID_SIZE) {
337                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize public key ID");
338         }
339
340         if (pubPwdExists) {
341                 sOut.Pull(pubKeyTag);
342         }
343
344         sOut.Pull(privKeyId);
345         if (privKeyId.size() != KM_KEY_ID_SIZE) {
346                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize private key ID");
347         }
348
349         if (privPwdExists) {
350                 sOut.Pull(privKeyTag);
351         }
352 }
353
354 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
355                                                                         const RawBuffer &pubPwd,
356                                                                         const RawBuffer &pubPwdIv,
357                                                                         const RawBuffer &privPwd,
358                                                                         const RawBuffer &privPwdIv,
359                                                                         RawBuffer &pubKeyId,
360                                                                         RawBuffer &pubKeyTag,
361                                                                         RawBuffer &privKeyId,
362                                                                         RawBuffer &privKeyTag)
363 {
364         // command ID = CMD_GENERATE_RSA_KEYPAIR
365         //
366         // TEEC_Operation layout:
367         // params:
368         //   [0].value.b - key bit size
369         //   [1].memref - reference to serialized buffer:
370         //       flag marking the public key password presence,
371         //       public key password data if the flag above is not 0,
372         //       flag marking the private key password presence,
373         //       public key private data if the flag above is not 0,
374         // output:
375         //   [0].value.a - return code
376         //   [2].memref
377         //       Public key ID,
378         //       public key tag if password was present,
379         //       Private key ID,
380         //       private key tag if password was present,
381
382         TZSerializer sIn;
383
384         GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
385                      sIn,
386                      keySizeBits,
387                      pubPwd,
388                      pubPwdIv,
389                      privPwd,
390                      privPwdIv,
391                      pubKeyId,
392                      pubKeyTag,
393                      privKeyId,
394                      privKeyTag);
395 }
396
397 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
398                                                                         const RawBuffer &prime,
399                                                                         const RawBuffer &subprime,
400                                                                         const RawBuffer &base,
401                                                                         const RawBuffer &pubPwd,
402                                                                         const RawBuffer &pubPwdIv,
403                                                                         const RawBuffer &privPwd,
404                                                                         const RawBuffer &privPwdIv,
405                                                                         RawBuffer &pubKeyId,
406                                                                         RawBuffer &pubKeyTag,
407                                                                         RawBuffer &privKeyId,
408                                                                         RawBuffer &privKeyTag)
409 {
410         // command ID = CMD_GENERATE_DSA_KEYPAIR
411         //
412         // TEEC_Operation layout:
413         // params:
414         //   [0].value.b - key bit size
415         //   [1].memref - reference to serialized buffer:
416         //       prime, subprime, base,
417         //       flag marking the public key password presence,
418         //       public key password data if the flag above is not 0,
419         //       flag marking the private key password presence,
420         //       public key private data if the flag above is not 0,
421         // output:
422         //   [0].value.a - return code
423         //   [2].memref
424         //       Public key ID,
425         //       public key tag if password was present,
426         //       Private key ID,
427         //       private key tag if password was present,
428
429         TZSerializer sIn;
430         sIn.Push(new TZSerializableBinary(prime));
431         sIn.Push(new TZSerializableBinary(subprime));
432         sIn.Push(new TZSerializableBinary(base));
433
434         GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
435                      sIn,
436                      keySizeBits,
437                      pubPwd,
438                      pubPwdIv,
439                      privPwd,
440                      privPwdIv,
441                      pubKeyId,
442                      pubKeyTag,
443                      privKeyId,
444                      privKeyTag);
445 }
446
447 void TrustZoneContext::executeCrypt(tz_command cmd,
448                                                                         tz_algo_type algo,
449                                                                         const RawBuffer &keyId,
450                                                                         const Pwd &pwd,
451                                                                         const RawBuffer &iv,
452                                                                         const RawBuffer &data,
453                                                                         RawBuffer &out)
454 {
455         // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
456         //
457         // TEEC_Operation layout:
458         // params:
459         //   [0].value.a - keyid
460         //   [0].value.b - algo
461         //   [1].memref - input data (serialized key/input)
462         // returned:
463         //   [0].value.a - return code
464         //   [2].memref - serialized output buffer
465
466         if (keyId.size() != KM_KEY_ID_SIZE) {
467                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
468                         + std::to_string(keyId.size()) + ")");
469         }
470
471         KM_BufferSizeDesc bufSize;
472
473         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
474         bufSize.input_size = static_cast<uint32_t>(data.size());
475         bufSize.with_pwd_data = true;
476         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
477         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
478         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
479         bufSize.iv_size = static_cast<uint32_t>(iv.size());
480         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
481         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
482         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
483
484         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
485
486         // decrypt operation does not require padding
487         bufSize.out_size = static_cast<uint32_t>(data.size());
488         if (cmd == CMD_ENCRYPT) {
489                 if (algo == ALGO_RSA) {
490                         // We don't know the key length
491                         bufSize.out_size = MAX_KEY_SIZE.at(ALGO_RSA);
492                 } else {
493                         bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
494                 }
495         }
496         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
497         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
498
499         KM_SymmetricInput* input = nullptr;
500         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
501         if (ret) {
502                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
503         }
504
505         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
506         if (ret) {
507                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
508         }
509
510         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
511         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
512                                                                         pwd.getIV().data(), pwd.getIV().size(),
513                                                                         pwd.getTag().data(), pwd.getTag().size(),
514                                                                         Params::DERIVED_KEY_LENGTH_BITS,
515                                                                         Params::DERIVED_KEY_ITERATIONS,
516                                                                         pwdTagSizeBits);
517         if (ret) {
518                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
519         }
520
521         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
522         if (ret) {
523                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
524         }
525
526         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
527         if (ret) {
528                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
529         }
530
531         TEEC_Operation op;
532         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
533                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
534         op.params[0].value.a = algo;
535         op.params[1].memref.parent = inMemory.Get();
536         op.params[1].memref.offset = 0;
537         op.params[1].memref.size = inMemory.Get()->size;
538         op.params[2].memref.parent = outMemory.Get();
539         op.params[2].memref.offset = 0;
540         op.params[2].memref.size = outMemory.Get()->size;
541         Execute(cmd, &op);
542
543         KM_SymmetricInput* output = nullptr;
544         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
545         if (ret) {
546                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
547         }
548
549         KM_OutData* outData = nullptr;
550         ret = KM_ParamsDeserializeOutData(output, &outData);
551         if (ret) {
552                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
553         }
554
555         // data_size should contain how much memory we actually took for our cipher operation
556         out.clear();
557         if (outData) {
558                 out.resize(outData->data_size);
559                 memcpy(out.data(), outData->data, outData->data_size);
560         }
561 }
562
563 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
564                                                                                 const Pwd &pwd,
565                                                                                 const RawBuffer &iv,
566                                                                                 int tagSizeBits,
567                                                                                 const RawBuffer &aad,
568                                                                                 const RawBuffer &data,
569                                                                                 RawBuffer &out,
570                                                                                 RawBuffer &tag)
571 {
572         // command ID = CMD_ENCRYPT (from km_ta_defines.h)
573         //
574         // TEEC_Operation layout:
575         // params:
576         //   [0].value.a - keyid
577         //   [0].value.b - algo
578         //   [1].memref - input data (serialized key/input/iv/aad)
579         // returned:
580         //   [0].value.a - return code
581         //   [2].memref - output
582
583         if (keyId.size() != KM_KEY_ID_SIZE) {
584                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
585         }
586
587         uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
588         KM_BufferSizeDesc bufSize;
589
590         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
591         bufSize.input_size = static_cast<uint32_t>(data.size());
592         bufSize.with_pwd_data = true;
593         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
594         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
595         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
596         bufSize.iv_size = static_cast<uint32_t>(iv.size());
597         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
598         bufSize.with_ae_data = true;
599         bufSize.aad_size = static_cast<uint32_t>(aad.size());
600         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
601         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
602
603         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
604         bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
605         bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
606         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
607         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
608
609         KM_SymmetricInput* input = nullptr;
610         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
611         if (ret) {
612                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
613         }
614
615         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
616         if (ret) {
617                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
618         }
619
620         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
621         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
622                                                                         pwd.getIV().data(), pwd.getIV().size(),
623                                                                         pwd.getTag().data(), pwd.getTag().size(),
624                                                                         Params::DERIVED_KEY_LENGTH_BITS,
625                                                                         Params::DERIVED_KEY_ITERATIONS,
626                                                                         pwdTagSizeBits);
627         if (ret) {
628                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
629         }
630
631         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
632         if (ret) {
633                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
634         }
635
636         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
637         if (ret) {
638                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
639         }
640
641         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
642         if (ret) {
643                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
644         }
645
646         TEEC_Operation op;
647         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
648                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
649         op.params[0].value.a = ALGO_AES_GCM;
650         op.params[1].memref.parent = inMemory.Get();
651         op.params[1].memref.offset = 0;
652         op.params[1].memref.size = inMemory.Get()->size;
653         op.params[2].memref.parent = outMemory.Get();
654         op.params[2].memref.offset = 0;
655         op.params[2].memref.size = outMemory.Get()->size;
656         Execute(CMD_ENCRYPT, &op);
657
658         KM_SymmetricInput* output = nullptr;
659         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
660         if (ret) {
661                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
662         }
663
664         KM_OutData* outData = nullptr;
665         ret = KM_ParamsDeserializeOutData(output, &outData);
666         if (ret) {
667                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
668         }
669
670         KM_TagData* tagData = nullptr;
671         ret = KM_ParamsDeserializeTagData(output, &tagData);
672         if (ret) {
673                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
674         }
675
676         out.clear();
677         if (outData) {
678                 out.resize(outData->data_size);
679                 memcpy(out.data(), outData->data, outData->data_size);
680         }
681
682         tag.clear();
683         if (tagData && tagData->data_size) {
684                 tag.resize(tagData->data_size);
685                 memcpy(tag.data(), tagData->data, tagData->data_size);
686         }
687 }
688
689 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
690                                                                                 const Pwd &pwd,
691                                                                                 const RawBuffer &iv,
692                                                                                 int tagSizeBits,
693                                                                                 const RawBuffer &tag,
694                                                                                 const RawBuffer &aad,
695                                                                                 const RawBuffer &data,
696                                                                                 RawBuffer &out)
697 {
698         // command ID = CMD_DECRYPT (from km_ta_defines.h)
699         //
700         // TEEC_Operation layout:
701         // params:
702         //   [0].value.a - keyid
703         //   [0].value.b - algo
704         //   [1].memref - input data (serialized key/input/iv/tag/aad)
705         // returned:
706         //   [0].value.a - output size
707         //   [2].memref - output (decrypted data)
708
709         if (keyId.size() != KM_KEY_ID_SIZE) {
710                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
711         }
712
713         KM_BufferSizeDesc bufSize;
714
715         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
716         bufSize.input_size = static_cast<uint32_t>(data.size());
717         bufSize.with_pwd_data = true;
718         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
719         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
720         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
721         bufSize.iv_size = static_cast<uint32_t>(iv.size());
722         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
723         bufSize.with_ae_data = true;
724         bufSize.aad_size = static_cast<uint32_t>(aad.size());
725         bufSize.tag_size = static_cast<uint32_t>(tag.size());
726         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
727         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
728
729         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
730         bufSize.out_size = static_cast<uint32_t>(data.size());
731         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
732         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
733
734         KM_SymmetricInput* input = nullptr;
735         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
736         if (ret) {
737                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
738         }
739
740         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
741         if (ret) {
742                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
743         }
744
745         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
746         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
747                                                                         pwd.getIV().data(), pwd.getIV().size(),
748                                                                         pwd.getTag().data(), pwd.getTag().size(),
749                                                                         Params::DERIVED_KEY_LENGTH_BITS,
750                                                                         Params::DERIVED_KEY_ITERATIONS,
751                                                                         pwdTagSizeBits);
752         if (ret) {
753                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
754         }
755
756         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
757         if (ret) {
758                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
759         }
760
761         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
762         if (ret) {
763                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
764         }
765
766         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
767         if (ret) {
768                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
769         }
770
771         ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
772         if (ret) {
773                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
774         }
775
776         TEEC_Operation op;
777         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
778                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
779         op.params[0].value.a = ALGO_AES_GCM;
780         op.params[1].memref.parent = inMemory.Get();
781         op.params[1].memref.offset = 0;
782         op.params[1].memref.size = inMemory.Get()->size;
783         op.params[2].memref.parent = outMemory.Get();
784         op.params[2].memref.offset = 0;
785         op.params[2].memref.size = outMemory.Get()->size;
786         Execute(CMD_DECRYPT, &op);
787
788         KM_SymmetricInput* output = nullptr;
789         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
790         if (ret) {
791                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
792         }
793
794         KM_OutData* outData = nullptr;
795         ret = KM_ParamsDeserializeOutData(output, &outData);
796         if (ret) {
797                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
798         }
799
800         out.clear();
801         if (outData) {
802                 out.resize(outData->data_size);
803                 memcpy(out.data(), outData->data, outData->data_size);
804         }
805 }
806
807 void TrustZoneContext::executeSign(tz_algo_type algo,
808                                                                 tz_hash_type hash,
809                                                                 const RawBuffer &keyId,
810                                                                 const Pwd &pwd,
811                                                                 const RawBuffer &message,
812                                                                 RawBuffer &signature)
813 {
814         // command ID = CMD_SIGN (from km_ta_defines.h)
815         //
816         // TEEC_Operation layout:
817         // input params:
818         //   [0].value.a - algorithm type (tz_algo_type)
819         //   [0].value.b - hash type (tz_hash_type)
820         //   [1].memref  - reference to serialized buffer:
821         //       KM_ParamsSerializeInputData with data to sign
822         //       KM_ParamsSerializeKeyId with key id
823         // output params:
824         //   [0].value.a - return code
825         //   [2].memref  - reference to serialized buffer:
826         //       KM_ParamsSerializeOutData with signature data
827
828         if (keyId.size() != KM_KEY_ID_SIZE) {
829                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
830                         + std::to_string(keyId.size()) + ")");
831         }
832
833         KM_BufferSizeDesc bufSize;
834
835         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
836         bufSize.input_size = static_cast<uint32_t>(message.size());
837         bufSize.with_pwd_data = true;
838         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
839         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
840         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
841         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
842         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
843         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
844
845         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
846         bufSize.out_size = MAX_KEY_SIZE.at(algo);
847         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
848         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
849
850         KM_SymmetricInput* input = nullptr;
851         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
852         if (ret) {
853                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
854         }
855
856         ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
857         if (ret) {
858                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
859         }
860
861         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
862         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
863                                                                         pwd.getIV().data(), pwd.getIV().size(),
864                                                                         pwd.getTag().data(), pwd.getTag().size(),
865                                                                         Params::DERIVED_KEY_LENGTH_BITS,
866                                                                         Params::DERIVED_KEY_ITERATIONS,
867                                                                         pwdTagSizeBits);
868         if (ret) {
869                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
870         }
871
872         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
873         if (ret) {
874                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
875         }
876
877         TEEC_Operation op;
878         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
879                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
880         op.params[0].value.a = algo;
881         op.params[0].value.b = hash;
882         op.params[1].memref.parent = inMemory.Get();
883         op.params[1].memref.offset = 0;
884         op.params[1].memref.size = inMemory.Get()->size;
885         op.params[2].memref.parent = outMemory.Get();
886         op.params[2].memref.offset = 0;
887         op.params[2].memref.size = outMemory.Get()->size;
888         Execute(CMD_SIGN, &op);
889
890         KM_SymmetricInput* output = nullptr;
891         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
892         if (ret) {
893                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
894         }
895
896         KM_OutData* outData = nullptr;
897         ret = KM_ParamsDeserializeOutData(output, &outData);
898         if (ret || !outData || outData->data_size == 0) {
899                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
900         }
901
902         signature.resize(outData->data_size);
903         memcpy(signature.data(), outData->data, outData->data_size);
904 }
905
906 int TrustZoneContext::executeVerify(tz_algo_type algo,
907                                                                         tz_hash_type hash,
908                                                                         const RawBuffer &keyId,
909                                                                         const Pwd &pwd,
910                                                                         const RawBuffer &message,
911                                                                         const RawBuffer &signature)
912 {
913         // command ID = CMD_VERIFY (from km_ta_defines.h)
914         //
915         // TEEC_Operation layout:
916         // input params:
917         //   [0].value.a - algorithm type (tz_algo_type)
918         //   [0].value.b - hash type (tz_hash_type)
919         //   [1].memref  - reference to serialized buffer:
920         //       KM_ParamsSerializeInputData with verify data (signature hidden in Tag data)
921         //       KM_ParamsSerializeKeyId with key id
922         // output params:
923         //   [0].value.a - return code
924
925         if (keyId.size() != KM_KEY_ID_SIZE) {
926                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
927                         + std::to_string(keyId.size()) + ")");
928         }
929
930         KM_BufferSizeDesc bufSize;
931
932         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
933         bufSize.input_size = static_cast<uint32_t>(message.size());
934         bufSize.with_pwd_data = true;
935         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
936         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
937         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
938         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
939         bufSize.tag_size = static_cast<uint32_t>(signature.size());
940         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
941         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
942
943         KM_SymmetricInput* input = nullptr;
944         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
945         if (ret) {
946                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
947         }
948
949         ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
950         if (ret) {
951                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
952         }
953
954         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
955         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
956                                                                         pwd.getIV().data(), pwd.getIV().size(),
957                                                                         pwd.getTag().data(), pwd.getTag().size(),
958                                                                         Params::DERIVED_KEY_LENGTH_BITS,
959                                                                         Params::DERIVED_KEY_ITERATIONS,
960                                                                         pwdTagSizeBits);
961         if (ret) {
962                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
963         }
964
965         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
966         if (ret) {
967                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
968         }
969
970         ret = KM_ParamsSerializeTagData(input, signature.data(), signature.size());
971         if (ret) {
972                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize signature data for TZ sign operation: ", ret);
973         }
974
975         TEEC_Operation op;
976         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
977                                                                         TEEC_NONE, TEEC_NONE);
978         op.params[0].value.a = algo;
979         op.params[0].value.b = hash;
980         op.params[1].memref.parent = inMemory.Get();
981         op.params[1].memref.offset = 0;
982         op.params[1].memref.size = inMemory.Get()->size;
983         Execute(CMD_VERIFY, &op);
984
985         int opRet = op.params[0].value.a;
986         switch (opRet) {
987         case KM_TA_SUCCESS:
988                 return CKM_API_SUCCESS;
989         case KM_TA_ERROR_SIGNATURE:
990                 LogWarning("Signature verification failed");
991                 return CKM_API_ERROR_VERIFICATION_FAILED;
992         default:
993                 assert(false); // This condition should be checked inside Execute() function
994                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
995         }
996 }
997
998 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
999 {
1000         // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
1001         //
1002         // TEEC_Operation layout:
1003         // input params:
1004         //   [1].memref - input data (serialized key ID)
1005         // output params:
1006         //   [0].value.a - return code
1007
1008         if (keyId.size() != KM_KEY_ID_SIZE) {
1009                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
1010         }
1011
1012         KM_BufferSizeDesc bufSize;
1013
1014         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
1015         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
1016         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
1017         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
1018
1019         KM_SymmetricInput* input = nullptr;
1020         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
1021         if (ret) {
1022                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
1023         }
1024
1025         ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
1026         if (ret) {
1027                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
1028         }
1029
1030         TEEC_Operation op;
1031         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1032                                                                         TEEC_NONE, TEEC_NONE);
1033         op.params[1].memref.parent = inMemory.Get();
1034         op.params[1].memref.offset = 0;
1035         op.params[1].memref.size = inMemory.Get()->size;
1036         Execute(CMD_DESTROY_KEY, &op);
1037 }
1038
1039 void TrustZoneContext::importData(
1040                                 const uint32_t dataType,
1041                                 const RawBuffer &data,
1042                                 const Crypto::EncryptionParams &encData,
1043                                 const RawBuffer &pwd,
1044                                 const RawBuffer &iv,
1045                                 const uint32_t keySizeBits,
1046                                 const uint32_t pwdTagSizeBits,
1047                                 RawBuffer &dataId,
1048                                 RawBuffer &pwdTag)
1049 {
1050         // command ID = CMD_IMPORT_DATA
1051         // input:
1052         //    [1].memref  - reference to serialized buffer:
1053         //        uint32_t dataType contains information about type stored as binary data
1054         //        KM_BinaryData with binary data
1055         //        uint32_t binary/key size in bits
1056         //        KM_BinaryData IV for data decryption with built in key
1057         //        KM_BinaryData TAG for data decryption with built in key
1058         //        uint32_t boolean value - true if password is provided
1059         //        KM_PwdData with password (optional)
1060         // Output:
1061         //    [0].value.a - return code
1062         //    [2].memref  - reference to serialized buffer:
1063         //        KM_BinaryData with data id
1064         //        KM_BinaryData with tag id (optional, if password was provided)
1065
1066         TZSerializer sIn;
1067         sIn.Push(new TZSerializableFlag(dataType));
1068         sIn.Push(new TZSerializableBinary(data));
1069         sIn.Push(new TZSerializableFlag(keySizeBits));
1070         sIn.Push(new TZSerializableBinary(encData.iv));
1071         sIn.Push(new TZSerializableBinary(encData.tag));
1072
1073         uint32_t pwd_flag = pwd.empty() ? 0 : 1;
1074         sIn.Push(new TZSerializableFlag(pwd_flag));
1075         if (pwd_flag)
1076                 sIn.Push(new TZSerializablePwdData(pwd, iv, pwdTagSizeBits));
1077
1078         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1079         sIn.Serialize(inMemory);
1080
1081
1082         TZSerializer sOut;
1083         sOut.Push(new TZSerializableBinary(KM_DATA_ID_SIZE));
1084         if (pwd_flag) {
1085                 sOut.Push(new TZSerializableBinary(pwdTagSizeBits / 8));
1086         }
1087
1088         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
1089
1090         TEEC_Operation op;
1091         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
1092                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
1093         op.params[1].memref.parent = inMemory.Get();
1094         op.params[1].memref.offset = 0;
1095         op.params[1].memref.size = inMemory.Get()->size;
1096         op.params[2].memref.parent = outMemory.Get();
1097         op.params[2].memref.offset = 0;
1098         op.params[2].memref.size = outMemory.Get()->size;
1099
1100         Execute(CMD_IMPORT_DATA, &op);
1101
1102         sOut.Deserialize(outMemory);
1103         sOut.Pull(dataId);
1104         if (pwd_flag) {
1105                 sOut.Pull(pwdTag);
1106         }
1107
1108         LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
1109 }
1110
1111 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
1112 {
1113         // command ID = CMD_GET_DATA_SIZE
1114         // TA will decrypt data with password if provided
1115         // Parameters:
1116         //    [1].memref  - reference to serialized buffer:
1117         //        KM_BinaryData with object ID
1118         // Output:
1119         //    [0].value.a - return code
1120         //    [0].value.b - size of buffer to be passed from CA
1121         LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
1122
1123         TZSerializer sIn;
1124         sIn.Push(new TZSerializableBinary(dataId));
1125
1126         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1127         sIn.Serialize(inMemory);
1128
1129         TEEC_Operation op;
1130         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1131                                                                         TEEC_NONE, TEEC_NONE);
1132
1133         op.params[1].memref.parent = inMemory.Get();
1134         op.params[1].memref.offset = 0;
1135         op.params[1].memref.size = inMemory.Get()->size;
1136         Execute(CMD_GET_DATA_SIZE, &op);
1137         dataSize = op.params[0].value.b;
1138 }
1139
1140 void TrustZoneContext::getData(const RawBuffer &dataId,
1141                          const Pwd &pwd,
1142                          RawBuffer &data)
1143 {
1144         // command ID = CMD_GET_DATA
1145         // TA will decrypt data with password if provided
1146         // Parameters:
1147         //    [1].memref  - reference to serialized buffer:
1148         //        KM_BinaryData with object ID
1149         //        uint32_t boolean value - true if password is provided
1150         //        KM_PwdData with password (optional)
1151         // Output:
1152         //    [0].value.a - return code
1153         //    [2].memref  - reference to serialized buffer:
1154         //        KM_BinaryData with binary data
1155         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
1156
1157         TZSerializer sIn;
1158         sIn.Push(new TZSerializableBinary(dataId));
1159
1160         uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
1161         sIn.Push(new TZSerializableFlag(pwd_flag));
1162
1163         if (pwd_flag) {
1164                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
1165                                                   pwd.getIV(),
1166                                                   Params::DEFAULT_AES_GCM_TAG_LEN_BITS,
1167                                                   pwd.getTag()));
1168         }
1169
1170         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1171         sIn.Serialize(inMemory);
1172
1173         uint32_t data_size = 0;
1174         GetDataSize(dataId, data_size);
1175
1176         TZSerializer sOut;
1177         sOut.Push(new TZSerializableBinary(data_size));
1178         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
1179         sOut.Serialize(outMemory);
1180
1181         TEEC_Operation op;
1182         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
1183                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
1184         op.params[1].memref.parent = inMemory.Get();
1185         op.params[1].memref.offset = 0;
1186         op.params[1].memref.size = inMemory.Get()->size;
1187         op.params[2].memref.parent = outMemory.Get();
1188         op.params[2].memref.offset = 0;
1189         op.params[2].memref.size = outMemory.Get()->size;
1190
1191         Execute(CMD_GET_DATA, &op);
1192
1193         sOut.Deserialize(outMemory);
1194         sOut.Pull(data);
1195 }
1196
1197
1198 void TrustZoneContext::destroyData(const RawBuffer &dataId)
1199 {
1200         //      command ID = CMD_DESTROY_DATA
1201         //  TEEC_Operation parameters layout:
1202         //      input:
1203         //     [1].memref  - reference to serialized buffer:
1204         //         KM_BinaryData with object ID
1205         //  output:
1206         //     [0].value.a - return code
1207         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
1208         TZSerializer sIn;
1209         sIn.Push(new TZSerializableBinary(dataId));
1210
1211         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1212         sIn.Serialize(inMemory);
1213
1214         TEEC_Operation op;
1215         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1216                                                                         TEEC_NONE, TEEC_NONE);
1217
1218         op.params[1].memref.parent = inMemory.Get();
1219         op.params[1].memref.offset = 0;
1220         op.params[1].memref.size = inMemory.Get()->size;
1221         Execute(CMD_DESTROY_DATA, &op);
1222 }
1223
1224 void TrustZoneContext::Initialize()
1225 {
1226         TEEC_Operation op;
1227         TEEC_Result result;
1228         uint32_t retOrigin;
1229
1230         op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1231
1232         result = TEEC_InitializeContext(nullptr, &m_Context);
1233         if (result != TEEC_SUCCESS) {
1234                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
1235         }
1236         m_ContextInitialized = true;
1237
1238         result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
1239         if (result != TEEC_SUCCESS) {
1240                 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
1241         }
1242         m_SessionInitialized = true;
1243 }
1244
1245 void TrustZoneContext::Destroy()
1246 {
1247         if (m_SessionInitialized) {
1248                 TEEC_CloseSession(&m_Session);
1249                 m_SessionInitialized = false;
1250         }
1251
1252         if (m_ContextInitialized) {
1253                 TEEC_FinalizeContext(&m_Context);
1254                 m_ContextInitialized = false;
1255         }
1256 }
1257
1258 void TrustZoneContext::Reload()
1259 {
1260         Destroy();
1261         Initialize();
1262 }
1263
1264 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1265 {
1266         uint32_t retOrigin = 0;
1267         LogDebug("Executing TZ operation " << commandID);
1268
1269         TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
1270         if (result != TEEC_SUCCESS) {
1271                 switch (result) {
1272                 case TEEC_ERROR_TARGET_DEAD:
1273                         Reload();
1274                         ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1275                                         static_cast<unsigned int>(commandID));
1276                 case TEEC_ERROR_BAD_PARAMETERS:
1277                         ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1278                 default:
1279                         ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1280                                         static_cast<unsigned int>(commandID), " with error: ", std::hex,
1281                                         static_cast<unsigned int>(result), " with origin: ", std::hex,
1282                                         retOrigin);
1283                 }
1284         }
1285
1286         int ta_ret = op->params[0].value.a;
1287         switch (ta_ret) {
1288         case KM_TA_SUCCESS:
1289         case KM_TA_ERROR_SIGNATURE:
1290                 break;
1291         case KM_TA_ERROR_AUTH_FAILED:
1292                 // Authentication cipher failed - notify with proper exception
1293                 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1294         default:
1295                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1296         }
1297 }
1298
1299 } // namespace Internals
1300 } // namespace TZ
1301 } // namespace Crypto
1302 } // namespace CKM