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 // Maximum size of GCM tag in bytes.
54 const size_t MAX_GCM_TAG_SIZE = 16;
56 // Identifier of our TA
57 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
59 //raw to hex string conversion to print persistent storage data ID
60 static std::string rawToHexString(const RawBuffer &raw)
62 return hexDump<std::string>(raw);
66 * Maximum size for given key type in bytes according to key-manager-ta implementation.
67 * Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
69 const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
70 { ALGO_RSA, 4096 / 8 },
71 { ALGO_RSA_SV, 4096 / 8 },
72 { ALGO_DSA_SV, 4096 / 8 },
73 { ALGO_ECDSA_SV, 1024 / 8 } // 384*2 + additional space for DERR encoding
77 const RawBuffer &password;
82 void push(TZSerializer& ser, const T& value)
84 ser.Push(new TZSerializableFlag(static_cast<uint32_t>(value)));
88 void push<RawBuffer>(TZSerializer& ser, const RawBuffer& value)
90 ser.Push(new TZSerializableBinary(value));
94 void push<Pwd>(TZSerializer& ser, const Pwd& value)
96 int32_t pwd_flag = value.getPassword().empty() ? 0 : 1;
97 ser.Push(new TZSerializableFlag(pwd_flag));
99 ser.Push(new TZSerializablePwdData(value.getPassword(),
101 value.getTag().size() * 8,
106 void push<EncPwd>(TZSerializer& ser, const EncPwd& value)
108 int32_t pwd_flag = value.password.empty() ? 0 : 1;
109 ser.Push(new TZSerializableFlag(pwd_flag));
111 ser.Push(new TZSerializablePwdData(value.password,
113 Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
116 template <typename T, typename ...Args>
117 void push(TZSerializer& ser, const T& first, const Args&... args)
120 push<Args...>(ser, args...);
123 template <typename ...Args>
124 TZSerializer makeSerializer(const Args&... args)
127 push<Args...>(ser, args...);
131 } // anonymous namespace
133 TrustZoneContext::TrustZoneContext()
134 : m_ContextInitialized(false)
135 , m_SessionInitialized(false)
140 TrustZoneContext::~TrustZoneContext()
145 TrustZoneContext& TrustZoneContext::Instance()
147 static TrustZoneContext instance;
151 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1)
155 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE);
157 op.params[1].memref.parent = mem1.Get();
158 op.params[1].memref.offset = 0;
159 op.params[1].memref.size = mem1.Get()->size;
163 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2)
165 TEEC_Operation op = makeOp(value, mem1);
167 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE);
169 op.params[2].memref.parent = mem2.Get();
170 op.params[2].memref.offset = 0;
171 op.params[2].memref.size = mem2.Get()->size;
176 void TrustZoneContext::generateIV(RawBuffer& iv)
178 // command ID = CMD_GENERATE_IV
179 // IV generation is a simple call - no need to serialize data
180 // just provide the output buffer with size equal to iv.
181 uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
182 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
184 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, ivMemory);
186 Execute(CMD_GENERATE_IV, &op);
189 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
192 void TrustZoneContext::generateSKey(tz_algo_type algo,
193 uint32_t keySizeBits,
194 const RawBuffer &hash)
196 // command ID = CMD_GENERATE_KEY
197 auto sIn = makeSerializer(hash);
198 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
199 sIn.Serialize(inMemory);
201 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
202 op.params[0].value.a = algo;
203 op.params[0].value.b = keySizeBits;
205 Execute(CMD_GENERATE_KEY, &op);
208 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
209 const RawBuffer &pwd,
211 const uint32_t keySizeBits,
213 const RawBuffer &hash)
215 // command ID = CMD_GENERATE_KEY_PWD
217 sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
218 sIn.Push(new TZSerializableBinary(hash));
219 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
220 sIn.Serialize(inMemory);
223 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
224 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
226 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
227 op.params[0].value.a = algo;
228 op.params[0].value.b = keySizeBits;
230 Execute(CMD_GENERATE_KEY_PWD, &op);
232 sOut.Deserialize(outMemory);
235 if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
236 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
240 void TrustZoneContext::GenerateAKey(tz_command commandId,
242 uint32_t genParam, // key size in bits or EC type
243 const RawBuffer &pubPwd,
244 const RawBuffer &pubPwdIv,
245 const RawBuffer &privPwd,
246 const RawBuffer &privPwdIv,
247 RawBuffer &pubKeyTag,
248 RawBuffer &privKeyTag,
249 const RawBuffer &hashPriv,
250 const RawBuffer &hashPub)
252 uint32_t pubTagSize = 0;
253 uint32_t privTagSize = 0;
254 uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
256 pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
258 uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
260 privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
263 push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub);
264 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
265 sIn.Serialize(inMemory);
268 sOut.Push(new TZSerializableBinary(pubTagSize));
269 sOut.Push(new TZSerializableBinary(privTagSize));
271 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
273 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
274 op.params[0].value.b = genParam;
276 Execute(commandId, &op);
278 sOut.Deserialize(outMemory);
280 sOut.Pull(pubKeyTag);
284 sOut.Pull(privKeyTag);
288 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
289 const RawBuffer &pubPwd,
290 const RawBuffer &pubPwdIv,
291 const RawBuffer &privPwd,
292 const RawBuffer &privPwdIv,
293 RawBuffer &pubKeyTag,
294 RawBuffer &privKeyTag,
295 const RawBuffer &hashPriv,
296 const RawBuffer &hashPub)
298 // command ID = CMD_GENERATE_RSA_KEYPAIR
301 GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
314 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
315 const RawBuffer &prime,
316 const RawBuffer &subprime,
317 const RawBuffer &base,
318 const RawBuffer &pubPwd,
319 const RawBuffer &pubPwdIv,
320 const RawBuffer &privPwd,
321 const RawBuffer &privPwdIv,
322 RawBuffer &pubKeyTag,
323 RawBuffer &privKeyTag,
324 const RawBuffer &hashPriv,
325 const RawBuffer &hashPub)
327 // command ID = CMD_GENERATE_DSA_KEYPAIR
328 auto sIn = makeSerializer(prime, subprime, base);
330 GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
343 void TrustZoneContext::generateECKey(tz_ec ec,
344 const RawBuffer &pubPwd,
345 const RawBuffer &pubPwdIv,
346 const RawBuffer &privPwd,
347 const RawBuffer &privPwdIv,
348 RawBuffer &pubKeyTag,
349 RawBuffer &privKeyTag,
350 const RawBuffer &hashPriv,
351 const RawBuffer &hashPub)
353 // command ID = CMD_GENERATE_EC_KEYPAIR
356 GenerateAKey(CMD_GENERATE_EC_KEYPAIR,
358 static_cast<uint32_t>(ec),
369 void TrustZoneContext::executeCrypt(tz_command cmd,
371 const RawBuffer &keyId,
374 const RawBuffer &data,
377 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
378 if (keyId.size() != KM_KEY_ID_SIZE) {
379 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
380 + std::to_string(keyId.size()) + ")");
384 if (algo == ALGO_RSA)
385 sIn = makeSerializer(data, pwd, keyId);
387 sIn = makeSerializer(data, pwd, iv, keyId);
389 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
390 sIn.Serialize(inMemory);
392 // decrypt operation does not require padding
393 uint32_t outMemorySize = data.size();
394 if (cmd == CMD_ENCRYPT) {
395 if (algo == ALGO_RSA) {
396 // We don't know the key length
397 outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
399 outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
404 sOut.Push(new TZSerializableBinary(outMemorySize, false));
405 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
407 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
408 op.params[0].value.a = algo;
412 sOut.Deserialize(outMemory);
416 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
420 const RawBuffer &aad,
421 const RawBuffer &data,
425 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
426 if (keyId.size() != KM_KEY_ID_SIZE) {
427 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
430 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
431 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
432 sIn.Serialize(inMemory);
434 uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
435 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
438 sOut.Push(new TZSerializableBinary(outMemorySize, false));
439 sOut.Push(new TZSerializableBinary(tagSizeBytes));
440 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
442 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
443 op.params[0].value.a = ALGO_AES_GCM;
445 Execute(CMD_ENCRYPT, &op);
447 sOut.Deserialize(outMemory);
452 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
456 const RawBuffer &tag,
457 const RawBuffer &aad,
458 const RawBuffer &data,
461 // command ID = CMD_DECRYPT (from km_ta_defines.h)
462 if (keyId.size() != KM_KEY_ID_SIZE) {
463 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
466 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
467 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
468 sIn.Serialize(inMemory);
471 sOut.Push(new TZSerializableBinary(data.size()));
472 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
474 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
475 op.params[0].value.a = ALGO_AES_GCM;
477 Execute(CMD_DECRYPT, &op);
479 sOut.Deserialize(outMemory);
483 uint32_t TrustZoneContext::initGcmCipher(uint32_t encrypt,
484 const RawBuffer &keyId,
488 const RawBuffer &aad)
490 // command ID = CMD_CIPHER_INIT (from km_ta_defines.h)
491 if (keyId.size() != KM_KEY_ID_SIZE) {
492 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
495 auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
496 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
497 sIn.Serialize(inMemory);
499 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
500 op.params[0].value.a = ALGO_AES_GCM;
501 op.params[0].value.b = encrypt;
503 Execute(CMD_CIPHER_INIT, &op);
505 return op.params[0].value.b;
508 void TrustZoneContext::addGcmAAD(uint32_t opId,
509 const RawBuffer &aad)
511 // command ID = CMD_CIPHER_INIT_AAD (from km_ta_defines.h)
512 auto sIn = makeSerializer(aad);
513 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
514 sIn.Serialize(inMemory);
516 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
517 op.params[0].value.a = opId;
519 Execute(CMD_CIPHER_INIT_AAD, &op);
522 RawBuffer TrustZoneContext::updateGcmCipher(uint32_t opId,
523 const RawBuffer &data)
525 auto sIn = makeSerializer(data);
526 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
527 sIn.Serialize(inMemory);
530 sOut.Push(new TZSerializableBinary(data.size()));
531 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
533 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
534 op.params[0].value.a = opId;
536 Execute(CMD_CIPHER_UPDATE, &op);
538 sOut.Deserialize(outMemory);
545 RawBuffer TrustZoneContext::finalizeGcmCipher(uint32_t opId,
546 const RawBuffer &data)
548 auto sIn = makeSerializer(data);
549 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
550 sIn.Serialize(inMemory);
553 sOut.Push(new TZSerializableBinary(MAX_GCM_TAG_SIZE, false));
554 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
556 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
557 op.params[0].value.a = opId;
559 Execute(CMD_CIPHER_FINALIZE, &op);
561 sOut.Deserialize(outMemory);
568 void TrustZoneContext::executeSign(tz_algo_type algo,
570 const RawBuffer &keyId,
572 const RawBuffer &message,
573 RawBuffer &signature)
575 // command ID = CMD_SIGN (from km_ta_defines.h)
576 if (keyId.size() != KM_KEY_ID_SIZE) {
577 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
578 + std::to_string(keyId.size()) + ")");
581 auto sIn = makeSerializer(message, pwd, keyId);
582 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
583 sIn.Serialize(inMemory);
586 sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
587 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
589 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
590 op.params[0].value.a = algo;
591 op.params[0].value.b = hash;
593 Execute(CMD_SIGN, &op);
595 sOut.Deserialize(outMemory);
596 sOut.Pull(signature);
599 int TrustZoneContext::executeVerify(tz_algo_type algo,
601 const RawBuffer &keyId,
603 const RawBuffer &message,
604 const RawBuffer &signature)
606 // command ID = CMD_VERIFY (from km_ta_defines.h)
607 if (keyId.size() != KM_KEY_ID_SIZE) {
608 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
609 + std::to_string(keyId.size()) + ")");
612 auto sIn = makeSerializer(message, signature, pwd, keyId);
613 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
614 sIn.Serialize(inMemory);
616 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
617 op.params[0].value.a = algo;
618 op.params[0].value.b = hash;
620 Execute(CMD_VERIFY, &op);
622 int opRet = op.params[0].value.a;
625 return CKM_API_SUCCESS;
626 case KM_TA_ERROR_SIGNATURE:
627 LogWarning("Signature verification failed");
628 return CKM_API_ERROR_VERIFICATION_FAILED;
630 assert(false); // This condition should be checked inside Execute() function
631 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
635 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
637 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
638 if (keyId.size() != KM_KEY_ID_SIZE) {
639 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
642 auto sIn = makeSerializer(keyId);
643 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
644 sIn.Serialize(inMemory);
646 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
648 Execute(CMD_DESTROY_KEY, &op);
651 void TrustZoneContext::importData(
652 const uint32_t dataType,
653 const RawBuffer &data,
654 const Crypto::EncryptionParams &encData,
655 const RawBuffer &pwd,
657 const uint32_t keySizeBits,
659 const RawBuffer &hash)
661 // command ID = CMD_IMPORT_DATA
662 LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
664 auto sIn = makeSerializer(
665 dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
667 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
668 sIn.Serialize(inMemory);
672 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
675 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
677 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
679 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
681 Execute(CMD_IMPORT_DATA, &op);
684 sOut.Deserialize(outMemory);
688 LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
691 void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKeyId,
692 const Pwd &wrappingKeyPwd,
695 const uint32_t ctrLenOrTagSizeBits,
696 const RawBuffer &aad,
697 const tz_data_type encryptedKeyType,
698 const RawBuffer &encryptedKey,
699 const RawBuffer &encryptedKeyPwdBuf,
700 const RawBuffer &encryptedKeyIV,
701 RawBuffer &encryptedKeyTag,
702 const RawBuffer &encryptedKeyId)
704 // command ID = CMD_IMPORT_WRAPPED_KEY
705 LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
707 auto sIn = makeSerializer(wrappingKeyId,
715 EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
718 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
719 sIn.Serialize(inMemory);
722 if (!encryptedKeyPwdBuf.empty()) {
723 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
726 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
728 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
729 if (!encryptedKeyPwdBuf.empty())
730 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
732 Execute(CMD_IMPORT_WRAPPED_KEY, &op);
734 if (!encryptedKeyPwdBuf.empty()) {
735 sOut.Deserialize(outMemory);
736 sOut.Pull(encryptedKeyTag);
739 LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
742 RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKeyId,
743 const Pwd &wrappingKeyPwd,
746 const uint32_t ctrLenOrTagSizeBits,
747 const RawBuffer &aad,
748 const RawBuffer &keyToWrapId,
749 const Pwd &keyToWrapPwd)
751 // command ID = CMD_EXPORT_WRAPPED_KEY
752 LogDebug("TrustZoneContext::exportWrappedKey");
754 auto sIn = makeSerializer(wrappingKeyId,
763 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
764 sIn.Serialize(inMemory);
766 uint32_t data_size = 0;
767 GetDataSize(keyToWrapId, data_size);
769 LogDebug("GetData data_size = [" << data_size << "]");
771 // encrypted data may be longer
773 sOut.Push(new TZSerializableBinary(data_size + KM_ENCRYPTION_OVERHEAD));
774 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
775 sOut.Serialize(outMemory);
777 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
779 Execute(CMD_EXPORT_WRAPPED_KEY, &op);
781 sOut.Deserialize(outMemory);
783 RawBuffer wrappedKey;
784 sOut.Pull(wrappedKey);
789 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
791 // command ID = CMD_GET_DATA_SIZE
792 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
794 auto sIn = makeSerializer(dataId);
795 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
796 sIn.Serialize(inMemory);
798 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
800 Execute(CMD_GET_DATA_SIZE, &op);
801 dataSize = op.params[0].value.b;
804 void TrustZoneContext::getData(const RawBuffer &dataId,
808 // command ID = CMD_GET_DATA
809 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
811 auto sIn = makeSerializer(dataId, pwd);
812 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
813 sIn.Serialize(inMemory);
815 uint32_t data_size = 0;
816 GetDataSize(dataId, data_size);
818 LogDebug("GetData data_size = [" << data_size << "]");
821 sOut.Push(new TZSerializableBinary(data_size));
822 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
823 sOut.Serialize(outMemory);
825 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
827 Execute(CMD_GET_DATA, &op);
829 sOut.Deserialize(outMemory);
834 void TrustZoneContext::destroyData(const RawBuffer &dataId)
836 // command ID = CMD_DESTROY_DATA
837 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
838 auto sIn = makeSerializer(dataId);
839 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
840 sIn.Serialize(inMemory);
842 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
844 Execute(CMD_DESTROY_DATA, &op);
847 TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
849 auto &tag = pwd.getTag();
850 return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
853 void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
854 const Pwd &prvKeyPwd,
855 const RawBuffer &pubX,
856 const RawBuffer &pubY,
857 const RawBuffer &secretPwdBuf,
858 const RawBuffer &secretPwdIV,
859 RawBuffer &secretTag,
860 const RawBuffer &secretHash)
862 // command ID = CMD_DERIVE
863 LogDebug("TrustZoneContext::executeEcdh");
865 auto sIn = makeSerializer(
866 prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
867 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
868 sIn.Serialize(inMemory);
871 if (!secretPwdBuf.empty()) {
872 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
875 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
877 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
878 if (!secretPwdBuf.empty())
879 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
880 op.params[0].value.a = ALGO_ECDH_DRV;
882 Execute(CMD_DERIVE, &op);
884 if (!secretPwdBuf.empty()) {
885 sOut.Deserialize(outMemory);
886 sOut.Pull(secretTag);
889 LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
892 void TrustZoneContext::executeKbkdf(const RawBuffer& secretId,
893 const RawBuffer& label,
894 const RawBuffer& context,
895 const RawBuffer& fixed,
898 tz_kbkdf_ctr_loc location,
902 const RawBuffer &keyPwdBuf,
903 const RawBuffer &keyPwdIV,
905 const RawBuffer &keyHash)
907 // command ID = CMD_DERIVE
908 LogDebug("TrustZoneContext::executeKbkdf");
910 auto sIn = makeSerializer(secretId,
920 EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
922 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
923 sIn.Serialize(inMemory);
926 if (!keyPwdBuf.empty()) {
927 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
930 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
932 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
933 if (!keyPwdBuf.empty())
934 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
935 op.params[0].value.a = ALGO_KBKDF_DRV;
937 Execute(CMD_DERIVE, &op);
939 if (!keyPwdBuf.empty()) {
940 sOut.Deserialize(outMemory);
944 LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
947 void TrustZoneContext::Initialize()
953 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
955 result = TEEC_InitializeContext(nullptr, &m_Context);
956 if (result != TEEC_SUCCESS) {
957 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
959 m_ContextInitialized = true;
961 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
962 if (result != TEEC_SUCCESS) {
963 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
965 m_SessionInitialized = true;
968 void TrustZoneContext::Destroy()
970 if (m_SessionInitialized) {
971 TEEC_CloseSession(&m_Session);
972 m_SessionInitialized = false;
975 if (m_ContextInitialized) {
976 TEEC_FinalizeContext(&m_Context);
977 m_ContextInitialized = false;
981 void TrustZoneContext::Reload()
987 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
989 uint32_t retOrigin = 0;
990 LogDebug("Executing TZ operation " << commandID);
992 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
993 if (result != TEEC_SUCCESS) {
995 case TEEC_ERROR_TARGET_DEAD:
997 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
998 static_cast<unsigned int>(commandID));
999 case TEEC_ERROR_BAD_PARAMETERS:
1000 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1002 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1003 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1004 static_cast<unsigned int>(result), " with origin: ", std::hex,
1009 int ta_ret = op->params[0].value.a;
1012 case KM_TA_ERROR_SIGNATURE:
1014 case KM_TA_ERROR_AUTH_FAILED:
1015 // Authentication cipher failed - notify with proper exception
1016 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1018 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1022 } // namespace Internals
1024 } // namespace Crypto