Use fixed object ID in TZ backend
[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                                 const uint32_t pwdTagSizeBits,
588                                 RawBuffer &pwdTag,
589                                 const RawBuffer &hash)
590 {
591         // command ID = CMD_IMPORT_DATA
592         LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
593         TZSerializer sIn;
594         sIn.Push(new TZSerializableFlag(dataType));
595         sIn.Push(new TZSerializableBinary(data));
596         sIn.Push(new TZSerializableFlag(keySizeBits));
597         sIn.Push(new TZSerializableBinary(encData.iv));
598         sIn.Push(new TZSerializableBinary(encData.tag));
599
600         uint32_t pwd_flag = pwd.empty() ? 0 : 1;
601         sIn.Push(new TZSerializableFlag(pwd_flag));
602         if (pwd_flag)
603                 sIn.Push(new TZSerializablePwdData(pwd, iv, pwdTagSizeBits));
604
605         sIn.Push(new TZSerializableBinary(hash));
606
607         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
608         sIn.Serialize(inMemory);
609
610
611         TZSerializer sOut;
612         if (pwd_flag) {
613                 sOut.Push(new TZSerializableBinary(pwdTagSizeBits / 8));
614         }
615
616         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
617
618         TEEC_Operation op;
619         if (pwd_flag) {
620                 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
621                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
622         }
623         else {
624                 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
625                                                                         TEEC_NONE, TEEC_NONE);
626         }
627
628         op.params[1].memref.parent = inMemory.Get();
629         op.params[1].memref.offset = 0;
630         op.params[1].memref.size = inMemory.Get()->size;
631         op.params[2].memref.parent = outMemory.Get();
632         op.params[2].memref.offset = 0;
633         op.params[2].memref.size = outMemory.Get()->size;
634
635         Execute(CMD_IMPORT_DATA, &op);
636
637         if (pwd_flag) {
638                 sOut.Deserialize(outMemory);
639                 sOut.Pull(pwdTag);
640         }
641
642         LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
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         LogDebug("GetData data_size = [" << data_size << "]");
694
695         TZSerializer sOut;
696         sOut.Push(new TZSerializableBinary(data_size));
697         TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
698         sOut.Serialize(outMemory);
699
700         TEEC_Operation op;
701         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
702                                                                         TEEC_MEMREF_WHOLE, TEEC_NONE);
703         op.params[1].memref.parent = inMemory.Get();
704         op.params[1].memref.offset = 0;
705         op.params[1].memref.size = inMemory.Get()->size;
706         op.params[2].memref.parent = outMemory.Get();
707         op.params[2].memref.offset = 0;
708         op.params[2].memref.size = outMemory.Get()->size;
709
710         Execute(CMD_GET_DATA, &op);
711
712         sOut.Deserialize(outMemory);
713         sOut.Pull(data);
714 }
715
716
717 void TrustZoneContext::destroyData(const RawBuffer &dataId)
718 {
719         //      command ID = CMD_DESTROY_DATA
720         LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
721         TZSerializer sIn;
722         sIn.Push(new TZSerializableBinary(dataId));
723
724         TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
725         sIn.Serialize(inMemory);
726
727         TEEC_Operation op;
728         op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
729                                                                         TEEC_NONE, TEEC_NONE);
730
731         op.params[1].memref.parent = inMemory.Get();
732         op.params[1].memref.offset = 0;
733         op.params[1].memref.size = inMemory.Get()->size;
734         Execute(CMD_DESTROY_DATA, &op);
735 }
736
737 void TrustZoneContext::Initialize()
738 {
739         TEEC_Operation op;
740         TEEC_Result result;
741         uint32_t retOrigin;
742
743         op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
744
745         result = TEEC_InitializeContext(nullptr, &m_Context);
746         if (result != TEEC_SUCCESS) {
747                 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
748         }
749         m_ContextInitialized = true;
750
751         result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
752         if (result != TEEC_SUCCESS) {
753                 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
754         }
755         m_SessionInitialized = true;
756 }
757
758 void TrustZoneContext::Destroy()
759 {
760         if (m_SessionInitialized) {
761                 TEEC_CloseSession(&m_Session);
762                 m_SessionInitialized = false;
763         }
764
765         if (m_ContextInitialized) {
766                 TEEC_FinalizeContext(&m_Context);
767                 m_ContextInitialized = false;
768         }
769 }
770
771 void TrustZoneContext::Reload()
772 {
773         Destroy();
774         Initialize();
775 }
776
777 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
778 {
779         uint32_t retOrigin = 0;
780         LogDebug("Executing TZ operation " << commandID);
781
782         TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
783         if (result != TEEC_SUCCESS) {
784                 switch (result) {
785                 case TEEC_ERROR_TARGET_DEAD:
786                         Reload();
787                         ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
788                                         static_cast<unsigned int>(commandID));
789                 case TEEC_ERROR_BAD_PARAMETERS:
790                         ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
791                 default:
792                         ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
793                                         static_cast<unsigned int>(commandID), " with error: ", std::hex,
794                                         static_cast<unsigned int>(result), " with origin: ", std::hex,
795                                         retOrigin);
796                 }
797         }
798
799         int ta_ret = op->params[0].value.a;
800         switch (ta_ret) {
801         case KM_TA_SUCCESS:
802         case KM_TA_ERROR_SIGNATURE:
803                 break;
804         case KM_TA_ERROR_AUTH_FAILED:
805                 // Authentication cipher failed - notify with proper exception
806                 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
807         default:
808                 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
809         }
810 }
811
812 } // namespace Internals
813 } // namespace TZ
814 } // namespace Crypto
815 } // namespace CKM