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 <generic-backend/encryption-params.h>
27 #include <dpl/log/log.h>
29 #include <km_serialization.h>
30 #include <km_ta_defines.h>
42 // A little bit of extra memory to add to output buffers.
44 // We need this extra memory to output for padding purposes - after encryption
45 // we can resize the result memory back to its proper size according to
46 // whatever TA will return us.
47 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
49 // Identifier of our TA
50 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
52 //raw to hex string conversion to print persistent storage data ID
53 static std::string rawToHexString(const RawBuffer &raw)
59 snprintf(buf, sizeof(buf), "%02x", (e & 0xff));
60 dump.push_back(buf[0]);
61 dump.push_back(buf[1]);
67 } // anonymous namespace
69 TrustZoneContext::TrustZoneContext()
70 : m_ContextInitialized(false)
71 , m_SessionInitialized(false)
76 TrustZoneContext::~TrustZoneContext()
81 TrustZoneContext& TrustZoneContext::Instance()
83 static TrustZoneContext instance;
87 void TrustZoneContext::generateIV(RawBuffer& iv)
89 // command ID = CMD_GENERATE_IV
91 // TEEC_Operation layout:
93 // [1].memref.buffer - output
94 // [1].memref.size - output size
96 // [0].value.a - return code
98 // IV generation is a simple call - no need to serialize data
99 // just provide the output buffer with size equal to iv.
100 uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
101 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
104 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
105 TEEC_NONE, TEEC_NONE);
106 op.params[1].memref.parent = ivMemory.Get();
107 op.params[1].memref.offset = 0;
108 op.params[1].memref.size = ivMemory.Get()->size;
109 Execute(CMD_GENERATE_IV, &op);
112 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
115 void TrustZoneContext::generateSKey(tz_algo_type algo,
116 uint32_t keySizeBits,
119 // command ID = CMD_GENERATE_KEY
121 // TEEC_Operation layout:
123 // [0].value.a - key type
124 // [0].value.b - key bit size
126 // [0].value.a - return code
127 // [1].memref - serialized key reference
129 KM_BufferSizeDesc bufSize;
131 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
132 bufSize.out_size = KM_KEY_ID_SIZE;
133 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
134 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
137 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
138 TEEC_NONE, TEEC_NONE);
139 op.params[0].value.a = algo;
140 op.params[0].value.b = keySizeBits;
141 op.params[1].memref.parent = keyMemory.Get();
142 op.params[1].memref.offset = 0;
143 op.params[1].memref.size = keyMemorySize;
144 Execute(CMD_GENERATE_KEY, &op);
146 KM_SymmetricInput* output = nullptr;
147 int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
149 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
152 KM_OutData* outData = nullptr;
153 ret = KM_ParamsDeserializeOutData(output, &outData);
155 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
158 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
159 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
162 keyId.resize(KM_KEY_ID_SIZE);
163 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
166 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
167 const RawBuffer &pwd,
169 const uint32_t keySizeBits,
173 // command ID = CMD_GENERATE_KEY_PWD
175 // TEEC_Operation layout:
177 // [0].value.a - key type
178 // [0].value.b - key size in bits
179 // [1].memref - input (seralized pwd/iv for pbkdf2)
181 // [0].value.a - return code
182 // [2].memref - serialized key reference ID
184 KM_BufferSizeDesc bufSize;
186 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
187 bufSize.with_pwd_data = true;
188 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
189 bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
190 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
191 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
193 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
194 bufSize.out_size = KM_KEY_ID_SIZE;
195 bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
196 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
197 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
199 KM_SymmetricInput* input = nullptr;
200 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
202 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
205 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
206 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
207 Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
209 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
213 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
214 TEEC_MEMREF_WHOLE, TEEC_NONE);
215 op.params[0].value.a = algo;
216 op.params[0].value.b = keySizeBits;
217 op.params[1].memref.parent = inMemory.Get();
218 op.params[1].memref.offset = 0;
219 op.params[1].memref.size = inMemory.Get()->size;
220 op.params[2].memref.parent = keyMemory.Get();
221 op.params[2].memref.offset = 0;
222 op.params[2].memref.size = keyMemory.Get()->size;
223 Execute(CMD_GENERATE_KEY_PWD, &op);
225 KM_SymmetricInput* output = nullptr;
226 ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
228 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
231 KM_OutData* outData = nullptr;
232 ret = KM_ParamsDeserializeOutData(output, &outData);
234 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
237 KM_TagData* tagData = nullptr;
238 ret = KM_ParamsDeserializeTagData(output, &tagData);
240 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
243 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
244 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
247 if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
248 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
251 keyId.resize(KM_KEY_ID_SIZE);
252 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
254 pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
255 memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
258 void TrustZoneContext::executeCrypt(tz_command cmd,
260 const RawBuffer &key,
263 const RawBuffer &data,
266 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
268 // TEEC_Operation layout:
270 // [0].value.a - keyid
271 // [0].value.b - algo
272 // [1].memref - input data (serialized key/input)
274 // [0].value.a - return code
275 // [2].memref - serialized output buffer
277 if (key.size() != KM_KEY_ID_SIZE) {
278 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
279 + std::to_string(key.size()) + ")");
282 KM_BufferSizeDesc bufSize;
284 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
285 bufSize.input_size = static_cast<uint32_t>(data.size());
286 bufSize.with_pwd_data = true;
287 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
288 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
289 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
290 bufSize.iv_size = static_cast<uint32_t>(iv.size());
291 bufSize.key_id_size = static_cast<uint32_t>(key.size());
292 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
293 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
295 // decrypt operation does not require padding
296 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
297 bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
298 data.size() + CIPHER_EXTRA_PADDING_SIZE :
300 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
301 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
303 KM_SymmetricInput* input = nullptr;
304 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
306 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
309 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
311 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
314 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
315 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
316 pwd.getIV().data(), pwd.getIV().size(),
317 pwd.getTag().data(), pwd.getTag().size(),
318 Params::DERIVED_KEY_LENGTH_BITS,
319 Params::DERIVED_KEY_ITERATIONS,
322 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
325 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
327 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
330 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
332 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
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;
347 KM_SymmetricInput* output = nullptr;
348 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
350 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
353 KM_OutData* outData = nullptr;
354 ret = KM_ParamsDeserializeOutData(output, &outData);
356 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
359 // data_size should contain how much memory we actually took for our cipher operation
360 out.resize(outData->data_size);
361 memcpy(out.data(), outData->data, outData->data_size);
364 void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
368 const RawBuffer &aad,
369 const RawBuffer &data,
373 // command ID = CMD_ENCRYPT (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/iv/aad)
381 // [0].value.a - return code
382 // [2].memref - output
384 if (key.size() != KM_KEY_ID_SIZE) {
385 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
388 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
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 bufSize.with_ae_data = true;
400 bufSize.aad_size = static_cast<uint32_t>(aad.size());
401 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
402 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
404 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
405 bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
406 bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
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);
442 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
444 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
448 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
449 TEEC_MEMREF_WHOLE, TEEC_NONE);
450 op.params[0].value.a = ALGO_AES_GCM;
451 op.params[1].memref.parent = inMemory.Get();
452 op.params[1].memref.offset = 0;
453 op.params[1].memref.size = inMemory.Get()->size;
454 op.params[2].memref.parent = outMemory.Get();
455 op.params[2].memref.offset = 0;
456 op.params[2].memref.size = outMemory.Get()->size;
457 Execute(CMD_ENCRYPT, &op);
459 KM_SymmetricInput* output = nullptr;
460 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
462 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
465 KM_OutData* outData = nullptr;
466 ret = KM_ParamsDeserializeOutData(output, &outData);
468 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
471 KM_TagData* tagData = nullptr;
472 ret = KM_ParamsDeserializeTagData(output, &tagData);
474 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
477 out.resize(outData->data_size);
478 memcpy(out.data(), outData->data, outData->data_size);
480 if (tagData->data_size) {
481 tag.resize(tagData->data_size);
482 memcpy(tag.data(), tagData->data, tagData->data_size);
486 void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
490 const RawBuffer &tag,
491 const RawBuffer &aad,
492 const RawBuffer &data,
495 // command ID = CMD_DECRYPT (from km_ta_defines.h)
497 // TEEC_Operation layout:
499 // [0].value.a - keyid
500 // [0].value.b - algo
501 // [1].memref - input data (serialized key/input/iv/tag/aad)
503 // [0].value.a - output size
504 // [2].memref - output (decrypted data)
506 if (key.size() != KM_KEY_ID_SIZE) {
507 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
510 KM_BufferSizeDesc bufSize;
512 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
513 bufSize.input_size = static_cast<uint32_t>(data.size());
514 bufSize.with_pwd_data = true;
515 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
516 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
517 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
518 bufSize.iv_size = static_cast<uint32_t>(iv.size());
519 bufSize.key_id_size = static_cast<uint32_t>(key.size());
520 bufSize.with_ae_data = true;
521 bufSize.aad_size = static_cast<uint32_t>(aad.size());
522 bufSize.tag_size = static_cast<uint32_t>(tag.size());
523 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
524 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
526 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
527 bufSize.out_size = static_cast<uint32_t>(data.size());
528 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
529 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
531 KM_SymmetricInput* input = nullptr;
532 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
534 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
537 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
539 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
542 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
543 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
544 pwd.getIV().data(), pwd.getIV().size(),
545 pwd.getTag().data(), pwd.getTag().size(),
546 Params::DERIVED_KEY_LENGTH_BITS,
547 Params::DERIVED_KEY_ITERATIONS,
550 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
553 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
555 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
558 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
560 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
563 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
565 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
568 ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
570 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
574 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
575 TEEC_MEMREF_WHOLE, TEEC_NONE);
576 op.params[0].value.a = ALGO_AES_GCM;
577 op.params[1].memref.parent = inMemory.Get();
578 op.params[1].memref.offset = 0;
579 op.params[1].memref.size = inMemory.Get()->size;
580 op.params[2].memref.parent = outMemory.Get();
581 op.params[2].memref.offset = 0;
582 op.params[2].memref.size = outMemory.Get()->size;
583 Execute(CMD_DECRYPT, &op);
585 KM_SymmetricInput* output = nullptr;
586 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
588 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
591 KM_OutData* outData = nullptr;
592 ret = KM_ParamsDeserializeOutData(output, &outData);
594 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
597 out.resize(outData->data_size);
598 memcpy(out.data(), outData->data, outData->data_size);
601 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
603 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
605 // TEEC_Operation layout:
607 // [1].memref - input data (serialized key ID)
609 // [0].value.a - return code
611 if (keyId.size() != KM_KEY_ID_SIZE) {
612 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
615 KM_BufferSizeDesc bufSize;
617 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
618 bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
619 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
620 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
622 KM_SymmetricInput* input = nullptr;
623 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
625 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
628 ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
630 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
634 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
635 TEEC_NONE, TEEC_NONE);
636 op.params[1].memref.parent = inMemory.Get();
637 op.params[1].memref.offset = 0;
638 op.params[1].memref.size = inMemory.Get()->size;
639 Execute(CMD_DESTROY_KEY, &op);
642 void TrustZoneContext::importData(
643 const uint32_t dataType,
644 const RawBuffer &data,
645 const Crypto::EncryptionParams &encData,
646 const RawBuffer &pwd,
648 const uint32_t keySizeBits,
649 const uint32_t pwdTagSizeBits,
653 // command ID = CMD_IMPORT_DATA
655 // [1].memref - reference to serialized buffer:
656 // uint32_t dataType contains information about type stored as binary data
657 // KM_BinaryData with binary data
658 // uint32_t binary/key size in bits
659 // KM_BinaryData IV for data decryption with built in key
660 // KM_BinaryData TAG for data decryption with built in key
661 // uint32_t boolean value - true if password is provided
662 // KM_PwdData with password (optional)
664 // [0].value.a - return code
665 // [2].memref - reference to serialized buffer:
666 // KM_BinaryData with data id
667 // KM_BinaryData with tag id (optional, if password was provided)
668 uint32_t inMemorySize = 0;
670 // place for dataType
671 inMemorySize += KM_SizeOfFlag();
673 KM_BinaryData ta_data;
674 ta_data.data_size = static_cast<uint32_t>(data.size());
675 ta_data.data = const_cast<unsigned char *>(data.data());
676 inMemorySize += KM_SizeOfBinaryData(&ta_data);
678 uint32_t keySizeBits_flags = static_cast<uint32_t>(keySizeBits);
679 inMemorySize += KM_SizeOfFlag();
681 KM_BinaryData ta_data_enc_iv;
682 ta_data_enc_iv.data_size = static_cast<uint32_t>(encData.iv.size());
683 ta_data_enc_iv.data = const_cast<unsigned char *>(encData.iv.data());
684 inMemorySize += KM_SizeOfBinaryData(&ta_data_enc_iv);
686 KM_BinaryData ta_data_enc_tag;
687 ta_data_enc_tag.data_size = static_cast<uint32_t>(encData.tag.size());
688 ta_data_enc_tag.data = const_cast<unsigned char *>(encData.tag.data());
689 inMemorySize += KM_SizeOfBinaryData(&ta_data_enc_tag);
691 uint32_t pwd_flag = pwd.empty() ? 0 : 1;
692 inMemorySize += KM_SizeOfFlag();
694 KM_PwdData kmPwdData;
696 memset(&kmPwdData, 0, sizeof(KM_PwdData));
697 kmPwdData.pwd = const_cast<unsigned char *>(pwd.data());
698 kmPwdData.pwd_size = pwd.size();
699 kmPwdData.iv = const_cast<unsigned char *>(iv.data());
700 kmPwdData.iv_size = iv.size();
701 kmPwdData.tag = NULL;
702 kmPwdData.tag_size = 0;
703 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
704 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
705 kmPwdData.tag_len_bits = pwdTagSizeBits;
707 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
710 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
711 void *inMemoryPtr = inMemory.Get()->buffer;
713 int ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, dataType);
715 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
718 ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &ta_data);
720 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
723 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, keySizeBits_flags);
725 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
728 ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &ta_data_enc_iv);
730 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
733 ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &ta_data_enc_tag);
735 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
738 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
740 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
744 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
746 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
750 KM_BinaryData kmDataId;
752 memset(&kmDataId, 0, sizeof(KM_BinaryData));
753 memset(&kmTag, 0, sizeof(KM_BinaryData));
754 kmDataId.data_size = KM_DATA_ID_SIZE;
755 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmDataId);
757 kmTag.data_size = pwdTagSizeBits / 8;
758 outMemorySize += KM_SizeOfBinaryData(&kmTag);
761 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
762 void *outMemoryPtr = outMemory.Get()->buffer;
765 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
766 TEEC_MEMREF_WHOLE, TEEC_NONE);
767 op.params[1].memref.parent = inMemory.Get();
768 op.params[1].memref.offset = 0;
769 op.params[1].memref.size = inMemory.Get()->size;
770 op.params[2].memref.parent = outMemory.Get();
771 op.params[2].memref.offset = 0;
772 op.params[2].memref.size = outMemory.Get()->size;
774 Execute(CMD_IMPORT_DATA, &op);
776 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmDataId);
778 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
780 dataId.resize(kmDataId.data_size);
781 memcpy(dataId.data(), kmDataId.data, kmDataId.data_size);
783 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmTag);
785 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
787 pwdTag.resize(kmTag.data_size);
788 memcpy(pwdTag.data(), kmTag.data, kmTag.data_size);
791 LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
794 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
796 // command ID = CMD_GET_DATA_SIZE
797 // TA will decrypt data with password if provided
799 // [1].memref - reference to serialized buffer:
800 // KM_BinaryData with object ID
802 // [0].value.a - return code
803 // [0].value.b - size of buffer to be passed from CA
804 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
805 KM_BinaryData kmDataId;
806 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
807 kmDataId.data = const_cast<unsigned char *>(dataId.data());
808 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
809 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
810 void *inMemoryPtr = inMemory.Get()->buffer;
811 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
813 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret);
816 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
817 TEEC_NONE, TEEC_NONE);
819 op.params[1].memref.parent = inMemory.Get();
820 op.params[1].memref.offset = 0;
821 op.params[1].memref.size = inMemory.Get()->size;
822 Execute(CMD_GET_DATA_SIZE, &op);
823 dataSize = op.params[0].value.b;
826 void TrustZoneContext::getData(const RawBuffer &dataId,
830 // command ID = CMD_GET_DATA
831 // TA will decrypt data with password if provided
833 // [1].memref - reference to serialized buffer:
834 // KM_BinaryData with object ID
835 // uint32_t boolean value - true if password is provided
836 // KM_PwdData with password (optional)
838 // [0].value.a - return code
839 // [2].memref - reference to serialized buffer:
840 // KM_BinaryData with binary data
841 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
842 uint32_t data_size = 0;
843 GetDataSize(dataId, data_size);
845 KM_BinaryData kmDataId;
846 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
847 kmDataId.data = const_cast<unsigned char *>(dataId.data());
848 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId) + KM_SizeOfFlag();
849 uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
850 uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
852 KM_PwdData kmPwdData;
854 memset(&kmPwdData, 0, sizeof(KM_PwdData));
855 kmPwdData.pwd = const_cast<unsigned char *>(pwd.getPassword().data());
856 kmPwdData.pwd_size = pwd.getPassword().size();
857 kmPwdData.iv = const_cast<unsigned char *>(pwd.getIV().data());
858 kmPwdData.iv_size = pwd.getIV().size();
859 kmPwdData.tag = const_cast<unsigned char *>(pwd.getTag().data());
860 kmPwdData.tag_size = pwd.getTag().size();
861 kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS;
862 kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS;
863 kmPwdData.tag_len_bits = pwdTagSizeBits;
865 inMemorySize += KM_SizeOfPwdData(&kmPwdData);
868 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
869 void *inMemoryPtr = inMemory.Get()->buffer;
871 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
873 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
875 ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag);
877 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
880 ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData);
882 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
886 KM_BinaryData kmExtractedData;
887 memset(&kmExtractedData, 0, sizeof(KM_BinaryData));
888 kmExtractedData.data_size = data_size;
890 uint32_t outMemorySize = KM_SizeOfBinaryData(&kmExtractedData);
891 uint32_t outMemorySize2 = outMemorySize;
893 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
894 void *outMemoryPtr = outMemory.Get()->buffer;
895 void *outMemoryPtr2 = outMemory.Get()->buffer;
897 // requesting size is saved in this buffer
898 ret = KM_SerializeBinaryData(&outMemoryPtr2, &outMemorySize2, &kmExtractedData);
900 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
904 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
905 TEEC_MEMREF_WHOLE, TEEC_NONE);
906 op.params[1].memref.parent = inMemory.Get();
907 op.params[1].memref.offset = 0;
908 op.params[1].memref.size = inMemory.Get()->size;
909 op.params[2].memref.parent = outMemory.Get();
910 op.params[2].memref.offset = 0;
911 op.params[2].memref.size = outMemory.Get()->size;
913 Execute(CMD_GET_DATA, &op);
915 ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmExtractedData);
917 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
920 data.resize(kmExtractedData.data_size);
921 memcpy(data.data(), kmExtractedData.data, kmExtractedData.data_size);
925 void TrustZoneContext::destroyData(const RawBuffer &dataId)
927 // command ID = CMD_DESTROY_DATA
928 // TEEC_Operation parameters layout:
930 // [1].memref - reference to serialized buffer:
931 // KM_BinaryData with object ID
933 // [0].value.a - return code
934 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
935 KM_BinaryData kmDataId;
936 kmDataId.data_size = static_cast<uint32_t>(dataId.size());
937 kmDataId.data = const_cast<unsigned char *>(dataId.data());
938 uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId);
939 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
940 void *inMemoryPtr = inMemory.Get()->buffer;
942 int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId);
945 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret);
949 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
950 TEEC_NONE, TEEC_NONE);
952 op.params[1].memref.parent = inMemory.Get();
953 op.params[1].memref.offset = 0;
954 op.params[1].memref.size = inMemory.Get()->size;
955 Execute(CMD_DESTROY_DATA, &op);
958 void TrustZoneContext::Initialize()
964 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
966 result = TEEC_InitializeContext(nullptr, &m_Context);
967 if (result != TEEC_SUCCESS) {
968 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
970 m_ContextInitialized = true;
972 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
973 if (result != TEEC_SUCCESS) {
974 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
976 m_SessionInitialized = true;
979 void TrustZoneContext::Destroy()
981 if (m_SessionInitialized) {
982 TEEC_CloseSession(&m_Session);
983 m_SessionInitialized = false;
986 if (m_ContextInitialized) {
987 TEEC_FinalizeContext(&m_Context);
988 m_ContextInitialized = false;
992 void TrustZoneContext::Reload()
998 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1000 uint32_t retOrigin = 0;
1001 LogDebug("Executing TZ operation " << commandID);
1003 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
1004 if (result != TEEC_SUCCESS) {
1006 case TEEC_ERROR_TARGET_DEAD:
1008 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1009 static_cast<unsigned int>(commandID));
1010 case TEEC_ERROR_BAD_PARAMETERS:
1011 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1013 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1014 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1015 static_cast<unsigned int>(result), " with origin: ", std::hex,
1020 int ta_ret = op->params[0].value.a;
1021 if (ta_ret != KM_TA_SUCCESS) {
1023 case KM_TA_ERROR_AUTH_FAILED:
1024 // Authentication cipher failed - notify with proper exception
1025 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1027 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1032 } // namespace Internals
1034 } // namespace Crypto