2 * Copyright (c) 2017-2021 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 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
24 #include <tz-backend/tz-context.h>
25 #include <tz-backend/tz-memory.h>
26 #include <generic-backend/exception.h>
27 #include <generic-backend/crypto-params.h>
28 #include <generic-backend/encryption-params.h>
29 #include <dpl/log/log.h>
31 #include <km_serialization.h>
32 #include <km_ta_defines.h>
37 #include <unordered_map>
46 // A little bit of extra memory to add to output buffers.
48 // We need this extra memory to output for padding purposes - after encryption
49 // we can resize the result memory back to its proper size according to
50 // whatever TA will return us.
51 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
53 // Identifier of our TA
54 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
56 //raw to hex string conversion to print persistent storage data ID
57 static std::string rawToHexString(const RawBuffer &raw)
59 return hexDump<std::string>(raw);
63 * Maximum size for given key type in bytes according to key-manager-ta implementation.
64 * Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
66 const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
67 { ALGO_RSA, 4096 / 8 },
68 { ALGO_RSA_SV, 4096 / 8 },
69 { ALGO_DSA_SV, 4096 / 8 }
73 const RawBuffer &password;
78 void push(TZSerializer& ser, const T& value)
80 ser.Push(new TZSerializableFlag(static_cast<uint32_t>(value)));
84 void push<RawBuffer>(TZSerializer& ser, const RawBuffer& value)
86 ser.Push(new TZSerializableBinary(value));
90 void push<Pwd>(TZSerializer& ser, const Pwd& value)
92 int32_t pwd_flag = value.getPassword().empty() ? 0 : 1;
93 ser.Push(new TZSerializableFlag(pwd_flag));
95 ser.Push(new TZSerializablePwdData(value.getPassword(),
97 value.getTag().size() * 8,
102 void push<EncPwd>(TZSerializer& ser, const EncPwd& value)
104 int32_t pwd_flag = value.password.empty() ? 0 : 1;
105 ser.Push(new TZSerializableFlag(pwd_flag));
107 ser.Push(new TZSerializablePwdData(value.password,
109 Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
112 template <typename T, typename ...Args>
113 void push(TZSerializer& ser, const T& first, const Args&... args)
116 push<Args...>(ser, args...);
119 template <typename ...Args>
120 TZSerializer makeSerializer(const Args&... args)
123 push<Args...>(ser, args...);
127 } // anonymous namespace
129 TrustZoneContext::TrustZoneContext()
130 : m_ContextInitialized(false)
131 , m_SessionInitialized(false)
136 TrustZoneContext::~TrustZoneContext()
141 TrustZoneContext& TrustZoneContext::Instance()
143 static TrustZoneContext instance;
147 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1)
151 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE);
153 op.params[1].memref.parent = mem1.Get();
154 op.params[1].memref.offset = 0;
155 op.params[1].memref.size = mem1.Get()->size;
159 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2)
161 TEEC_Operation op = makeOp(value, mem1);
163 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE);
165 op.params[2].memref.parent = mem2.Get();
166 op.params[2].memref.offset = 0;
167 op.params[2].memref.size = mem2.Get()->size;
172 void TrustZoneContext::generateIV(RawBuffer& iv)
174 // command ID = CMD_GENERATE_IV
175 // IV generation is a simple call - no need to serialize data
176 // just provide the output buffer with size equal to iv.
177 uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
178 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
180 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, ivMemory);
182 Execute(CMD_GENERATE_IV, &op);
185 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
188 void TrustZoneContext::generateSKey(tz_algo_type algo,
189 uint32_t keySizeBits,
190 const RawBuffer &hash)
192 // command ID = CMD_GENERATE_KEY
193 auto sIn = makeSerializer(hash);
194 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
195 sIn.Serialize(inMemory);
197 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
198 op.params[0].value.a = algo;
199 op.params[0].value.b = keySizeBits;
201 Execute(CMD_GENERATE_KEY, &op);
204 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
205 const RawBuffer &pwd,
207 const uint32_t keySizeBits,
209 const RawBuffer &hash)
211 // command ID = CMD_GENERATE_KEY_PWD
213 sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
214 sIn.Push(new TZSerializableBinary(hash));
215 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
216 sIn.Serialize(inMemory);
219 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
220 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
222 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
223 op.params[0].value.a = algo;
224 op.params[0].value.b = keySizeBits;
226 Execute(CMD_GENERATE_KEY_PWD, &op);
228 sOut.Deserialize(outMemory);
231 if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
232 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
236 void TrustZoneContext::GenerateAKey(tz_command commandId,
238 uint32_t genParam, // key size in bits or EC type
239 const RawBuffer &pubPwd,
240 const RawBuffer &pubPwdIv,
241 const RawBuffer &privPwd,
242 const RawBuffer &privPwdIv,
243 RawBuffer &pubKeyTag,
244 RawBuffer &privKeyTag,
245 const RawBuffer &hashPriv,
246 const RawBuffer &hashPub)
248 uint32_t pubTagSize = 0;
249 uint32_t privTagSize = 0;
250 uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
252 pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
254 uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
256 privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
259 push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub);
260 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
261 sIn.Serialize(inMemory);
264 sOut.Push(new TZSerializableBinary(pubTagSize));
265 sOut.Push(new TZSerializableBinary(privTagSize));
267 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
269 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
270 op.params[0].value.b = genParam;
272 Execute(commandId, &op);
274 sOut.Deserialize(outMemory);
276 sOut.Pull(pubKeyTag);
280 sOut.Pull(privKeyTag);
284 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
285 const RawBuffer &pubPwd,
286 const RawBuffer &pubPwdIv,
287 const RawBuffer &privPwd,
288 const RawBuffer &privPwdIv,
289 RawBuffer &pubKeyTag,
290 RawBuffer &privKeyTag,
291 const RawBuffer &hashPriv,
292 const RawBuffer &hashPub)
294 // command ID = CMD_GENERATE_RSA_KEYPAIR
297 GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
310 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
311 const RawBuffer &prime,
312 const RawBuffer &subprime,
313 const RawBuffer &base,
314 const RawBuffer &pubPwd,
315 const RawBuffer &pubPwdIv,
316 const RawBuffer &privPwd,
317 const RawBuffer &privPwdIv,
318 RawBuffer &pubKeyTag,
319 RawBuffer &privKeyTag,
320 const RawBuffer &hashPriv,
321 const RawBuffer &hashPub)
323 // command ID = CMD_GENERATE_DSA_KEYPAIR
324 auto sIn = makeSerializer(prime, subprime, base);
326 GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
339 void TrustZoneContext::generateECKey(tz_ec ec,
340 const RawBuffer &pubPwd,
341 const RawBuffer &pubPwdIv,
342 const RawBuffer &privPwd,
343 const RawBuffer &privPwdIv,
344 RawBuffer &pubKeyTag,
345 RawBuffer &privKeyTag,
346 const RawBuffer &hashPriv,
347 const RawBuffer &hashPub)
349 // command ID = CMD_GENERATE_EC_KEYPAIR
352 GenerateAKey(CMD_GENERATE_EC_KEYPAIR,
354 static_cast<uint32_t>(ec),
365 void TrustZoneContext::executeCrypt(tz_command cmd,
367 const RawBuffer &keyId,
370 const RawBuffer &data,
373 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
374 if (keyId.size() != KM_KEY_ID_SIZE) {
375 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
376 + std::to_string(keyId.size()) + ")");
380 if (algo == ALGO_RSA)
381 sIn = makeSerializer(data, pwd, keyId);
383 sIn = makeSerializer(data, pwd, iv, keyId);
385 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
386 sIn.Serialize(inMemory);
388 // decrypt operation does not require padding
389 uint32_t outMemorySize = data.size();
390 if (cmd == CMD_ENCRYPT) {
391 if (algo == ALGO_RSA) {
392 // We don't know the key length
393 outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
395 outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
400 sOut.Push(new TZSerializableBinary(outMemorySize, false));
401 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
403 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
404 op.params[0].value.a = algo;
408 sOut.Deserialize(outMemory);
412 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
416 const RawBuffer &aad,
417 const RawBuffer &data,
421 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
422 if (keyId.size() != KM_KEY_ID_SIZE) {
423 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
426 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
427 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
428 sIn.Serialize(inMemory);
430 uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
431 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
434 sOut.Push(new TZSerializableBinary(outMemorySize, false));
435 sOut.Push(new TZSerializableBinary(tagSizeBytes));
436 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
438 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
439 op.params[0].value.a = ALGO_AES_GCM;
441 Execute(CMD_ENCRYPT, &op);
443 sOut.Deserialize(outMemory);
448 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
452 const RawBuffer &tag,
453 const RawBuffer &aad,
454 const RawBuffer &data,
457 // command ID = CMD_DECRYPT (from km_ta_defines.h)
458 if (keyId.size() != KM_KEY_ID_SIZE) {
459 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
462 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
463 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
464 sIn.Serialize(inMemory);
467 sOut.Push(new TZSerializableBinary(data.size()));
468 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
470 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
471 op.params[0].value.a = ALGO_AES_GCM;
473 Execute(CMD_DECRYPT, &op);
475 sOut.Deserialize(outMemory);
479 void TrustZoneContext::executeSign(tz_algo_type algo,
481 const RawBuffer &keyId,
483 const RawBuffer &message,
484 RawBuffer &signature)
486 // command ID = CMD_SIGN (from km_ta_defines.h)
487 if (keyId.size() != KM_KEY_ID_SIZE) {
488 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
489 + std::to_string(keyId.size()) + ")");
492 auto sIn = makeSerializer(message, pwd, keyId);
493 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
494 sIn.Serialize(inMemory);
497 sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
498 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
500 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
501 op.params[0].value.a = algo;
502 op.params[0].value.b = hash;
504 Execute(CMD_SIGN, &op);
506 sOut.Deserialize(outMemory);
507 sOut.Pull(signature);
510 int TrustZoneContext::executeVerify(tz_algo_type algo,
512 const RawBuffer &keyId,
514 const RawBuffer &message,
515 const RawBuffer &signature)
517 // command ID = CMD_VERIFY (from km_ta_defines.h)
518 if (keyId.size() != KM_KEY_ID_SIZE) {
519 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
520 + std::to_string(keyId.size()) + ")");
523 auto sIn = makeSerializer(message, signature, pwd, keyId);
524 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
525 sIn.Serialize(inMemory);
527 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
528 op.params[0].value.a = algo;
529 op.params[0].value.b = hash;
531 Execute(CMD_VERIFY, &op);
533 int opRet = op.params[0].value.a;
536 return CKM_API_SUCCESS;
537 case KM_TA_ERROR_SIGNATURE:
538 LogWarning("Signature verification failed");
539 return CKM_API_ERROR_VERIFICATION_FAILED;
541 assert(false); // This condition should be checked inside Execute() function
542 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
546 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
548 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
549 if (keyId.size() != KM_KEY_ID_SIZE) {
550 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
553 auto sIn = makeSerializer(keyId);
554 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
555 sIn.Serialize(inMemory);
557 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
559 Execute(CMD_DESTROY_KEY, &op);
562 void TrustZoneContext::importData(
563 const uint32_t dataType,
564 const RawBuffer &data,
565 const Crypto::EncryptionParams &encData,
566 const RawBuffer &pwd,
568 const uint32_t keySizeBits,
570 const RawBuffer &hash)
572 // command ID = CMD_IMPORT_DATA
573 LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
575 auto sIn = makeSerializer(
576 dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
578 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
579 sIn.Serialize(inMemory);
583 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
586 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
588 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
590 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
592 Execute(CMD_IMPORT_DATA, &op);
595 sOut.Deserialize(outMemory);
599 LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
602 void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKey,
603 const Pwd &wrappingKeyPwd,
606 const uint32_t ctrLenOrTagSizeBits,
607 const RawBuffer &aad,
608 const tz_data_type encryptedKeyType,
609 const RawBuffer &encryptedKey,
610 const RawBuffer &encryptedKeyPwdBuf,
611 const RawBuffer &encryptedKeyIV,
612 RawBuffer &encryptedKeyTag,
613 const RawBuffer &encryptedKeyId)
615 // command ID = CMD_IMPORT_WRAPPED_KEY
616 LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
618 auto sIn = makeSerializer(wrappingKey,
626 EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
629 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
630 sIn.Serialize(inMemory);
633 if (!encryptedKeyPwdBuf.empty()) {
634 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
637 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
639 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
640 if (!encryptedKeyPwdBuf.empty())
641 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
643 Execute(CMD_IMPORT_WRAPPED_KEY, &op);
645 if (!encryptedKeyPwdBuf.empty()) {
646 sOut.Deserialize(outMemory);
647 sOut.Pull(encryptedKeyTag);
650 LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
653 RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKey,
654 const Pwd &wrappingKeyPwd,
657 const uint32_t ctrLenOrTagSizeBits,
658 const RawBuffer &aad,
659 const RawBuffer &keyToWrapId,
660 const Pwd &keyToWrapPwd)
662 // command ID = CMD_EXPORT_WRAPPED_KEY
663 LogDebug("TrustZoneContext::exportWrappedKey");
665 auto sIn = makeSerializer(wrappingKey,
674 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
675 sIn.Serialize(inMemory);
677 uint32_t data_size = 0;
678 GetDataSize(keyToWrapId, data_size);
680 LogDebug("GetData data_size = [" << data_size << "]");
682 // encrypted data may be longer
684 sOut.Push(new TZSerializableBinary(data_size + KM_ENCRYPTION_OVERHEAD));
685 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
686 sOut.Serialize(outMemory);
688 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
690 Execute(CMD_EXPORT_WRAPPED_KEY, &op);
692 sOut.Deserialize(outMemory);
694 RawBuffer wrappedKey;
695 sOut.Pull(wrappedKey);
700 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
702 // command ID = CMD_GET_DATA_SIZE
703 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
705 auto sIn = makeSerializer(dataId);
706 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
707 sIn.Serialize(inMemory);
709 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
711 Execute(CMD_GET_DATA_SIZE, &op);
712 dataSize = op.params[0].value.b;
715 void TrustZoneContext::getData(const RawBuffer &dataId,
719 // command ID = CMD_GET_DATA
720 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
722 auto sIn = makeSerializer(dataId, pwd);
723 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
724 sIn.Serialize(inMemory);
726 uint32_t data_size = 0;
727 GetDataSize(dataId, data_size);
729 LogDebug("GetData data_size = [" << data_size << "]");
732 sOut.Push(new TZSerializableBinary(data_size));
733 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
734 sOut.Serialize(outMemory);
736 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
738 Execute(CMD_GET_DATA, &op);
740 sOut.Deserialize(outMemory);
745 void TrustZoneContext::destroyData(const RawBuffer &dataId)
747 // command ID = CMD_DESTROY_DATA
748 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
749 auto sIn = makeSerializer(dataId);
750 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
751 sIn.Serialize(inMemory);
753 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
755 Execute(CMD_DESTROY_DATA, &op);
758 TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
760 auto &tag = pwd.getTag();
761 return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
764 void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
765 const Pwd &prvKeyPwd,
766 const RawBuffer &pubX,
767 const RawBuffer &pubY,
768 const RawBuffer &secretPwdBuf,
769 const RawBuffer &secretPwdIV,
770 RawBuffer &secretTag,
771 const RawBuffer &secretHash)
773 // command ID = CMD_DERIVE
774 LogDebug("TrustZoneContext::executeEcdh");
776 auto sIn = makeSerializer(
777 prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
778 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
779 sIn.Serialize(inMemory);
782 if (!secretPwdBuf.empty()) {
783 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
786 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
788 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
789 if (!secretPwdBuf.empty())
790 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
791 op.params[0].value.a = ALGO_ECDH_DRV;
793 Execute(CMD_DERIVE, &op);
795 if (!secretPwdBuf.empty()) {
796 sOut.Deserialize(outMemory);
797 sOut.Pull(secretTag);
800 LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
803 void TrustZoneContext::executeKbkdf(const RawBuffer& secret,
806 tz_kbkdf_ctr_loc location,
810 const RawBuffer &keyPwdBuf,
811 const RawBuffer &keyPwdIV,
813 const RawBuffer &keyHash)
815 // command ID = CMD_DERIVE
816 LogDebug("TrustZoneContext::executeKbkdf");
818 auto sIn = makeSerializer(
819 secret, prf, mode, location, rlen, llen, noSeparator, EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
820 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
821 sIn.Serialize(inMemory);
824 if (!keyPwdBuf.empty()) {
825 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
828 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
830 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
831 if (!keyPwdBuf.empty())
832 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
833 op.params[0].value.a = ALGO_KBKDF_DRV;
835 Execute(CMD_DERIVE, &op);
837 if (!keyPwdBuf.empty()) {
838 sOut.Deserialize(outMemory);
842 LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
845 void TrustZoneContext::Initialize()
851 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
853 result = TEEC_InitializeContext(nullptr, &m_Context);
854 if (result != TEEC_SUCCESS) {
855 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
857 m_ContextInitialized = true;
859 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
860 if (result != TEEC_SUCCESS) {
861 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
863 m_SessionInitialized = true;
866 void TrustZoneContext::Destroy()
868 if (m_SessionInitialized) {
869 TEEC_CloseSession(&m_Session);
870 m_SessionInitialized = false;
873 if (m_ContextInitialized) {
874 TEEC_FinalizeContext(&m_Context);
875 m_ContextInitialized = false;
879 void TrustZoneContext::Reload()
885 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
887 uint32_t retOrigin = 0;
888 LogDebug("Executing TZ operation " << commandID);
890 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
891 if (result != TEEC_SUCCESS) {
893 case TEEC_ERROR_TARGET_DEAD:
895 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
896 static_cast<unsigned int>(commandID));
897 case TEEC_ERROR_BAD_PARAMETERS:
898 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
900 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
901 static_cast<unsigned int>(commandID), " with error: ", std::hex,
902 static_cast<unsigned int>(result), " with origin: ", std::hex,
907 int ta_ret = op->params[0].value.a;
910 case KM_TA_ERROR_SIGNATURE:
912 case KM_TA_ERROR_AUTH_FAILED:
913 // Authentication cipher failed - notify with proper exception
914 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
916 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
920 } // namespace Internals
922 } // namespace Crypto