2 * Copyright (c) 2017 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 } // anonymous namespace
53 TrustZoneContext::TrustZoneContext()
54 : m_ContextInitialized(false)
55 , m_SessionInitialized(false)
60 TrustZoneContext::~TrustZoneContext()
65 TrustZoneContext& TrustZoneContext::Instance()
67 static TrustZoneContext instance;
71 void TrustZoneContext::generateIV(uint32_t ivSize, RawBuffer& iv)
73 // command ID = CMD_GENERATE_IV
75 // TEEC_Operation layout:
77 // [1].memref.buffer - output
78 // [1].memref.size - output size
80 // [0].value.a - return code
82 // IV generation is a simple call - no need to serialize data
83 // just provide the output buffer with size equal to iv.
84 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
87 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
88 TEEC_NONE, TEEC_NONE);
89 op.params[1].memref.parent = ivMemory.Get();
90 op.params[1].memref.offset = 0;
91 op.params[1].memref.size = ivMemory.Get()->size;
92 Execute(CMD_GENERATE_IV, &op);
95 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
98 void TrustZoneContext::generateSKey(tz_algo_type algo,
102 // command ID = CMD_GENERATE_KEY
104 // TEEC_Operation layout:
106 // [0].value.a - key type
107 // [0].value.b - key bit size
109 // [0].value.a - return code
110 // [1].memref - serialized key reference
112 KM_BufferSizeDesc bufSize;
114 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
115 bufSize.out_size = KM_KEY_ID_SIZE;
116 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
117 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
120 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
121 TEEC_NONE, TEEC_NONE);
122 op.params[0].value.a = algo;
123 op.params[0].value.b = keySizeBits;
124 op.params[1].memref.parent = keyMemory.Get();
125 op.params[1].memref.offset = 0;
126 op.params[1].memref.size = keyMemorySize;
127 Execute(CMD_GENERATE_KEY, &op);
129 KM_SymmetricInput* output = nullptr;
130 int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
132 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
135 KM_OutData* outData = nullptr;
136 ret = KM_ParamsDeserializeOutData(output, &outData);
138 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
141 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
142 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
145 keyId.resize(KM_KEY_ID_SIZE);
146 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
149 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
150 const RawBuffer &pwd,
152 const uint32_t keySizeBits,
153 const uint32_t pwdTagSizeBits,
157 // command ID = CMD_GENERATE_KEY_PWD
159 // TEEC_Operation layout:
161 // [0].value.a - key type
162 // [0].value.b - key size in bits
163 // [1].memref - input (seralized pwd/iv for pbkdf2)
165 // [0].value.a - return code
166 // [2].memref - serialized key reference ID
168 KM_BufferSizeDesc bufSize;
170 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
171 bufSize.with_pwd_data = true;
172 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
173 bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
174 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
175 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
177 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
178 bufSize.out_size = KM_KEY_ID_SIZE;
179 bufSize.tag_size = pwdTagSizeBits / 8;
180 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
181 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
183 KM_SymmetricInput* input = nullptr;
184 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
186 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
189 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
190 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
191 Params::DERIVED_KEY_ITERATIONS, pwdTagSizeBits);
193 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
197 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
198 TEEC_MEMREF_WHOLE, TEEC_NONE);
199 op.params[0].value.a = algo;
200 op.params[0].value.b = keySizeBits;
201 op.params[1].memref.parent = inMemory.Get();
202 op.params[1].memref.offset = 0;
203 op.params[1].memref.size = inMemory.Get()->size;
204 op.params[2].memref.parent = keyMemory.Get();
205 op.params[2].memref.offset = 0;
206 op.params[2].memref.size = keyMemory.Get()->size;
207 Execute(CMD_GENERATE_KEY_PWD, &op);
209 KM_SymmetricInput* output = nullptr;
210 ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
212 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
215 KM_OutData* outData = nullptr;
216 ret = KM_ParamsDeserializeOutData(output, &outData);
218 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
221 KM_TagData* tagData = nullptr;
222 ret = KM_ParamsDeserializeTagData(output, &tagData);
224 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
227 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
228 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
231 if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
232 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
235 keyId.resize(KM_KEY_ID_SIZE);
236 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
238 pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
239 memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
243 void TrustZoneContext::importKey(tz_algo_type algo,
244 const RawBuffer &key,
245 const RawBuffer &pwd,
247 const uint32_t keySizeBits,
248 const uint32_t pwdTagSizeBits,
252 // command ID = CMD_IMPORT_KEY
254 // TEEC_Operation layout:
256 // [0].value.a - key type
257 // [0].value.b - key size in bits
258 // [1].memref - seralized key & password data
260 // [0].value.a - return code
261 // [2].memref - serialized key reference ID
263 KM_BufferSizeDesc bufSize;
265 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
266 bufSize.input_size = static_cast<uint32_t>(key.size());
268 bufSize.with_pwd_data = true;
269 bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
270 bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
272 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
273 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
275 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
276 bufSize.out_size = KM_KEY_ID_SIZE;
277 bufSize.tag_size = pwdTagSizeBits / 8;
278 uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
279 TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
281 KM_SymmetricInput* input = nullptr;
282 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
284 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for key import: ", ret);
287 ret = KM_ParamsSerializeInputData(input, key.data(), key.size());
289 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key to import: ", ret);
293 ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
294 nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
295 Params::DERIVED_KEY_ITERATIONS, pwdTagSizeBits);
297 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key data for import: ", ret);
302 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
303 TEEC_MEMREF_WHOLE, TEEC_NONE);
304 op.params[0].value.a = algo;
305 op.params[0].value.b = keySizeBits;
306 op.params[1].memref.parent = inMemory.Get();
307 op.params[1].memref.offset = 0;
308 op.params[1].memref.size = inMemory.Get()->size;
309 op.params[2].memref.parent = keyMemory.Get();
310 op.params[2].memref.offset = 0;
311 op.params[2].memref.size = keyMemory.Get()->size;
312 Execute(CMD_IMPORT_KEY, &op);
314 KM_SymmetricInput* output = nullptr;
315 ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
317 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for imported key ID");
320 KM_OutData* outData = nullptr;
321 ret = KM_ParamsDeserializeOutData(output, &outData);
323 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key ID");
326 if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
327 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
330 keyId.resize(KM_KEY_ID_SIZE);
331 memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
334 KM_TagData* tagData = nullptr;
335 uint32_t pwdTagSizeBytes = pwdTagSizeBits / 8;
337 ret = KM_ParamsDeserializeTagData(output, &tagData);
339 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key's tag");
342 if (tagData == nullptr || tagData->data_size != pwdTagSizeBytes) {
343 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
346 pwdTag.resize(pwdTagSizeBytes);
347 memcpy(pwdTag.data(), tagData->data, pwdTagSizeBytes);
351 void TrustZoneContext::executeCrypt(tz_command cmd,
353 const RawBuffer &key,
356 const RawBuffer &data,
359 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
361 // TEEC_Operation layout:
363 // [0].value.a - keyid
364 // [0].value.b - algo
365 // [1].memref - input data (serialized key/input)
367 // [0].value.a - return code
368 // [2].memref - serialized output buffer
370 if (key.size() != KM_KEY_ID_SIZE) {
371 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
372 + std::to_string(key.size()) + ")");
375 KM_BufferSizeDesc bufSize;
377 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
378 bufSize.input_size = static_cast<uint32_t>(data.size());
379 bufSize.with_pwd_data = true;
380 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
381 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
382 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
383 bufSize.iv_size = static_cast<uint32_t>(iv.size());
384 bufSize.key_id_size = static_cast<uint32_t>(key.size());
385 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
386 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
388 // decrypt operation does not require padding
389 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
390 bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
391 data.size() + CIPHER_EXTRA_PADDING_SIZE :
393 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
394 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
396 KM_SymmetricInput* input = nullptr;
397 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
399 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
402 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
404 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
407 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
408 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
409 pwd.getIV().data(), pwd.getIV().size(),
410 pwd.getTag().data(), pwd.getTag().size(),
411 Params::DERIVED_KEY_LENGTH_BITS,
412 Params::DERIVED_KEY_ITERATIONS,
415 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
418 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
420 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
423 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
425 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
429 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
430 TEEC_MEMREF_WHOLE, TEEC_NONE);
431 op.params[0].value.a = algo;
432 op.params[1].memref.parent = inMemory.Get();
433 op.params[1].memref.offset = 0;
434 op.params[1].memref.size = inMemory.Get()->size;
435 op.params[2].memref.parent = outMemory.Get();
436 op.params[2].memref.offset = 0;
437 op.params[2].memref.size = outMemory.Get()->size;
440 KM_SymmetricInput* output = nullptr;
441 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
443 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
446 KM_OutData* outData = nullptr;
447 ret = KM_ParamsDeserializeOutData(output, &outData);
449 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
452 // data_size should contain how much memory we actually took for our cipher operation
453 out.resize(outData->data_size);
454 memcpy(out.data(), outData->data, outData->data_size);
457 void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
461 const RawBuffer &aad,
462 const RawBuffer &data,
466 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
468 // TEEC_Operation layout:
470 // [0].value.a - keyid
471 // [0].value.b - algo
472 // [1].memref - input data (serialized key/input/iv/aad)
474 // [0].value.a - return code
475 // [2].memref - output
477 if (key.size() != KM_KEY_ID_SIZE) {
478 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
481 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
482 KM_BufferSizeDesc bufSize;
484 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
485 bufSize.input_size = static_cast<uint32_t>(data.size());
486 bufSize.with_pwd_data = true;
487 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
488 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
489 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
490 bufSize.iv_size = static_cast<uint32_t>(iv.size());
491 bufSize.key_id_size = static_cast<uint32_t>(key.size());
492 bufSize.with_ae_data = true;
493 bufSize.aad_size = static_cast<uint32_t>(aad.size());
494 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
495 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
497 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
498 bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
499 bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
500 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
501 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
503 KM_SymmetricInput* input = nullptr;
504 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
506 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
509 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
511 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
514 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
515 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
516 pwd.getIV().data(), pwd.getIV().size(),
517 pwd.getTag().data(), pwd.getTag().size(),
518 Params::DERIVED_KEY_LENGTH_BITS,
519 Params::DERIVED_KEY_ITERATIONS,
522 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
525 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
527 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
530 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
532 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
535 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
537 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
541 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
542 TEEC_MEMREF_WHOLE, TEEC_NONE);
543 op.params[0].value.a = ALGO_AES_GCM;
544 op.params[1].memref.parent = inMemory.Get();
545 op.params[1].memref.offset = 0;
546 op.params[1].memref.size = inMemory.Get()->size;
547 op.params[2].memref.parent = outMemory.Get();
548 op.params[2].memref.offset = 0;
549 op.params[2].memref.size = outMemory.Get()->size;
550 Execute(CMD_ENCRYPT, &op);
552 KM_SymmetricInput* output = nullptr;
553 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
555 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
558 KM_OutData* outData = nullptr;
559 ret = KM_ParamsDeserializeOutData(output, &outData);
561 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
564 KM_TagData* tagData = nullptr;
565 ret = KM_ParamsDeserializeTagData(output, &tagData);
567 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
570 out.resize(outData->data_size);
571 memcpy(out.data(), outData->data, outData->data_size);
573 if (tagData->data_size) {
574 tag.resize(tagData->data_size);
575 memcpy(tag.data(), tagData->data, tagData->data_size);
579 void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
583 const RawBuffer &tag,
584 const RawBuffer &aad,
585 const RawBuffer &data,
588 // command ID = CMD_DECRYPT (from km_ta_defines.h)
590 // TEEC_Operation layout:
592 // [0].value.a - keyid
593 // [0].value.b - algo
594 // [1].memref - input data (serialized key/input/iv/tag/aad)
596 // [0].value.a - output size
597 // [2].memref - output (decrypted data)
599 if (key.size() != KM_KEY_ID_SIZE) {
600 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
603 KM_BufferSizeDesc bufSize;
605 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
606 bufSize.input_size = static_cast<uint32_t>(data.size());
607 bufSize.with_pwd_data = true;
608 bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
609 bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
610 bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
611 bufSize.iv_size = static_cast<uint32_t>(iv.size());
612 bufSize.key_id_size = static_cast<uint32_t>(key.size());
613 bufSize.with_ae_data = true;
614 bufSize.aad_size = static_cast<uint32_t>(aad.size());
615 bufSize.tag_size = static_cast<uint32_t>(tag.size());
616 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
617 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
619 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
620 bufSize.out_size = static_cast<uint32_t>(data.size());
621 uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
622 TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
624 KM_SymmetricInput* input = nullptr;
625 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
627 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
630 ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
632 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
635 uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
636 ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
637 pwd.getIV().data(), pwd.getIV().size(),
638 pwd.getTag().data(), pwd.getTag().size(),
639 Params::DERIVED_KEY_LENGTH_BITS,
640 Params::DERIVED_KEY_ITERATIONS,
643 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
646 ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
648 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
651 ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
653 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
656 ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
658 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
661 ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
663 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
667 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
668 TEEC_MEMREF_WHOLE, TEEC_NONE);
669 op.params[0].value.a = ALGO_AES_GCM;
670 op.params[1].memref.parent = inMemory.Get();
671 op.params[1].memref.offset = 0;
672 op.params[1].memref.size = inMemory.Get()->size;
673 op.params[2].memref.parent = outMemory.Get();
674 op.params[2].memref.offset = 0;
675 op.params[2].memref.size = outMemory.Get()->size;
676 Execute(CMD_DECRYPT, &op);
678 KM_SymmetricInput* output = nullptr;
679 ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
681 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
684 KM_OutData* outData = nullptr;
685 ret = KM_ParamsDeserializeOutData(output, &outData);
687 ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
690 out.resize(outData->data_size);
691 memcpy(out.data(), outData->data, outData->data_size);
694 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
696 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
698 // TEEC_Operation layout:
700 // [1].memref - input data (serialized key ID)
702 // [0].value.a - return code
704 if (keyId.size() != KM_KEY_ID_SIZE) {
705 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
708 KM_BufferSizeDesc bufSize;
710 memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
711 bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
712 uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
713 TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
715 KM_SymmetricInput* input = nullptr;
716 int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
718 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
721 ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
723 ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
727 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
728 TEEC_NONE, TEEC_NONE);
729 op.params[1].memref.parent = inMemory.Get();
730 op.params[1].memref.offset = 0;
731 op.params[1].memref.size = inMemory.Get()->size;
732 Execute(CMD_DESTROY_KEY, &op);
735 void TrustZoneContext::Initialize()
741 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
743 result = TEEC_InitializeContext(nullptr, &m_Context);
744 if (result != TEEC_SUCCESS) {
745 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
747 m_ContextInitialized = true;
749 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
750 if (result != TEEC_SUCCESS) {
751 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
753 m_SessionInitialized = true;
756 void TrustZoneContext::Destroy()
758 if (m_SessionInitialized) {
759 TEEC_CloseSession(&m_Session);
760 m_SessionInitialized = false;
763 if (m_ContextInitialized) {
764 TEEC_FinalizeContext(&m_Context);
765 m_ContextInitialized = false;
769 void TrustZoneContext::Reload()
775 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
777 LogDebug("Executing TZ operation " << commandID);
779 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, NULL);
780 if (result != TEEC_SUCCESS) {
782 case TEEC_ERROR_TARGET_DEAD:
784 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
785 static_cast<unsigned int>(commandID));
786 case TEEC_ERROR_BAD_PARAMETERS:
787 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
789 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
790 static_cast<unsigned int>(commandID), " with error: ", std::hex,
791 static_cast<unsigned int>(result));
795 int ta_ret = op->params[0].value.a;
796 if (ta_ret != KM_TA_SUCCESS) {
798 case KM_TA_ERROR_AUTH_FAILED:
799 // Authentication cipher failed - notify with proper exception
800 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
802 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
807 } // namespace Internals
809 } // namespace Crypto