tz-backend: Implement asymmetric operations
[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.resize(outData->data_size);
557         memcpy(out.data(), outData->data, outData->data_size);
558 }
559
560 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
561                                                                                 const Pwd &pwd,
562                                                                                 const RawBuffer &iv,
563                                                                                 int tagSizeBits,
564                                                                                 const RawBuffer &aad,
565                                                                                 const RawBuffer &data,
566                                                                                 RawBuffer &out,
567                                                                                 RawBuffer &tag)
568 {
569         // command ID = CMD_ENCRYPT (from km_ta_defines.h)
570         //
571         // TEEC_Operation layout:
572         // params:
573         //   [0].value.a - keyid
574         //   [0].value.b - algo
575         //   [1].memref - input data (serialized key/input/iv/aad)
576         // returned:
577         //   [0].value.a - return code
578         //   [2].memref - output
579
580         if (keyId.size() != KM_KEY_ID_SIZE) {
581                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
582         }
583
584         uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
585         KM_BufferSizeDesc bufSize;
586
587         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
588         bufSize.input_size = static_cast<uint32_t>(data.size());
589         bufSize.with_pwd_data = true;
590         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
591         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
592         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
593         bufSize.iv_size = static_cast<uint32_t>(iv.size());
594         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
595         bufSize.with_ae_data = true;
596         bufSize.aad_size = static_cast<uint32_t>(aad.size());
597         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
598         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
599
600         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
601         bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
602         bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
603         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
604         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
605
606         KM_SymmetricInput* input = nullptr;
607         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
608         if (ret) {
609                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
610         }
611
612         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
613         if (ret) {
614                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
615         }
616
617         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
618         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
619                                                                         pwd.getIV().data(), pwd.getIV().size(),
620                                                                         pwd.getTag().data(), pwd.getTag().size(),
621                                                                         Params::DERIVED_KEY_LENGTH_BITS,
622                                                                         Params::DERIVED_KEY_ITERATIONS,
623                                                                         pwdTagSizeBits);
624         if (ret) {
625                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
626         }
627
628         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
629         if (ret) {
630                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
631         }
632
633         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
634         if (ret) {
635                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
636         }
637
638         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
639         if (ret) {
640                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
641         }
642
643         TEEC_Operation op;
644         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
645                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
646         op.params[0].value.a = ALGO_AES_GCM;
647         op.params[1].memref.parent = inMemory.Get();
648         op.params[1].memref.offset = 0;
649         op.params[1].memref.size = inMemory.Get()->size;
650         op.params[2].memref.parent = outMemory.Get();
651         op.params[2].memref.offset = 0;
652         op.params[2].memref.size = outMemory.Get()->size;
653         Execute(CMD_ENCRYPT, &op);
654
655         KM_SymmetricInput* output = nullptr;
656         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
657         if (ret) {
658                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
659         }
660
661         KM_OutData* outData = nullptr;
662         ret = KM_ParamsDeserializeOutData(output, &outData);
663         if (ret) {
664                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
665         }
666
667         KM_TagData* tagData = nullptr;
668         ret = KM_ParamsDeserializeTagData(output, &tagData);
669         if (ret) {
670                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
671         }
672
673         out.resize(outData->data_size);
674         memcpy(out.data(), outData->data, outData->data_size);
675
676         if (tagData->data_size) {
677                 tag.resize(tagData->data_size);
678                 memcpy(tag.data(), tagData->data, tagData->data_size);
679         }
680 }
681
682 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
683                                                                                 const Pwd &pwd,
684                                                                                 const RawBuffer &iv,
685                                                                                 int tagSizeBits,
686                                                                                 const RawBuffer &tag,
687                                                                                 const RawBuffer &aad,
688                                                                                 const RawBuffer &data,
689                                                                                 RawBuffer &out)
690 {
691         // command ID = CMD_DECRYPT (from km_ta_defines.h)
692         //
693         // TEEC_Operation layout:
694         // params:
695         //   [0].value.a - keyid
696         //   [0].value.b - algo
697         //   [1].memref - input data (serialized key/input/iv/tag/aad)
698         // returned:
699         //   [0].value.a - output size
700         //   [2].memref - output (decrypted data)
701
702         if (keyId.size() != KM_KEY_ID_SIZE) {
703                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
704         }
705
706         KM_BufferSizeDesc bufSize;
707
708         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
709         bufSize.input_size = static_cast<uint32_t>(data.size());
710         bufSize.with_pwd_data = true;
711         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
712         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
713         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
714         bufSize.iv_size = static_cast<uint32_t>(iv.size());
715         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
716         bufSize.with_ae_data = true;
717         bufSize.aad_size = static_cast<uint32_t>(aad.size());
718         bufSize.tag_size = static_cast<uint32_t>(tag.size());
719         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
720         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
721
722         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
723         bufSize.out_size = static_cast<uint32_t>(data.size());
724         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
725         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
726
727         KM_SymmetricInput* input = nullptr;
728         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
729         if (ret) {
730                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
731         }
732
733         ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
734         if (ret) {
735                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
736         }
737
738         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
739         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
740                                                                         pwd.getIV().data(), pwd.getIV().size(),
741                                                                         pwd.getTag().data(), pwd.getTag().size(),
742                                                                         Params::DERIVED_KEY_LENGTH_BITS,
743                                                                         Params::DERIVED_KEY_ITERATIONS,
744                                                                         pwdTagSizeBits);
745         if (ret) {
746                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
747         }
748
749         ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
750         if (ret) {
751                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
752         }
753
754         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
755         if (ret) {
756                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
757         }
758
759         ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
760         if (ret) {
761                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
762         }
763
764         ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
765         if (ret) {
766                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
767         }
768
769         TEEC_Operation op;
770         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
771                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
772         op.params[0].value.a = ALGO_AES_GCM;
773         op.params[1].memref.parent = inMemory.Get();
774         op.params[1].memref.offset = 0;
775         op.params[1].memref.size = inMemory.Get()->size;
776         op.params[2].memref.parent = outMemory.Get();
777         op.params[2].memref.offset = 0;
778         op.params[2].memref.size = outMemory.Get()->size;
779         Execute(CMD_DECRYPT, &op);
780
781         KM_SymmetricInput* output = nullptr;
782         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
783         if (ret) {
784                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
785         }
786
787         KM_OutData* outData = nullptr;
788         ret = KM_ParamsDeserializeOutData(output, &outData);
789         if (ret) {
790                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
791         }
792
793         out.resize(outData->data_size);
794         memcpy(out.data(), outData->data, outData->data_size);
795 }
796
797 void TrustZoneContext::executeSign(tz_algo_type algo,
798                                                                 tz_hash_type hash,
799                                                                 const RawBuffer &keyId,
800                                                                 const Pwd &pwd,
801                                                                 const RawBuffer &message,
802                                                                 RawBuffer &signature)
803 {
804         // command ID = CMD_SIGN (from km_ta_defines.h)
805         //
806         // TEEC_Operation layout:
807         // input params:
808         //   [0].value.a - algorithm type (tz_algo_type)
809         //   [0].value.b - hash type (tz_hash_type)
810         //   [1].memref  - reference to serialized buffer:
811         //       KM_ParamsSerializeInputData with data to sign
812         //       KM_ParamsSerializeKeyId with key id
813         // output params:
814         //   [0].value.a - return code
815         //   [2].memref  - reference to serialized buffer:
816         //       KM_ParamsSerializeOutData with signature data
817
818         if (keyId.size() != KM_KEY_ID_SIZE) {
819                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
820                         + std::to_string(keyId.size()) + ")");
821         }
822
823         KM_BufferSizeDesc bufSize;
824
825         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
826         bufSize.input_size = static_cast<uint32_t>(message.size());
827         bufSize.with_pwd_data = true;
828         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
829         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
830         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
831         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
832         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
833         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
834
835         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
836         bufSize.out_size = MAX_KEY_SIZE.at(algo);
837         uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
838         TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
839
840         KM_SymmetricInput* input = nullptr;
841         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
842         if (ret) {
843                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
844         }
845
846         ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
847         if (ret) {
848                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
849         }
850
851         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
852         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
853                                                                         pwd.getIV().data(), pwd.getIV().size(),
854                                                                         pwd.getTag().data(), pwd.getTag().size(),
855                                                                         Params::DERIVED_KEY_LENGTH_BITS,
856                                                                         Params::DERIVED_KEY_ITERATIONS,
857                                                                         pwdTagSizeBits);
858         if (ret) {
859                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
860         }
861
862         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
863         if (ret) {
864                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
865         }
866
867         TEEC_Operation op;
868         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
869                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
870         op.params[0].value.a = algo;
871         op.params[0].value.b = hash;
872         op.params[1].memref.parent = inMemory.Get();
873         op.params[1].memref.offset = 0;
874         op.params[1].memref.size = inMemory.Get()->size;
875         op.params[2].memref.parent = outMemory.Get();
876         op.params[2].memref.offset = 0;
877         op.params[2].memref.size = outMemory.Get()->size;
878         Execute(CMD_SIGN, &op);
879
880         KM_SymmetricInput* output = nullptr;
881         ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
882         if (ret) {
883                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
884         }
885
886         KM_OutData* outData = nullptr;
887         ret = KM_ParamsDeserializeOutData(output, &outData);
888         if (ret) {
889                 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
890         }
891
892         signature.resize(outData->data_size);
893         memcpy(signature.data(), outData->data, outData->data_size);
894 }
895
896 int TrustZoneContext::executeVerify(tz_algo_type algo,
897                                                                         tz_hash_type hash,
898                                                                         const RawBuffer &keyId,
899                                                                         const Pwd &pwd,
900                                                                         const RawBuffer &message,
901                                                                         const RawBuffer &signature)
902 {
903         // command ID = CMD_VERIFY (from km_ta_defines.h)
904         //
905         // TEEC_Operation layout:
906         // input params:
907         //   [0].value.a - algorithm type (tz_algo_type)
908         //   [0].value.b - hash type (tz_hash_type)
909         //   [1].memref  - reference to serialized buffer:
910         //       KM_ParamsSerializeInputData with verify data (signature hidden in Tag data)
911         //       KM_ParamsSerializeKeyId with key id
912         // output params:
913         //   [0].value.a - return code
914
915         if (keyId.size() != KM_KEY_ID_SIZE) {
916                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
917                         + std::to_string(keyId.size()) + ")");
918         }
919
920         KM_BufferSizeDesc bufSize;
921
922         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
923         bufSize.input_size = static_cast<uint32_t>(message.size());
924         bufSize.with_pwd_data = true;
925         bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
926         bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
927         bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
928         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
929         bufSize.tag_size = static_cast<uint32_t>(signature.size());
930         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
931         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
932
933         KM_SymmetricInput* input = nullptr;
934         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
935         if (ret) {
936                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
937         }
938
939         ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
940         if (ret) {
941                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
942         }
943
944         uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
945         ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
946                                                                         pwd.getIV().data(), pwd.getIV().size(),
947                                                                         pwd.getTag().data(), pwd.getTag().size(),
948                                                                         Params::DERIVED_KEY_LENGTH_BITS,
949                                                                         Params::DERIVED_KEY_ITERATIONS,
950                                                                         pwdTagSizeBits);
951         if (ret) {
952                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
953         }
954
955         ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
956         if (ret) {
957                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
958         }
959
960         ret = KM_ParamsSerializeTagData(input, signature.data(), signature.size());
961         if (ret) {
962                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize signature data for TZ sign operation: ", ret);
963         }
964
965         TEEC_Operation op;
966         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
967                                                                         TEEC_NONE, TEEC_NONE);
968         op.params[0].value.a = algo;
969         op.params[0].value.b = hash;
970         op.params[1].memref.parent = inMemory.Get();
971         op.params[1].memref.offset = 0;
972         op.params[1].memref.size = inMemory.Get()->size;
973         Execute(CMD_VERIFY, &op);
974
975         int opRet = op.params[0].value.a;
976         switch (opRet) {
977         case KM_TA_SUCCESS:
978                 return CKM_API_SUCCESS;
979         case KM_TA_ERROR_SIGNATURE:
980                 LogWarning("Signature verification failed");
981                 return CKM_API_ERROR_VERIFICATION_FAILED;
982         default:
983                 assert(false); // This condition should be checked inside Execute() function
984                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
985         }
986 }
987
988 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
989 {
990         // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
991         //
992         // TEEC_Operation layout:
993         // input params:
994         //   [1].memref - input data (serialized key ID)
995         // output params:
996         //   [0].value.a - return code
997
998         if (keyId.size() != KM_KEY_ID_SIZE) {
999                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
1000         }
1001
1002         KM_BufferSizeDesc bufSize;
1003
1004         memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
1005         bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
1006         uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
1007         TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
1008
1009         KM_SymmetricInput* input = nullptr;
1010         int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
1011         if (ret) {
1012                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
1013         }
1014
1015         ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
1016         if (ret) {
1017                 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
1018         }
1019
1020         TEEC_Operation op;
1021         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1022                                                                         TEEC_NONE, TEEC_NONE);
1023         op.params[1].memref.parent = inMemory.Get();
1024         op.params[1].memref.offset = 0;
1025         op.params[1].memref.size = inMemory.Get()->size;
1026         Execute(CMD_DESTROY_KEY, &op);
1027 }
1028
1029 void TrustZoneContext::importData(
1030                                 const uint32_t dataType,
1031                                 const RawBuffer &data,
1032                                 const Crypto::EncryptionParams &encData,
1033                                 const RawBuffer &pwd,
1034                                 const RawBuffer &iv,
1035                                 const uint32_t keySizeBits,
1036                                 const uint32_t pwdTagSizeBits,
1037                                 RawBuffer &dataId,
1038                                 RawBuffer &pwdTag)
1039 {
1040         // command ID = CMD_IMPORT_DATA
1041         // input:
1042         //    [1].memref  - reference to serialized buffer:
1043         //        uint32_t dataType contains information about type stored as binary data
1044         //        KM_BinaryData with binary data
1045         //        uint32_t binary/key size in bits
1046         //        KM_BinaryData IV for data decryption with built in key
1047         //        KM_BinaryData TAG for data decryption with built in key
1048         //        uint32_t boolean value - true if password is provided
1049         //        KM_PwdData with password (optional)
1050         // Output:
1051         //    [0].value.a - return code
1052         //    [2].memref  - reference to serialized buffer:
1053         //        KM_BinaryData with data id
1054         //        KM_BinaryData with tag id (optional, if password was provided)
1055
1056         TZSerializer sIn;
1057         sIn.Push(new TZSerializableFlag(dataType));
1058         sIn.Push(new TZSerializableBinary(data));
1059         sIn.Push(new TZSerializableFlag(keySizeBits));
1060         sIn.Push(new TZSerializableBinary(encData.iv));
1061         sIn.Push(new TZSerializableBinary(encData.tag));
1062
1063         uint32_t pwd_flag = pwd.empty() ? 0 : 1;
1064         sIn.Push(new TZSerializableFlag(pwd_flag));
1065         if (pwd_flag)
1066                 sIn.Push(new TZSerializablePwdData(pwd, iv, pwdTagSizeBits));
1067
1068         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1069         sIn.Serialize(inMemory);
1070
1071
1072         TZSerializer sOut;
1073         sOut.Push(new TZSerializableBinary(KM_DATA_ID_SIZE));
1074         if (pwd_flag) {
1075                 sOut.Push(new TZSerializableBinary(pwdTagSizeBits / 8));
1076         }
1077
1078         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
1079
1080         TEEC_Operation op;
1081         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
1082                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
1083         op.params[1].memref.parent = inMemory.Get();
1084         op.params[1].memref.offset = 0;
1085         op.params[1].memref.size = inMemory.Get()->size;
1086         op.params[2].memref.parent = outMemory.Get();
1087         op.params[2].memref.offset = 0;
1088         op.params[2].memref.size = outMemory.Get()->size;
1089
1090         Execute(CMD_IMPORT_DATA, &op);
1091
1092         sOut.Deserialize(outMemory);
1093         sOut.Pull(dataId);
1094         if (pwd_flag) {
1095                 sOut.Pull(pwdTag);
1096         }
1097
1098         LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
1099 }
1100
1101 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
1102 {
1103         // command ID = CMD_GET_DATA_SIZE
1104         // TA will decrypt data with password if provided
1105         // Parameters:
1106         //    [1].memref  - reference to serialized buffer:
1107         //        KM_BinaryData with object ID
1108         // Output:
1109         //    [0].value.a - return code
1110         //    [0].value.b - size of buffer to be passed from CA
1111         LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
1112
1113         TZSerializer sIn;
1114         sIn.Push(new TZSerializableBinary(dataId));
1115
1116         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1117         sIn.Serialize(inMemory);
1118
1119         TEEC_Operation op;
1120         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1121                                                                         TEEC_NONE, TEEC_NONE);
1122
1123         op.params[1].memref.parent = inMemory.Get();
1124         op.params[1].memref.offset = 0;
1125         op.params[1].memref.size = inMemory.Get()->size;
1126         Execute(CMD_GET_DATA_SIZE, &op);
1127         dataSize = op.params[0].value.b;
1128 }
1129
1130 void TrustZoneContext::getData(const RawBuffer &dataId,
1131                          const Pwd &pwd,
1132                          RawBuffer &data)
1133 {
1134         // command ID = CMD_GET_DATA
1135         // TA will decrypt data with password if provided
1136         // Parameters:
1137         //    [1].memref  - reference to serialized buffer:
1138         //        KM_BinaryData with object ID
1139         //        uint32_t boolean value - true if password is provided
1140         //        KM_PwdData with password (optional)
1141         // Output:
1142         //    [0].value.a - return code
1143         //    [2].memref  - reference to serialized buffer:
1144         //        KM_BinaryData with binary data
1145         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
1146
1147         TZSerializer sIn;
1148         sIn.Push(new TZSerializableBinary(dataId));
1149
1150         uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
1151         sIn.Push(new TZSerializableFlag(pwd_flag));
1152
1153         if (pwd_flag) {
1154                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
1155                                                   pwd.getIV(),
1156                                                   Params::DEFAULT_AES_GCM_TAG_LEN_BITS,
1157                                                   pwd.getTag()));
1158         }
1159
1160         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1161         sIn.Serialize(inMemory);
1162
1163         uint32_t data_size = 0;
1164         GetDataSize(dataId, data_size);
1165
1166         TZSerializer sOut;
1167         sOut.Push(new TZSerializableBinary(data_size));
1168         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
1169         sOut.Serialize(outMemory);
1170
1171         TEEC_Operation op;
1172         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
1173                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
1174         op.params[1].memref.parent = inMemory.Get();
1175         op.params[1].memref.offset = 0;
1176         op.params[1].memref.size = inMemory.Get()->size;
1177         op.params[2].memref.parent = outMemory.Get();
1178         op.params[2].memref.offset = 0;
1179         op.params[2].memref.size = outMemory.Get()->size;
1180
1181         Execute(CMD_GET_DATA, &op);
1182
1183         sOut.Deserialize(outMemory);
1184         sOut.Pull(data);
1185 }
1186
1187
1188 void TrustZoneContext::destroyData(const RawBuffer &dataId)
1189 {
1190         //      command ID = CMD_DESTROY_DATA
1191         //  TEEC_Operation parameters layout:
1192         //      input:
1193         //     [1].memref  - reference to serialized buffer:
1194         //         KM_BinaryData with object ID
1195         //  output:
1196         //     [0].value.a - return code
1197         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
1198         TZSerializer sIn;
1199         sIn.Push(new TZSerializableBinary(dataId));
1200
1201         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
1202         sIn.Serialize(inMemory);
1203
1204         TEEC_Operation op;
1205         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1206                                                                         TEEC_NONE, TEEC_NONE);
1207
1208         op.params[1].memref.parent = inMemory.Get();
1209         op.params[1].memref.offset = 0;
1210         op.params[1].memref.size = inMemory.Get()->size;
1211         Execute(CMD_DESTROY_DATA, &op);
1212 }
1213
1214 void TrustZoneContext::Initialize()
1215 {
1216         TEEC_Operation op;
1217         TEEC_Result result;
1218         uint32_t retOrigin;
1219
1220         op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1221
1222         result = TEEC_InitializeContext(nullptr, &m_Context);
1223         if (result != TEEC_SUCCESS) {
1224                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
1225         }
1226         m_ContextInitialized = true;
1227
1228         result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
1229         if (result != TEEC_SUCCESS) {
1230                 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
1231         }
1232         m_SessionInitialized = true;
1233 }
1234
1235 void TrustZoneContext::Destroy()
1236 {
1237         if (m_SessionInitialized) {
1238                 TEEC_CloseSession(&m_Session);
1239                 m_SessionInitialized = false;
1240         }
1241
1242         if (m_ContextInitialized) {
1243                 TEEC_FinalizeContext(&m_Context);
1244                 m_ContextInitialized = false;
1245         }
1246 }
1247
1248 void TrustZoneContext::Reload()
1249 {
1250         Destroy();
1251         Initialize();
1252 }
1253
1254 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1255 {
1256         uint32_t retOrigin = 0;
1257         LogDebug("Executing TZ operation " << commandID);
1258
1259         TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
1260         if (result != TEEC_SUCCESS) {
1261                 switch (result) {
1262                 case TEEC_ERROR_TARGET_DEAD:
1263                         Reload();
1264                         ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1265                                         static_cast<unsigned int>(commandID));
1266                 case TEEC_ERROR_BAD_PARAMETERS:
1267                         ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1268                 default:
1269                         ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1270                                         static_cast<unsigned int>(commandID), " with error: ", std::hex,
1271                                         static_cast<unsigned int>(result), " with origin: ", std::hex,
1272                                         retOrigin);
1273                 }
1274         }
1275
1276         int ta_ret = op->params[0].value.a;
1277         switch (ta_ret) {
1278         case KM_TA_SUCCESS:
1279         case KM_TA_ERROR_SIGNATURE:
1280                 break;
1281         case KM_TA_ERROR_AUTH_FAILED:
1282                 // Authentication cipher failed - notify with proper exception
1283                 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1284         default:
1285                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1286         }
1287 }
1288
1289 } // namespace Internals
1290 } // namespace TZ
1291 } // namespace Crypto
1292 } // namespace CKM