Unification of import methods in gstore
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / tz-context.cpp
1 /*
2  *  Copyright (c) 2017 - 2018 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 <dpl/log/log.h>
27
28 #include <km_serialization.h>
29 #include <km_ta_defines.h>
30
31 #include <cstdint>
32 #include <cstring>
33
34 namespace CKM {
35 namespace Crypto {
36 namespace TZ {
37 namespace Internals {
38
39 namespace {
40
41 // A little bit of extra memory to add to output buffers.
42 //
43 // We need this extra memory to output for padding purposes - after encryption
44 // we can resize the result memory back to its proper size according to
45 // whatever TA will return us.
46 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
47
48 // Identifier of our TA
49 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
50
51 //raw to hex string conversion to print persistent storage data ID
52 static std::string rawToHexString(const RawBuffer &raw)
53 {
54         std::string dump;
55
56         for (auto &e : raw) {
57                 char buf[3];
58                 snprintf(buf, sizeof(buf), "%02x", (e & 0xff));
59                 dump.push_back(buf[0]);
60                 dump.push_back(buf[1]);
61         }
62
63         return dump;
64 }
65
66 } // anonymous namespace
67
68 TrustZoneContext::TrustZoneContext()
69         : m_ContextInitialized(false)
70         , m_SessionInitialized(false)
71 {
72         Initialize();
73 }
74
75 TrustZoneContext::~TrustZoneContext()
76 {
77         Destroy();
78 }
79
80 TrustZoneContext& TrustZoneContext::Instance()
81 {
82         static TrustZoneContext instance;
83         return instance;
84 }
85
86 void TrustZoneContext::generateIV(RawBuffer& iv)
87 {
88         // command ID = CMD_GENERATE_IV
89         //
90         // TEEC_Operation layout:
91         // params:
92         //   [1].memref.buffer - output
93         //   [1].memref.size - output size
94         // output:
95         //   [0].value.a - return code
96
97         // IV generation is a simple call - no need to serialize data
98         // just provide the output buffer with size equal to iv.
99         uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
100         TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
101
102         TEEC_Operation op;
103         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
104                                                                         TEEC_NONE, TEEC_NONE);
105         op.params[1].memref.parent = ivMemory.Get();
106         op.params[1].memref.offset = 0;
107         op.params[1].memref.size = ivMemory.Get()->size;
108         Execute(CMD_GENERATE_IV, &op);
109
110         iv.resize(ivSize);
111         memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
112 }
113
114 void TrustZoneContext::generateSKey(tz_algo_type algo,
115                                                                         uint32_t keySizeBits,
116                                                                         RawBuffer &keyId)
117 {
118         // command ID = CMD_GENERATE_KEY
119         //
120         // TEEC_Operation layout:
121         // params:
122         //   [0].value.a - key type
123         //   [0].value.b - key bit size
124         // output:
125         //   [0].value.a - return code
126         //   [1].memref - serialized key reference
127
128         KM_BufferSizeDesc bufSize;
129
130         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
131         bufSize.out_size = KM_KEY_ID_SIZE;
132         uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
133         TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
134
135         TEEC_Operation op;
136         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
137                                                                         TEEC_NONE, TEEC_NONE);
138         op.params[0].value.a = algo;
139         op.params[0].value.b = keySizeBits;
140         op.params[1].memref.parent = keyMemory.Get();
141         op.params[1].memref.offset = 0;
142         op.params[1].memref.size = keyMemorySize;
143         Execute(CMD_GENERATE_KEY, &op);
144
145         KM_SymmetricInput* output = nullptr;
146         int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
147         if (ret) {
148                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
149         }
150
151         KM_OutData* outData = nullptr;
152         ret = KM_ParamsDeserializeOutData(output, &outData);
153         if (ret) {
154                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
155         }
156
157         if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
158                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
159         }
160
161         keyId.resize(KM_KEY_ID_SIZE);
162         memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
163 }
164
165 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
166                                                                         const RawBuffer &pwd,
167                                                                         const RawBuffer &iv,
168                                                                         const uint32_t keySizeBits,
169                                                                         RawBuffer &keyId,
170                                                                         RawBuffer &pwdTag)
171 {
172         // command ID = CMD_GENERATE_KEY_PWD
173         //
174         // TEEC_Operation layout:
175         // params:
176         //   [0].value.a - key type
177         //   [0].value.b - key size in bits
178         //   [1].memref  - input (seralized pwd/iv for pbkdf2)
179         // output:
180         //   [0].value.a - return code
181         //   [2].memref - serialized key reference ID
182
183         KM_BufferSizeDesc bufSize;
184
185         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
186         bufSize.with_pwd_data = true;
187         bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
188         bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
189         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
190         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
191
192         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
193         bufSize.out_size = KM_KEY_ID_SIZE;
194         bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
195         uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
196         TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
197
198         KM_SymmetricInput* input = nullptr;
199         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
200         if (ret) {
201                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
202         }
203
204         ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
205                                                                         nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
206                                                                         Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
207         if (ret) {
208                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
209         }
210
211         TEEC_Operation op;
212         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
213                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
214         op.params[0].value.a = algo;
215         op.params[0].value.b = keySizeBits;
216         op.params[1].memref.parent = inMemory.Get();
217         op.params[1].memref.offset = 0;
218         op.params[1].memref.size = inMemory.Get()->size;
219         op.params[2].memref.parent = keyMemory.Get();
220         op.params[2].memref.offset = 0;
221         op.params[2].memref.size = keyMemory.Get()->size;
222         Execute(CMD_GENERATE_KEY_PWD, &op);
223
224         KM_SymmetricInput* output = nullptr;
225         ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
226         if (ret) {
227                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
228         }
229
230         KM_OutData* outData = nullptr;
231         ret = KM_ParamsDeserializeOutData(output, &outData);
232         if (ret) {
233                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
234         }
235
236         KM_TagData* tagData = nullptr;
237         ret = KM_ParamsDeserializeTagData(output, &tagData);
238         if (ret) {
239                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
240         }
241
242         if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
243                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
244         }
245
246         if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
247                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
248         }
249
250         keyId.resize(KM_KEY_ID_SIZE);
251         memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
252
253         pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
254         memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
255 }
256
257
258 void TrustZoneContext::importKey(tz_algo_type algo,
259                                                                 const RawBuffer &key,
260                                                                 const RawBuffer &encIV,
261                                                                 const RawBuffer &pwd,
262                                                                 const RawBuffer &pwdIV,
263                                                                 RawBuffer &keyId,
264                                                                 RawBuffer &pwdTag)
265 {
266         (void)encIV;
267         // command ID = CMD_IMPORT_KEY
268         //
269         // TEEC_Operation layout:
270         // params:
271         //   [0].value.a - key type
272         //   [0].value.b - key size in bits
273         //   [1].memref  - seralized key & password data
274         // output:
275         //   [0].value.a - return code
276         //   [2].memref - serialized key reference ID
277
278         KM_BufferSizeDesc bufSize;
279
280         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
281         bufSize.input_size = static_cast<uint32_t>(key.size());
282         if (!pwd.empty()) {
283                 bufSize.with_pwd_data = true;
284                 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
285                 bufSize.pwd_iv_size = static_cast<uint32_t>(pwdIV.size());
286         }
287         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
288         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
289
290         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
291         bufSize.out_size = KM_KEY_ID_SIZE;
292         bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
293         uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
294         TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
295
296         KM_SymmetricInput* input = nullptr;
297         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
298         if (ret) {
299                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for key import: ", ret);
300         }
301
302         ret = KM_ParamsSerializeInputData(input, key.data(), key.size());
303         if (ret) {
304                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key to import: ", ret);
305         }
306
307         if (!pwd.empty()) {
308                 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), pwdIV.data(), pwdIV.size(),
309                                                                                 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
310                                                                                 Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
311                 if (ret) {
312                         ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key data for import: ", ret);
313                 }
314         }
315
316         TEEC_Operation op;
317         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
318                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
319         op.params[0].value.a = algo;
320         op.params[0].value.b = key.size() * 8;
321         op.params[1].memref.parent = inMemory.Get();
322         op.params[1].memref.offset = 0;
323         op.params[1].memref.size = inMemory.Get()->size;
324         op.params[2].memref.parent = keyMemory.Get();
325         op.params[2].memref.offset = 0;
326         op.params[2].memref.size = keyMemory.Get()->size;
327         Execute(CMD_IMPORT_KEY, &op);
328
329         KM_SymmetricInput* output = nullptr;
330         ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
331         if (ret) {
332                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for imported key ID");
333         }
334
335         KM_OutData* outData = nullptr;
336         ret = KM_ParamsDeserializeOutData(output, &outData);
337         if (ret) {
338                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key ID");
339         }
340
341         if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
342                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
343         }
344
345         keyId.resize(KM_KEY_ID_SIZE);
346         memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
347
348         if (!pwd.empty()) {
349                 KM_TagData* tagData = nullptr;
350
351                 ret = KM_ParamsDeserializeTagData(output, &tagData);
352                 if (ret) {
353                         ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key's tag");
354                 }
355
356                 if (tagData == nullptr || tagData->data_size != bufSize.tag_size) {
357                         ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
358                 }
359
360                 pwdTag.resize(bufSize.tag_size);
361                 memcpy(pwdTag.data(), tagData->data, bufSize.tag_size);
362         }
363 }
364
365 void TrustZoneContext::executeCrypt(tz_command cmd,
366                                                                         tz_algo_type algo,
367                                                                         const RawBuffer &key,
368                                                                         const Pwd &pwd,
369                                                                         const RawBuffer &iv,
370                                                                         const RawBuffer &data,
371                                                                         RawBuffer &out)
372 {
373         // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
374         //
375         // TEEC_Operation layout:
376         // params:
377         //   [0].value.a - keyid
378         //   [0].value.b - algo
379         //   [1].memref - input data (serialized key/input)
380         // returned:
381         //   [0].value.a - return code
382         //   [2].memref - serialized output buffer
383
384         if (key.size() != KM_KEY_ID_SIZE) {
385                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
386                         + std::to_string(key.size()) + ")");
387         }
388
389         KM_BufferSizeDesc bufSize;
390
391         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
392         bufSize.input_size = static_cast<uint32_t>(data.size());
393         bufSize.with_pwd_data = true;
394         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
395         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
396         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
397         bufSize.iv_size = static_cast<uint32_t>(iv.size());
398         bufSize.key_id_size = static_cast<uint32_t>(key.size());
399         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
400         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
401
402         // decrypt operation does not require padding
403         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
404         bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
405                                                         data.size() + CIPHER_EXTRA_PADDING_SIZE :
406                                                         data.size());
407         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
408         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
409
410         KM_SymmetricInput* input = nullptr;
411         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
412         if (ret) {
413                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
414         }
415
416         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
417         if (ret) {
418                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
419         }
420
421         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
422         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
423                                                                         pwd.getIV().data(), pwd.getIV().size(),
424                                                                         pwd.getTag().data(), pwd.getTag().size(),
425                                                                         Params::DERIVED_KEY_LENGTH_BITS,
426                                                                         Params::DERIVED_KEY_ITERATIONS,
427                                                                         pwdTagSizeBits);
428         if (ret) {
429                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
430         }
431
432         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
433         if (ret) {
434                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
435         }
436
437         ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
438         if (ret) {
439                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
440         }
441
442         TEEC_Operation op;
443         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
444                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
445         op.params[0].value.a = algo;
446         op.params[1].memref.parent = inMemory.Get();
447         op.params[1].memref.offset = 0;
448         op.params[1].memref.size = inMemory.Get()->size;
449         op.params[2].memref.parent = outMemory.Get();
450         op.params[2].memref.offset = 0;
451         op.params[2].memref.size = outMemory.Get()->size;
452         Execute(cmd, &op);
453
454         KM_SymmetricInput* output = nullptr;
455         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
456         if (ret) {
457                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
458         }
459
460         KM_OutData* outData = nullptr;
461         ret = KM_ParamsDeserializeOutData(output, &outData);
462         if (ret) {
463                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
464         }
465
466         // data_size should contain how much memory we actually took for our cipher operation
467         out.resize(outData->data_size);
468         memcpy(out.data(), outData->data, outData->data_size);
469 }
470
471 void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
472                                                                                 const Pwd &pwd,
473                                                                                 const RawBuffer &iv,
474                                                                                 int tagSizeBits,
475                                                                                 const RawBuffer &aad,
476                                                                                 const RawBuffer &data,
477                                                                                 RawBuffer &out,
478                                                                                 RawBuffer &tag)
479 {
480         // command ID = CMD_ENCRYPT (from km_ta_defines.h)
481         //
482         // TEEC_Operation layout:
483         // params:
484         //   [0].value.a - keyid
485         //   [0].value.b - algo
486         //   [1].memref - input data (serialized key/input/iv/aad)
487         // returned:
488         //   [0].value.a - return code
489         //   [2].memref - output
490
491         if (key.size() != KM_KEY_ID_SIZE) {
492                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
493         }
494
495         uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
496         KM_BufferSizeDesc bufSize;
497
498         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
499         bufSize.input_size = static_cast<uint32_t>(data.size());
500         bufSize.with_pwd_data = true;
501         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
502         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
503         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
504         bufSize.iv_size = static_cast<uint32_t>(iv.size());
505         bufSize.key_id_size = static_cast<uint32_t>(key.size());
506         bufSize.with_ae_data = true;
507         bufSize.aad_size = static_cast<uint32_t>(aad.size());
508         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
509         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
510
511         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
512         bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
513         bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
514         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
515         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
516
517         KM_SymmetricInput* input = nullptr;
518         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
519         if (ret) {
520                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
521         }
522
523         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
524         if (ret) {
525                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
526         }
527
528         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
529         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
530                                                                         pwd.getIV().data(), pwd.getIV().size(),
531                                                                         pwd.getTag().data(), pwd.getTag().size(),
532                                                                         Params::DERIVED_KEY_LENGTH_BITS,
533                                                                         Params::DERIVED_KEY_ITERATIONS,
534                                                                         pwdTagSizeBits);
535         if (ret) {
536                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
537         }
538
539         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
540         if (ret) {
541                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
542         }
543
544         ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
545         if (ret) {
546                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
547         }
548
549         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
550         if (ret) {
551                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
552         }
553
554         TEEC_Operation op;
555         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
556                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
557         op.params[0].value.a = ALGO_AES_GCM;
558         op.params[1].memref.parent = inMemory.Get();
559         op.params[1].memref.offset = 0;
560         op.params[1].memref.size = inMemory.Get()->size;
561         op.params[2].memref.parent = outMemory.Get();
562         op.params[2].memref.offset = 0;
563         op.params[2].memref.size = outMemory.Get()->size;
564         Execute(CMD_ENCRYPT, &op);
565
566         KM_SymmetricInput* output = nullptr;
567         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
568         if (ret) {
569                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
570         }
571
572         KM_OutData* outData = nullptr;
573         ret = KM_ParamsDeserializeOutData(output, &outData);
574         if (ret) {
575                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
576         }
577
578         KM_TagData* tagData = nullptr;
579         ret = KM_ParamsDeserializeTagData(output, &tagData);
580         if (ret) {
581                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
582         }
583
584         out.resize(outData->data_size);
585         memcpy(out.data(), outData->data, outData->data_size);
586
587         if (tagData->data_size) {
588                 tag.resize(tagData->data_size);
589                 memcpy(tag.data(), tagData->data, tagData->data_size);
590         }
591 }
592
593 void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
594                                                                                 const Pwd &pwd,
595                                                                                 const RawBuffer &iv,
596                                                                                 int tagSizeBits,
597                                                                                 const RawBuffer &tag,
598                                                                                 const RawBuffer &aad,
599                                                                                 const RawBuffer &data,
600                                                                                 RawBuffer &out)
601 {
602         // command ID = CMD_DECRYPT (from km_ta_defines.h)
603         //
604         // TEEC_Operation layout:
605         // params:
606         //   [0].value.a - keyid
607         //   [0].value.b - algo
608         //   [1].memref - input data (serialized key/input/iv/tag/aad)
609         // returned:
610         //   [0].value.a - output size
611         //   [2].memref - output (decrypted data)
612
613         if (key.size() != KM_KEY_ID_SIZE) {
614                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
615         }
616
617         KM_BufferSizeDesc bufSize;
618
619         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
620         bufSize.input_size = static_cast<uint32_t>(data.size());
621         bufSize.with_pwd_data = true;
622         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
623         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
624         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
625         bufSize.iv_size = static_cast<uint32_t>(iv.size());
626         bufSize.key_id_size = static_cast<uint32_t>(key.size());
627         bufSize.with_ae_data = true;
628         bufSize.aad_size = static_cast<uint32_t>(aad.size());
629         bufSize.tag_size = static_cast<uint32_t>(tag.size());
630         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
631         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
632
633         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
634         bufSize.out_size = static_cast<uint32_t>(data.size());
635         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
636         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
637
638         KM_SymmetricInput* input = nullptr;
639         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
640         if (ret) {
641                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
642         }
643
644         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
645         if (ret) {
646                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
647         }
648
649         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
650         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
651                                                                         pwd.getIV().data(), pwd.getIV().size(),
652                                                                         pwd.getTag().data(), pwd.getTag().size(),
653                                                                         Params::DERIVED_KEY_LENGTH_BITS,
654                                                                         Params::DERIVED_KEY_ITERATIONS,
655                                                                         pwdTagSizeBits);
656         if (ret) {
657                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
658         }
659
660         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
661         if (ret) {
662                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
663         }
664
665         ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
666         if (ret) {
667                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
668         }
669
670         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
671         if (ret) {
672                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
673         }
674
675         ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
676         if (ret) {
677                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
678         }
679
680         TEEC_Operation op;
681         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
682                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
683         op.params[0].value.a = ALGO_AES_GCM;
684         op.params[1].memref.parent = inMemory.Get();
685         op.params[1].memref.offset = 0;
686         op.params[1].memref.size = inMemory.Get()->size;
687         op.params[2].memref.parent = outMemory.Get();
688         op.params[2].memref.offset = 0;
689         op.params[2].memref.size = outMemory.Get()->size;
690         Execute(CMD_DECRYPT, &op);
691
692         KM_SymmetricInput* output = nullptr;
693         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
694         if (ret) {
695                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
696         }
697
698         KM_OutData* outData = nullptr;
699         ret = KM_ParamsDeserializeOutData(output, &outData);
700         if (ret) {
701                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
702         }
703
704         out.resize(outData->data_size);
705         memcpy(out.data(), outData->data, outData->data_size);
706 }
707
708 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
709 {
710         // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
711         //
712         // TEEC_Operation layout:
713         // input params:
714         //   [1].memref - input data (serialized key ID)
715         // output params:
716         //   [0].value.a - return code
717
718         if (keyId.size() != KM_KEY_ID_SIZE) {
719                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
720         }
721
722         KM_BufferSizeDesc bufSize;
723
724         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
725         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
726         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
727         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
728
729         KM_SymmetricInput* input = nullptr;
730         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
731         if (ret) {
732                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
733         }
734
735         ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
736         if (ret) {
737                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
738         }
739
740         TEEC_Operation op;
741         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
742                                                                         TEEC_NONE, TEEC_NONE);
743         op.params[1].memref.parent = inMemory.Get();
744         op.params[1].memref.offset = 0;
745         op.params[1].memref.size = inMemory.Get()->size;
746         Execute(CMD_DESTROY_KEY, &op);
747 }
748
749 void TrustZoneContext::importData(const RawBuffer &data,
750                                 const RawBuffer &pwd,
751                                 const RawBuffer &iv,
752                                 RawBuffer &dataId,
753                                 RawBuffer &pwdTag)
754 {
755         // command ID = CMD_IMPORT_DATA
756         // input:
757         //    [1].memref  - reference to serialized buffer:
758         //        KM_BinaryData with binary data
759         //                uint32_t boolean value - true if password is provided
760         //        KM_PwdData with password (optional)
761         // Output:
762         //    [0].value.a - return code
763         //    [2].memref  - reference to serialized buffer:
764         //        KM_BinaryData with data id
765         //        KM_BinaryData with tag id (optional, if password was provided)
766         KM_BinaryData kmTaData;
767         uint32_t pwd_flag = pwd.empty() ? 0 : 1;
768         uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
769         kmTaData.data_size = static_cast<uint32_t>(data.size());
770         kmTaData.data = const_cast<unsigned char *>(data.data());
771         uint32_t inMemorySize = KM_SizeOfBinaryData(&kmTaData) + KM_SizeOfFlag();
772         KM_PwdData kmPwdData;
773         if (pwd_flag) {
774                 memset(&kmPwdData, 0, sizeof(KM_PwdData));
775                 kmPwdData.pwd = const_cast<unsigned char *>(pwd.data());
776                 kmPwdData.pwd_size = pwd.size();
777                 kmPwdData.iv = const_cast<unsigned char *>(iv.data());
778                 kmPwdData.iv_size = iv.size();
779                 kmPwdData.tag = NULL;
780                 kmPwdData.tag_size = 0;
781                 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
782                 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
783                 kmPwdData.tag_len_bits = pwdTagSizeBits;
784
785                 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
786         }
787
788         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
789         void *inMemoryPtr = inMemory.Get()->buffer;
790
791         int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmTaData);
792         if (ret) {
793                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
794         }
795         ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
796         if (ret) {
797                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
798         }
799         if (pwd_flag) {
800                 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
801                 if (ret) {
802                         ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
803                 }
804         }
805
806         KM_BinaryData kmDataId;
807         KM_BinaryData kmTag;
808         memset(&kmDataId, 0, sizeof(KM_BinaryData));
809         memset(&kmTag, 0, sizeof(KM_BinaryData));
810         kmDataId.data_size = KM_DATA_ID_SIZE;
811         uint32_t outMemorySize = KM_SizeOfBinaryData(&kmDataId);
812         if (pwd_flag) {
813                 kmTag.data_size = pwdTagSizeBits / 8;
814                 outMemorySize += KM_SizeOfBinaryData(&kmTag);
815         }
816
817         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
818         void *outMemoryPtr = outMemory.Get()->buffer;
819
820         TEEC_Operation op;
821         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
822                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
823         op.params[1].memref.parent = inMemory.Get();
824         op.params[1].memref.offset = 0;
825         op.params[1].memref.size = inMemory.Get()->size;
826         op.params[2].memref.parent = outMemory.Get();
827         op.params[2].memref.offset = 0;
828         op.params[2].memref.size = outMemory.Get()->size;
829
830         Execute(CMD_IMPORT_DATA, &op);
831
832         ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmDataId);
833         if (ret) {
834                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
835         }
836         dataId.resize(kmDataId.data_size);
837         memcpy(dataId.data(), kmDataId.data, kmDataId.data_size);
838         if (pwd_flag) {
839                 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmTag);
840                 if (ret) {
841                         ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
842                 }
843                 pwdTag.resize(kmTag.data_size);
844                 memcpy(pwdTag.data(), kmTag.data, kmTag.data_size);
845         }
846
847         LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
848 }
849
850 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
851 {
852         // command ID = CMD_GET_DATA_SIZE
853         // TA will decrypt data with password if provided
854         // Parameters:
855         //    [1].memref  - reference to serialized buffer:
856         //        KM_BinaryData with object ID
857         // Output:
858         //    [0].value.a - return code
859         //    [0].value.b - size of buffer to be passed from CA
860         LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
861         KM_BinaryData kmDataId;
862         kmDataId.data_size = static_cast<uint32_t>(dataId.size());
863         kmDataId.data = const_cast<unsigned char *>(dataId.data());
864         uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
865         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
866         void *inMemoryPtr = inMemory.Get()->buffer;
867         int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
868         if (ret) {
869                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
870         }
871         TEEC_Operation op;
872         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
873                                                                         TEEC_NONE, TEEC_NONE);
874
875         op.params[1].memref.parent = inMemory.Get();
876         op.params[1].memref.offset = 0;
877         op.params[1].memref.size = inMemory.Get()->size;
878         Execute(CMD_GET_DATA_SIZE, &op);
879         dataSize = op.params[0].value.b;
880 }
881
882 void TrustZoneContext::getData(const RawBuffer &dataId,
883                          const Pwd &pwd,
884                          RawBuffer &data)
885 {
886         // command ID = CMD_GET_DATA
887         // TA will decrypt data with password if provided
888         // Parameters:
889         //    [1].memref  - reference to serialized buffer:
890         //        KM_BinaryData with object ID
891         //        uint32_t boolean value - true if password is provided
892         //        KM_PwdData with password (optional)
893         // Output:
894         //    [0].value.a - return code
895         //    [2].memref  - reference to serialized buffer:
896         //        KM_BinaryData with binary data
897         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
898         uint32_t data_size = 0;
899         GetDataSize(dataId, data_size);
900
901         KM_BinaryData kmDataId;
902         kmDataId.data_size = static_cast<uint32_t>(dataId.size());
903         kmDataId.data = const_cast<unsigned char *>(dataId.data());
904         uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId) + KM_SizeOfFlag();
905         uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
906         uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
907
908         KM_PwdData kmPwdData;
909         if (pwd_flag) {
910                 memset(&kmPwdData, 0, sizeof(KM_PwdData));
911                 kmPwdData.pwd = const_cast<unsigned char *>(pwd.getPassword().data());
912                 kmPwdData.pwd_size = pwd.getPassword().size();
913                 kmPwdData.iv = const_cast<unsigned char *>(pwd.getIV().data());
914                 kmPwdData.iv_size = pwd.getIV().size();
915                 kmPwdData.tag = const_cast<unsigned char *>(pwd.getTag().data());
916                 kmPwdData.tag_size = pwd.getTag().size();
917                 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
918                 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
919                 kmPwdData.tag_len_bits = pwdTagSizeBits;
920
921                 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
922         }
923
924         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
925         void *inMemoryPtr = inMemory.Get()->buffer;
926
927         int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
928         if (ret) {
929                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
930         }
931         ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
932         if (ret) {
933                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
934         }
935         if (pwd_flag) {
936                 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
937                 if (ret) {
938                         ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
939                 }
940         }
941
942         KM_BinaryData kmExtractedData;
943         memset(&kmExtractedData, 0, sizeof(KM_BinaryData));
944         kmExtractedData.data_size = data_size;
945
946         uint32_t outMemorySize = KM_SizeOfBinaryData(&kmExtractedData);
947         uint32_t outMemorySize2 = outMemorySize;
948
949         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
950         void *outMemoryPtr = outMemory.Get()->buffer;
951         void *outMemoryPtr2 = outMemory.Get()->buffer;
952
953         // requesting size is saved in this buffer
954         ret = KM_SerializeBinaryData(&outMemoryPtr2, &outMemorySize2, &kmExtractedData);
955         if (ret) {
956                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
957         }
958
959         TEEC_Operation op;
960         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
961                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
962         op.params[1].memref.parent = inMemory.Get();
963         op.params[1].memref.offset = 0;
964         op.params[1].memref.size = inMemory.Get()->size;
965         op.params[2].memref.parent = outMemory.Get();
966         op.params[2].memref.offset = 0;
967         op.params[2].memref.size = outMemory.Get()->size;
968
969         Execute(CMD_GET_DATA, &op);
970
971         ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmExtractedData);
972         if (ret) {
973                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
974         }
975
976         data.resize(kmExtractedData.data_size);
977         memcpy(data.data(), kmExtractedData.data, kmExtractedData.data_size);
978 }
979
980
981 void TrustZoneContext::destroyData(const RawBuffer &dataId)
982 {
983         //      command ID = CMD_DESTROY_DATA
984         //  TEEC_Operation parameters layout:
985         //      input:
986         //     [1].memref  - reference to serialized buffer:
987         //         KM_BinaryData with object ID
988         //  output:
989         //     [0].value.a - return code
990         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
991         KM_BinaryData kmDataId;
992         kmDataId.data_size = static_cast<uint32_t>(dataId.size());
993         kmDataId.data = const_cast<unsigned char *>(dataId.data());
994         uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
995         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
996         void *inMemoryPtr = inMemory.Get()->buffer;
997
998         int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
999
1000         if (ret) {
1001                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
1002         }
1003
1004         TEEC_Operation op;
1005         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1006                                                                         TEEC_NONE, TEEC_NONE);
1007
1008         op.params[1].memref.parent = inMemory.Get();
1009         op.params[1].memref.offset = 0;
1010         op.params[1].memref.size = inMemory.Get()->size;
1011         Execute(CMD_DESTROY_DATA, &op);
1012 }
1013
1014 void TrustZoneContext::Initialize()
1015 {
1016         TEEC_Operation op;
1017         TEEC_Result result;
1018         uint32_t retOrigin;
1019
1020         op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1021
1022         result = TEEC_InitializeContext(nullptr, &m_Context);
1023         if (result != TEEC_SUCCESS) {
1024                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
1025         }
1026         m_ContextInitialized = true;
1027
1028         result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
1029         if (result != TEEC_SUCCESS) {
1030                 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
1031         }
1032         m_SessionInitialized = true;
1033 }
1034
1035 void TrustZoneContext::Destroy()
1036 {
1037         if (m_SessionInitialized) {
1038                 TEEC_CloseSession(&m_Session);
1039                 m_SessionInitialized = false;
1040         }
1041
1042         if (m_ContextInitialized) {
1043                 TEEC_FinalizeContext(&m_Context);
1044                 m_ContextInitialized = false;
1045         }
1046 }
1047
1048 void TrustZoneContext::Reload()
1049 {
1050         Destroy();
1051         Initialize();
1052 }
1053
1054 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1055 {
1056         LogDebug("Executing TZ operation " << commandID);
1057
1058         TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, NULL);
1059         if (result != TEEC_SUCCESS) {
1060                 switch (result) {
1061                 case TEEC_ERROR_TARGET_DEAD:
1062                         Reload();
1063                         ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1064                                         static_cast<unsigned int>(commandID));
1065                 case TEEC_ERROR_BAD_PARAMETERS:
1066                         ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1067                 default:
1068                         ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1069                                         static_cast<unsigned int>(commandID), " with error: ", std::hex,
1070                                         static_cast<unsigned int>(result));
1071                 }
1072         }
1073
1074         int ta_ret = op->params[0].value.a;
1075         if (ta_ret != KM_TA_SUCCESS) {
1076                 switch (ta_ret) {
1077                 case KM_TA_ERROR_AUTH_FAILED:
1078                         // Authentication cipher failed - notify with proper exception
1079                         ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1080                 default:
1081                         ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1082                 }
1083         }
1084 }
1085
1086 } // namespace Internals
1087 } // namespace TZ
1088 } // namespace Crypto
1089 } // namespace CKM