Use proper constant in TZ data import
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / tz-context.cpp
1 /*
2  *  Copyright (c) 2017-2021 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 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
23
24 #include <tz-backend/tz-context.h>
25 #include <tz-backend/tz-memory.h>
26 #include <generic-backend/exception.h>
27 #include <generic-backend/crypto-params.h>
28 #include <generic-backend/encryption-params.h>
29 #include <dpl/log/log.h>
30
31 #include <km_serialization.h>
32 #include <km_ta_defines.h>
33
34 #include <cstdint>
35 #include <cstring>
36 #include <cassert>
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         return hexDump<std::string>(raw);
60 }
61
62 /*
63  * Maximum size for given key type in bytes according to key-manager-ta implementation.
64  * Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
65  */
66 const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
67         { ALGO_RSA, 4096 / 8 },
68         { ALGO_RSA_SV, 4096 / 8 },
69         { ALGO_DSA_SV, 4096 / 8 }
70 };
71
72 } // anonymous namespace
73
74 TrustZoneContext::TrustZoneContext()
75         : m_ContextInitialized(false)
76         , m_SessionInitialized(false)
77 {
78         Initialize();
79 }
80
81 TrustZoneContext::~TrustZoneContext()
82 {
83         Destroy();
84 }
85
86 TrustZoneContext& TrustZoneContext::Instance()
87 {
88         static TrustZoneContext instance;
89         return instance;
90 }
91
92 void TrustZoneContext::generateIV(RawBuffer& iv)
93 {
94         // command ID = CMD_GENERATE_IV
95         // IV generation is a simple call - no need to serialize data
96         // just provide the output buffer with size equal to iv.
97         uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
98         TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
99
100         TEEC_Operation op;
101         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
102                                                                         TEEC_NONE, TEEC_NONE);
103         op.params[1].memref.parent = ivMemory.Get();
104         op.params[1].memref.offset = 0;
105         op.params[1].memref.size = ivMemory.Get()->size;
106         Execute(CMD_GENERATE_IV, &op);
107
108         iv.resize(ivSize);
109         memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
110 }
111
112 void TrustZoneContext::generateSKey(tz_algo_type algo,
113                                                                         uint32_t keySizeBits,
114                                                                         const RawBuffer &hash)
115 {
116         // command ID = CMD_GENERATE_KEY
117         TZSerializer sIn;
118         sIn.Push(new TZSerializableBinary(hash));
119         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
120         sIn.Serialize(inMemory);
121
122         TEEC_Operation op;
123         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
124                                                                         TEEC_NONE, TEEC_NONE);
125         op.params[0].value.a = algo;
126         op.params[0].value.b = keySizeBits;
127         op.params[1].memref.parent = inMemory.Get();
128         op.params[1].memref.offset = 0;
129         op.params[1].memref.size = inMemory.Get()->size;
130         Execute(CMD_GENERATE_KEY, &op);
131 }
132
133 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
134                                                                         const RawBuffer &pwd,
135                                                                         const RawBuffer &iv,
136                                                                         const uint32_t keySizeBits,
137                                                                         RawBuffer &pwdTag,
138                                                                         const RawBuffer &hash)
139 {
140         // command ID = CMD_GENERATE_KEY_PWD
141         TZSerializer sIn;
142         sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
143         sIn.Push(new TZSerializableBinary(hash));
144         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
145         sIn.Serialize(inMemory);
146
147         TZSerializer sOut;
148         sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
149         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
150
151         TEEC_Operation op;
152         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
153                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
154         op.params[0].value.a = algo;
155         op.params[0].value.b = keySizeBits;
156         op.params[1].memref.parent = inMemory.Get();
157         op.params[1].memref.offset = 0;
158         op.params[1].memref.size = inMemory.Get()->size;
159         op.params[2].memref.parent = outMemory.Get();
160         op.params[2].memref.offset = 0;
161         op.params[2].memref.size = outMemory.Get()->size;
162         Execute(CMD_GENERATE_KEY_PWD, &op);
163
164         sOut.Deserialize(outMemory);
165         sOut.Pull(pwdTag);
166
167         if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
168                 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
169         }
170 }
171
172 void TrustZoneContext::GenerateAKey(tz_command commandId,
173                                     TZSerializer &sIn,
174                                     uint32_t keySizeBits,
175                                     const RawBuffer &pubPwd,
176                                     const RawBuffer &pubPwdIv,
177                                     const RawBuffer &privPwd,
178                                     const RawBuffer &privPwdIv,
179                                     RawBuffer &pubKeyTag,
180                                     RawBuffer &privKeyTag,
181                                     const RawBuffer &hashPriv,
182                                                                         const RawBuffer &hashPub)
183 {
184         uint32_t pubTagSize = 0;
185         uint32_t privTagSize = 0;
186
187         uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
188         sIn.Push(new TZSerializableFlag(pubPwdExists));
189         if (pubPwdExists) {
190                 sIn.Push(new TZSerializablePwdData(pubPwd, pubPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
191                 pubTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
192         }
193         uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
194         sIn.Push(new TZSerializableFlag(privPwdExists));
195         if (privPwdExists) {
196                 sIn.Push(new TZSerializablePwdData(privPwd, privPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
197                 privTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
198         }
199         sIn.Push(new TZSerializableBinary(hashPriv));
200         sIn.Push(new TZSerializableBinary(hashPub));
201         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
202         sIn.Serialize(inMemory);
203
204         TZSerializer sOut;
205         sOut.Push(new TZSerializableBinary(pubTagSize));
206         sOut.Push(new TZSerializableBinary(privTagSize));
207
208         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
209
210         TEEC_Operation op;
211         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
212                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
213         op.params[0].value.b = keySizeBits;
214         op.params[1].memref.parent = inMemory.Get();
215         op.params[1].memref.offset = 0;
216         op.params[1].memref.size = inMemory.Get()->size;
217         op.params[2].memref.parent = outMemory.Get();
218         op.params[2].memref.offset = 0;
219         op.params[2].memref.size = outMemory.Get()->size;
220         Execute(commandId, &op);
221
222         sOut.Deserialize(outMemory);
223         if (pubPwdExists) {
224                 sOut.Pull(pubKeyTag);
225         }
226
227         if (privPwdExists) {
228                 sOut.Pull(privKeyTag);
229         }
230 }
231
232 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
233                                                                         const RawBuffer &pubPwd,
234                                                                         const RawBuffer &pubPwdIv,
235                                                                         const RawBuffer &privPwd,
236                                                                         const RawBuffer &privPwdIv,
237                                                                         RawBuffer &pubKeyTag,
238                                                                         RawBuffer &privKeyTag,
239                                                                         const RawBuffer &hashPriv,
240                                                                         const RawBuffer &hashPub)
241 {
242         // command ID = CMD_GENERATE_RSA_KEYPAIR
243         TZSerializer sIn;
244
245         GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
246                      sIn,
247                      keySizeBits,
248                      pubPwd,
249                      pubPwdIv,
250                      privPwd,
251                      privPwdIv,
252                      pubKeyTag,
253                      privKeyTag,
254                      hashPriv,
255                      hashPub);
256 }
257
258 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
259                                                                         const RawBuffer &prime,
260                                                                         const RawBuffer &subprime,
261                                                                         const RawBuffer &base,
262                                                                         const RawBuffer &pubPwd,
263                                                                         const RawBuffer &pubPwdIv,
264                                                                         const RawBuffer &privPwd,
265                                                                         const RawBuffer &privPwdIv,
266                                                                         RawBuffer &pubKeyTag,
267                                                                         RawBuffer &privKeyTag,
268                                                                         const RawBuffer &hashPriv,
269                                                                         const RawBuffer &hashPub)
270 {
271         // command ID = CMD_GENERATE_DSA_KEYPAIR
272         TZSerializer sIn;
273         sIn.Push(new TZSerializableBinary(prime));
274         sIn.Push(new TZSerializableBinary(subprime));
275         sIn.Push(new TZSerializableBinary(base));
276
277         GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
278                      sIn,
279                      keySizeBits,
280                      pubPwd,
281                      pubPwdIv,
282                      privPwd,
283                      privPwdIv,
284                      pubKeyTag,
285                      privKeyTag,
286                      hashPriv,
287                      hashPub);
288 }
289
290 void TrustZoneContext::executeCrypt(tz_command cmd,
291                                                                         tz_algo_type algo,
292                                                                         const RawBuffer &keyId,
293                                                                         const Pwd &pwd,
294                                                                         const RawBuffer &iv,
295                                                                         const RawBuffer &data,
296                                                                         RawBuffer &out)
297 {
298         // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
299         if (keyId.size() != KM_KEY_ID_SIZE) {
300                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
301                         + std::to_string(keyId.size()) + ")");
302         }
303
304         TZSerializer sIn;
305         sIn.Push(new TZSerializableBinary(data));
306         int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
307         sIn.Push(new TZSerializableFlag(pwd_flag));
308         if (pwd_flag)
309                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
310                                                                            pwd.getIV(),
311                                                                            pwd.getTag().size() * 8,
312                                                                            pwd.getTag()));
313         if (algo != ALGO_RSA)
314                 sIn.Push(new TZSerializableBinary(iv));
315         sIn.Push(new TZSerializableBinary(keyId));
316
317         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
318         sIn.Serialize(inMemory);
319
320         // decrypt operation does not require padding
321         uint32_t outMemorySize = data.size();
322         if (cmd == CMD_ENCRYPT) {
323                 if (algo == ALGO_RSA) {
324                         // We don't know the key length
325                         outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
326                 } else {
327                         outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
328                 }
329         }
330
331         TZSerializer sOut;
332         sOut.Push(new TZSerializableBinary(outMemorySize, false));
333         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
334
335         TEEC_Operation op;
336         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
337                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
338         op.params[0].value.a = algo;
339         op.params[1].memref.parent = inMemory.Get();
340         op.params[1].memref.offset = 0;
341         op.params[1].memref.size = inMemory.Get()->size;
342         op.params[2].memref.parent = outMemory.Get();
343         op.params[2].memref.offset = 0;
344         op.params[2].memref.size = outMemory.Get()->size;
345
346         Execute(cmd, &op);
347
348         sOut.Deserialize(outMemory);
349         sOut.Pull(out);
350 }
351
352 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
353                                                                                 const Pwd &pwd,
354                                                                                 const RawBuffer &iv,
355                                                                                 int tagSizeBits,
356                                                                                 const RawBuffer &aad,
357                                                                                 const RawBuffer &data,
358                                                                                 RawBuffer &out,
359                                                                                 RawBuffer &tag)
360 {
361         // command ID = CMD_ENCRYPT (from km_ta_defines.h)
362         if (keyId.size() != KM_KEY_ID_SIZE) {
363                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
364         }
365
366         TZSerializer sIn;
367         sIn.Push(new TZSerializableBinary(data));
368         int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
369         sIn.Push(new TZSerializableFlag(pwd_flag));
370         if (pwd_flag)
371                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
372                                                                            pwd.getIV(),
373                                                                            pwd.getTag().size() * 8,
374                                                                            pwd.getTag()));
375         sIn.Push(new TZSerializableBinary(iv));
376         sIn.Push(new TZSerializableBinary(keyId));
377         sIn.Push(new TZSerializableBinary(aad));
378         sIn.Push(new TZSerializableFlag(tagSizeBits));
379
380         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
381         sIn.Serialize(inMemory);
382
383         uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
384         uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
385
386         TZSerializer sOut;
387         sOut.Push(new TZSerializableBinary(outMemorySize, false));
388         sOut.Push(new TZSerializableBinary(tagSizeBytes));
389         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
390
391         TEEC_Operation op;
392         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
393                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
394         op.params[0].value.a = ALGO_AES_GCM;
395         op.params[1].memref.parent = inMemory.Get();
396         op.params[1].memref.offset = 0;
397         op.params[1].memref.size = inMemory.Get()->size;
398         op.params[2].memref.parent = outMemory.Get();
399         op.params[2].memref.offset = 0;
400         op.params[2].memref.size = outMemory.Get()->size;
401
402         Execute(CMD_ENCRYPT, &op);
403
404         sOut.Deserialize(outMemory);
405         sOut.Pull(out);
406         sOut.Pull(tag);
407 }
408
409 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
410                                                                                 const Pwd &pwd,
411                                                                                 const RawBuffer &iv,
412                                                                                 int  tagSizeBits,
413                                                                                 const RawBuffer &tag,
414                                                                                 const RawBuffer &aad,
415                                                                                 const RawBuffer &data,
416                                                                                 RawBuffer &out)
417 {
418         // command ID = CMD_DECRYPT (from km_ta_defines.h)
419         if (keyId.size() != KM_KEY_ID_SIZE) {
420                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
421         }
422
423         TZSerializer sIn;
424         sIn.Push(new TZSerializableBinary(data));
425         int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
426         sIn.Push(new TZSerializableFlag(pwd_flag));
427         if (pwd_flag)
428                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
429                                                                            pwd.getIV(),
430                                                                            pwd.getTag().size() * 8,
431                                                                            pwd.getTag()));
432         sIn.Push(new TZSerializableBinary(iv));
433         sIn.Push(new TZSerializableBinary(keyId));
434         sIn.Push(new TZSerializableBinary(aad));
435         sIn.Push(new TZSerializableFlag(tagSizeBits));
436         sIn.Push(new TZSerializableBinary(tag));
437
438         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
439         sIn.Serialize(inMemory);
440
441         TZSerializer sOut;
442         sOut.Push(new TZSerializableBinary(data.size()));
443         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
444
445         TEEC_Operation op;
446         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
447                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
448         op.params[0].value.a = ALGO_AES_GCM;
449         op.params[1].memref.parent = inMemory.Get();
450         op.params[1].memref.offset = 0;
451         op.params[1].memref.size = inMemory.Get()->size;
452         op.params[2].memref.parent = outMemory.Get();
453         op.params[2].memref.offset = 0;
454         op.params[2].memref.size = outMemory.Get()->size;
455
456         Execute(CMD_DECRYPT, &op);
457
458         sOut.Deserialize(outMemory);
459         sOut.Pull(out);
460 }
461
462 void TrustZoneContext::executeSign(tz_algo_type algo,
463                                                                 tz_hash_type hash,
464                                                                 const RawBuffer &keyId,
465                                                                 const Pwd &pwd,
466                                                                 const RawBuffer &message,
467                                                                 RawBuffer &signature)
468 {
469         // command ID = CMD_SIGN (from km_ta_defines.h)
470         if (keyId.size() != KM_KEY_ID_SIZE) {
471                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
472                         + std::to_string(keyId.size()) + ")");
473         }
474
475         TZSerializer sIn;
476         sIn.Push(new TZSerializableBinary(message));
477         int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
478         sIn.Push(new TZSerializableFlag(pwd_flag));
479         if (pwd_flag)
480                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
481                                                                            pwd.getIV(),
482                                                                            pwd.getTag().size() * 8,
483                                                                            pwd.getTag()));
484         sIn.Push(new TZSerializableBinary(keyId));
485         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
486         sIn.Serialize(inMemory);
487
488         TZSerializer sOut;
489         sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
490         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
491
492         TEEC_Operation op;
493         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
494                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
495         op.params[0].value.a = algo;
496         op.params[0].value.b = hash;
497         op.params[1].memref.parent = inMemory.Get();
498         op.params[1].memref.offset = 0;
499         op.params[1].memref.size = inMemory.Get()->size;
500         op.params[2].memref.parent = outMemory.Get();
501         op.params[2].memref.offset = 0;
502         op.params[2].memref.size = outMemory.Get()->size;
503         Execute(CMD_SIGN, &op);
504
505         sOut.Deserialize(outMemory);
506         sOut.Pull(signature);
507 }
508
509 int TrustZoneContext::executeVerify(tz_algo_type algo,
510                                                                         tz_hash_type hash,
511                                                                         const RawBuffer &keyId,
512                                                                         const Pwd &pwd,
513                                                                         const RawBuffer &message,
514                                                                         const RawBuffer &signature)
515 {
516         // command ID = CMD_VERIFY (from km_ta_defines.h)
517         if (keyId.size() != KM_KEY_ID_SIZE) {
518                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
519                         + std::to_string(keyId.size()) + ")");
520         }
521
522         TZSerializer sIn;
523         sIn.Push(new TZSerializableBinary(message));
524         sIn.Push(new TZSerializableBinary(signature));
525         int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
526         sIn.Push(new TZSerializableFlag(pwd_flag));
527         if (pwd_flag)
528                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
529                                                                            pwd.getIV(),
530                                                                            pwd.getTag().size() * 8,
531                                                                            pwd.getTag()));
532         sIn.Push(new TZSerializableBinary(keyId));
533         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
534         sIn.Serialize(inMemory);
535
536         TEEC_Operation op;
537         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
538                                                                         TEEC_NONE, TEEC_NONE);
539         op.params[0].value.a = algo;
540         op.params[0].value.b = hash;
541         op.params[1].memref.parent = inMemory.Get();
542         op.params[1].memref.offset = 0;
543         op.params[1].memref.size = inMemory.Get()->size;
544         Execute(CMD_VERIFY, &op);
545
546         int opRet = op.params[0].value.a;
547         switch (opRet) {
548         case KM_TA_SUCCESS:
549                 return CKM_API_SUCCESS;
550         case KM_TA_ERROR_SIGNATURE:
551                 LogWarning("Signature verification failed");
552                 return CKM_API_ERROR_VERIFICATION_FAILED;
553         default:
554                 assert(false); // This condition should be checked inside Execute() function
555                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
556         }
557 }
558
559 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
560 {
561         // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
562         if (keyId.size() != KM_KEY_ID_SIZE) {
563                 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
564         }
565
566         TZSerializer sIn;
567         sIn.Push(new TZSerializableBinary(keyId));
568         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
569         sIn.Serialize(inMemory);
570
571         TEEC_Operation op;
572         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
573                                                                         TEEC_NONE, TEEC_NONE);
574         op.params[1].memref.parent = inMemory.Get();
575         op.params[1].memref.offset = 0;
576         op.params[1].memref.size = inMemory.Get()->size;
577         Execute(CMD_DESTROY_KEY, &op);
578 }
579
580 void TrustZoneContext::importData(
581                                 const uint32_t dataType,
582                                 const RawBuffer &data,
583                                 const Crypto::EncryptionParams &encData,
584                                 const RawBuffer &pwd,
585                                 const RawBuffer &iv,
586                                 const uint32_t keySizeBits,
587                                 RawBuffer &pwdTag,
588                                 const RawBuffer &hash)
589 {
590         // command ID = CMD_IMPORT_DATA
591         LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
592         TZSerializer sIn;
593         sIn.Push(new TZSerializableFlag(dataType));
594         sIn.Push(new TZSerializableBinary(data));
595         sIn.Push(new TZSerializableFlag(keySizeBits));
596         sIn.Push(new TZSerializableBinary(encData.iv));
597         sIn.Push(new TZSerializableBinary(encData.tag));
598
599         uint32_t pwd_flag = pwd.empty() ? 0 : 1;
600         sIn.Push(new TZSerializableFlag(pwd_flag));
601         if (pwd_flag)
602                 sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
603
604         sIn.Push(new TZSerializableBinary(hash));
605
606         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
607         sIn.Serialize(inMemory);
608
609
610         TZSerializer sOut;
611         if (pwd_flag) {
612                 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
613         }
614
615         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
616
617         TEEC_Operation op;
618         if (pwd_flag) {
619                 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
620                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
621         }
622         else {
623                 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
624                                                                         TEEC_NONE, TEEC_NONE);
625         }
626
627         op.params[1].memref.parent = inMemory.Get();
628         op.params[1].memref.offset = 0;
629         op.params[1].memref.size = inMemory.Get()->size;
630         op.params[2].memref.parent = outMemory.Get();
631         op.params[2].memref.offset = 0;
632         op.params[2].memref.size = outMemory.Get()->size;
633
634         Execute(CMD_IMPORT_DATA, &op);
635
636         if (pwd_flag) {
637                 sOut.Deserialize(outMemory);
638                 sOut.Pull(pwdTag);
639         }
640
641         LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
642 }
643
644 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
645 {
646         // command ID = CMD_GET_DATA_SIZE
647         LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
648
649         TZSerializer sIn;
650         sIn.Push(new TZSerializableBinary(dataId));
651
652         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
653         sIn.Serialize(inMemory);
654
655         TEEC_Operation op;
656         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
657                                                                         TEEC_NONE, TEEC_NONE);
658
659         op.params[1].memref.parent = inMemory.Get();
660         op.params[1].memref.offset = 0;
661         op.params[1].memref.size = inMemory.Get()->size;
662         Execute(CMD_GET_DATA_SIZE, &op);
663         dataSize = op.params[0].value.b;
664 }
665
666 void TrustZoneContext::getData(const RawBuffer &dataId,
667                          const Pwd &pwd,
668                          RawBuffer &data)
669 {
670         // command ID = CMD_GET_DATA
671         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
672
673         TZSerializer sIn;
674         sIn.Push(new TZSerializableBinary(dataId));
675
676         uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
677         sIn.Push(new TZSerializableFlag(pwd_flag));
678
679         if (pwd_flag) {
680                 sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
681                                                   pwd.getIV(),
682                                                   Params::DEFAULT_AES_GCM_TAG_LEN_BITS,
683                                                   pwd.getTag()));
684         }
685
686         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
687         sIn.Serialize(inMemory);
688
689         uint32_t data_size = 0;
690         GetDataSize(dataId, data_size);
691
692         LogDebug("GetData data_size = [" << data_size << "]");
693
694         TZSerializer sOut;
695         sOut.Push(new TZSerializableBinary(data_size));
696         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
697         sOut.Serialize(outMemory);
698
699         TEEC_Operation op;
700         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
701                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
702         op.params[1].memref.parent = inMemory.Get();
703         op.params[1].memref.offset = 0;
704         op.params[1].memref.size = inMemory.Get()->size;
705         op.params[2].memref.parent = outMemory.Get();
706         op.params[2].memref.offset = 0;
707         op.params[2].memref.size = outMemory.Get()->size;
708
709         Execute(CMD_GET_DATA, &op);
710
711         sOut.Deserialize(outMemory);
712         sOut.Pull(data);
713 }
714
715
716 void TrustZoneContext::destroyData(const RawBuffer &dataId)
717 {
718         //      command ID = CMD_DESTROY_DATA
719         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
720         TZSerializer sIn;
721         sIn.Push(new TZSerializableBinary(dataId));
722
723         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
724         sIn.Serialize(inMemory);
725
726         TEEC_Operation op;
727         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
728                                                                         TEEC_NONE, TEEC_NONE);
729
730         op.params[1].memref.parent = inMemory.Get();
731         op.params[1].memref.offset = 0;
732         op.params[1].memref.size = inMemory.Get()->size;
733         Execute(CMD_DESTROY_DATA, &op);
734 }
735
736 void TrustZoneContext::Initialize()
737 {
738         TEEC_Operation op;
739         TEEC_Result result;
740         uint32_t retOrigin;
741
742         op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
743
744         result = TEEC_InitializeContext(nullptr, &m_Context);
745         if (result != TEEC_SUCCESS) {
746                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
747         }
748         m_ContextInitialized = true;
749
750         result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
751         if (result != TEEC_SUCCESS) {
752                 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
753         }
754         m_SessionInitialized = true;
755 }
756
757 void TrustZoneContext::Destroy()
758 {
759         if (m_SessionInitialized) {
760                 TEEC_CloseSession(&m_Session);
761                 m_SessionInitialized = false;
762         }
763
764         if (m_ContextInitialized) {
765                 TEEC_FinalizeContext(&m_Context);
766                 m_ContextInitialized = false;
767         }
768 }
769
770 void TrustZoneContext::Reload()
771 {
772         Destroy();
773         Initialize();
774 }
775
776 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
777 {
778         uint32_t retOrigin = 0;
779         LogDebug("Executing TZ operation " << commandID);
780
781         TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
782         if (result != TEEC_SUCCESS) {
783                 switch (result) {
784                 case TEEC_ERROR_TARGET_DEAD:
785                         Reload();
786                         ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
787                                         static_cast<unsigned int>(commandID));
788                 case TEEC_ERROR_BAD_PARAMETERS:
789                         ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
790                 default:
791                         ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
792                                         static_cast<unsigned int>(commandID), " with error: ", std::hex,
793                                         static_cast<unsigned int>(result), " with origin: ", std::hex,
794                                         retOrigin);
795                 }
796         }
797
798         int ta_ret = op->params[0].value.a;
799         switch (ta_ret) {
800         case KM_TA_SUCCESS:
801         case KM_TA_ERROR_SIGNATURE:
802                 break;
803         case KM_TA_ERROR_AUTH_FAILED:
804                 // Authentication cipher failed - notify with proper exception
805                 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
806         default:
807                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
808         }
809 }
810
811 } // namespace Internals
812 } // namespace TZ
813 } // namespace Crypto
814 } // namespace CKM