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 uint32_t TrustZoneContext::initGcmCipher(uint32_t encrypt,
480 const RawBuffer &keyId,
484 const RawBuffer &aad)
486 // command ID = CMD_CIPHER_INIT (from km_ta_defines.h)
487 if (keyId.size() != KM_KEY_ID_SIZE) {
488 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
491 auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
492 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
493 sIn.Serialize(inMemory);
495 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
496 op.params[0].value.a = ALGO_AES_GCM;
497 op.params[0].value.b = encrypt;
499 Execute(CMD_CIPHER_INIT, &op);
501 return op.params[0].value.b;
504 void TrustZoneContext::addGcmAAD(uint32_t opId,
505 const RawBuffer &aad)
507 // command ID = CMD_CIPHER_INIT_AAD (from km_ta_defines.h)
508 auto sIn = makeSerializer(aad);
509 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
510 sIn.Serialize(inMemory);
512 TEEC_Operation op = makeOp(TEEC_VALUE_INPUT, inMemory);
513 op.params[0].value.a = opId;
515 Execute(CMD_CIPHER_INIT_AAD, &op);
518 RawBuffer TrustZoneContext::updateGcmCipher(uint32_t opId,
519 const RawBuffer &data)
521 auto sIn = makeSerializer(data);
522 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
523 sIn.Serialize(inMemory);
526 sOut.Push(new TZSerializableBinary(data.size()));
527 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
529 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
530 op.params[0].value.a = opId;
532 Execute(CMD_CIPHER_UPDATE, &op);
534 sOut.Deserialize(outMemory);
541 RawBuffer TrustZoneContext::finalizeGcmCipher(uint32_t opId,
542 const RawBuffer &data)
544 auto sIn = makeSerializer(data);
545 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
546 sIn.Serialize(inMemory);
549 sOut.Push(new TZSerializableBinary(data.size()));
550 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
552 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
553 op.params[0].value.a = opId;
555 Execute(CMD_CIPHER_FINALIZE, &op);
557 sOut.Deserialize(outMemory);
564 void TrustZoneContext::executeSign(tz_algo_type algo,
566 const RawBuffer &keyId,
568 const RawBuffer &message,
569 RawBuffer &signature)
571 // command ID = CMD_SIGN (from km_ta_defines.h)
572 if (keyId.size() != KM_KEY_ID_SIZE) {
573 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
574 + std::to_string(keyId.size()) + ")");
577 auto sIn = makeSerializer(message, pwd, keyId);
578 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
579 sIn.Serialize(inMemory);
582 sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
583 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
585 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
586 op.params[0].value.a = algo;
587 op.params[0].value.b = hash;
589 Execute(CMD_SIGN, &op);
591 sOut.Deserialize(outMemory);
592 sOut.Pull(signature);
595 int TrustZoneContext::executeVerify(tz_algo_type algo,
597 const RawBuffer &keyId,
599 const RawBuffer &message,
600 const RawBuffer &signature)
602 // command ID = CMD_VERIFY (from km_ta_defines.h)
603 if (keyId.size() != KM_KEY_ID_SIZE) {
604 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
605 + std::to_string(keyId.size()) + ")");
608 auto sIn = makeSerializer(message, signature, pwd, keyId);
609 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
610 sIn.Serialize(inMemory);
612 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
613 op.params[0].value.a = algo;
614 op.params[0].value.b = hash;
616 Execute(CMD_VERIFY, &op);
618 int opRet = op.params[0].value.a;
621 return CKM_API_SUCCESS;
622 case KM_TA_ERROR_SIGNATURE:
623 LogWarning("Signature verification failed");
624 return CKM_API_ERROR_VERIFICATION_FAILED;
626 assert(false); // This condition should be checked inside Execute() function
627 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
631 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
633 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
634 if (keyId.size() != KM_KEY_ID_SIZE) {
635 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
638 auto sIn = makeSerializer(keyId);
639 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
640 sIn.Serialize(inMemory);
642 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
644 Execute(CMD_DESTROY_KEY, &op);
647 void TrustZoneContext::importData(
648 const uint32_t dataType,
649 const RawBuffer &data,
650 const Crypto::EncryptionParams &encData,
651 const RawBuffer &pwd,
653 const uint32_t keySizeBits,
655 const RawBuffer &hash)
657 // command ID = CMD_IMPORT_DATA
658 LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
660 auto sIn = makeSerializer(
661 dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
663 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
664 sIn.Serialize(inMemory);
668 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
671 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
673 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
675 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
677 Execute(CMD_IMPORT_DATA, &op);
680 sOut.Deserialize(outMemory);
684 LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
687 void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKey,
688 const Pwd &wrappingKeyPwd,
691 const uint32_t ctrLenOrTagSizeBits,
692 const RawBuffer &aad,
693 const tz_data_type encryptedKeyType,
694 const RawBuffer &encryptedKey,
695 const RawBuffer &encryptedKeyPwdBuf,
696 const RawBuffer &encryptedKeyIV,
697 RawBuffer &encryptedKeyTag,
698 const RawBuffer &encryptedKeyId)
700 // command ID = CMD_IMPORT_WRAPPED_KEY
701 LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
703 auto sIn = makeSerializer(wrappingKey,
711 EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
714 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
715 sIn.Serialize(inMemory);
718 if (!encryptedKeyPwdBuf.empty()) {
719 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
722 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
724 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
725 if (!encryptedKeyPwdBuf.empty())
726 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
728 Execute(CMD_IMPORT_WRAPPED_KEY, &op);
730 if (!encryptedKeyPwdBuf.empty()) {
731 sOut.Deserialize(outMemory);
732 sOut.Pull(encryptedKeyTag);
735 LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
738 RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKey,
739 const Pwd &wrappingKeyPwd,
742 const uint32_t ctrLenOrTagSizeBits,
743 const RawBuffer &aad,
744 const RawBuffer &keyToWrapId,
745 const Pwd &keyToWrapPwd)
747 // command ID = CMD_EXPORT_WRAPPED_KEY
748 LogDebug("TrustZoneContext::exportWrappedKey");
750 auto sIn = makeSerializer(wrappingKey,
759 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
760 sIn.Serialize(inMemory);
762 uint32_t data_size = 0;
763 GetDataSize(keyToWrapId, data_size);
765 LogDebug("GetData data_size = [" << data_size << "]");
767 // encrypted data may be longer
769 sOut.Push(new TZSerializableBinary(data_size + KM_ENCRYPTION_OVERHEAD));
770 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
771 sOut.Serialize(outMemory);
773 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
775 Execute(CMD_EXPORT_WRAPPED_KEY, &op);
777 sOut.Deserialize(outMemory);
779 RawBuffer wrappedKey;
780 sOut.Pull(wrappedKey);
785 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
787 // command ID = CMD_GET_DATA_SIZE
788 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
790 auto sIn = makeSerializer(dataId);
791 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
792 sIn.Serialize(inMemory);
794 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
796 Execute(CMD_GET_DATA_SIZE, &op);
797 dataSize = op.params[0].value.b;
800 void TrustZoneContext::getData(const RawBuffer &dataId,
804 // command ID = CMD_GET_DATA
805 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
807 auto sIn = makeSerializer(dataId, pwd);
808 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
809 sIn.Serialize(inMemory);
811 uint32_t data_size = 0;
812 GetDataSize(dataId, data_size);
814 LogDebug("GetData data_size = [" << data_size << "]");
817 sOut.Push(new TZSerializableBinary(data_size));
818 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
819 sOut.Serialize(outMemory);
821 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
823 Execute(CMD_GET_DATA, &op);
825 sOut.Deserialize(outMemory);
830 void TrustZoneContext::destroyData(const RawBuffer &dataId)
832 // command ID = CMD_DESTROY_DATA
833 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
834 auto sIn = makeSerializer(dataId);
835 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
836 sIn.Serialize(inMemory);
838 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
840 Execute(CMD_DESTROY_DATA, &op);
843 TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
845 auto &tag = pwd.getTag();
846 return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
849 void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
850 const Pwd &prvKeyPwd,
851 const RawBuffer &pubX,
852 const RawBuffer &pubY,
853 const RawBuffer &secretPwdBuf,
854 const RawBuffer &secretPwdIV,
855 RawBuffer &secretTag,
856 const RawBuffer &secretHash)
858 // command ID = CMD_DERIVE
859 LogDebug("TrustZoneContext::executeEcdh");
861 auto sIn = makeSerializer(
862 prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
863 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
864 sIn.Serialize(inMemory);
867 if (!secretPwdBuf.empty()) {
868 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
871 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
873 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
874 if (!secretPwdBuf.empty())
875 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
876 op.params[0].value.a = ALGO_ECDH_DRV;
878 Execute(CMD_DERIVE, &op);
880 if (!secretPwdBuf.empty()) {
881 sOut.Deserialize(outMemory);
882 sOut.Pull(secretTag);
885 LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
888 void TrustZoneContext::executeKbkdf(const RawBuffer& secret,
889 const RawBuffer& label,
890 const RawBuffer& context,
891 const RawBuffer& fixed,
894 tz_kbkdf_ctr_loc location,
898 const RawBuffer &keyPwdBuf,
899 const RawBuffer &keyPwdIV,
901 const RawBuffer &keyHash)
903 // command ID = CMD_DERIVE
904 LogDebug("TrustZoneContext::executeKbkdf");
906 auto sIn = makeSerializer(secret,
916 EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
918 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
919 sIn.Serialize(inMemory);
922 if (!keyPwdBuf.empty()) {
923 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
926 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
928 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
929 if (!keyPwdBuf.empty())
930 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
931 op.params[0].value.a = ALGO_KBKDF_DRV;
933 Execute(CMD_DERIVE, &op);
935 if (!keyPwdBuf.empty()) {
936 sOut.Deserialize(outMemory);
940 LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
943 void TrustZoneContext::Initialize()
949 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
951 result = TEEC_InitializeContext(nullptr, &m_Context);
952 if (result != TEEC_SUCCESS) {
953 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
955 m_ContextInitialized = true;
957 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
958 if (result != TEEC_SUCCESS) {
959 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
961 m_SessionInitialized = true;
964 void TrustZoneContext::Destroy()
966 if (m_SessionInitialized) {
967 TEEC_CloseSession(&m_Session);
968 m_SessionInitialized = false;
971 if (m_ContextInitialized) {
972 TEEC_FinalizeContext(&m_Context);
973 m_ContextInitialized = false;
977 void TrustZoneContext::Reload()
983 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
985 uint32_t retOrigin = 0;
986 LogDebug("Executing TZ operation " << commandID);
988 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
989 if (result != TEEC_SUCCESS) {
991 case TEEC_ERROR_TARGET_DEAD:
993 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
994 static_cast<unsigned int>(commandID));
995 case TEEC_ERROR_BAD_PARAMETERS:
996 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
998 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
999 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1000 static_cast<unsigned int>(result), " with origin: ", std::hex,
1005 int ta_ret = op->params[0].value.a;
1008 case KM_TA_ERROR_SIGNATURE:
1010 case KM_TA_ERROR_AUTH_FAILED:
1011 // Authentication cipher failed - notify with proper exception
1012 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1014 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1018 } // namespace Internals
1020 } // namespace Crypto