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);
257 void TrustZoneContext::executeCrypt(tz_command cmd,
259 const RawBuffer &key,
262 const RawBuffer &data,
265 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
267 // TEEC_Operation layout:
269 // [0].value.a - keyid
270 // [0].value.b - algo
271 // [1].memref - input data (serialized key/input)
273 // [0].value.a - return code
274 // [2].memref - serialized output buffer
276 if (key.size() != KM_KEY_ID_SIZE) {
277 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
278 + std::to_string(key.size()) + ")");
281 KM_BufferSizeDesc bufSize;
283 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
284 bufSize.input_size = static_cast<uint32_t>(data.size());
285 bufSize.with_pwd_data = true;
286 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
287 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
288 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
289 bufSize.iv_size = static_cast<uint32_t>(iv.size());
290 bufSize.key_id_size = static_cast<uint32_t>(key.size());
291 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
292 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
294 // decrypt operation does not require padding
295 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
296 bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
297 data.size() + CIPHER_EXTRA_PADDING_SIZE :
299 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
300 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
302 KM_SymmetricInput* input = nullptr;
303 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
305 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
308 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
310 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
313 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
314 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
315 pwd.getIV().data(), pwd.getIV().size(),
316 pwd.getTag().data(), pwd.getTag().size(),
317 Params::DERIVED_KEY_LENGTH_BITS,
318 Params::DERIVED_KEY_ITERATIONS,
321 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
324 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
326 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
329 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
331 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
335 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
336 TEEC_MEMREF_WHOLE, TEEC_NONE);
337 op.params[0].value.a = algo;
338 op.params[1].memref.parent = inMemory.Get();
339 op.params[1].memref.offset = 0;
340 op.params[1].memref.size = inMemory.Get()->size;
341 op.params[2].memref.parent = outMemory.Get();
342 op.params[2].memref.offset = 0;
343 op.params[2].memref.size = outMemory.Get()->size;
346 KM_SymmetricInput* output = nullptr;
347 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
349 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
352 KM_OutData* outData = nullptr;
353 ret = KM_ParamsDeserializeOutData(output, &outData);
355 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
358 // data_size should contain how much memory we actually took for our cipher operation
359 out.resize(outData->data_size);
360 memcpy(out.data(), outData->data, outData->data_size);
363 void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
367 const RawBuffer &aad,
368 const RawBuffer &data,
372 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
374 // TEEC_Operation layout:
376 // [0].value.a - keyid
377 // [0].value.b - algo
378 // [1].memref - input data (serialized key/input/iv/aad)
380 // [0].value.a - return code
381 // [2].memref - output
383 if (key.size() != KM_KEY_ID_SIZE) {
384 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
387 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
388 KM_BufferSizeDesc bufSize;
390 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
391 bufSize.input_size = static_cast<uint32_t>(data.size());
392 bufSize.with_pwd_data = true;
393 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
394 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
395 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
396 bufSize.iv_size = static_cast<uint32_t>(iv.size());
397 bufSize.key_id_size = static_cast<uint32_t>(key.size());
398 bufSize.with_ae_data = true;
399 bufSize.aad_size = static_cast<uint32_t>(aad.size());
400 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
401 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
403 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
404 bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
405 bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
406 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
407 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
409 KM_SymmetricInput* input = nullptr;
410 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
412 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
415 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
417 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
420 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
421 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
422 pwd.getIV().data(), pwd.getIV().size(),
423 pwd.getTag().data(), pwd.getTag().size(),
424 Params::DERIVED_KEY_LENGTH_BITS,
425 Params::DERIVED_KEY_ITERATIONS,
428 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
431 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
433 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
436 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
438 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
441 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
443 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
447 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
448 TEEC_MEMREF_WHOLE, TEEC_NONE);
449 op.params[0].value.a = ALGO_AES_GCM;
450 op.params[1].memref.parent = inMemory.Get();
451 op.params[1].memref.offset = 0;
452 op.params[1].memref.size = inMemory.Get()->size;
453 op.params[2].memref.parent = outMemory.Get();
454 op.params[2].memref.offset = 0;
455 op.params[2].memref.size = outMemory.Get()->size;
456 Execute(CMD_ENCRYPT, &op);
458 KM_SymmetricInput* output = nullptr;
459 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
461 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
464 KM_OutData* outData = nullptr;
465 ret = KM_ParamsDeserializeOutData(output, &outData);
467 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
470 KM_TagData* tagData = nullptr;
471 ret = KM_ParamsDeserializeTagData(output, &tagData);
473 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
476 out.resize(outData->data_size);
477 memcpy(out.data(), outData->data, outData->data_size);
479 if (tagData->data_size) {
480 tag.resize(tagData->data_size);
481 memcpy(tag.data(), tagData->data, tagData->data_size);
485 void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
489 const RawBuffer &tag,
490 const RawBuffer &aad,
491 const RawBuffer &data,
494 // command ID = CMD_DECRYPT (from km_ta_defines.h)
496 // TEEC_Operation layout:
498 // [0].value.a - keyid
499 // [0].value.b - algo
500 // [1].memref - input data (serialized key/input/iv/tag/aad)
502 // [0].value.a - output size
503 // [2].memref - output (decrypted data)
505 if (key.size() != KM_KEY_ID_SIZE) {
506 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
509 KM_BufferSizeDesc bufSize;
511 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
512 bufSize.input_size = static_cast<uint32_t>(data.size());
513 bufSize.with_pwd_data = true;
514 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
515 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
516 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
517 bufSize.iv_size = static_cast<uint32_t>(iv.size());
518 bufSize.key_id_size = static_cast<uint32_t>(key.size());
519 bufSize.with_ae_data = true;
520 bufSize.aad_size = static_cast<uint32_t>(aad.size());
521 bufSize.tag_size = static_cast<uint32_t>(tag.size());
522 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
523 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
525 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
526 bufSize.out_size = static_cast<uint32_t>(data.size());
527 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
528 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
530 KM_SymmetricInput* input = nullptr;
531 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
533 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
536 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
538 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
541 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
542 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
543 pwd.getIV().data(), pwd.getIV().size(),
544 pwd.getTag().data(), pwd.getTag().size(),
545 Params::DERIVED_KEY_LENGTH_BITS,
546 Params::DERIVED_KEY_ITERATIONS,
549 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
552 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
554 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
557 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
559 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
562 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
564 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
567 ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
569 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
573 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
574 TEEC_MEMREF_WHOLE, TEEC_NONE);
575 op.params[0].value.a = ALGO_AES_GCM;
576 op.params[1].memref.parent = inMemory.Get();
577 op.params[1].memref.offset = 0;
578 op.params[1].memref.size = inMemory.Get()->size;
579 op.params[2].memref.parent = outMemory.Get();
580 op.params[2].memref.offset = 0;
581 op.params[2].memref.size = outMemory.Get()->size;
582 Execute(CMD_DECRYPT, &op);
584 KM_SymmetricInput* output = nullptr;
585 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
587 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
590 KM_OutData* outData = nullptr;
591 ret = KM_ParamsDeserializeOutData(output, &outData);
593 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
596 out.resize(outData->data_size);
597 memcpy(out.data(), outData->data, outData->data_size);
600 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
602 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
604 // TEEC_Operation layout:
606 // [1].memref - input data (serialized key ID)
608 // [0].value.a - return code
610 if (keyId.size() != KM_KEY_ID_SIZE) {
611 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
614 KM_BufferSizeDesc bufSize;
616 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
617 bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
618 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
619 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
621 KM_SymmetricInput* input = nullptr;
622 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
624 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
627 ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
629 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
633 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
634 TEEC_NONE, TEEC_NONE);
635 op.params[1].memref.parent = inMemory.Get();
636 op.params[1].memref.offset = 0;
637 op.params[1].memref.size = inMemory.Get()->size;
638 Execute(CMD_DESTROY_KEY, &op);
641 void TrustZoneContext::importData(
642 const uint32_t dataType,
643 const RawBuffer &data,
644 const RawBuffer &encIV,
645 const RawBuffer &pwd,
647 const uint32_t keySizeBits,
648 const uint32_t pwdTagSizeBits,
652 // command ID = CMD_IMPORT_DATA
654 // [1].memref - reference to serialized buffer:
655 // uint32_t dataType contains information about type stored as binary data
656 // KM_BinaryData with binary data
657 // uint32_t binary/key size in bits
658 // KM_BinaryData IV for data decryption with build in key
659 // uint32_t boolean value - true if password is provided
660 // KM_PwdData with password (optional)
662 // [0].value.a - return code
663 // [2].memref - reference to serialized buffer:
664 // KM_BinaryData with data id
665 // KM_BinaryData with tag id (optional, if password was provided)
666 uint32_t inMemorySize = 0;
668 // place for dataType
669 inMemorySize += KM_SizeOfFlag();
671 KM_BinaryData ta_data;
672 ta_data.data_size = static_cast<uint32_t>(data.size());
673 ta_data.data = const_cast<unsigned char *>(data.data());
674 inMemorySize += KM_SizeOfBinaryData(&ta_data);
676 uint32_t keySizeBits_flags = static_cast<uint32_t>(keySizeBits);
677 inMemorySize += KM_SizeOfFlag();
679 KM_BinaryData ta_data_enc_iv;
680 ta_data_enc_iv.data_size = static_cast<uint32_t>(encIV.size());
681 ta_data_enc_iv.data = const_cast<unsigned char *>(encIV.data());
682 inMemorySize += KM_SizeOfBinaryData(&ta_data_enc_iv);
684 uint32_t pwd_flag = pwd.empty() ? 0 : 1;
685 inMemorySize += KM_SizeOfFlag();
687 KM_PwdData kmPwdData;
689 memset(&kmPwdData, 0, sizeof(KM_PwdData));
690 kmPwdData.pwd = const_cast<unsigned char *>(pwd.data());
691 kmPwdData.pwd_size = pwd.size();
692 kmPwdData.iv = const_cast<unsigned char *>(iv.data());
693 kmPwdData.iv_size = iv.size();
694 kmPwdData.tag = NULL;
695 kmPwdData.tag_size = 0;
696 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
697 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
698 kmPwdData.tag_len_bits = pwdTagSizeBits;
700 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
703 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
704 void *inMemoryPtr = inMemory.Get()->buffer;
706 int ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, dataType);
708 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
711 ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &ta_data);
713 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
716 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, keySizeBits_flags);
718 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
721 ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &ta_data_enc_iv);
723 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
726 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
728 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
732 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
734 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
738 KM_BinaryData kmDataId;
740 memset(&kmDataId, 0, sizeof(KM_BinaryData));
741 memset(&kmTag, 0, sizeof(KM_BinaryData));
742 kmDataId.data_size = KM_DATA_ID_SIZE;
743 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmDataId);
745 kmTag.data_size = pwdTagSizeBits / 8;
746 outMemorySize += KM_SizeOfBinaryData(&kmTag);
749 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
750 void *outMemoryPtr = outMemory.Get()->buffer;
753 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
754 TEEC_MEMREF_WHOLE, TEEC_NONE);
755 op.params[1].memref.parent = inMemory.Get();
756 op.params[1].memref.offset = 0;
757 op.params[1].memref.size = inMemory.Get()->size;
758 op.params[2].memref.parent = outMemory.Get();
759 op.params[2].memref.offset = 0;
760 op.params[2].memref.size = outMemory.Get()->size;
762 Execute(CMD_IMPORT_DATA, &op);
764 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmDataId);
766 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
768 dataId.resize(kmDataId.data_size);
769 memcpy(dataId.data(), kmDataId.data, kmDataId.data_size);
771 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmTag);
773 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
775 pwdTag.resize(kmTag.data_size);
776 memcpy(pwdTag.data(), kmTag.data, kmTag.data_size);
779 LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
782 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
784 // command ID = CMD_GET_DATA_SIZE
785 // TA will decrypt data with password if provided
787 // [1].memref - reference to serialized buffer:
788 // KM_BinaryData with object ID
790 // [0].value.a - return code
791 // [0].value.b - size of buffer to be passed from CA
792 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
793 KM_BinaryData kmDataId;
794 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
795 kmDataId.data = const_cast<unsigned char *>(dataId.data());
796 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
797 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
798 void *inMemoryPtr = inMemory.Get()->buffer;
799 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
801 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
804 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
805 TEEC_NONE, TEEC_NONE);
807 op.params[1].memref.parent = inMemory.Get();
808 op.params[1].memref.offset = 0;
809 op.params[1].memref.size = inMemory.Get()->size;
810 Execute(CMD_GET_DATA_SIZE, &op);
811 dataSize = op.params[0].value.b;
814 void TrustZoneContext::getData(const RawBuffer &dataId,
818 // command ID = CMD_GET_DATA
819 // TA will decrypt data with password if provided
821 // [1].memref - reference to serialized buffer:
822 // KM_BinaryData with object ID
823 // uint32_t boolean value - true if password is provided
824 // KM_PwdData with password (optional)
826 // [0].value.a - return code
827 // [2].memref - reference to serialized buffer:
828 // KM_BinaryData with binary data
829 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
830 uint32_t data_size = 0;
831 GetDataSize(dataId, data_size);
833 KM_BinaryData kmDataId;
834 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
835 kmDataId.data = const_cast<unsigned char *>(dataId.data());
836 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId) + KM_SizeOfFlag();
837 uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
838 uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
840 KM_PwdData kmPwdData;
842 memset(&kmPwdData, 0, sizeof(KM_PwdData));
843 kmPwdData.pwd = const_cast<unsigned char *>(pwd.getPassword().data());
844 kmPwdData.pwd_size = pwd.getPassword().size();
845 kmPwdData.iv = const_cast<unsigned char *>(pwd.getIV().data());
846 kmPwdData.iv_size = pwd.getIV().size();
847 kmPwdData.tag = const_cast<unsigned char *>(pwd.getTag().data());
848 kmPwdData.tag_size = pwd.getTag().size();
849 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
850 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
851 kmPwdData.tag_len_bits = pwdTagSizeBits;
853 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
856 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
857 void *inMemoryPtr = inMemory.Get()->buffer;
859 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
861 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
863 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
865 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
868 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
870 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
874 KM_BinaryData kmExtractedData;
875 memset(&kmExtractedData, 0, sizeof(KM_BinaryData));
876 kmExtractedData.data_size = data_size;
878 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmExtractedData);
879 uint32_t outMemorySize2 = outMemorySize;
881 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
882 void *outMemoryPtr = outMemory.Get()->buffer;
883 void *outMemoryPtr2 = outMemory.Get()->buffer;
885 // requesting size is saved in this buffer
886 ret = KM_SerializeBinaryData(&outMemoryPtr2, &outMemorySize2, &kmExtractedData);
888 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
892 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
893 TEEC_MEMREF_WHOLE, TEEC_NONE);
894 op.params[1].memref.parent = inMemory.Get();
895 op.params[1].memref.offset = 0;
896 op.params[1].memref.size = inMemory.Get()->size;
897 op.params[2].memref.parent = outMemory.Get();
898 op.params[2].memref.offset = 0;
899 op.params[2].memref.size = outMemory.Get()->size;
901 Execute(CMD_GET_DATA, &op);
903 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmExtractedData);
905 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
908 data.resize(kmExtractedData.data_size);
909 memcpy(data.data(), kmExtractedData.data, kmExtractedData.data_size);
913 void TrustZoneContext::destroyData(const RawBuffer &dataId)
915 // command ID = CMD_DESTROY_DATA
916 // TEEC_Operation parameters layout:
918 // [1].memref - reference to serialized buffer:
919 // KM_BinaryData with object ID
921 // [0].value.a - return code
922 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
923 KM_BinaryData kmDataId;
924 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
925 kmDataId.data = const_cast<unsigned char *>(dataId.data());
926 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
927 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
928 void *inMemoryPtr = inMemory.Get()->buffer;
930 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
933 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
937 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
938 TEEC_NONE, TEEC_NONE);
940 op.params[1].memref.parent = inMemory.Get();
941 op.params[1].memref.offset = 0;
942 op.params[1].memref.size = inMemory.Get()->size;
943 Execute(CMD_DESTROY_DATA, &op);
946 void TrustZoneContext::Initialize()
952 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
954 result = TEEC_InitializeContext(nullptr, &m_Context);
955 if (result != TEEC_SUCCESS) {
956 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
958 m_ContextInitialized = true;
960 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
961 if (result != TEEC_SUCCESS) {
962 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
964 m_SessionInitialized = true;
967 void TrustZoneContext::Destroy()
969 if (m_SessionInitialized) {
970 TEEC_CloseSession(&m_Session);
971 m_SessionInitialized = false;
974 if (m_ContextInitialized) {
975 TEEC_FinalizeContext(&m_Context);
976 m_ContextInitialized = false;
980 void TrustZoneContext::Reload()
986 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
988 LogDebug("Executing TZ operation " << commandID);
990 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, NULL);
991 if (result != TEEC_SUCCESS) {
993 case TEEC_ERROR_TARGET_DEAD:
995 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
996 static_cast<unsigned int>(commandID));
997 case TEEC_ERROR_BAD_PARAMETERS:
998 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1000 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1001 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1002 static_cast<unsigned int>(result));
1006 int ta_ret = op->params[0].value.a;
1007 if (ta_ret != KM_TA_SUCCESS) {
1009 case KM_TA_ERROR_AUTH_FAILED:
1010 // Authentication cipher failed - notify with proper exception
1011 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1013 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1018 } // namespace Internals
1020 } // namespace Crypto