2 * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 * @file tz-context.cpp
18 * @author Lukasz Kostyra (l.kostyra@samsung.com)
22 #include <tz-backend/tz-context.h>
23 #include <tz-backend/tz-memory.h>
24 #include <generic-backend/exception.h>
25 #include <generic-backend/crypto-params.h>
26 #include <dpl/log/log.h>
28 #include <km_serialization.h>
29 #include <km_ta_defines.h>
41 // A little bit of extra memory to add to output buffers.
43 // We need this extra memory to output for padding purposes - after encryption
44 // we can resize the result memory back to its proper size according to
45 // whatever TA will return us.
46 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
48 // Identifier of our TA
49 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
51 //raw to hex string conversion to print persistent storage data ID
52 static std::string rawToHexString(const RawBuffer &raw)
58 snprintf(buf, sizeof(buf), "%02x", (e & 0xff));
59 dump.push_back(buf[0]);
60 dump.push_back(buf[1]);
66 } // anonymous namespace
68 TrustZoneContext::TrustZoneContext()
69 : m_ContextInitialized(false)
70 , m_SessionInitialized(false)
75 TrustZoneContext::~TrustZoneContext()
80 TrustZoneContext& TrustZoneContext::Instance()
82 static TrustZoneContext instance;
86 void TrustZoneContext::generateIV(RawBuffer& iv)
88 // command ID = CMD_GENERATE_IV
90 // TEEC_Operation layout:
92 // [1].memref.buffer - output
93 // [1].memref.size - output size
95 // [0].value.a - return code
97 // IV generation is a simple call - no need to serialize data
98 // just provide the output buffer with size equal to iv.
99 uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
100 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
103 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
104 TEEC_NONE, TEEC_NONE);
105 op.params[1].memref.parent = ivMemory.Get();
106 op.params[1].memref.offset = 0;
107 op.params[1].memref.size = ivMemory.Get()->size;
108 Execute(CMD_GENERATE_IV, &op);
111 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
114 void TrustZoneContext::generateSKey(tz_algo_type algo,
115 uint32_t keySizeBits,
118 // command ID = CMD_GENERATE_KEY
120 // TEEC_Operation layout:
122 // [0].value.a - key type
123 // [0].value.b - key bit size
125 // [0].value.a - return code
126 // [1].memref - serialized key reference
128 KM_BufferSizeDesc bufSize;
130 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
131 bufSize.out_size = KM_KEY_ID_SIZE;
132 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
133 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
136 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
137 TEEC_NONE, TEEC_NONE);
138 op.params[0].value.a = algo;
139 op.params[0].value.b = keySizeBits;
140 op.params[1].memref.parent = keyMemory.Get();
141 op.params[1].memref.offset = 0;
142 op.params[1].memref.size = keyMemorySize;
143 Execute(CMD_GENERATE_KEY, &op);
145 KM_SymmetricInput* output = nullptr;
146 int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
148 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
151 KM_OutData* outData = nullptr;
152 ret = KM_ParamsDeserializeOutData(output, &outData);
154 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
157 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
158 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
161 keyId.resize(KM_KEY_ID_SIZE);
162 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
165 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
166 const RawBuffer &pwd,
168 const uint32_t keySizeBits,
172 // command ID = CMD_GENERATE_KEY_PWD
174 // TEEC_Operation layout:
176 // [0].value.a - key type
177 // [0].value.b - key size in bits
178 // [1].memref - input (seralized pwd/iv for pbkdf2)
180 // [0].value.a - return code
181 // [2].memref - serialized key reference ID
183 KM_BufferSizeDesc bufSize;
185 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
186 bufSize.with_pwd_data = true;
187 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
188 bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
189 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
190 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
192 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
193 bufSize.out_size = KM_KEY_ID_SIZE;
194 bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
195 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
196 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
198 KM_SymmetricInput* input = nullptr;
199 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
201 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
204 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
205 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
206 Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
208 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
212 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
213 TEEC_MEMREF_WHOLE, TEEC_NONE);
214 op.params[0].value.a = algo;
215 op.params[0].value.b = keySizeBits;
216 op.params[1].memref.parent = inMemory.Get();
217 op.params[1].memref.offset = 0;
218 op.params[1].memref.size = inMemory.Get()->size;
219 op.params[2].memref.parent = keyMemory.Get();
220 op.params[2].memref.offset = 0;
221 op.params[2].memref.size = keyMemory.Get()->size;
222 Execute(CMD_GENERATE_KEY_PWD, &op);
224 KM_SymmetricInput* output = nullptr;
225 ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
227 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
230 KM_OutData* outData = nullptr;
231 ret = KM_ParamsDeserializeOutData(output, &outData);
233 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
236 KM_TagData* tagData = nullptr;
237 ret = KM_ParamsDeserializeTagData(output, &tagData);
239 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
242 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
243 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
246 if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
247 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
250 keyId.resize(KM_KEY_ID_SIZE);
251 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
253 pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
254 memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
258 void TrustZoneContext::importKey(tz_algo_type algo,
259 const RawBuffer &key,
260 const RawBuffer &encIV,
261 const RawBuffer &pwd,
262 const RawBuffer &pwdIV,
267 // command ID = CMD_IMPORT_KEY
269 // TEEC_Operation layout:
271 // [0].value.a - key type
272 // [0].value.b - key size in bits
273 // [1].memref - seralized key & password data
275 // [0].value.a - return code
276 // [2].memref - serialized key reference ID
278 KM_BufferSizeDesc bufSize;
280 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
281 bufSize.input_size = static_cast<uint32_t>(key.size());
283 bufSize.with_pwd_data = true;
284 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
285 bufSize.pwd_iv_size = static_cast<uint32_t>(pwdIV.size());
287 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
288 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
290 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
291 bufSize.out_size = KM_KEY_ID_SIZE;
292 bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
293 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
294 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
296 KM_SymmetricInput* input = nullptr;
297 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
299 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for key import: ", ret);
302 ret = KM_ParamsSerializeInputData(input, key.data(), key.size());
304 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key to import: ", ret);
308 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), pwdIV.data(), pwdIV.size(),
309 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
310 Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
312 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key data for import: ", ret);
317 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
318 TEEC_MEMREF_WHOLE, TEEC_NONE);
319 op.params[0].value.a = algo;
320 op.params[0].value.b = key.size() * 8;
321 op.params[1].memref.parent = inMemory.Get();
322 op.params[1].memref.offset = 0;
323 op.params[1].memref.size = inMemory.Get()->size;
324 op.params[2].memref.parent = keyMemory.Get();
325 op.params[2].memref.offset = 0;
326 op.params[2].memref.size = keyMemory.Get()->size;
327 Execute(CMD_IMPORT_KEY, &op);
329 KM_SymmetricInput* output = nullptr;
330 ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
332 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for imported key ID");
335 KM_OutData* outData = nullptr;
336 ret = KM_ParamsDeserializeOutData(output, &outData);
338 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key ID");
341 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
342 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
345 keyId.resize(KM_KEY_ID_SIZE);
346 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
349 KM_TagData* tagData = nullptr;
351 ret = KM_ParamsDeserializeTagData(output, &tagData);
353 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key's tag");
356 if (tagData == nullptr || tagData->data_size != bufSize.tag_size) {
357 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
360 pwdTag.resize(bufSize.tag_size);
361 memcpy(pwdTag.data(), tagData->data, bufSize.tag_size);
365 void TrustZoneContext::executeCrypt(tz_command cmd,
367 const RawBuffer &key,
370 const RawBuffer &data,
373 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
375 // TEEC_Operation layout:
377 // [0].value.a - keyid
378 // [0].value.b - algo
379 // [1].memref - input data (serialized key/input)
381 // [0].value.a - return code
382 // [2].memref - serialized output buffer
384 if (key.size() != KM_KEY_ID_SIZE) {
385 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
386 + std::to_string(key.size()) + ")");
389 KM_BufferSizeDesc bufSize;
391 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
392 bufSize.input_size = static_cast<uint32_t>(data.size());
393 bufSize.with_pwd_data = true;
394 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
395 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
396 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
397 bufSize.iv_size = static_cast<uint32_t>(iv.size());
398 bufSize.key_id_size = static_cast<uint32_t>(key.size());
399 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
400 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
402 // decrypt operation does not require padding
403 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
404 bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
405 data.size() + CIPHER_EXTRA_PADDING_SIZE :
407 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
408 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
410 KM_SymmetricInput* input = nullptr;
411 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
413 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
416 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
418 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
421 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
422 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
423 pwd.getIV().data(), pwd.getIV().size(),
424 pwd.getTag().data(), pwd.getTag().size(),
425 Params::DERIVED_KEY_LENGTH_BITS,
426 Params::DERIVED_KEY_ITERATIONS,
429 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
432 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
434 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
437 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
439 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
443 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
444 TEEC_MEMREF_WHOLE, TEEC_NONE);
445 op.params[0].value.a = algo;
446 op.params[1].memref.parent = inMemory.Get();
447 op.params[1].memref.offset = 0;
448 op.params[1].memref.size = inMemory.Get()->size;
449 op.params[2].memref.parent = outMemory.Get();
450 op.params[2].memref.offset = 0;
451 op.params[2].memref.size = outMemory.Get()->size;
454 KM_SymmetricInput* output = nullptr;
455 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
457 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
460 KM_OutData* outData = nullptr;
461 ret = KM_ParamsDeserializeOutData(output, &outData);
463 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
466 // data_size should contain how much memory we actually took for our cipher operation
467 out.resize(outData->data_size);
468 memcpy(out.data(), outData->data, outData->data_size);
471 void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
475 const RawBuffer &aad,
476 const RawBuffer &data,
480 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
482 // TEEC_Operation layout:
484 // [0].value.a - keyid
485 // [0].value.b - algo
486 // [1].memref - input data (serialized key/input/iv/aad)
488 // [0].value.a - return code
489 // [2].memref - output
491 if (key.size() != KM_KEY_ID_SIZE) {
492 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
495 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
496 KM_BufferSizeDesc bufSize;
498 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
499 bufSize.input_size = static_cast<uint32_t>(data.size());
500 bufSize.with_pwd_data = true;
501 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
502 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
503 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
504 bufSize.iv_size = static_cast<uint32_t>(iv.size());
505 bufSize.key_id_size = static_cast<uint32_t>(key.size());
506 bufSize.with_ae_data = true;
507 bufSize.aad_size = static_cast<uint32_t>(aad.size());
508 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
509 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
511 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
512 bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
513 bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
514 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
515 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
517 KM_SymmetricInput* input = nullptr;
518 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
520 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
523 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
525 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
528 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
529 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
530 pwd.getIV().data(), pwd.getIV().size(),
531 pwd.getTag().data(), pwd.getTag().size(),
532 Params::DERIVED_KEY_LENGTH_BITS,
533 Params::DERIVED_KEY_ITERATIONS,
536 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
539 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
541 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
544 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
546 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
549 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
551 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
555 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
556 TEEC_MEMREF_WHOLE, TEEC_NONE);
557 op.params[0].value.a = ALGO_AES_GCM;
558 op.params[1].memref.parent = inMemory.Get();
559 op.params[1].memref.offset = 0;
560 op.params[1].memref.size = inMemory.Get()->size;
561 op.params[2].memref.parent = outMemory.Get();
562 op.params[2].memref.offset = 0;
563 op.params[2].memref.size = outMemory.Get()->size;
564 Execute(CMD_ENCRYPT, &op);
566 KM_SymmetricInput* output = nullptr;
567 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
569 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
572 KM_OutData* outData = nullptr;
573 ret = KM_ParamsDeserializeOutData(output, &outData);
575 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
578 KM_TagData* tagData = nullptr;
579 ret = KM_ParamsDeserializeTagData(output, &tagData);
581 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
584 out.resize(outData->data_size);
585 memcpy(out.data(), outData->data, outData->data_size);
587 if (tagData->data_size) {
588 tag.resize(tagData->data_size);
589 memcpy(tag.data(), tagData->data, tagData->data_size);
593 void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
597 const RawBuffer &tag,
598 const RawBuffer &aad,
599 const RawBuffer &data,
602 // command ID = CMD_DECRYPT (from km_ta_defines.h)
604 // TEEC_Operation layout:
606 // [0].value.a - keyid
607 // [0].value.b - algo
608 // [1].memref - input data (serialized key/input/iv/tag/aad)
610 // [0].value.a - output size
611 // [2].memref - output (decrypted data)
613 if (key.size() != KM_KEY_ID_SIZE) {
614 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
617 KM_BufferSizeDesc bufSize;
619 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
620 bufSize.input_size = static_cast<uint32_t>(data.size());
621 bufSize.with_pwd_data = true;
622 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
623 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
624 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
625 bufSize.iv_size = static_cast<uint32_t>(iv.size());
626 bufSize.key_id_size = static_cast<uint32_t>(key.size());
627 bufSize.with_ae_data = true;
628 bufSize.aad_size = static_cast<uint32_t>(aad.size());
629 bufSize.tag_size = static_cast<uint32_t>(tag.size());
630 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
631 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
633 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
634 bufSize.out_size = static_cast<uint32_t>(data.size());
635 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
636 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
638 KM_SymmetricInput* input = nullptr;
639 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
641 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
644 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
646 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
649 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
650 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
651 pwd.getIV().data(), pwd.getIV().size(),
652 pwd.getTag().data(), pwd.getTag().size(),
653 Params::DERIVED_KEY_LENGTH_BITS,
654 Params::DERIVED_KEY_ITERATIONS,
657 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
660 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
662 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
665 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
667 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
670 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
672 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
675 ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
677 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
681 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
682 TEEC_MEMREF_WHOLE, TEEC_NONE);
683 op.params[0].value.a = ALGO_AES_GCM;
684 op.params[1].memref.parent = inMemory.Get();
685 op.params[1].memref.offset = 0;
686 op.params[1].memref.size = inMemory.Get()->size;
687 op.params[2].memref.parent = outMemory.Get();
688 op.params[2].memref.offset = 0;
689 op.params[2].memref.size = outMemory.Get()->size;
690 Execute(CMD_DECRYPT, &op);
692 KM_SymmetricInput* output = nullptr;
693 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
695 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
698 KM_OutData* outData = nullptr;
699 ret = KM_ParamsDeserializeOutData(output, &outData);
701 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
704 out.resize(outData->data_size);
705 memcpy(out.data(), outData->data, outData->data_size);
708 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
710 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
712 // TEEC_Operation layout:
714 // [1].memref - input data (serialized key ID)
716 // [0].value.a - return code
718 if (keyId.size() != KM_KEY_ID_SIZE) {
719 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
722 KM_BufferSizeDesc bufSize;
724 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
725 bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
726 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
727 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
729 KM_SymmetricInput* input = nullptr;
730 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
732 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
735 ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
737 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
741 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
742 TEEC_NONE, TEEC_NONE);
743 op.params[1].memref.parent = inMemory.Get();
744 op.params[1].memref.offset = 0;
745 op.params[1].memref.size = inMemory.Get()->size;
746 Execute(CMD_DESTROY_KEY, &op);
749 void TrustZoneContext::importData(const RawBuffer &data,
750 const RawBuffer &pwd,
755 // command ID = CMD_IMPORT_DATA
757 // [1].memref - reference to serialized buffer:
758 // KM_BinaryData with binary data
759 // uint32_t boolean value - true if password is provided
760 // KM_PwdData with password (optional)
762 // [0].value.a - return code
763 // [2].memref - reference to serialized buffer:
764 // KM_BinaryData with data id
765 // KM_BinaryData with tag id (optional, if password was provided)
766 KM_BinaryData kmTaData;
767 uint32_t pwd_flag = pwd.empty() ? 0 : 1;
768 uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
769 kmTaData.data_size = static_cast<uint32_t>(data.size());
770 kmTaData.data = const_cast<unsigned char *>(data.data());
771 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmTaData) + KM_SizeOfFlag();
772 KM_PwdData kmPwdData;
774 memset(&kmPwdData, 0, sizeof(KM_PwdData));
775 kmPwdData.pwd = const_cast<unsigned char *>(pwd.data());
776 kmPwdData.pwd_size = pwd.size();
777 kmPwdData.iv = const_cast<unsigned char *>(iv.data());
778 kmPwdData.iv_size = iv.size();
779 kmPwdData.tag = NULL;
780 kmPwdData.tag_size = 0;
781 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
782 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
783 kmPwdData.tag_len_bits = pwdTagSizeBits;
785 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
788 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
789 void *inMemoryPtr = inMemory.Get()->buffer;
791 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmTaData);
793 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
795 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
797 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
800 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
802 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
806 KM_BinaryData kmDataId;
808 memset(&kmDataId, 0, sizeof(KM_BinaryData));
809 memset(&kmTag, 0, sizeof(KM_BinaryData));
810 kmDataId.data_size = KM_DATA_ID_SIZE;
811 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmDataId);
813 kmTag.data_size = pwdTagSizeBits / 8;
814 outMemorySize += KM_SizeOfBinaryData(&kmTag);
817 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
818 void *outMemoryPtr = outMemory.Get()->buffer;
821 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
822 TEEC_MEMREF_WHOLE, TEEC_NONE);
823 op.params[1].memref.parent = inMemory.Get();
824 op.params[1].memref.offset = 0;
825 op.params[1].memref.size = inMemory.Get()->size;
826 op.params[2].memref.parent = outMemory.Get();
827 op.params[2].memref.offset = 0;
828 op.params[2].memref.size = outMemory.Get()->size;
830 Execute(CMD_IMPORT_DATA, &op);
832 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmDataId);
834 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
836 dataId.resize(kmDataId.data_size);
837 memcpy(dataId.data(), kmDataId.data, kmDataId.data_size);
839 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmTag);
841 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
843 pwdTag.resize(kmTag.data_size);
844 memcpy(pwdTag.data(), kmTag.data, kmTag.data_size);
847 LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
850 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
852 // command ID = CMD_GET_DATA_SIZE
853 // TA will decrypt data with password if provided
855 // [1].memref - reference to serialized buffer:
856 // KM_BinaryData with object ID
858 // [0].value.a - return code
859 // [0].value.b - size of buffer to be passed from CA
860 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
861 KM_BinaryData kmDataId;
862 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
863 kmDataId.data = const_cast<unsigned char *>(dataId.data());
864 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
865 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
866 void *inMemoryPtr = inMemory.Get()->buffer;
867 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
869 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
872 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
873 TEEC_NONE, TEEC_NONE);
875 op.params[1].memref.parent = inMemory.Get();
876 op.params[1].memref.offset = 0;
877 op.params[1].memref.size = inMemory.Get()->size;
878 Execute(CMD_GET_DATA_SIZE, &op);
879 dataSize = op.params[0].value.b;
882 void TrustZoneContext::getData(const RawBuffer &dataId,
886 // command ID = CMD_GET_DATA
887 // TA will decrypt data with password if provided
889 // [1].memref - reference to serialized buffer:
890 // KM_BinaryData with object ID
891 // uint32_t boolean value - true if password is provided
892 // KM_PwdData with password (optional)
894 // [0].value.a - return code
895 // [2].memref - reference to serialized buffer:
896 // KM_BinaryData with binary data
897 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
898 uint32_t data_size = 0;
899 GetDataSize(dataId, data_size);
901 KM_BinaryData kmDataId;
902 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
903 kmDataId.data = const_cast<unsigned char *>(dataId.data());
904 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId) + KM_SizeOfFlag();
905 uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
906 uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
908 KM_PwdData kmPwdData;
910 memset(&kmPwdData, 0, sizeof(KM_PwdData));
911 kmPwdData.pwd = const_cast<unsigned char *>(pwd.getPassword().data());
912 kmPwdData.pwd_size = pwd.getPassword().size();
913 kmPwdData.iv = const_cast<unsigned char *>(pwd.getIV().data());
914 kmPwdData.iv_size = pwd.getIV().size();
915 kmPwdData.tag = const_cast<unsigned char *>(pwd.getTag().data());
916 kmPwdData.tag_size = pwd.getTag().size();
917 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
918 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
919 kmPwdData.tag_len_bits = pwdTagSizeBits;
921 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
924 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
925 void *inMemoryPtr = inMemory.Get()->buffer;
927 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
929 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
931 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
933 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
936 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
938 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
942 KM_BinaryData kmExtractedData;
943 memset(&kmExtractedData, 0, sizeof(KM_BinaryData));
944 kmExtractedData.data_size = data_size;
946 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmExtractedData);
947 uint32_t outMemorySize2 = outMemorySize;
949 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
950 void *outMemoryPtr = outMemory.Get()->buffer;
951 void *outMemoryPtr2 = outMemory.Get()->buffer;
953 // requesting size is saved in this buffer
954 ret = KM_SerializeBinaryData(&outMemoryPtr2, &outMemorySize2, &kmExtractedData);
956 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
960 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
961 TEEC_MEMREF_WHOLE, TEEC_NONE);
962 op.params[1].memref.parent = inMemory.Get();
963 op.params[1].memref.offset = 0;
964 op.params[1].memref.size = inMemory.Get()->size;
965 op.params[2].memref.parent = outMemory.Get();
966 op.params[2].memref.offset = 0;
967 op.params[2].memref.size = outMemory.Get()->size;
969 Execute(CMD_GET_DATA, &op);
971 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmExtractedData);
973 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
976 data.resize(kmExtractedData.data_size);
977 memcpy(data.data(), kmExtractedData.data, kmExtractedData.data_size);
981 void TrustZoneContext::destroyData(const RawBuffer &dataId)
983 // command ID = CMD_DESTROY_DATA
984 // TEEC_Operation parameters layout:
986 // [1].memref - reference to serialized buffer:
987 // KM_BinaryData with object ID
989 // [0].value.a - return code
990 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
991 KM_BinaryData kmDataId;
992 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
993 kmDataId.data = const_cast<unsigned char *>(dataId.data());
994 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
995 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
996 void *inMemoryPtr = inMemory.Get()->buffer;
998 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
1001 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
1005 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
1006 TEEC_NONE, TEEC_NONE);
1008 op.params[1].memref.parent = inMemory.Get();
1009 op.params[1].memref.offset = 0;
1010 op.params[1].memref.size = inMemory.Get()->size;
1011 Execute(CMD_DESTROY_DATA, &op);
1014 void TrustZoneContext::Initialize()
1020 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1022 result = TEEC_InitializeContext(nullptr, &m_Context);
1023 if (result != TEEC_SUCCESS) {
1024 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
1026 m_ContextInitialized = true;
1028 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
1029 if (result != TEEC_SUCCESS) {
1030 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
1032 m_SessionInitialized = true;
1035 void TrustZoneContext::Destroy()
1037 if (m_SessionInitialized) {
1038 TEEC_CloseSession(&m_Session);
1039 m_SessionInitialized = false;
1042 if (m_ContextInitialized) {
1043 TEEC_FinalizeContext(&m_Context);
1044 m_ContextInitialized = false;
1048 void TrustZoneContext::Reload()
1054 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1056 LogDebug("Executing TZ operation " << commandID);
1058 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, NULL);
1059 if (result != TEEC_SUCCESS) {
1061 case TEEC_ERROR_TARGET_DEAD:
1063 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1064 static_cast<unsigned int>(commandID));
1065 case TEEC_ERROR_BAD_PARAMETERS:
1066 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1068 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1069 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1070 static_cast<unsigned int>(result));
1074 int ta_ret = op->params[0].value.a;
1075 if (ta_ret != KM_TA_SUCCESS) {
1077 case KM_TA_ERROR_AUTH_FAILED:
1078 // Authentication cipher failed - notify with proper exception
1079 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1081 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1086 } // namespace Internals
1088 } // namespace Crypto