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 pubPwdExists = pubPwd.empty() ? 0 : 1;
255 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
257 uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
259 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
261 push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub);
262 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
263 sIn.Serialize(inMemory);
265 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
268 if (sOut.GetSize() == 0) {
269 op = makeOp(TEEC_VALUE_INOUT, inMemory);
271 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
273 op.params[0].value.b = genParam;
275 Execute(commandId, &op);
277 sOut.Deserialize(outMemory);
279 sOut.Pull(pubKeyTag);
283 sOut.Pull(privKeyTag);
287 void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
288 const RawBuffer &pubPwd,
289 const RawBuffer &pubPwdIv,
290 const RawBuffer &privPwd,
291 const RawBuffer &privPwdIv,
292 RawBuffer &pubKeyTag,
293 RawBuffer &privKeyTag,
294 const RawBuffer &hashPriv,
295 const RawBuffer &hashPub)
297 // command ID = CMD_GENERATE_RSA_KEYPAIR
300 GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
313 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
314 const RawBuffer &prime,
315 const RawBuffer &subprime,
316 const RawBuffer &base,
317 const RawBuffer &pubPwd,
318 const RawBuffer &pubPwdIv,
319 const RawBuffer &privPwd,
320 const RawBuffer &privPwdIv,
321 RawBuffer &pubKeyTag,
322 RawBuffer &privKeyTag,
323 const RawBuffer &hashPriv,
324 const RawBuffer &hashPub)
326 // command ID = CMD_GENERATE_DSA_KEYPAIR
327 auto sIn = makeSerializer(prime, subprime, base);
329 GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
342 void TrustZoneContext::generateECKey(tz_ec ec,
343 const RawBuffer &pubPwd,
344 const RawBuffer &pubPwdIv,
345 const RawBuffer &privPwd,
346 const RawBuffer &privPwdIv,
347 RawBuffer &pubKeyTag,
348 RawBuffer &privKeyTag,
349 const RawBuffer &hashPriv,
350 const RawBuffer &hashPub)
352 // command ID = CMD_GENERATE_EC_KEYPAIR
355 GenerateAKey(CMD_GENERATE_EC_KEYPAIR,
357 static_cast<uint32_t>(ec),
368 void TrustZoneContext::executeCrypt(tz_command cmd,
370 const RawBuffer &keyId,
373 const RawBuffer &data,
376 // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
377 if (keyId.size() != KM_KEY_ID_SIZE) {
378 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
379 + std::to_string(keyId.size()) + ")");
383 if (algo == ALGO_RSA)
384 sIn = makeSerializer(data, pwd, keyId);
386 sIn = makeSerializer(data, pwd, iv, keyId);
388 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
389 sIn.Serialize(inMemory);
391 // decrypt operation does not require padding
392 uint32_t outMemorySize = data.size();
393 if (cmd == CMD_ENCRYPT) {
394 if (algo == ALGO_RSA) {
395 // We don't know the key length
396 outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
398 outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
403 sOut.Push(new TZSerializableBinary(outMemorySize, false));
404 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
406 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
407 op.params[0].value.a = algo;
411 sOut.Deserialize(outMemory);
415 void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
419 const RawBuffer &aad,
420 const RawBuffer &data,
424 // command ID = CMD_ENCRYPT (from km_ta_defines.h)
425 if (keyId.size() != KM_KEY_ID_SIZE) {
426 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
429 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
430 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
431 sIn.Serialize(inMemory);
433 uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
434 uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
437 sOut.Push(new TZSerializableBinary(outMemorySize, false));
438 sOut.Push(new TZSerializableBinary(tagSizeBytes));
439 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
441 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
442 op.params[0].value.a = ALGO_AES_GCM;
444 Execute(CMD_ENCRYPT, &op);
446 sOut.Deserialize(outMemory);
451 void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
455 const RawBuffer &tag,
456 const RawBuffer &aad,
457 const RawBuffer &data,
460 // command ID = CMD_DECRYPT (from km_ta_defines.h)
461 if (keyId.size() != KM_KEY_ID_SIZE) {
462 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
465 auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
466 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
467 sIn.Serialize(inMemory);
470 sOut.Push(new TZSerializableBinary(data.size()));
471 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
473 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
474 op.params[0].value.a = ALGO_AES_GCM;
476 Execute(CMD_DECRYPT, &op);
478 sOut.Deserialize(outMemory);
482 uint32_t TrustZoneContext::initGcmCipher(uint32_t encrypt,
483 const RawBuffer &keyId,
487 const RawBuffer &aad)
489 // command ID = CMD_CIPHER_INIT (from km_ta_defines.h)
490 if (keyId.size() != KM_KEY_ID_SIZE) {
491 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
494 auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
495 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
496 sIn.Serialize(inMemory);
498 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
499 op.params[0].value.a = ALGO_AES_GCM;
500 op.params[0].value.b = encrypt;
502 Execute(CMD_CIPHER_INIT, &op);
504 return op.params[0].value.b;
507 void TrustZoneContext::addGcmAAD(uint32_t opId,
508 const RawBuffer &aad)
510 // command ID = CMD_CIPHER_INIT_AAD (from km_ta_defines.h)
511 auto sIn = makeSerializer(aad);
512 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
513 sIn.Serialize(inMemory);
515 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
516 op.params[0].value.a = opId;
518 Execute(CMD_CIPHER_INIT_AAD, &op);
521 RawBuffer TrustZoneContext::updateGcmCipher(uint32_t opId,
522 const RawBuffer &data)
524 auto sIn = makeSerializer(data);
525 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
526 sIn.Serialize(inMemory);
529 sOut.Push(new TZSerializableBinary(data.size()));
530 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
532 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
533 op.params[0].value.a = opId;
535 Execute(CMD_CIPHER_UPDATE, &op);
537 sOut.Deserialize(outMemory);
544 RawBuffer TrustZoneContext::finalizeGcmCipher(uint32_t opId,
545 const RawBuffer &data)
547 auto sIn = makeSerializer(data);
548 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
549 sIn.Serialize(inMemory);
552 sOut.Push(new TZSerializableBinary(MAX_GCM_TAG_SIZE, false));
553 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
555 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
556 op.params[0].value.a = opId;
558 Execute(CMD_CIPHER_FINALIZE, &op);
560 sOut.Deserialize(outMemory);
567 void TrustZoneContext::cleanupCipher(uint32_t opId)
570 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
571 op.params[0].value.a = opId;
573 Execute(CMD_CIPHER_CLEANUP, &op);
576 void TrustZoneContext::executeSign(tz_algo_type algo,
578 const RawBuffer &keyId,
580 const RawBuffer &message,
581 RawBuffer &signature)
583 // command ID = CMD_SIGN (from km_ta_defines.h)
584 if (keyId.size() != KM_KEY_ID_SIZE) {
585 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
586 + std::to_string(keyId.size()) + ")");
589 auto sIn = makeSerializer(message, pwd, keyId);
590 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
591 sIn.Serialize(inMemory);
594 sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
595 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
597 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
598 op.params[0].value.a = algo;
599 op.params[0].value.b = hash;
601 Execute(CMD_SIGN, &op);
603 sOut.Deserialize(outMemory);
604 sOut.Pull(signature);
607 int TrustZoneContext::executeVerify(tz_algo_type algo,
609 const RawBuffer &keyId,
611 const RawBuffer &message,
612 const RawBuffer &signature)
614 // command ID = CMD_VERIFY (from km_ta_defines.h)
615 if (keyId.size() != KM_KEY_ID_SIZE) {
616 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
617 + std::to_string(keyId.size()) + ")");
620 auto sIn = makeSerializer(message, signature, pwd, keyId);
621 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
622 sIn.Serialize(inMemory);
624 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
625 op.params[0].value.a = algo;
626 op.params[0].value.b = hash;
628 Execute(CMD_VERIFY, &op);
630 int opRet = op.params[0].value.a;
633 return CKM_API_SUCCESS;
634 case KM_TA_ERROR_SIGNATURE:
635 LogWarning("Signature verification failed");
636 return CKM_API_ERROR_VERIFICATION_FAILED;
638 assert(false); // This condition should be checked inside Execute() function
639 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
643 void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
645 // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
646 if (keyId.size() != KM_KEY_ID_SIZE) {
647 ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
650 auto sIn = makeSerializer(keyId);
651 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
652 sIn.Serialize(inMemory);
654 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
656 Execute(CMD_DESTROY_KEY, &op);
659 void TrustZoneContext::importData(
660 const uint32_t dataType,
661 const RawBuffer &data,
662 const Crypto::EncryptionParams &encData,
663 const RawBuffer &pwd,
665 const uint32_t keySizeBits,
667 const RawBuffer &hash)
669 // command ID = CMD_IMPORT_DATA
670 LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
672 auto sIn = makeSerializer(
673 dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
675 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
676 sIn.Serialize(inMemory);
680 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
683 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
685 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
687 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
689 Execute(CMD_IMPORT_DATA, &op);
692 sOut.Deserialize(outMemory);
696 LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
699 void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKeyId,
700 const Pwd &wrappingKeyPwd,
703 const uint32_t ctrLenOrTagSizeBits,
704 const RawBuffer &aad,
705 const tz_data_type encryptedKeyType,
706 const RawBuffer &encryptedKey,
707 const RawBuffer &encryptedKeyPwdBuf,
708 const RawBuffer &encryptedKeyIV,
709 RawBuffer &encryptedKeyTag,
710 const RawBuffer &encryptedKeyId)
712 // command ID = CMD_IMPORT_WRAPPED_KEY
713 LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
715 auto sIn = makeSerializer(wrappingKeyId,
723 EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
726 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
727 sIn.Serialize(inMemory);
730 if (!encryptedKeyPwdBuf.empty()) {
731 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
734 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
736 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
737 if (!encryptedKeyPwdBuf.empty())
738 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
740 Execute(CMD_IMPORT_WRAPPED_KEY, &op);
742 if (!encryptedKeyPwdBuf.empty()) {
743 sOut.Deserialize(outMemory);
744 sOut.Pull(encryptedKeyTag);
747 LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
750 RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKeyId,
751 const Pwd &wrappingKeyPwd,
754 const uint32_t ctrLenOrTagSizeBits,
755 const RawBuffer &aad,
756 const RawBuffer &keyToWrapId,
757 const Pwd &keyToWrapPwd,
758 tz_data_type keyToWrapType)
760 // command ID = CMD_EXPORT_WRAPPED_KEY
761 LogDebug("TrustZoneContext::exportWrappedKey");
763 auto sIn = makeSerializer(wrappingKeyId,
773 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
774 sIn.Serialize(inMemory);
776 uint32_t dataSize = 0;
777 GetDataSize(keyToWrapId, keyToWrapPwd, keyToWrapType, dataSize);
779 LogDebug("GetData data_size = [" << dataSize << "]");
781 uint32_t enc_overhead = KM_ENCRYPTION_OVERHEAD;
782 if (algo == ALGO_RSA)
783 enc_overhead = KM_RSA_BLOCK_SIZE;
785 // encrypted data may be longer
787 sOut.Push(new TZSerializableBinary(dataSize + enc_overhead, false));
788 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
789 sOut.Serialize(outMemory);
791 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
793 Execute(CMD_EXPORT_WRAPPED_KEY, &op);
795 sOut.Deserialize(outMemory);
797 RawBuffer wrappedKey;
798 sOut.Pull(wrappedKey);
803 void TrustZoneContext::GetDataSize(const RawBuffer &dataId,
805 const tz_data_type type,
808 // command ID = CMD_GET_DATA_SIZE
809 LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
811 auto sIn = makeSerializer(dataId, pwd, type);
812 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
813 sIn.Serialize(inMemory);
815 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
817 Execute(CMD_GET_DATA_SIZE, &op);
818 dataSize = op.params[0].value.b;
821 void TrustZoneContext::getData(const RawBuffer &dataId,
823 const tz_data_type type,
826 // command ID = CMD_GET_DATA
827 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
829 auto sIn = makeSerializer(dataId, pwd, type);
830 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
831 sIn.Serialize(inMemory);
833 uint32_t data_size = 0;
834 GetDataSize(dataId, pwd, type, data_size);
836 LogDebug("GetData data_size = [" << data_size << "]");
839 sOut.Push(new TZSerializableBinary(data_size));
840 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
841 sOut.Serialize(outMemory);
843 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
845 Execute(CMD_GET_DATA, &op);
847 sOut.Deserialize(outMemory);
852 void TrustZoneContext::destroyData(const RawBuffer &dataId)
854 // command ID = CMD_DESTROY_DATA
855 LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
856 auto sIn = makeSerializer(dataId);
857 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
858 sIn.Serialize(inMemory);
860 TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
862 Execute(CMD_DESTROY_DATA, &op);
865 TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
867 auto &tag = pwd.getTag();
868 return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
871 void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
872 const Pwd &prvKeyPwd,
874 const RawBuffer &pubX,
875 const RawBuffer &pubY,
876 const RawBuffer &secretPwdBuf,
877 const RawBuffer &secretPwdIV,
878 RawBuffer &secretTag,
879 const RawBuffer &secretHash)
881 // command ID = CMD_DERIVE
882 LogDebug("TrustZoneContext::executeEcdh");
884 auto sIn = makeSerializer(
885 prvKeyId, prvKeyPwd, curve, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
886 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
887 sIn.Serialize(inMemory);
890 if (!secretPwdBuf.empty()) {
891 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
894 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
896 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
897 if (!secretPwdBuf.empty())
898 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
899 op.params[0].value.a = ALGO_ECDH_DRV;
901 Execute(CMD_DERIVE, &op);
903 if (!secretPwdBuf.empty()) {
904 sOut.Deserialize(outMemory);
905 sOut.Pull(secretTag);
908 LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
911 void TrustZoneContext::executeKbkdf(const RawBuffer& secretId,
912 const Pwd& secretPwd,
914 const RawBuffer& label,
915 const RawBuffer& context,
916 const RawBuffer& fixed,
919 tz_kbkdf_ctr_loc location,
923 const RawBuffer &keyPwdBuf,
924 const RawBuffer &keyPwdIV,
926 const RawBuffer &keyHash)
928 // command ID = CMD_DERIVE
929 LogDebug("TrustZoneContext::executeKbkdf");
931 auto sIn = makeSerializer(secretId,
943 EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
945 TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
946 sIn.Serialize(inMemory);
949 if (!keyPwdBuf.empty()) {
950 sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
953 TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
955 TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
956 if (!keyPwdBuf.empty())
957 op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
958 op.params[0].value.a = ALGO_KBKDF_DRV;
960 Execute(CMD_DERIVE, &op);
962 if (!keyPwdBuf.empty()) {
963 sOut.Deserialize(outMemory);
967 LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
970 uint32_t TrustZoneContext::getMaxChunkSize()
972 // command ID = CMD_GET_MAX_CHUNK_SIZE
973 LogDebug("TrustZoneContext::getMaxChunkSize");
976 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
978 Execute(CMD_GET_MAX_CHUNK_SIZE, &op);
980 return op.params[0].value.b;
983 void TrustZoneContext::Initialize()
989 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
991 result = TEEC_InitializeContext(nullptr, &m_Context);
992 if (result != TEEC_SUCCESS) {
993 ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
995 m_ContextInitialized = true;
997 result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
998 if (result != TEEC_SUCCESS) {
999 ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
1001 m_SessionInitialized = true;
1004 void TrustZoneContext::Destroy()
1006 if (m_SessionInitialized) {
1007 TEEC_CloseSession(&m_Session);
1008 m_SessionInitialized = false;
1011 if (m_ContextInitialized) {
1012 TEEC_FinalizeContext(&m_Context);
1013 m_ContextInitialized = false;
1017 void TrustZoneContext::Reload()
1023 void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
1025 uint32_t retOrigin = 0;
1026 LogDebug("Executing TZ operation " << commandID);
1028 TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, &retOrigin);
1029 if (result != TEEC_SUCCESS) {
1031 case TEEC_ERROR_TARGET_DEAD:
1033 ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
1034 static_cast<unsigned int>(commandID));
1035 case TEEC_ERROR_BAD_PARAMETERS:
1036 ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
1038 ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
1039 static_cast<unsigned int>(commandID), " with error: ", std::hex,
1040 static_cast<unsigned int>(result), " with origin: ", std::hex,
1045 int ta_ret = op->params[0].value.a;
1048 case KM_TA_ERROR_SIGNATURE:
1050 case KM_TA_ERROR_AUTH_FAILED:
1051 // Authentication cipher failed - notify with proper exception
1052 ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
1054 ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
1058 } // namespace Internals
1060 } // namespace Crypto