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 },
70 { ALGO_ECDSA_SV, 1024 / 8 } // 384*2 + additional space for DERR encoding
74 const RawBuffer &password;
79 void push(TZSerializer& ser, const T& value)
81 ser.Push(new TZSerializableFlag(static_cast<uint32_t>(value)));
85 void push<RawBuffer>(TZSerializer& ser, const RawBuffer& value)
87 ser.Push(new TZSerializableBinary(value));
91 void push<Pwd>(TZSerializer& ser, const Pwd& value)
93 int32_t pwd_flag = value.getPassword().empty() ? 0 : 1;
94 ser.Push(new TZSerializableFlag(pwd_flag));
96 ser.Push(new TZSerializablePwdData(value.getPassword(),
98 value.getTag().size() * 8,
103 void push<EncPwd>(TZSerializer& ser, const EncPwd& value)
105 int32_t pwd_flag = value.password.empty() ? 0 : 1;
106 ser.Push(new TZSerializableFlag(pwd_flag));
108 ser.Push(new TZSerializablePwdData(value.password,
110 Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
113 template <typename T, typename ...Args>
114 void push(TZSerializer& ser, const T& first, const Args&... args)
117 push<Args...>(ser, args...);
120 template <typename ...Args>
121 TZSerializer makeSerializer(const Args&... args)
124 push<Args...>(ser, args...);
128 } // anonymous namespace
130 TrustZoneContext::TrustZoneContext()
131 : m_ContextInitialized(false)
132 , m_SessionInitialized(false)
137 TrustZoneContext::~TrustZoneContext()
142 TrustZoneContext& TrustZoneContext::Instance()
144 static TrustZoneContext instance;
148 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1)
152 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE);
154 op.params[1].memref.parent = mem1.Get();
155 op.params[1].memref.offset = 0;
156 op.params[1].memref.size = mem1.Get()->size;
160 TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2)
162 TEEC_Operation op = makeOp(value, mem1);
164 op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE);
166 op.params[2].memref.parent = mem2.Get();
167 op.params[2].memref.offset = 0;
168 op.params[2].memref.size = mem2.Get()->size;
173 void TrustZoneContext::generateIV(RawBuffer& iv)
175 // command ID = CMD_GENERATE_IV
176 // IV generation is a simple call - no need to serialize data
177 // just provide the output buffer with size equal to iv.
178 uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
179 TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
181 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, ivMemory);
183 Execute(CMD_GENERATE_IV, &op);
186 memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
189 void TrustZoneContext::generateSKey(tz_algo_type algo,
190 uint32_t keySizeBits,
191 const RawBuffer &hash)
193 // command ID = CMD_GENERATE_KEY
194 auto sIn = makeSerializer(hash);
195 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
196 sIn.Serialize(inMemory);
198 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
199 op.params[0].value.a = algo;
200 op.params[0].value.b = keySizeBits;
202 Execute(CMD_GENERATE_KEY, &op);
205 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
206 const RawBuffer &pwd,
208 const uint32_t keySizeBits,
210 const RawBuffer &hash)
212 // command ID = CMD_GENERATE_KEY_PWD
214 sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
215 sIn.Push(new TZSerializableBinary(hash));
216 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
217 sIn.Serialize(inMemory);
220 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
221 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
223 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
224 op.params[0].value.a = algo;
225 op.params[0].value.b = keySizeBits;
227 Execute(CMD_GENERATE_KEY_PWD, &op);
229 sOut.Deserialize(outMemory);
232 if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
233 ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
237 void TrustZoneContext::GenerateAKey(tz_command commandId,
239 uint32_t genParam, // key size in bits or EC type
240 const RawBuffer &pubPwd,
241 const RawBuffer &pubPwdIv,
242 const RawBuffer &privPwd,
243 const RawBuffer &privPwdIv,
244 RawBuffer &pubKeyTag,
245 RawBuffer &privKeyTag,
246 const RawBuffer &hashPriv,
247 const RawBuffer &hashPub)
249 uint32_t pubTagSize = 0;
250 uint32_t privTagSize = 0;
251 uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
253 pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
255 uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
257 privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
260 push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub);
261 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
262 sIn.Serialize(inMemory);
265 sOut.Push(new TZSerializableBinary(pubTagSize));
266 sOut.Push(new TZSerializableBinary(privTagSize));
268 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
270 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
271 op.params[0].value.b = genParam;
273 Execute(commandId, &op);
275 sOut.Deserialize(outMemory);
277 sOut.Pull(pubKeyTag);
281 sOut.Pull(privKeyTag);
285 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
286 const RawBuffer &pubPwd,
287 const RawBuffer &pubPwdIv,
288 const RawBuffer &privPwd,
289 const RawBuffer &privPwdIv,
290 RawBuffer &pubKeyTag,
291 RawBuffer &privKeyTag,
292 const RawBuffer &hashPriv,
293 const RawBuffer &hashPub)
295 // command ID = CMD_GENERATE_RSA_KEYPAIR
298 GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
311 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
312 const RawBuffer &prime,
313 const RawBuffer &subprime,
314 const RawBuffer &base,
315 const RawBuffer &pubPwd,
316 const RawBuffer &pubPwdIv,
317 const RawBuffer &privPwd,
318 const RawBuffer &privPwdIv,
319 RawBuffer &pubKeyTag,
320 RawBuffer &privKeyTag,
321 const RawBuffer &hashPriv,
322 const RawBuffer &hashPub)
324 // command ID = CMD_GENERATE_DSA_KEYPAIR
325 auto sIn = makeSerializer(prime, subprime, base);
327 GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
340 void TrustZoneContext::generateECKey(tz_ec ec,
341 const RawBuffer &pubPwd,
342 const RawBuffer &pubPwdIv,
343 const RawBuffer &privPwd,
344 const RawBuffer &privPwdIv,
345 RawBuffer &pubKeyTag,
346 RawBuffer &privKeyTag,
347 const RawBuffer &hashPriv,
348 const RawBuffer &hashPub)
350 // command ID = CMD_GENERATE_EC_KEYPAIR
353 GenerateAKey(CMD_GENERATE_EC_KEYPAIR,
355 static_cast<uint32_t>(ec),
366 void TrustZoneContext::executeCrypt(tz_command cmd,
368 const RawBuffer &keyId,
371 const RawBuffer &data,
374 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
375 if (keyId.size() != KM_KEY_ID_SIZE) {
376 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
377 + std::to_string(keyId.size()) + ")");
381 if (algo == ALGO_RSA)
382 sIn = makeSerializer(data, pwd, keyId);
384 sIn = makeSerializer(data, pwd, iv, keyId);
386 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
387 sIn.Serialize(inMemory);
389 // decrypt operation does not require padding
390 uint32_t outMemorySize = data.size();
391 if (cmd == CMD_ENCRYPT) {
392 if (algo == ALGO_RSA) {
393 // We don't know the key length
394 outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
396 outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
401 sOut.Push(new TZSerializableBinary(outMemorySize, false));
402 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
404 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
405 op.params[0].value.a = algo;
409 sOut.Deserialize(outMemory);
413 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
417 const RawBuffer &aad,
418 const RawBuffer &data,
422 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
423 if (keyId.size() != KM_KEY_ID_SIZE) {
424 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
427 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
428 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
429 sIn.Serialize(inMemory);
431 uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
432 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
435 sOut.Push(new TZSerializableBinary(outMemorySize, false));
436 sOut.Push(new TZSerializableBinary(tagSizeBytes));
437 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
439 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
440 op.params[0].value.a = ALGO_AES_GCM;
442 Execute(CMD_ENCRYPT, &op);
444 sOut.Deserialize(outMemory);
449 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
453 const RawBuffer &tag,
454 const RawBuffer &aad,
455 const RawBuffer &data,
458 // command ID = CMD_DECRYPT (from km_ta_defines.h)
459 if (keyId.size() != KM_KEY_ID_SIZE) {
460 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
463 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
464 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
465 sIn.Serialize(inMemory);
468 sOut.Push(new TZSerializableBinary(data.size()));
469 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
471 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
472 op.params[0].value.a = ALGO_AES_GCM;
474 Execute(CMD_DECRYPT, &op);
476 sOut.Deserialize(outMemory);
480 uint32_t TrustZoneContext::initGcmCipher(uint32_t encrypt,
481 const RawBuffer &keyId,
485 const RawBuffer &aad)
487 // command ID = CMD_CIPHER_INIT (from km_ta_defines.h)
488 if (keyId.size() != KM_KEY_ID_SIZE) {
489 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
492 auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
493 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
494 sIn.Serialize(inMemory);
496 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
497 op.params[0].value.a = ALGO_AES_GCM;
498 op.params[0].value.b = encrypt;
500 Execute(CMD_CIPHER_INIT, &op);
502 return op.params[0].value.b;
505 void TrustZoneContext::addGcmAAD(uint32_t opId,
506 const RawBuffer &aad)
508 // command ID = CMD_CIPHER_INIT_AAD (from km_ta_defines.h)
509 auto sIn = makeSerializer(aad);
510 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
511 sIn.Serialize(inMemory);
513 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
514 op.params[0].value.a = opId;
516 Execute(CMD_CIPHER_INIT_AAD, &op);
519 RawBuffer TrustZoneContext::updateGcmCipher(uint32_t opId,
520 const RawBuffer &data)
522 auto sIn = makeSerializer(data);
523 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
524 sIn.Serialize(inMemory);
527 sOut.Push(new TZSerializableBinary(data.size()));
528 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
530 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
531 op.params[0].value.a = opId;
533 Execute(CMD_CIPHER_UPDATE, &op);
535 sOut.Deserialize(outMemory);
542 RawBuffer TrustZoneContext::finalizeGcmCipher(uint32_t opId,
543 const RawBuffer &data)
545 auto sIn = makeSerializer(data);
546 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
547 sIn.Serialize(inMemory);
550 sOut.Push(new TZSerializableBinary(data.size()));
551 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
553 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
554 op.params[0].value.a = opId;
556 Execute(CMD_CIPHER_FINALIZE, &op);
558 sOut.Deserialize(outMemory);
565 void TrustZoneContext::executeSign(tz_algo_type algo,
567 const RawBuffer &keyId,
569 const RawBuffer &message,
570 RawBuffer &signature)
572 // command ID = CMD_SIGN (from km_ta_defines.h)
573 if (keyId.size() != KM_KEY_ID_SIZE) {
574 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
575 + std::to_string(keyId.size()) + ")");
578 auto sIn = makeSerializer(message, pwd, keyId);
579 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
580 sIn.Serialize(inMemory);
583 sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
584 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
586 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
587 op.params[0].value.a = algo;
588 op.params[0].value.b = hash;
590 Execute(CMD_SIGN, &op);
592 sOut.Deserialize(outMemory);
593 sOut.Pull(signature);
596 int TrustZoneContext::executeVerify(tz_algo_type algo,
598 const RawBuffer &keyId,
600 const RawBuffer &message,
601 const RawBuffer &signature)
603 // command ID = CMD_VERIFY (from km_ta_defines.h)
604 if (keyId.size() != KM_KEY_ID_SIZE) {
605 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
606 + std::to_string(keyId.size()) + ")");
609 auto sIn = makeSerializer(message, signature, pwd, keyId);
610 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
611 sIn.Serialize(inMemory);
613 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
614 op.params[0].value.a = algo;
615 op.params[0].value.b = hash;
617 Execute(CMD_VERIFY, &op);
619 int opRet = op.params[0].value.a;
622 return CKM_API_SUCCESS;
623 case KM_TA_ERROR_SIGNATURE:
624 LogWarning("Signature verification failed");
625 return CKM_API_ERROR_VERIFICATION_FAILED;
627 assert(false); // This condition should be checked inside Execute() function
628 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
632 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
634 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
635 if (keyId.size() != KM_KEY_ID_SIZE) {
636 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
639 auto sIn = makeSerializer(keyId);
640 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
641 sIn.Serialize(inMemory);
643 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
645 Execute(CMD_DESTROY_KEY, &op);
648 void TrustZoneContext::importData(
649 const uint32_t dataType,
650 const RawBuffer &data,
651 const Crypto::EncryptionParams &encData,
652 const RawBuffer &pwd,
654 const uint32_t keySizeBits,
656 const RawBuffer &hash)
658 // command ID = CMD_IMPORT_DATA
659 LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
661 auto sIn = makeSerializer(
662 dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
664 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
665 sIn.Serialize(inMemory);
669 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
672 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
674 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
676 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
678 Execute(CMD_IMPORT_DATA, &op);
681 sOut.Deserialize(outMemory);
685 LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
688 void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKeyId,
689 const Pwd &wrappingKeyPwd,
692 const uint32_t ctrLenOrTagSizeBits,
693 const RawBuffer &aad,
694 const tz_data_type encryptedKeyType,
695 const RawBuffer &encryptedKey,
696 const RawBuffer &encryptedKeyPwdBuf,
697 const RawBuffer &encryptedKeyIV,
698 RawBuffer &encryptedKeyTag,
699 const RawBuffer &encryptedKeyId)
701 // command ID = CMD_IMPORT_WRAPPED_KEY
702 LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
704 auto sIn = makeSerializer(wrappingKeyId,
712 EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
715 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
716 sIn.Serialize(inMemory);
719 if (!encryptedKeyPwdBuf.empty()) {
720 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
723 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
725 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
726 if (!encryptedKeyPwdBuf.empty())
727 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
729 Execute(CMD_IMPORT_WRAPPED_KEY, &op);
731 if (!encryptedKeyPwdBuf.empty()) {
732 sOut.Deserialize(outMemory);
733 sOut.Pull(encryptedKeyTag);
736 LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
739 RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKeyId,
740 const Pwd &wrappingKeyPwd,
743 const uint32_t ctrLenOrTagSizeBits,
744 const RawBuffer &aad,
745 const RawBuffer &keyToWrapId,
746 const Pwd &keyToWrapPwd)
748 // command ID = CMD_EXPORT_WRAPPED_KEY
749 LogDebug("TrustZoneContext::exportWrappedKey");
751 auto sIn = makeSerializer(wrappingKeyId,
760 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
761 sIn.Serialize(inMemory);
763 uint32_t data_size = 0;
764 GetDataSize(keyToWrapId, data_size);
766 LogDebug("GetData data_size = [" << data_size << "]");
768 // encrypted data may be longer
770 sOut.Push(new TZSerializableBinary(data_size + KM_ENCRYPTION_OVERHEAD));
771 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
772 sOut.Serialize(outMemory);
774 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
776 Execute(CMD_EXPORT_WRAPPED_KEY, &op);
778 sOut.Deserialize(outMemory);
780 RawBuffer wrappedKey;
781 sOut.Pull(wrappedKey);
786 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
788 // command ID = CMD_GET_DATA_SIZE
789 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
791 auto sIn = makeSerializer(dataId);
792 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
793 sIn.Serialize(inMemory);
795 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
797 Execute(CMD_GET_DATA_SIZE, &op);
798 dataSize = op.params[0].value.b;
801 void TrustZoneContext::getData(const RawBuffer &dataId,
805 // command ID = CMD_GET_DATA
806 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
808 auto sIn = makeSerializer(dataId, pwd);
809 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
810 sIn.Serialize(inMemory);
812 uint32_t data_size = 0;
813 GetDataSize(dataId, data_size);
815 LogDebug("GetData data_size = [" << data_size << "]");
818 sOut.Push(new TZSerializableBinary(data_size));
819 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
820 sOut.Serialize(outMemory);
822 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
824 Execute(CMD_GET_DATA, &op);
826 sOut.Deserialize(outMemory);
831 void TrustZoneContext::destroyData(const RawBuffer &dataId)
833 // command ID = CMD_DESTROY_DATA
834 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
835 auto sIn = makeSerializer(dataId);
836 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
837 sIn.Serialize(inMemory);
839 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
841 Execute(CMD_DESTROY_DATA, &op);
844 TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
846 auto &tag = pwd.getTag();
847 return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
850 void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
851 const Pwd &prvKeyPwd,
852 const RawBuffer &pubX,
853 const RawBuffer &pubY,
854 const RawBuffer &secretPwdBuf,
855 const RawBuffer &secretPwdIV,
856 RawBuffer &secretTag,
857 const RawBuffer &secretHash)
859 // command ID = CMD_DERIVE
860 LogDebug("TrustZoneContext::executeEcdh");
862 auto sIn = makeSerializer(
863 prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
864 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
865 sIn.Serialize(inMemory);
868 if (!secretPwdBuf.empty()) {
869 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
872 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
874 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
875 if (!secretPwdBuf.empty())
876 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
877 op.params[0].value.a = ALGO_ECDH_DRV;
879 Execute(CMD_DERIVE, &op);
881 if (!secretPwdBuf.empty()) {
882 sOut.Deserialize(outMemory);
883 sOut.Pull(secretTag);
886 LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
889 void TrustZoneContext::executeKbkdf(const RawBuffer& secretId,
890 const RawBuffer& label,
891 const RawBuffer& context,
892 const RawBuffer& fixed,
895 tz_kbkdf_ctr_loc location,
899 const RawBuffer &keyPwdBuf,
900 const RawBuffer &keyPwdIV,
902 const RawBuffer &keyHash)
904 // command ID = CMD_DERIVE
905 LogDebug("TrustZoneContext::executeKbkdf");
907 auto sIn = makeSerializer(secretId,
917 EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
919 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
920 sIn.Serialize(inMemory);
923 if (!keyPwdBuf.empty()) {
924 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
927 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
929 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
930 if (!keyPwdBuf.empty())
931 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
932 op.params[0].value.a = ALGO_KBKDF_DRV;
934 Execute(CMD_DERIVE, &op);
936 if (!keyPwdBuf.empty()) {
937 sOut.Deserialize(outMemory);
941 LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
944 void TrustZoneContext::Initialize()
950 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
952 result = TEEC_InitializeContext(nullptr, &m_Context);
953 if (result != TEEC_SUCCESS) {
954 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
956 m_ContextInitialized = true;
958 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
959 if (result != TEEC_SUCCESS) {
960 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
962 m_SessionInitialized = true;
965 void TrustZoneContext::Destroy()
967 if (m_SessionInitialized) {
968 TEEC_CloseSession(&m_Session);
969 m_SessionInitialized = false;
972 if (m_ContextInitialized) {
973 TEEC_FinalizeContext(&m_Context);
974 m_ContextInitialized = false;
978 void TrustZoneContext::Reload()
984 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
986 uint32_t retOrigin = 0;
987 LogDebug("Executing TZ operation " << commandID);
989 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
990 if (result != TEEC_SUCCESS) {
992 case TEEC_ERROR_TARGET_DEAD:
994 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
995 static_cast<unsigned int>(commandID));
996 case TEEC_ERROR_BAD_PARAMETERS:
997 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
999 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1000 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1001 static_cast<unsigned int>(result), " with origin: ", std::hex,
1006 int ta_ret = op->params[0].value.a;
1009 case KM_TA_ERROR_SIGNATURE:
1011 case KM_TA_ERROR_AUTH_FAILED:
1012 // Authentication cipher failed - notify with proper exception
1013 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1015 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1019 } // namespace Internals
1021 } // namespace Crypto