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