From a6f9aec24eda2bfb5b6dac8f70749fcff7e0802c Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 13 Feb 2023 10:10:39 +0100 Subject: [PATCH 01/16] KBKDF HMAC implementation in sw backend Unit tests included Change-Id: If4287b38c61fe3842024c5e7baf4934685f92566 --- src/manager/crypto/sw-backend/internals.cpp | 107 ++++++++++++- src/manager/crypto/sw-backend/internals.h | 1 + src/manager/crypto/sw-backend/obj.cpp | 11 +- src/manager/crypto/sw-backend/obj.h | 1 + unit-tests/test_sw-backend.cpp | 227 ++++++++++++++++++++++++++++ 5 files changed, 344 insertions(+), 3 deletions(-) diff --git a/src/manager/crypto/sw-backend/internals.cpp b/src/manager/crypto/sw-backend/internals.cpp index e1e40a5..9796b2e 100644 --- a/src/manager/crypto/sw-backend/internals.cpp +++ b/src/manager/crypto/sw-backend/internals.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -45,8 +46,8 @@ #include #include #include - #include +#include "kbkdf.h" #define OPENSSL_SUCCESS 1 // DO NOT CHANGE THIS VALUE #define OPENSSL_FAIL 0 // DO NOT CHANGE THIS VALUE @@ -197,6 +198,46 @@ typedef ParamCheck> EcdhPubKeyCheck; +typedef ParamCheck::Equals> IsKbkdf; + +typedef ParamCheck::Equals> KdfPrfCheck; + +typedef ParamCheck::Equals> KbkdfModeCheck; + +typedef ParamCheck::Equals<16, 24, 32>> KdfLenCheck; + +typedef ParamCheck::Equals> KbkdfCounterLocationCheck; + +typedef ParamCheck::Equals<8, 16, 24, 32>> KbkdfRlenCheck; + +typedef ParamCheck::Equals<0, 8, 16, 24, 32>> KbkdfLlenCheck; + + typedef std::map ValidatorMap; ValidatorMap initValidators() { @@ -214,6 +255,12 @@ ValidatorMap initValidators() validators.emplace(AlgoType::AES_GCM, VBuilder::Build()); validators.emplace(AlgoType::RSA_OAEP, VBuilder::Build()); validators.emplace(AlgoType::ECDH, VBuilder::Build()); + validators.emplace(AlgoType::KBKDF, VBuilder::Build()); return validators; }; @@ -986,6 +1033,64 @@ Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg) return { DataType::BINARY_DATA, std::move(secret)}; } +Data deriveKBKDF(const RawBuffer &secret, const CryptoAlgorithm &alg) +{ + validateParams(alg); + + RawBuffer label, context, fixed; + KbkdfCounterLocation counterLocation; + KdfPrf prf; + size_t length, rlenBits = 32, llenBits = 0, tmp; + bool hasLabel = alg.getParam(ParamName::KBKDF_LABEL, label); + bool hasContext = alg.getParam(ParamName::KBKDF_CONTEXT, context); + bool hasFixed = alg.getParam(ParamName::KBKDF_FIXED_INPUT, fixed); + alg.getParam(ParamName::KBKDF_COUNTER_LOCATION, counterLocation); + alg.getParam(ParamName::KDF_PRF, prf); + alg.getParam(ParamName::KDF_LEN, length); + alg.getParam(ParamName::KBKDF_RLEN, rlenBits); + alg.getParam(ParamName::KBKDF_LLEN, llenBits); + bool useSeparator = !alg.getParam(ParamName::KBKDF_NO_SEPARATOR, tmp); + + const EVP_MD* md = nullptr; + switch (prf) { + case KdfPrf::HMAC_SHA256: + md = EVP_sha256(); + break; + case KdfPrf::HMAC_SHA384: + md = EVP_sha384(); + break; + case KdfPrf::HMAC_SHA512: + md = EVP_sha512(); + break; + default: + assert(false); // prf is checked in validateParams above + } + + RawBuffer key; + if (hasFixed) { + if (hasLabel || hasContext || !useSeparator || llenBits > 0 || + counterLocation == KbkdfCounterLocation::MIDDLE_FIXED) + ThrowErr(Exc::Crypto::InputParam, "Unexpected parameters for fixed input mode."); + + key = deriveKbkdfHmac(secret, length * 8, md, counterLocation, rlenBits, fixed); + } else { + if (!hasLabel || !hasContext) + ThrowErr(Exc::Crypto::InputParam, "Missing label and/or context."); + + key = deriveKbkdfHmac(secret, + length * 8, + md, + counterLocation, + rlenBits, + llenBits, + label, + context, + useSeparator); + } + + return { DataType::KEY_AES, std::move(key)}; +} + } // namespace Internals } // namespace SW } // namespace Crypto diff --git a/src/manager/crypto/sw-backend/internals.h b/src/manager/crypto/sw-backend/internals.h index 52f8a2e..b2669a6 100644 --- a/src/manager/crypto/sw-backend/internals.h +++ b/src/manager/crypto/sw-backend/internals.h @@ -91,6 +91,7 @@ int verify(EVP_PKEY *pkey, const RawBuffer &signature); Data deriveECDH(const EvpShPtr &pkey, const CryptoAlgorithm &alg); +Data deriveKBKDF(const RawBuffer &secret, const CryptoAlgorithm &alg); } // namespace Internals } // namespace SW diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index f256eea..9b4e1a2 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -58,9 +58,11 @@ AlgoType key2algo(DataType type) } // namespace anonymous -Token BData::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) +Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &) { - return Token(); + auto data = Internals::deriveKBKDF(getBinary(), alg); + + return Token(backendId(), data.type, Store::pack(data.buffer, pass)); } RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) @@ -182,6 +184,11 @@ EvpShPtr Cert::getEvpShPtr() return m_evp; } +Token Cert::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) +{ + ThrowErr(Exc::Crypto::OperationNotSupported); +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h index ffb8231..2712341 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -82,6 +82,7 @@ class Cert : public AKey { public: Cert(CryptoBackend backendId, RawBuffer buffer, DataType dataType) : AKey(backendId, std::move(buffer), dataType) {} + Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override; protected: EvpShPtr getEvpShPtr() override; diff --git a/unit-tests/test_sw-backend.cpp b/unit-tests/test_sw-backend.cpp index f21e679..4de683e 100644 --- a/unit-tests/test_sw-backend.cpp +++ b/unit-tests/test_sw-backend.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -228,6 +229,121 @@ struct CertHelper : public Cert { using Cert::getEvpShPtr; }; +const std::optional NO_BUF; +const std::optional NO_SIZE; +const std::optional NO_PRF; +const std::optional NO_MODE; +const std::optional NO_LOC; + +constexpr KdfPrf HMAC256 = KdfPrf::HMAC_SHA256; +constexpr KdfPrf HMAC384 = KdfPrf::HMAC_SHA384; +constexpr KdfPrf HMAC512 = KdfPrf::HMAC_SHA512; +constexpr KbkdfCounterLocation BEFORE = KbkdfCounterLocation::BEFORE_FIXED; +constexpr KbkdfCounterLocation AFTER = KbkdfCounterLocation::AFTER_FIXED; +constexpr KbkdfCounterLocation MIDDLE = KbkdfCounterLocation::MIDDLE_FIXED; +constexpr KbkdfMode COUNTER = KbkdfMode::COUNTER; + +const RawBuffer CTX{'c','o','n','t','e','x','t'}; +const RawBuffer LAB{'l','a','b','e','l'}; +const RawBuffer FIX{'f','i','x','e','d'}; +const RawBuffer ONE(1); +const RawBuffer EMPTY; + +class KbkdfParamTester { +public: + KbkdfParamTester() { + Token token; + BOOST_REQUIRE_NO_THROW(token = STORE.import(Data(DataType::BINARY_DATA, RawBuffer(16)), + "", + EncryptionParams(), + RawBuffer())); + + BOOST_REQUIRE_NO_THROW(secret = STORE.getObject(token, "")); + } + + void Ok(const std::optional& len, + const std::optional& prf, + const std::optional& mode, + const std::optional& location, + const std::optional& context, + const std::optional& label, + const std::optional& fixed, + const std::optional& rlen, + const std::optional& llen, + bool noSeparator = false) + { + return Test(true, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator); + } + + void Fail(const std::optional& len, + const std::optional& prf, + const std::optional& mode, + const std::optional& location, + const std::optional& context, + const std::optional& label, + const std::optional& fixed, + const std::optional& rlen, + const std::optional& llen, + bool noSeparator = false) + { + return Test( + false, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator); + } +private: + void Test(bool ok, + const std::optional& len, + const std::optional& prf, + const std::optional& mode, + const std::optional& location, + const std::optional& context, + const std::optional& label, + const std::optional& fixed, + const std::optional& rlen, + const std::optional& llen, + bool noSeparator = false) + { + CryptoAlgorithm derive; + derive.setParam(ParamName::ALGO_TYPE, AlgoType::KBKDF); + if (len) + derive.setParam(ParamName::KDF_LEN, *len); + if (prf) + derive.setParam(ParamName::KDF_PRF, *prf); + if (mode) + derive.setParam(ParamName::KBKDF_MODE, *mode); + if (location) + derive.setParam(ParamName::KBKDF_COUNTER_LOCATION, *location); + if (context) + derive.setParam(ParamName::KBKDF_CONTEXT, *context); + if (label) + derive.setParam(ParamName::KBKDF_LABEL, *label); + if (fixed) + derive.setParam(ParamName::KBKDF_FIXED_INPUT, *fixed); + if (rlen) + derive.setParam(ParamName::KBKDF_RLEN, *rlen); + if (llen) + derive.setParam(ParamName::KBKDF_LLEN, *llen); + if (noSeparator) + derive.setParam(ParamName::KBKDF_NO_SEPARATOR, 1); + + GObjUPtr key; + if (ok) { + Token derived; + BOOST_REQUIRE_NO_THROW(derived = secret->derive(derive, "", RawBuffer())); + + BOOST_REQUIRE(derived.backendId == CryptoBackend::OpenSSL); + BOOST_REQUIRE(derived.dataType == DataType::KEY_AES); + + BOOST_REQUIRE_NO_THROW(key = STORE.getObject(derived, "")); + + BOOST_REQUIRE(key->getBinary().size() == *len); + } else { + BOOST_REQUIRE_THROW(secret->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam); + } + } + + GObjUPtr secret; +}; + } // namespace BOOST_AUTO_TEST_SUITE(SW_TEST) @@ -1112,4 +1228,115 @@ NEGATIVE_TEST_CASE(deriveECDH) BOOST_REQUIRE_THROW(rsaPrivate->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam); } +POSITIVE_TEST_CASE(deriveKBKDFHMAC) +{ + KbkdfParamTester test; + + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Ok(16, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(24, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC384, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC512, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, AFTER, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, MIDDLE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, BEFORE, ONE, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, EMPTY, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, ONE, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, EMPTY, NO_BUF, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, EMPTY, EMPTY, NO_BUF, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, BEFORE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, AFTER, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, BEFORE, NO_BUF, NO_BUF, ONE, NO_SIZE, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, NO_BUF, NO_BUF, EMPTY, NO_SIZE, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 32, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 24, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 16, NO_SIZE); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 8, NO_SIZE); + + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 32); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 24); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 16); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 8); + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 0); + + test.Ok(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true); + test.Ok(32, HMAC256, COUNTER, MIDDLE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE, true); +} + +NEGATIVE_TEST_CASE(deriveKBKDFHMACwrongAlgo) +{ + Token token; + BOOST_REQUIRE_NO_THROW(token = STORE.import(Data(DataType::BINARY_DATA, RawBuffer(16)), + "", + EncryptionParams(), + RawBuffer())); + + GObjUPtr secret; + BOOST_REQUIRE_NO_THROW(secret = STORE.getObject(token, "")); + + CryptoAlgorithm derive; + + // no algorithm + BOOST_REQUIRE_THROW(secret->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam); + + // wrong algorithm + derive.setParam(ParamName::ALGO_TYPE, AlgoType::ECDH); + BOOST_REQUIRE_THROW(secret->derive(derive, "", RawBuffer()), Exc::Crypto::InputParam); +} + +NEGATIVE_TEST_CASE(deriveKBKDFHMACwrongParams) +{ + KbkdfParamTester test; + + // missing parameters + test.Fail(NO_SIZE, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, NO_PRF, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, NO_MODE, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, NO_LOC, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, NO_BUF, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, NO_BUF, NO_BUF, NO_SIZE, NO_SIZE); + + // conflicting parameters + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, FIX, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, NO_BUF, LAB, FIX, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, NO_BUF, FIX, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, 32); + test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, 0); + test.Fail(32, HMAC256, COUNTER, MIDDLE, NO_BUF, NO_BUF, FIX, NO_SIZE, NO_SIZE, true); + + // invalid values + test.Fail(0, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(1, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(8, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(64, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Fail(32, static_cast(0), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, static_cast(4), COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Fail(32, HMAC256, static_cast(0), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, static_cast(2), BEFORE, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + auto wrongLocation1 = static_cast(0); + auto wrongLocation2 = static_cast(4); + test.Fail(32, HMAC256, COUNTER, wrongLocation1, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, wrongLocation2, CTX, LAB, NO_BUF, NO_SIZE, NO_SIZE); + + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 0, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 1, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 7, NO_SIZE); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, 64, NO_SIZE); + + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 1); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 7); + test.Fail(32, HMAC256, COUNTER, BEFORE, CTX, LAB, NO_BUF, NO_SIZE, 64); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From cdb94bc8e98f08138b948c8bbc4fd7d2ab1a9ec0 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 20 Jan 2023 20:41:55 +0100 Subject: [PATCH 02/16] Add ECDH+KBKDF example Add an ECDH+KBKDF example in form of a doxygen snippet. The code used in it is compiled together with the project. Disclaimer: I don't know how to generate Tizen API documentation. Basing on other projects I made an assumption that doxygen's EXAMPLE_PATH points to doc subdirectory. With such assumption, vanilla doxygen generates the code snippet properly. Change-Id: I7cdc98ff204238be0ad2440a8816ed53a61e7efc --- doc/CMakeLists.txt | 2 + doc/examples/CMakeLists.txt | 11 ++++ doc/examples/key_derive.cpp | 124 ++++++++++++++++++++++++++++++++++++++++ src/include/ckmc/ckmc-manager.h | 3 + 4 files changed, 140 insertions(+) create mode 100644 doc/examples/CMakeLists.txt create mode 100644 doc/examples/key_derive.cpp diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index ae81725..b5ad3aa 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -17,3 +17,5 @@ # @brief # INSTALL(FILES initial_values.xsd DESTINATION ${RO_DATA_DIR}) + +ADD_SUBDIRECTORY(examples) \ No newline at end of file diff --git a/doc/examples/CMakeLists.txt b/doc/examples/CMakeLists.txt new file mode 100644 index 0000000..dd2822f --- /dev/null +++ b/doc/examples/CMakeLists.txt @@ -0,0 +1,11 @@ +SET(TARGET_EXAMPLES "examples") + +SET(EXAMPLE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/key_derive.cpp +) + +ADD_LIBRARY(${TARGET_EXAMPLES} STATIC ${EXAMPLE_SOURCES}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_EXAMPLES} PRIVATE + ${PROJECT_SOURCE_DIR}/src/include +) diff --git a/doc/examples/key_derive.cpp b/doc/examples/key_derive.cpp new file mode 100644 index 0000000..79c6507 --- /dev/null +++ b/doc/examples/key_derive.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include + +//! [KEY_DERIVE example] +int key_derive(const ckmc_raw_buffer_s* peers_public) +{ + int ret; + + const char* const SECRET_ALIAS = "shared_secret"; + const char* const KEY_ALIAS = "derived_key"; + const char* const OURS_PRV_ALIAS = "ours_private"; + const char* const OURS_PUB_ALIAS = "ours_public"; + + ckmc_policy_s unexportable { nullptr, false }; + ckmc_policy_s exportable { nullptr, true }; + + // generate EC key pair + ret = ckmc_create_key_pair_ecdsa(CKMC_EC_PRIME256V1, + OURS_PRV_ALIAS, + OURS_PUB_ALIAS, + unexportable, + exportable); + if (ret != CKMC_ERROR_NONE) + return -1; + + // set ECDH params + ckmc_param_list_h ecdh_params; + ret = ckmc_param_list_new(&ecdh_params); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(ecdh_params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_buffer(ecdh_params, CKMC_PARAM_ECDH_PUBKEY, peers_public); + if (ret != CKMC_ERROR_NONE) + return -1; + + // derive shared secret + ret = ckmc_key_derive(ecdh_params, OURS_PRV_ALIAS, nullptr, SECRET_ALIAS, unexportable); + if (ret != CKMC_ERROR_NONE) + return -1; + + // set KBKDF params + ckmc_param_list_h kbkdf_params; + ret = ckmc_param_list_new(&kbkdf_params); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KDF_PRF, CKMC_KDF_PRF_HMAC_SHA256); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KBKDF_MODE, CKMC_KBKDF_MODE_COUNTER); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(kbkdf_params, + CKMC_PARAM_KBKDF_COUNTER_LOCATION, + CKMC_KBKDF_COUNTER_BEFORE_FIXED); + if (ret != CKMC_ERROR_NONE) + return -1; + + char label[] = "label"; + ckmc_raw_buffer_s* label_buf = nullptr; + ret = ckmc_buffer_new(reinterpret_cast(label), strlen(label), &label_buf); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_buffer(kbkdf_params, CKMC_PARAM_KBKDF_LABEL, label_buf); + ckmc_buffer_free(label_buf); + if (ret != CKMC_ERROR_NONE) + return -1; + + char context[] = "context"; + ckmc_raw_buffer_s* context_buf = nullptr; + ret = ckmc_buffer_new(reinterpret_cast(context), strlen(context), &context_buf); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_buffer(kbkdf_params, CKMC_PARAM_KBKDF_CONTEXT, context_buf); + ckmc_buffer_free(context_buf); + if (ret != CKMC_ERROR_NONE) + return -1; + + ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KDF_LEN, 32); + if (ret != CKMC_ERROR_NONE) + return -1; + + // derive symmetric key + ret = ckmc_key_derive(kbkdf_params, SECRET_ALIAS, nullptr, KEY_ALIAS, unexportable); + if (ret != CKMC_ERROR_NONE) + return -1; + + // remove shared secret + ret = ckmc_remove_key(SECRET_ALIAS); + if (ret != CKMC_ERROR_NONE) + return -1; + + return 0; +} +//! [KEY_DERIVE example] diff --git a/src/include/ckmc/ckmc-manager.h b/src/include/ckmc/ckmc-manager.h index 0ae6af5..54c5ab5 100644 --- a/src/include/ckmc/ckmc-manager.h +++ b/src/include/ckmc/ckmc-manager.h @@ -1126,6 +1126,9 @@ int ckmc_export_wrapped_key(const ckmc_param_list_h params, * * @pre User is already logged in and the user key is already loaded into memory in plain text form. * + * @par Example + * @snippet examples/key_derive.cpp KEY_DERIVE example + * * @see #ckmc_param_list_h * @see #ckmc_policy_s */ -- 2.7.4 From 8f3a3a0c8a64f799e303070c373fe0ea3db4d1ad Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 20 Mar 2023 13:32:40 +0100 Subject: [PATCH 03/16] Use proper constant in TZ data import Change-Id: I4510a29f1bb8d8dfc2216199465cd2a76701ddb6 --- src/manager/crypto/tz-backend/internals.cpp | 1 - src/manager/crypto/tz-backend/tz-context.cpp | 5 ++--- src/manager/crypto/tz-backend/tz-context.h | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index 0c4c022..e9fe00b 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -283,7 +283,6 @@ void importData(const Data &data, pwdBuf, pwdIV, keySizeBits, - Params::DERIVED_KEY_LENGTH_BITS, tag, hash); } diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index 2e0ffd9..9b08cae 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -584,7 +584,6 @@ void TrustZoneContext::importData( const RawBuffer &pwd, const RawBuffer &iv, const uint32_t keySizeBits, - const uint32_t pwdTagSizeBits, RawBuffer &pwdTag, const RawBuffer &hash) { @@ -600,7 +599,7 @@ void TrustZoneContext::importData( uint32_t pwd_flag = pwd.empty() ? 0 : 1; sIn.Push(new TZSerializableFlag(pwd_flag)); if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd, iv, pwdTagSizeBits)); + sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS)); sIn.Push(new TZSerializableBinary(hash)); @@ -610,7 +609,7 @@ void TrustZoneContext::importData( TZSerializer sOut; if (pwd_flag) { - sOut.Push(new TZSerializableBinary(pwdTagSizeBits / 8)); + sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES)); } TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h index 0ccfbc5..4f5a69c 100644 --- a/src/manager/crypto/tz-backend/tz-context.h +++ b/src/manager/crypto/tz-backend/tz-context.h @@ -77,7 +77,6 @@ public: const RawBuffer &pwd, const RawBuffer &pwdIV, const uint32_t keySizeBits, - const uint32_t powTagSizeBits, RawBuffer &pwdTag, const RawBuffer &hash); -- 2.7.4 From 1ffdde75cb5e39af1cc263b782c57fb496c1a8b5 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 20 Mar 2023 10:41:57 +0100 Subject: [PATCH 04/16] TZ backend helpers Change-Id: I4d81f000ca130a468352c31060608d9c78b771ce --- src/manager/crypto/tz-backend/tz-context.cpp | 352 +++++++++----------------- src/manager/crypto/tz-backend/tz-serializer.h | 2 + 2 files changed, 127 insertions(+), 227 deletions(-) diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index 9b08cae..672573f 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -69,6 +69,61 @@ const std::unordered_map MAX_KEY_SIZE = { { ALGO_DSA_SV, 4096 / 8 } }; +struct EncPwd { + const RawBuffer &password; + const RawBuffer &iv; +}; + +template +void push(TZSerializer& ser, const T& value) +{ + ser.Push(new TZSerializableFlag(static_cast(value))); +} + +template<> +void push(TZSerializer& ser, const RawBuffer& value) +{ + ser.Push(new TZSerializableBinary(value)); +} + +template<> +void push(TZSerializer& ser, const Pwd& value) +{ + int32_t pwd_flag = value.getPassword().empty() ? 0 : 1; + ser.Push(new TZSerializableFlag(pwd_flag)); + if (pwd_flag) + ser.Push(new TZSerializablePwdData(value.getPassword(), + value.getIV(), + value.getTag().size() * 8, + value.getTag())); +} + +template<> +void push(TZSerializer& ser, const EncPwd& value) +{ + int32_t pwd_flag = value.password.empty() ? 0 : 1; + ser.Push(new TZSerializableFlag(pwd_flag)); + if (pwd_flag) + ser.Push(new TZSerializablePwdData(value.password, + value.iv, + Params::DEFAULT_AES_GCM_TAG_LEN_BITS)); +} + +template +void push(TZSerializer& ser, const T& first, const Args&... args) +{ + push(ser, first); + push(ser, args...); +} + +template +TZSerializer makeSerializer(const Args&... args) +{ + TZSerializer ser; + push(ser, args...); + return ser; +} + } // anonymous namespace TrustZoneContext::TrustZoneContext() @@ -89,6 +144,31 @@ TrustZoneContext& TrustZoneContext::Instance() return instance; } +TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1) +{ + TEEC_Operation op; + + op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE); + + op.params[1].memref.parent = mem1.Get(); + op.params[1].memref.offset = 0; + op.params[1].memref.size = mem1.Get()->size; + return op; +} + +TEEC_Operation makeOp(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2) +{ + TEEC_Operation op = makeOp(value, mem1); + + op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE); + + op.params[2].memref.parent = mem2.Get(); + op.params[2].memref.offset = 0; + op.params[2].memref.size = mem2.Get()->size; + + return op; +} + void TrustZoneContext::generateIV(RawBuffer& iv) { // command ID = CMD_GENERATE_IV @@ -97,12 +177,8 @@ void TrustZoneContext::generateIV(RawBuffer& iv) uint32_t ivSize = Params::DEFAULT_AES_IV_LEN; TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); - op.params[1].memref.parent = ivMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = ivMemory.Get()->size; + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, ivMemory); + Execute(CMD_GENERATE_IV, &op); iv.resize(ivSize); @@ -114,19 +190,14 @@ void TrustZoneContext::generateSKey(tz_algo_type algo, const RawBuffer &hash) { // command ID = CMD_GENERATE_KEY - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(hash)); + auto sIn = makeSerializer(hash); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory); op.params[0].value.a = algo; op.params[0].value.b = keySizeBits; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; + Execute(CMD_GENERATE_KEY, &op); } @@ -148,17 +219,10 @@ void TrustZoneContext::generateSKeyPwd(tz_algo_type algo, sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES)); TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.a = algo; op.params[0].value.b = keySizeBits; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; + Execute(CMD_GENERATE_KEY_PWD, &op); sOut.Deserialize(outMemory); @@ -183,21 +247,16 @@ void TrustZoneContext::GenerateAKey(tz_command commandId, { uint32_t pubTagSize = 0; uint32_t privTagSize = 0; - uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pubPwdExists)); if (pubPwdExists) { - sIn.Push(new TZSerializablePwdData(pubPwd, pubPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS)); - pubTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3; + pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES; } uint32_t privPwdExists = privPwd.empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(privPwdExists)); if (privPwdExists) { - sIn.Push(new TZSerializablePwdData(privPwd, privPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS)); - privTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3; + privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES; } - sIn.Push(new TZSerializableBinary(hashPriv)); - sIn.Push(new TZSerializableBinary(hashPub)); + + push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -207,16 +266,9 @@ void TrustZoneContext::GenerateAKey(tz_command commandId, TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.b = keySizeBits; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; + Execute(commandId, &op); sOut.Deserialize(outMemory); @@ -269,10 +321,7 @@ void TrustZoneContext::generateDSAKey(uint32_t keySizeBits, const RawBuffer &hashPub) { // command ID = CMD_GENERATE_DSA_KEYPAIR - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(prime)); - sIn.Push(new TZSerializableBinary(subprime)); - sIn.Push(new TZSerializableBinary(base)); + auto sIn = makeSerializer(prime, subprime, base); GenerateAKey(CMD_GENERATE_DSA_KEYPAIR, sIn, @@ -302,17 +351,10 @@ void TrustZoneContext::executeCrypt(tz_command cmd, } TZSerializer sIn; - sIn.Push(new TZSerializableBinary(data)); - int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - pwd.getTag().size() * 8, - pwd.getTag())); - if (algo != ALGO_RSA) - sIn.Push(new TZSerializableBinary(iv)); - sIn.Push(new TZSerializableBinary(keyId)); + if (algo == ALGO_RSA) + sIn = makeSerializer(data, pwd, keyId); + else + sIn = makeSerializer(data, pwd, iv, keyId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -332,16 +374,8 @@ void TrustZoneContext::executeCrypt(tz_command cmd, sOut.Push(new TZSerializableBinary(outMemorySize, false)); TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.a = algo; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; Execute(cmd, &op); @@ -363,20 +397,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId, ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer"); } - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(data)); - int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - pwd.getTag().size() * 8, - pwd.getTag())); - sIn.Push(new TZSerializableBinary(iv)); - sIn.Push(new TZSerializableBinary(keyId)); - sIn.Push(new TZSerializableBinary(aad)); - sIn.Push(new TZSerializableFlag(tagSizeBits)); - + auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -388,16 +409,8 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId, sOut.Push(new TZSerializableBinary(tagSizeBytes)); TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.a = ALGO_AES_GCM; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; Execute(CMD_ENCRYPT, &op); @@ -420,21 +433,7 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId, ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer"); } - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(data)); - int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - pwd.getTag().size() * 8, - pwd.getTag())); - sIn.Push(new TZSerializableBinary(iv)); - sIn.Push(new TZSerializableBinary(keyId)); - sIn.Push(new TZSerializableBinary(aad)); - sIn.Push(new TZSerializableFlag(tagSizeBits)); - sIn.Push(new TZSerializableBinary(tag)); - + auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -442,16 +441,8 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId, sOut.Push(new TZSerializableBinary(data.size())); TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.a = ALGO_AES_GCM; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; Execute(CMD_DECRYPT, &op); @@ -472,16 +463,7 @@ void TrustZoneContext::executeSign(tz_algo_type algo, + std::to_string(keyId.size()) + ")"); } - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(message)); - int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - pwd.getTag().size() * 8, - pwd.getTag())); - sIn.Push(new TZSerializableBinary(keyId)); + auto sIn = makeSerializer(message, pwd, keyId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -489,17 +471,10 @@ void TrustZoneContext::executeSign(tz_algo_type algo, sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false)); TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); op.params[0].value.a = algo; op.params[0].value.b = hash; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; + Execute(CMD_SIGN, &op); sOut.Deserialize(outMemory); @@ -519,28 +494,14 @@ int TrustZoneContext::executeVerify(tz_algo_type algo, + std::to_string(keyId.size()) + ")"); } - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(message)); - sIn.Push(new TZSerializableBinary(signature)); - int32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - pwd.getTag().size() * 8, - pwd.getTag())); - sIn.Push(new TZSerializableBinary(keyId)); + auto sIn = makeSerializer(message, signature, pwd, keyId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory); op.params[0].value.a = algo; op.params[0].value.b = hash; - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; + Execute(CMD_VERIFY, &op); int opRet = op.params[0].value.a; @@ -563,17 +524,12 @@ void TrustZoneContext::executeDestroy(const RawBuffer &keyId) ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer"); } - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(keyId)); + auto sIn = makeSerializer(keyId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; + TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory); + Execute(CMD_DESTROY_KEY, &op); } @@ -589,51 +545,27 @@ void TrustZoneContext::importData( { // command ID = CMD_IMPORT_DATA LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]"); - TZSerializer sIn; - sIn.Push(new TZSerializableFlag(dataType)); - sIn.Push(new TZSerializableBinary(data)); - sIn.Push(new TZSerializableFlag(keySizeBits)); - sIn.Push(new TZSerializableBinary(encData.iv)); - sIn.Push(new TZSerializableBinary(encData.tag)); - - uint32_t pwd_flag = pwd.empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - if (pwd_flag) - sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS)); - sIn.Push(new TZSerializableBinary(hash)); + auto sIn = makeSerializer( + dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TZSerializer sOut; - if (pwd_flag) { + if (!pwd.empty()) { sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES)); } TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); - TEEC_Operation op; - if (pwd_flag) { - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); - } - else { - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); - } - - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory); + if (!pwd.empty()) + op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); Execute(CMD_IMPORT_DATA, &op); - if (pwd_flag) { + if (!pwd.empty()) { sOut.Deserialize(outMemory); sOut.Pull(pwdTag); } @@ -646,19 +578,12 @@ void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize) // command ID = CMD_GET_DATA_SIZE LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId)); - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(dataId)); - + auto sIn = makeSerializer(dataId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory); - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; Execute(CMD_GET_DATA_SIZE, &op); dataSize = op.params[0].value.b; } @@ -670,19 +595,7 @@ void TrustZoneContext::getData(const RawBuffer &dataId, // command ID = CMD_GET_DATA LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId)); - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(dataId)); - - uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; - sIn.Push(new TZSerializableFlag(pwd_flag)); - - if (pwd_flag) { - sIn.Push(new TZSerializablePwdData(pwd.getPassword(), - pwd.getIV(), - Params::DEFAULT_AES_GCM_TAG_LEN_BITS, - pwd.getTag())); - } - + auto sIn = makeSerializer(dataId, pwd); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); @@ -696,15 +609,7 @@ void TrustZoneContext::getData(const RawBuffer &dataId, TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); sOut.Serialize(outMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, - TEEC_MEMREF_WHOLE, TEEC_NONE); - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; - op.params[2].memref.parent = outMemory.Get(); - op.params[2].memref.offset = 0; - op.params[2].memref.size = outMemory.Get()->size; + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); Execute(CMD_GET_DATA, &op); @@ -717,19 +622,12 @@ void TrustZoneContext::destroyData(const RawBuffer &dataId) { // command ID = CMD_DESTROY_DATA LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId)); - TZSerializer sIn; - sIn.Push(new TZSerializableBinary(dataId)); - + auto sIn = makeSerializer(dataId); TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); sIn.Serialize(inMemory); - TEEC_Operation op; - op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE, - TEEC_NONE, TEEC_NONE); + TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory); - op.params[1].memref.parent = inMemory.Get(); - op.params[1].memref.offset = 0; - op.params[1].memref.size = inMemory.Get()->size; Execute(CMD_DESTROY_DATA, &op); } diff --git a/src/manager/crypto/tz-backend/tz-serializer.h b/src/manager/crypto/tz-backend/tz-serializer.h index b865477..8a1fbb4 100644 --- a/src/manager/crypto/tz-backend/tz-serializer.h +++ b/src/manager/crypto/tz-backend/tz-serializer.h @@ -99,7 +99,9 @@ public: TZSerializer() : m_memorySize(0) {} ~TZSerializer() {} TZSerializer(const TZSerializer&) = delete; + TZSerializer(TZSerializer&&) = default; TZSerializer& operator=(const TZSerializer&) = delete; + TZSerializer& operator=(TZSerializer&&) = default; void Push(TZSerializable *serializable); -- 2.7.4 From 4e6d4a578819a74a7143a7dab6ee7aa9a5c2427f Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 24 Mar 2023 17:01:55 +0100 Subject: [PATCH 05/16] Remove unused function Change-Id: I157503be4e191edc35c12453d0b780c8d1ed466b --- src/manager/crypto/tz-backend/internals.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index e9fe00b..61f7b60 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -133,26 +133,6 @@ tz_algo_type getAlgType(AlgoType type) }; } -tz_algo_type getAlgType(KeyType keyType) -{ - switch (keyType) - { - case KeyType::KEY_AES: - return ALGO_AES_GEN; - case KeyType::KEY_RSA_PUBLIC: - case KeyType::KEY_RSA_PRIVATE: - return ALGO_RSA_GEN; - case KeyType::KEY_DSA_PUBLIC: - case KeyType::KEY_DSA_PRIVATE: - return ALGO_DSA_GEN; - case KeyType::KEY_ECDSA_PUBLIC: - case KeyType::KEY_ECDSA_PRIVATE: - return ALGO_ECDSA_GEN; - default: - ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported"); - }; -} - tz_hash_type getHashType(HashAlgorithm hash) { switch (hash) -- 2.7.4 From 4c0940faf922b9301b3ff3c83a2e00ecffeab62f Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 21 Mar 2023 08:34:49 +0100 Subject: [PATCH 06/16] Implement EC key pair generation in TZ backend Change-Id: Id1199d174146dfeb7b75081783dca90624fe12de --- src/manager/crypto/tz-backend/internals.cpp | 26 +++++++++++++++++++++++- src/manager/crypto/tz-backend/store.cpp | 4 ++++ src/manager/crypto/tz-backend/tz-context.cpp | 30 ++++++++++++++++++++++++++-- src/manager/crypto/tz-backend/tz-context.h | 11 +++++++++- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index 61f7b60..0c8d537 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -101,6 +101,16 @@ tz_data_type toTzDataType(const CKM::DataType dataType) { } } +tz_ec toTzEc(CKM::ElipticCurve ec) +{ + switch(ec) { + case CKM::ElipticCurve::prime192v1: return EC_NIST_P192; + case CKM::ElipticCurve::prime256v1: return EC_NIST_P256; + case CKM::ElipticCurve::secp384r1: return EC_NIST_P384; + default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "EC not supported by tz-backend"); + } +} + } // namespace namespace CKM { @@ -189,7 +199,6 @@ AlgoType generateAKey(const CryptoAlgorithm &alg, const RawBuffer &hashPub) { AlgoType keyType = unpack(alg, ParamName::ALGO_TYPE); - int keyBits = unpack(alg, ParamName::GEN_KEY_LEN); RawBuffer pubPwdBuf; if (!pubPwd.empty()) @@ -201,6 +210,7 @@ AlgoType generateAKey(const CryptoAlgorithm &alg, switch (keyType) { case AlgoType::RSA_GEN: { + int keyBits = unpack(alg, ParamName::GEN_KEY_LEN); TrustZoneContext::Instance().generateRSAKey(keyBits, pubPwdBuf, pubPwdIv, @@ -213,6 +223,7 @@ AlgoType generateAKey(const CryptoAlgorithm &alg, break; } case AlgoType::DSA_GEN: { + int keyBits = unpack(alg, ParamName::GEN_KEY_LEN); RawBuffer prime; RawBuffer subprime; RawBuffer base; @@ -231,6 +242,19 @@ AlgoType generateAKey(const CryptoAlgorithm &alg, hashPub); break; } + case AlgoType::ECDSA_GEN: { + CKM::ElipticCurve ec = unpack(alg, ParamName::GEN_EC); + TrustZoneContext::Instance().generateECKey(toTzEc(ec), + pubPwdBuf, + pubPwdIv, + privPwdBuf, + privPwdIv, + pubTag, + privTag, + hashPriv, + hashPub); + break; + } default: { ThrowErr(Exc::Crypto::InputParam, "Invalid algo type provided for generateAKey function"); diff --git a/src/manager/crypto/tz-backend/store.cpp b/src/manager/crypto/tz-backend/store.cpp index 5035f74..e7e58fb 100644 --- a/src/manager/crypto/tz-backend/store.cpp +++ b/src/manager/crypto/tz-backend/store.cpp @@ -149,6 +149,10 @@ TokenPair Store::generateAKey(const CryptoAlgorithm &alg, const Password &privPa pubType= DataType(KeyType::KEY_DSA_PUBLIC); privType = DataType(KeyType::KEY_DSA_PRIVATE); } + else if(keyType == AlgoType::ECDSA_GEN){ + pubType= DataType(KeyType::KEY_ECDSA_PUBLIC); + privType = DataType(KeyType::KEY_ECDSA_PRIVATE); + } return std::make_pair( Token(m_backendId, privType, pack(hashPriv, privPass, privIv, privTag)), diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index 672573f..8a054bf 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -235,7 +235,7 @@ void TrustZoneContext::generateSKeyPwd(tz_algo_type algo, void TrustZoneContext::GenerateAKey(tz_command commandId, TZSerializer &sIn, - uint32_t keySizeBits, + uint32_t genParam, // key size in bits or EC type const RawBuffer &pubPwd, const RawBuffer &pubPwdIv, const RawBuffer &privPwd, @@ -267,7 +267,7 @@ void TrustZoneContext::GenerateAKey(tz_command commandId, TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); - op.params[0].value.b = keySizeBits; + op.params[0].value.b = genParam; Execute(commandId, &op); @@ -336,6 +336,32 @@ void TrustZoneContext::generateDSAKey(uint32_t keySizeBits, hashPub); } +void TrustZoneContext::generateECKey(tz_ec ec, + const RawBuffer &pubPwd, + const RawBuffer &pubPwdIv, + const RawBuffer &privPwd, + const RawBuffer &privPwdIv, + RawBuffer &pubKeyTag, + RawBuffer &privKeyTag, + const RawBuffer &hashPriv, + const RawBuffer &hashPub) +{ + // command ID = CMD_GENERATE_EC_KEYPAIR + TZSerializer sIn; + + GenerateAKey(CMD_GENERATE_EC_KEYPAIR, + sIn, + static_cast(ec), + pubPwd, + pubPwdIv, + privPwd, + privPwdIv, + pubKeyTag, + privKeyTag, + hashPriv, + hashPub); +} + void TrustZoneContext::executeCrypt(tz_command cmd, tz_algo_type algo, const RawBuffer &keyId, diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h index 4f5a69c..b85186e 100644 --- a/src/manager/crypto/tz-backend/tz-context.h +++ b/src/manager/crypto/tz-backend/tz-context.h @@ -70,6 +70,15 @@ public: RawBuffer &privKeyTag, const RawBuffer &hashPriv, const RawBuffer &hashPub); + void generateECKey(tz_ec ec, + const RawBuffer &pubPwd, + const RawBuffer &pubPwdIv, + const RawBuffer &privPwd, + const RawBuffer &privPwdIv, + RawBuffer &pubKeyTag, + RawBuffer &privKeyTag, + const RawBuffer &hashPriv, + const RawBuffer &hashPub); void importData(uint32_t dataType, const RawBuffer &data, @@ -142,7 +151,7 @@ private: void GenerateAKey(tz_command commandID, TZSerializer &sIn, - uint32_t keySizeBits, + uint32_t genParam, const RawBuffer &pubPwd, const RawBuffer &pubPwdIv, const RawBuffer &privPwd, -- 2.7.4 From c1cf2af3e7115a061c014f8e5dc091118eaf1e6b Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 16 Mar 2023 12:45:45 +0100 Subject: [PATCH 07/16] Key derivation in TZ backend Change-Id: I76a9b93d0e2deb82724ba941b97dcc4c995b08d7 --- src/manager/crypto/tz-backend/internals.cpp | 84 +++++++++++++++++++++++++++ src/manager/crypto/tz-backend/internals.h | 14 +++++ src/manager/crypto/tz-backend/obj.cpp | 43 ++++++++++++++ src/manager/crypto/tz-backend/obj.h | 2 + src/manager/crypto/tz-backend/store.cpp | 30 +++++----- src/manager/crypto/tz-backend/store.h | 5 ++ src/manager/crypto/tz-backend/tz-context.cpp | 87 ++++++++++++++++++++++++++++ src/manager/crypto/tz-backend/tz-context.h | 21 +++++++ 8 files changed, 272 insertions(+), 14 deletions(-) diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index 0c8d537..b8abe24 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include @@ -570,6 +572,88 @@ int verify(const RawBuffer &pkey, signature); } +void deriveECDH(const RawBuffer &prvKey, + const Pwd &prvKeyPwd, + const RawBuffer &pubKey, + const Password &secretPwd, + const RawBuffer &secretPwdIV, + RawBuffer &secretTag, + const RawBuffer &secretHash) +{ + auto peerKey = std::make_shared(pubKey); + if (peerKey->getType() != KeyType::KEY_ECDSA_PUBLIC) + ThrowErr(Exc::Crypto::InputParam, "ECDH requires peer's public EC key"); + auto peerEvp = peerKey->getEvpShPtr().get(); + assert(peerEvp); + + int subType = EVP_PKEY_type(EVP_PKEY_id(peerEvp)); + if (subType != EVP_PKEY_EC) + ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType); + + auto ecKey = EVP_PKEY_get0_EC_KEY(peerEvp); + if (!ecKey) + ThrowErr(Exc::Crypto::InternalError, "Can't get EC key"); + + auto ecPoint = EC_KEY_get0_public_key(ecKey); + if (!ecPoint) + ThrowErr(Exc::Crypto::InternalError, "Can't get EC public key"); + + auto ecGroup = EC_KEY_get0_group(ecKey); + if (!ecGroup) + ThrowErr(Exc::Crypto::InternalError, "Can't get EC group"); + + BIGNUM *x = BN_new(); + BIGNUM *y = BN_new(); + if (!EC_POINT_get_affine_coordinates(ecGroup, ecPoint, x, y, NULL)) + ThrowErr(Exc::Crypto::InternalError, "Failed to get EC pub key coordinates"); + + auto xBuf = extractBignumData(x); + auto yBuf = extractBignumData(y); + + RawBuffer secretPwdBuf(secretPwd.begin(), secretPwd.end()); + + TrustZoneContext::Instance().executeEcdh(prvKey, + prvKeyPwd, + xBuf, + yBuf, + secretPwdBuf, + secretPwdIV, + secretTag, + secretHash); +} + +void deriveKBKDF(const RawBuffer &secret, + const CryptoAlgorithm &alg, + const Password &keyPwd, + const RawBuffer &keyPwdIV, + RawBuffer &keyTag, + const RawBuffer &keyHash) +{ + auto prf = unpack(alg, ParamName::KDF_PRF); + auto mode = unpack(alg, ParamName::KBKDF_MODE); + auto location = unpack(alg, ParamName::KBKDF_COUNTER_LOCATION); + + size_t rlen = 32, llen = 32, dummy; + alg.getParam(ParamName::KBKDF_RLEN, rlen); + alg.getParam(ParamName::KBKDF_LLEN, llen); + bool noSeparator = alg.getParam(ParamName::KBKDF_NO_SEPARATOR, dummy); + + RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end()); + + TrustZoneContext::Instance().executeKbkdf(secret, + prf, + mode, + location, + rlen, + llen, + noSeparator, + keyPwdBuf, + keyPwdIV, + keyTag, + keyHash); +} + + } // namespace Internals } // namespace TZ } // namespace Crypto diff --git a/src/manager/crypto/tz-backend/internals.h b/src/manager/crypto/tz-backend/internals.h index 3322eee..bdfcc03 100644 --- a/src/manager/crypto/tz-backend/internals.h +++ b/src/manager/crypto/tz-backend/internals.h @@ -118,6 +118,20 @@ int verify(const RawBuffer &pkey, const RawBuffer &message, const RawBuffer &signature); +void deriveECDH(const RawBuffer &prvKey, + const Pwd &prvKeyPwd, + const RawBuffer &pubKey, + const Password &secretPwd, + const RawBuffer &secretPwdIV, + RawBuffer &secretTag, + const RawBuffer &secretHash); + +void deriveKBKDF(const RawBuffer &secret, + const CryptoAlgorithm &alg, + const Password &keyPwd, + const RawBuffer &keyPwdIV, + RawBuffer &keyTag, + const RawBuffer &keyHash); } // namespace Internals } // namespace TZ } // namespace Crypto diff --git a/src/manager/crypto/tz-backend/obj.cpp b/src/manager/crypto/tz-backend/obj.cpp index e6a91ee..86ac7a6 100644 --- a/src/manager/crypto/tz-backend/obj.cpp +++ b/src/manager/crypto/tz-backend/obj.cpp @@ -19,7 +19,9 @@ * @version 1.0 */ #include +#include #include +#include #include namespace CKM { @@ -48,6 +50,24 @@ AlgoType key2algo(DataType type) } } // namespace anonymous +Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &hash) +{ + auto algo = unpack(alg, ParamName::ALGO_TYPE); + if (algo != AlgoType::KBKDF) + ThrowErr(Exc::Crypto::InputParam, "Wrong algorithm"); + + RawBuffer iv; + RawBuffer tag; + if (!pass.empty()) { + // IV is needed for key encryption + iv = Internals::generateIV(); + } + + Internals::deriveKBKDF(getBinary(), alg, pass, iv, tag, hash); + + return Token(backendId(), DataType(KeyType::KEY_AES), Store::pack(hash, pass, iv, tag)); +} + RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) { return Internals::symmetricEncrypt(getBinary(), getPassword(), alg, data); @@ -68,6 +88,29 @@ RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher) return Internals::asymmetricDecrypt(getBinary(), getPassword(), alg, cipher); } +Token AKey::derive(const CryptoAlgorithm &alg, const Password &pass, const RawBuffer &hash) +{ + if (m_type != DataType::KEY_ECDSA_PRIVATE) + ThrowErr(Exc::Crypto::InputParam, "ECDH requires EC private key"); + + auto algo = unpack(alg, ParamName::ALGO_TYPE); + if (algo != AlgoType::ECDH) + ThrowErr(Exc::Crypto::InputParam, "Wrong algorithm"); + + auto pubKey = unpack(alg, ParamName::ECDH_PUBKEY); + + RawBuffer iv; + RawBuffer tag; + if (!pass.empty()) { + // IV is needed for key encryption + iv = Internals::generateIV(); + } + + Internals::deriveECDH(getBinary(), getPassword(), pubKey, pass, iv, tag, hash); + + return Token(backendId(), DataType::BINARY_DATA, Store::pack(hash, pass, iv, tag)); +} + RawBuffer AKey::sign( const CryptoAlgorithm &alg, const RawBuffer &message) diff --git a/src/manager/crypto/tz-backend/obj.h b/src/manager/crypto/tz-backend/obj.h index b4d77d8..77b3be8 100644 --- a/src/manager/crypto/tz-backend/obj.h +++ b/src/manager/crypto/tz-backend/obj.h @@ -66,6 +66,7 @@ public: { return m_raw; } + Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override; protected: RawBuffer m_raw; @@ -114,6 +115,7 @@ public: const RawBuffer &sign) override; RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &) override; RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &) override; + Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override; }; class Cert : public AKey { diff --git a/src/manager/crypto/tz-backend/store.cpp b/src/manager/crypto/tz-backend/store.cpp index e7e58fb..0847166 100644 --- a/src/manager/crypto/tz-backend/store.cpp +++ b/src/manager/crypto/tz-backend/store.cpp @@ -71,20 +71,6 @@ RawBuffer unpackData(const RawBuffer &packed) return data; } -RawBuffer pack(const RawBuffer &keyId, const Password &pwd, - const RawBuffer &iv, const RawBuffer &tag) -{ - // determine whether the key is password protected and store schema info - // we don't need to additionally encrypt key ID - int scheme = pwd.empty() ? EncryptionScheme::NONE : EncryptionScheme::PASSWORD; - - if (scheme == EncryptionScheme::PASSWORD) { - return SerializeMessage(scheme, keyId, iv, tag); - } else { - return SerializeMessage(scheme, keyId); - } -} - } // namespace Store::Store(CryptoBackend backendId) : @@ -204,6 +190,22 @@ void Store::destroy(const Token &token) Internals::destroyKey(id); } +RawBuffer Store::pack(const RawBuffer &keyId, + const Password &pwd, + const RawBuffer &iv, + const RawBuffer &tag) +{ + // determine whether the key is password protected and store schema info + // we don't need to additionally encrypt key ID + int scheme = pwd.empty() ? EncryptionScheme::NONE : EncryptionScheme::PASSWORD; + + if (scheme == EncryptionScheme::PASSWORD) { + return SerializeMessage(scheme, keyId, iv, tag); + } else { + return SerializeMessage(scheme, keyId); + } +} + } // namespace TZ } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/tz-backend/store.h b/src/manager/crypto/tz-backend/store.h index 21e3519..145c76b 100644 --- a/src/manager/crypto/tz-backend/store.h +++ b/src/manager/crypto/tz-backend/store.h @@ -44,6 +44,11 @@ public: const RawBuffer &); virtual void destroy(const Token &); + static RawBuffer pack(const RawBuffer &keyId, + const Password &pwd, + const RawBuffer &iv, + const RawBuffer &tag); + // TODO device key ID is needed here to support importEncrypted }; diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index 8a054bf..efeb4a9 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -657,6 +657,93 @@ void TrustZoneContext::destroyData(const RawBuffer &dataId) Execute(CMD_DESTROY_DATA, &op); } +TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd) +{ + auto &tag = pwd.getTag(); + return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag); +} + +void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId, + const Pwd &prvKeyPwd, + const RawBuffer &pubX, + const RawBuffer &pubY, + const RawBuffer &secretPwdBuf, + const RawBuffer &secretPwdIV, + RawBuffer &secretTag, + const RawBuffer &secretHash) +{ + // command ID = CMD_DERIVE + LogDebug("TrustZoneContext::executeEcdh"); + + auto sIn = makeSerializer( + prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash); + TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); + sIn.Serialize(inMemory); + + TZSerializer sOut; + if (!secretPwdBuf.empty()) { + sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES)); + } + + TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); + + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory); + if (!secretPwdBuf.empty()) + op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); + op.params[0].value.a = ALGO_ECDH_DRV; + + Execute(CMD_DERIVE, &op); + + if (!secretPwdBuf.empty()) { + sOut.Deserialize(outMemory); + sOut.Pull(secretTag); + } + + LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash)); +} + +void TrustZoneContext::executeKbkdf(const RawBuffer& secret, + KdfPrf prf, + KbkdfMode mode, + KbkdfCounterLocation location, + size_t rlen, + size_t llen, + bool noSeparator, + const RawBuffer &keyPwdBuf, + const RawBuffer &keyPwdIV, + RawBuffer &keyTag, + const RawBuffer &keyHash) +{ + // command ID = CMD_DERIVE + LogDebug("TrustZoneContext::executeKbkdf"); + + auto sIn = makeSerializer( + secret, prf, mode, location, rlen, llen, noSeparator, EncPwd{keyPwdBuf, keyPwdIV}, keyHash); + TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT); + sIn.Serialize(inMemory); + + TZSerializer sOut; + if (!keyPwdBuf.empty()) { + sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES)); + } + + TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT); + + TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory); + if (!keyPwdBuf.empty()) + op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory); + op.params[0].value.a = ALGO_KBKDF_DRV; + + Execute(CMD_DERIVE, &op); + + if (!keyPwdBuf.empty()) { + sOut.Deserialize(outMemory); + sOut.Pull(keyTag); + } + + LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash)); +} + void TrustZoneContext::Initialize() { TEEC_Operation op; diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h index b85186e..9f7ed02 100644 --- a/src/manager/crypto/tz-backend/tz-context.h +++ b/src/manager/crypto/tz-backend/tz-context.h @@ -135,6 +135,27 @@ public: void destroyData(const RawBuffer &dataId); + void executeEcdh(const RawBuffer &prvKeyId, + const Pwd &prvKeyPwd, + const RawBuffer &pubX, + const RawBuffer &pubY, + const RawBuffer &secretPwdBuf, + const RawBuffer &secretPwdIV, + RawBuffer &secretTag, + const RawBuffer &secretHash); + + void executeKbkdf(const RawBuffer& secret, + KdfPrf prf, + KbkdfMode mode, + KbkdfCounterLocation location, + size_t rlen, + size_t llen, + bool noSeparator, + const RawBuffer &keyPwdBuf, + const RawBuffer &keyPwdIV, + RawBuffer &keyTag, + const RawBuffer &keyHash); + private: TrustZoneContext(); ~TrustZoneContext(); -- 2.7.4 From fdb14ab8a2724e0231d8c1240c17d48f123715e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 22 Mar 2023 09:15:34 +0100 Subject: [PATCH 08/16] Replace 'virtual' with 'override' in TZ Store Change-Id: I5a5406be8a4e8f3429ddb18cc9603a8647ec66a2 --- src/manager/crypto/tz-backend/store.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/manager/crypto/tz-backend/store.h b/src/manager/crypto/tz-backend/store.h index 145c76b..28b5557 100644 --- a/src/manager/crypto/tz-backend/store.h +++ b/src/manager/crypto/tz-backend/store.h @@ -31,18 +31,18 @@ class Store : public GStore { public: explicit Store(CryptoBackend backendId); - virtual GObjUPtr getObject(const Token &, const Password &); - virtual TokenPair generateAKey(const CryptoAlgorithm &, - const Password &, - const Password &, - const RawBuffer &, - const RawBuffer &); - virtual Token generateSKey(const CryptoAlgorithm &, - const Password &, - const RawBuffer &); - virtual Token import(const Data &, const Password &, const EncryptionParams &, - const RawBuffer &); - virtual void destroy(const Token &); + GObjUPtr getObject(const Token &, const Password &) override; + TokenPair generateAKey(const CryptoAlgorithm &, + const Password &, + const Password &, + const RawBuffer &, + const RawBuffer &) override; + Token generateSKey(const CryptoAlgorithm &, + const Password &, + const RawBuffer &) override; + Token import(const Data &, const Password &, const EncryptionParams &, + const RawBuffer &) override; + void destroy(const Token &) override; static RawBuffer pack(const RawBuffer &keyId, const Password &pwd, -- 2.7.4 From 656a642e7cf5cecb4ff5c603a24ff337c548d9a6 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 24 Mar 2023 16:52:05 +0100 Subject: [PATCH 09/16] Make unpack a static GStore method Needed for key wrapping. Change-Id: I1ac65d92176237d61719944f7eb1688588c67117 --- src/manager/crypto/tz-backend/store.cpp | 55 +++++++++++++++++---------------- src/manager/crypto/tz-backend/store.h | 6 ++++ 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/manager/crypto/tz-backend/store.cpp b/src/manager/crypto/tz-backend/store.cpp index 0847166..ff992ed 100644 --- a/src/manager/crypto/tz-backend/store.cpp +++ b/src/manager/crypto/tz-backend/store.cpp @@ -40,24 +40,6 @@ enum EncryptionScheme { PASSWORD = 1 << 0 }; -void unpack(const RawBuffer &packed, - int &scheme, - RawBuffer &data, - RawBuffer &iv, - RawBuffer &tag) -{ - MessageBuffer buffer; - buffer.Push(RawBuffer(packed)); - - buffer.Deserialize(scheme); - - if (scheme == EncryptionScheme::PASSWORD) { - buffer.Deserialize(data, iv, tag); - } else { - buffer.Deserialize(data); - } -} - RawBuffer unpackData(const RawBuffer &packed) { MessageBuffer buffer; @@ -84,15 +66,7 @@ GObjUPtr Store::getObject(const Token &token, const Password &pass) RawBuffer id; RawBuffer iv; RawBuffer tag; - unpack(token.data, scheme, id, iv, tag); - - if (scheme & EncryptionScheme::PASSWORD && pass.empty()) { - ThrowErr(Exc::Crypto::AuthenticationFailed, - "This token is protected with password and none passed"); - } else if (!(scheme & EncryptionScheme::PASSWORD) && !pass.empty()) { - ThrowErr(Exc::Crypto::AuthenticationFailed, - "This token is not protected with password but passed one"); - } + unpack(token.data, pass, scheme, id, iv, tag); if (token.dataType.isKeyPrivate() || token.dataType.isKeyPublic()) return make(scheme, std::move(id), Pwd(pass, iv, tag), token.dataType); @@ -206,6 +180,33 @@ RawBuffer Store::pack(const RawBuffer &keyId, } } +void Store::unpack(const RawBuffer &packed, + const Password& password, + int &scheme, + RawBuffer &data, + RawBuffer &iv, + RawBuffer &tag) +{ + MessageBuffer buffer; + buffer.Push(RawBuffer(packed)); + + buffer.Deserialize(scheme); + + if (scheme == EncryptionScheme::PASSWORD) { + buffer.Deserialize(data, iv, tag); + } else { + buffer.Deserialize(data); + } + + if (scheme & EncryptionScheme::PASSWORD && password.empty()) { + ThrowErr(Exc::Crypto::AuthenticationFailed, + "This token is protected with password and none passed"); + } else if (!(scheme & EncryptionScheme::PASSWORD) && !password.empty()) { + ThrowErr(Exc::Crypto::AuthenticationFailed, + "This token is not protected with password but passed one"); + } +} + } // namespace TZ } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/tz-backend/store.h b/src/manager/crypto/tz-backend/store.h index 28b5557..d15fa09 100644 --- a/src/manager/crypto/tz-backend/store.h +++ b/src/manager/crypto/tz-backend/store.h @@ -49,6 +49,12 @@ public: const RawBuffer &iv, const RawBuffer &tag); + static void unpack(const RawBuffer &packed, + const Password& password, + int &scheme, + RawBuffer &data, + RawBuffer &iv, + RawBuffer &tag); // TODO device key ID is needed here to support importEncrypted }; -- 2.7.4 From 342d84e966499ed8234bf5338732e01107ee4f14 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 27 Mar 2023 12:47:45 +0200 Subject: [PATCH 10/16] Enable EC key pair generation in TZ backend Until now, the decider was redirecting such requests to SW backend at all times. Change-Id: Ibbda55fa8ecdb3b5b8b3803754bfbf226a612704 --- src/manager/crypto/platform/decider.cpp | 11 +++-------- src/manager/crypto/platform/decider.h | 2 +- src/manager/service/ckm-logic.cpp | 22 +--------------------- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/manager/crypto/platform/decider.cpp b/src/manager/crypto/platform/decider.cpp index 93cd7ae..9109fb2 100644 --- a/src/manager/crypto/platform/decider.cpp +++ b/src/manager/crypto/platform/decider.cpp @@ -114,15 +114,10 @@ GStore &Decider::getStore(DataType data, const Policy &policy, bool encrypted) })); } -GStore &Decider::getStore(const Policy &policyPrv, DataType prv, DataType pub) +GStore &Decider::getStore(const Policy &policyPrv) { - return getStore(chooseBackend(policyPrv, [&]{ - return - // extractable private key can only be handled by OpenSSL - policyPrv.extractable || - // ECDSA algorithm is unsupported by GP API 1.0 - prv.isEllipticCurve() || pub.isEllipticCurve(); - })); + // extractable private key can only be handled by OpenSSL + return getStore(chooseBackend(policyPrv, [&]{ return policyPrv.extractable; })); } } // namespace Crypto diff --git a/src/manager/crypto/platform/decider.h b/src/manager/crypto/platform/decider.h index ddf62b0..08ab78e 100644 --- a/src/manager/crypto/platform/decider.h +++ b/src/manager/crypto/platform/decider.h @@ -41,7 +41,7 @@ public: Decider(); GStore &getStore(const Token &token); GStore &getStore(DataType data, const Policy &policy, bool encrypted = false); - GStore &getStore(const Policy &policyPrv, DataType prv, DataType pub); + GStore &getStore(const Policy &policyPrv); private: GStore &getStore(CryptoBackend id); diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index bb07985..54bf913 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -55,16 +55,6 @@ bool isNameValid(const CKM::Name &name) return true; } -// keypair data type, having private key data type and public key data type -// private is assumed to be .first, public .second -using DataTypePair = std::pair; - -const std::map ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP = { - { CKM::AlgoType::RSA_GEN, { CKM::DataType(CKM::KeyType::KEY_RSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_RSA_PUBLIC) } }, - { CKM::AlgoType::DSA_GEN, { CKM::DataType(CKM::KeyType::KEY_DSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_DSA_PUBLIC) } }, - { CKM::AlgoType::ECDSA_GEN, { CKM::DataType(CKM::KeyType::KEY_ECDSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_ECDSA_PUBLIC) } }, -}; - } // anonymous namespace namespace CKM { @@ -1152,23 +1142,13 @@ RawBuffer CKMLogic::createKeyPair( if (retCodePub != CKM_API_SUCCESS) return retCodePub; - AlgoType keyType = AlgoType::RSA_GEN; - - if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType)) - ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found."); - - const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType); - if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end()) - ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value."); - const DataTypePair& dt = dtIt->second; - if (policyPrv.backend != policyPub.backend) ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend."); bool exportable = policyPrv.extractable || policyPub.extractable; Policy lessRestricted(Password(), exportable, policyPrv.backend); - TokenPair keys = m_decider.getStore(policyPrv, dt.first, dt.second).generateAKey( + TokenPair keys = m_decider.getStore(policyPrv).generateAKey( keyGenParams, policyPrv.password, policyPub.password, -- 2.7.4 From 3fdf767b56af3864d34e3296bee2ec251962ea40 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 23 Mar 2023 09:19:41 +0100 Subject: [PATCH 11/16] Simplify DB::Row/Token extraction For wrapped key export we need to pass 1 object to be wrapped by another. GObjUPtr is insufficient as it loses information about the specific type. We'll need that info in TZ backend. The wrapping API can be then made look as follows: RawBuffer GObj::wrap(const CryptoAlgorithm ¶ms, const Token &keyToWrap, const Password &keyToWrapPass); Change-Id: Ifeea08cbef43c6e86c067e37c68627d6b819bfcf --- src/manager/service/ckm-logic.cpp | 75 +++++++++++++++++++++++++----------- src/manager/service/ckm-logic.h | 21 +++++++++- src/manager/service/crypto-logic.cpp | 10 ++--- src/manager/service/crypto-logic.h | 2 +- unit-tests/test_crypto-logic.cpp | 39 ++++++++++--------- 5 files changed, 97 insertions(+), 50 deletions(-) diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 54bf913..496b95b 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -625,25 +625,20 @@ int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred, return m_accessControl.canRead(accessorCred, permission); } -Crypto::GObjUPtr CKMLogic::rowToObject( +void CKMLogic::decryptRow( UserData &handler, - DB::Row row, + DB::Row &row, const Password &password, const RawBuffer &hash) { - Crypto::GStore &store = m_decider.getStore(row); - - Password pass = m_accessControl.isCCMode() ? "" : password; - - // decrypt row - Crypto::GObjUPtr obj; - if (CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) { handler.crypto.decryptRow(Password(), row); - - obj = store.getObject(row, pass); } else { + Crypto::GStore &store = m_decider.getStore(row); + + Password pass = m_accessControl.isCCMode() ? "" : password; + // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data handler.crypto.decryptRow(pass, row); // destroy it in store @@ -655,20 +650,26 @@ Crypto::GObjUPtr CKMLogic::rowToObject( Crypto::EncryptionParams(), hash); - // get it from the store (it can be different than the data we imported into store) - obj = store.getObject(token, pass); - // update row with new token *static_cast(&row) = std::move(token); // encrypt it with app key: pass(data) -> b64(appkey(pass(data)) - handler.crypto.encryptRow(row); + auto encryptedRow = handler.crypto.encryptRow(row); // update it in db - handler.database.updateRow(row); + handler.database.updateRow(encryptedRow); } +} - return obj; +Crypto::GObjUPtr CKMLogic::rowToObject( + UserData &handler, + DB::Row row, + const Password &password, + const RawBuffer &hash) +{ + decryptRow(handler, row, password, hash); + + return decryptedRowToObj(row, password); } int CKMLogic::readDataHelper( @@ -740,21 +741,20 @@ int CKMLogic::readDataHelper( password, obj, objDataType); } -int CKMLogic::readDataHelper( +int CKMLogic::readRowHelper( bool exportFlag, const Credentials &cred, DataType dataType, const Name &name, const ClientId &owner, const Password &password, - Crypto::GObjUPtr &obj, + DB::Row &row, DataType &objDataType) { auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner); if (retCode != CKM_API_SUCCESS) return retCode; - DB::Row row; retCode = readSingleRow(name, owner, dataType, dbOp.database(), row); if (CKM_API_SUCCESS != retCode) return retCode; @@ -767,20 +767,49 @@ int CKMLogic::readDataHelper( // check access rights retCode = checkDataPermissionsHelper(cred, row, exportFlag, permission); - if (CKM_API_SUCCESS != retCode) + if (retCode != CKM_API_SUCCESS) return retCode; auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid); if (digest.empty()) return CKM_API_ERROR_HASH_ERROR; - obj = rowToObject(dbOp.handler(), std::move(row), password, digest); - // rowToObject may modify db + decryptRow(dbOp.handler(), row, password, digest); + + // decryptRow may modify db dbOp.transaction().commit(); return CKM_API_SUCCESS; } +Crypto::GObjUPtr CKMLogic::decryptedRowToObj(const DB::Row& row, const Password &password) +{ + Crypto::GStore &store = m_decider.getStore(row); + + Password pass = m_accessControl.isCCMode() ? "" : password; + return store.getObject(row, pass); +} + +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const ClientId &owner, + const Password &password, + Crypto::GObjUPtr &obj, + DataType &objDataType) +{ + DB::Row row; + int retCode = readRowHelper(exportFlag, cred, dataType, name, owner, password, row, objDataType); + if (retCode != CKM_API_SUCCESS) + return retCode; + + obj = decryptedRowToObj(row, password); + + return CKM_API_SUCCESS; +} + RawBuffer CKMLogic::getData( const Credentials &cred, int msgId, diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index 58d0700..8829612 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -253,6 +253,12 @@ private: bool exportFlag, const PermissionMask& permission); + void decryptRow( + UserData &handler, + DB::Row &row, + const Password &password, + const RawBuffer &hash); + Crypto::GObjUPtr rowToObject( UserData &handler, DB::Row row, @@ -269,6 +275,18 @@ protected: Crypto::GObjUPtr &obj); private: + int readRowHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const ClientId &owner, + const Password &password, + DB::Row &row, + DataType &objDataType); + + Crypto::GObjUPtr decryptedRowToObj(const DB::Row& row, const Password &password); + int readDataHelper( bool exportFlag, const Credentials &cred, @@ -326,8 +344,7 @@ private: DB::Row encryptOne(Token&& token, const Policy& policy) { DB::Row row(std::move(token), m_name, m_owner, static_cast(policy.extractable)); - m_handler.crypto.encryptRow(row); - return row; + return m_handler.crypto.encryptRow(row); } void finalize(Token&& token, const Policy& policy) { diff --git a/src/manager/service/crypto-logic.cpp b/src/manager/service/crypto-logic.cpp index bebdb7a..a0dd9fb 100644 --- a/src/manager/service/crypto-logic.cpp +++ b/src/manager/service/crypto-logic.cpp @@ -121,7 +121,7 @@ RawBuffer CryptoLogic::generateRandIV() const return civ; } -void CryptoLogic::encryptRow(DB::Row &row) +DB::Row CryptoLogic::encryptRow(const DB::Row &row) { DB::Row crow = row; RawBuffer key; @@ -132,14 +132,14 @@ void CryptoLogic::encryptRow(DB::Row &row) if (crow.dataSize <= 0) ThrowErr(Exc::InternalError, "Invalid dataSize."); - if (!haveKey(row.owner)) + if (!haveKey(crow.owner)) ThrowErr(Exc::InternalError, "Missing application key for ", - row.owner, " client."); + crow.owner, " client."); if (crow.iv.empty()) crow.iv = generateRandIV(); - key = m_keyMap[row.owner]; + key = m_keyMap[crow.owner]; CLEAR_FLAGS(crow.encryptionScheme); SET_FLAG(ENCR_APPKEY, crow.encryptionScheme); @@ -160,7 +160,7 @@ void CryptoLogic::encryptRow(DB::Row &row) SET_ENCRYPTION_VERSION(ENCRYPTION_V2, crow.encryptionScheme); - row = std::move(crow); + return crow; } int CryptoLogic::getSchemeVersion(int encryptionScheme) diff --git a/src/manager/service/crypto-logic.h b/src/manager/service/crypto-logic.h index 6054384..aec7352 100644 --- a/src/manager/service/crypto-logic.h +++ b/src/manager/service/crypto-logic.h @@ -39,7 +39,7 @@ public: virtual ~CryptoLogic() {} void decryptRow(const Password &password, DB::Row &row); - void encryptRow(DB::Row &row); + DB::Row encryptRow(const DB::Row &row); static int getSchemeVersion(int encryptionScheme); diff --git a/unit-tests/test_crypto-logic.cpp b/unit-tests/test_crypto-logic.cpp index b0b8c27..5c168a0 100644 --- a/unit-tests/test_crypto-logic.cpp +++ b/unit-tests/test_crypto-logic.cpp @@ -141,9 +141,9 @@ POSITIVE_TEST_CASE(row_encryption) CryptoLogic logic; - DB::Row rowCopy = row; + DB::Row rowCopy; BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY)); - BOOST_REQUIRE_NO_THROW(logic.encryptRow(rowCopy)); + BOOST_REQUIRE_NO_THROW(rowCopy = logic.encryptRow(row)); BOOST_REQUIRE(rowCopy.algorithmType == DBCMAlgType::AES_GCM_256); BOOST_REQUIRE(rowCopy.dataSize == static_cast(row.data.size())); BOOST_REQUIRE(!rowCopy.iv.empty()); @@ -191,64 +191,65 @@ NEGATIVE_TEST_CASE(row_encryption) row.iv.clear(); // correct encryption - BOOST_REQUIRE_NO_THROW(logic.encryptRow(row)); + DB::Row encryptedRow; + BOOST_REQUIRE_NO_THROW(encryptedRow = logic.encryptRow(row)); // wrong algorithm - row.algorithmType = DBCMAlgType::NONE; - BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed); - row.algorithmType = DBCMAlgType::AES_GCM_256; + encryptedRow.algorithmType = DBCMAlgType::NONE; + BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed); + encryptedRow.algorithmType = DBCMAlgType::AES_GCM_256; // unnecessary password - BOOST_REQUIRE_THROW(logic.decryptRow("unnecessary password", row), + BOOST_REQUIRE_THROW(logic.decryptRow("unnecessary password", encryptedRow), Exc::AuthenticationFailed); // no key BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT)); - BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed); + BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed); BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY)); // wrong owner - ++row.owner[0]; - BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed); - --row.owner[0]; + ++encryptedRow.owner[0]; + BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed); + --encryptedRow.owner[0]; // no iv - auto rowCopy = row; + auto rowCopy = encryptedRow; rowCopy.iv.clear(); BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError); // wrong iv (not base64) - rowCopy = row; + rowCopy = encryptedRow; rowCopy.iv[0] = 64; BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError); // wrong iv - rowCopy = row; + rowCopy = encryptedRow; changeBase64(rowCopy.iv); BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed); // no ciphertext - rowCopy = row; + rowCopy = encryptedRow; rowCopy.data.clear(); BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy),Exc::InternalError); // wrong ciphertext (not base64) - rowCopy = row; + rowCopy = encryptedRow; rowCopy.data[0] = 64; BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError); // wrong ciphertext - rowCopy = row; + rowCopy = encryptedRow; changeBase64(rowCopy.data); BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed); // wrong tag - rowCopy = row; + rowCopy = encryptedRow; ++rowCopy.tag[0]; BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed); // wrong dataSize - rowCopy = row; + rowCopy = encryptedRow; ++rowCopy.dataSize; BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed); } -- 2.7.4 From a242a6468206f9eb32d8a33a064c813122215a09 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 28 Mar 2023 12:48:12 +0200 Subject: [PATCH 12/16] isSKey mistake counter + a refactoring promise Change-Id: I9fd0a98db92c8c0a6c2c7091fc9da22d0325b16a --- src/manager/common/data-type.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/manager/common/data-type.h b/src/manager/common/data-type.h index 58dde1b..33884b7 100644 --- a/src/manager/common/data-type.h +++ b/src/manager/common/data-type.h @@ -79,6 +79,12 @@ public: operator int() const; bool isKey() const; + + /* + * Number of times someone mistook it for isKey() (or the opposite): 3 + * Increase the counter if it happened to you. + * I will rename this function if the counter reaches 4. + */ bool isSKey() const; bool isChainCert() const; bool isKeyPrivate() const; -- 2.7.4 From 4d7b002fa0e3953c7340609252c87dab916b57c0 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 28 Mar 2023 18:16:18 +0200 Subject: [PATCH 13/16] Use new types in key derivation Change-Id: I379f6a1c53c278c0adbaa71269b6232176601769 --- src/manager/crypto/tz-backend/internals.cpp | 37 +++++++++++++++++++++++++--- src/manager/crypto/tz-backend/tz-context.cpp | 6 ++--- src/manager/crypto/tz-backend/tz-context.h | 6 ++--- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index b8abe24..5b8ad1e 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -113,6 +113,37 @@ tz_ec toTzEc(CKM::ElipticCurve ec) } } +tz_prf toTzPrf(CKM::KdfPrf prf) +{ + switch(prf) { + case CKM::KdfPrf::HMAC_SHA256: return PRF_HMAC_SHA256; + case CKM::KdfPrf::HMAC_SHA384: return PRF_HMAC_SHA384; + case CKM::KdfPrf::HMAC_SHA512: return PRF_HMAC_SHA512; + default: ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "PRF not supported by tz-backend"); + } +} + +tz_kbkdf_mode toTzKbkdfMode(CKM::KbkdfMode mode) +{ + switch(mode) { + case CKM::KbkdfMode::COUNTER: return KBKDF_MODE_COUNTER; + default: + ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, "KBKDF mode not supported by tz-backend"); + } +} + +tz_kbkdf_ctr_loc toTzCtrLoc(CKM::KbkdfCounterLocation loc) +{ + switch(loc) { + case CKM::KbkdfCounterLocation::BEFORE_FIXED: return KBKDF_LOC_BEFORE_FIXED; + case CKM::KbkdfCounterLocation::AFTER_FIXED: return KBKDF_LOC_AFTER_FIXED; + case CKM::KbkdfCounterLocation::MIDDLE_FIXED: return KBKDF_LOC_MIDDLE_FIXED; + default: + ThrowErr(CKM::Exc::Crypto::DataTypeNotSupported, + "KBKDF counter location not supported by tz-backend"); + } +} + } // namespace namespace CKM { @@ -641,9 +672,9 @@ void deriveKBKDF(const RawBuffer &secret, RawBuffer keyPwdBuf(keyPwd.begin(), keyPwd.end()); TrustZoneContext::Instance().executeKbkdf(secret, - prf, - mode, - location, + toTzPrf(prf), + toTzKbkdfMode(mode), + toTzCtrLoc(location), rlen, llen, noSeparator, diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index efeb4a9..a058e1b 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -703,9 +703,9 @@ void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId, } void TrustZoneContext::executeKbkdf(const RawBuffer& secret, - KdfPrf prf, - KbkdfMode mode, - KbkdfCounterLocation location, + tz_prf prf, + tz_kbkdf_mode mode, + tz_kbkdf_ctr_loc location, size_t rlen, size_t llen, bool noSeparator, diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h index 9f7ed02..2a1cff3 100644 --- a/src/manager/crypto/tz-backend/tz-context.h +++ b/src/manager/crypto/tz-backend/tz-context.h @@ -145,9 +145,9 @@ public: const RawBuffer &secretHash); void executeKbkdf(const RawBuffer& secret, - KdfPrf prf, - KbkdfMode mode, - KbkdfCounterLocation location, + tz_prf prf, + tz_kbkdf_mode mode, + tz_kbkdf_ctr_loc location, size_t rlen, size_t llen, bool noSeparator, -- 2.7.4 From c36626103cad463618e75f57abca98919842fa71 Mon Sep 17 00:00:00 2001 From: "m.ksiezak" Date: Fri, 17 Feb 2023 14:57:55 +0100 Subject: [PATCH 14/16] Implementation of ckmc_import_wrapped_key Change-Id: Ic8d2a865de2a705d39a4de06e9b91de5a6f30ef5 --- src/include/ckm/ckm-manager.h | 9 ++++++- src/manager/client-capi/ckmc-manager.cpp | 34 ++++++++++++++++++++++++++ src/manager/client/client-manager-impl.cpp | 30 +++++++++++++++++++++++ src/manager/client/client-manager-impl.h | 7 ++++++ src/manager/client/client-manager.cpp | 20 +++++++++++++++ src/manager/common/protocols.h | 3 ++- src/manager/crypto/generic-backend/gobj.h | 16 ++++++++++++ src/manager/crypto/generic-backend/gstore.h | 8 ------ src/manager/crypto/sw-backend/obj.cpp | 34 ++++++++++++++++++++++++++ src/manager/crypto/sw-backend/obj.h | 27 ++++++++++++++------ src/manager/service/ckm-logic.cpp | 38 ++++++++++++++++++++++++++++- src/manager/service/ckm-logic.h | 14 +++++++++++ src/manager/service/ckm-service.cpp | 34 ++++++++++++++++++++++++++ unit-tests/test_sw-backend.cpp | 4 +-- 14 files changed, 257 insertions(+), 21 deletions(-) diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index 8a94b54..defe6ce 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -178,9 +178,16 @@ public: static ManagerShPtr create(); + int importWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const RawBuffer &encryptedKey, + const KeyType keyType, + const Policy &policy); + private: std::unique_ptr m_impl; }; } // namespace CKM - diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index ba72405..488f287 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -1012,6 +1012,40 @@ int ckmc_key_derive(const ckmc_param_list_h params, _tostring(secret_password), CKM::Alias(new_key_alias), _toCkmPolicy(new_key_policy))); + EXCEPTION_GUARD_END +} + +KEY_MANAGER_CAPI +int ckmc_import_wrapped_key(const ckmc_param_list_h params, + const char *wrapping_key_alias, + const char *wrapping_key_password, + const char *alias, + const ckmc_key_s *wrapped_key, + const ckmc_policy_s policy) +{ + EXCEPTION_GUARD_START_CAPI + + if (params == nullptr || + wrapping_key_alias == nullptr || + alias == nullptr || + wrapped_key == nullptr || + wrapped_key->raw_key == nullptr || + wrapped_key->key_size == 0) + return CKMC_ERROR_INVALID_PARAMETER; + + const CKM::CryptoAlgorithm *ca = reinterpret_cast + (params); + + auto mgr = CKM::Manager::create(); + + return to_ckmc_error(mgr->importWrappedKey(*ca, + CKM::Alias(wrapping_key_alias), + _tostring(wrapping_key_password), + CKM::Alias(alias), + CKM::RawBuffer(wrapped_key->raw_key, + wrapped_key->raw_key + wrapped_key->key_size), + static_cast(wrapped_key->key_type), + _toCkmPolicy(policy))); EXCEPTION_GUARD_END } diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 08d4157..5228f91 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -759,4 +759,34 @@ int Manager::Impl::deriveKey(const CryptoAlgorithm &algo, EXCEPTION_GUARD_END } +int Manager::Impl::importWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const RawBuffer &encryptedKey, + const KeyType keyType, + const Policy &policy) +{ + EXCEPTION_GUARD_START_CPPAPI + + AliasSupport wrapping_helper(wrappingKeyAlias); + AliasSupport helper(alias); + + return Request(*this, + LogicCommand::IMPORT_WRAPPED_KEY, + m_storageConnection, + CryptoAlgorithmSerializable(params), + wrappingKeyPassword, + encryptedKey, + DataType(keyType), + PolicySerializable(policy), + helper.getName(), + helper.getOwner(), + wrapping_helper.getName(), + wrapping_helper.getOwner() + ).maybeDeserialize(); + + EXCEPTION_GUARD_END +} + } // namespace CKM diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 6371bfe..19dbcc5 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -141,6 +141,13 @@ public: const Alias &newKeyAlias, const Policy &newKeyPolicy); + int importWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const RawBuffer &encryptedKey, + const KeyType keyType, + const Policy &policy); private: int saveBinaryData( diff --git a/src/manager/client/client-manager.cpp b/src/manager/client/client-manager.cpp index 45cc796..2c4d1d8 100644 --- a/src/manager/client/client-manager.cpp +++ b/src/manager/client/client-manager.cpp @@ -251,6 +251,26 @@ int Manager::verifySignature( cAlg); } +int Manager::importWrappedKey( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const RawBuffer &encryptedKey, + const KeyType keyType, + const Policy &policy) +{ + return m_impl->importWrappedKey( + params, + wrappingKeyAlias, + wrappingKeyPassword, + alias, + encryptedKey, + keyType, + policy + ); +} + int Manager::ocspCheck(const CertificateShPtrVector &certificateChainVector, int &ocspStatus) { diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 8796e5b..3670b9c 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -67,7 +67,8 @@ enum class LogicCommand : int { SAVE_PKCS12, GET_PKCS12, GET_PROTECTION_STATUS, - DERIVE + DERIVE, + IMPORT_WRAPPED_KEY }; enum class EncryptionCommand : int { diff --git a/src/manager/crypto/generic-backend/gobj.h b/src/manager/crypto/generic-backend/gobj.h index 4763878..7e60dab 100644 --- a/src/manager/crypto/generic-backend/gobj.h +++ b/src/manager/crypto/generic-backend/gobj.h @@ -32,6 +32,14 @@ namespace CKM { namespace Crypto { +// Data is very generic and does not say anything about content. +struct Data { + Data() {}; + Data(const DataType &t, RawBuffer d) : type(t), data(std::move(d)) {} + DataType type; + RawBuffer data; // buffer will be better? +}; + class GObj { protected: explicit GObj(CryptoBackend backendId) : m_backendId(backendId) {} @@ -68,6 +76,14 @@ public: ThrowErr(Exc::Crypto::OperationNotSupported); } + virtual Token unwrap(const CryptoAlgorithm &, + const Data &, + const Password &, + const RawBuffer &) + { + ThrowErr(Exc::Crypto::OperationNotSupported); + } + virtual ~GObj() { } diff --git a/src/manager/crypto/generic-backend/gstore.h b/src/manager/crypto/generic-backend/gstore.h index 191dc99..5d54c5a 100644 --- a/src/manager/crypto/generic-backend/gstore.h +++ b/src/manager/crypto/generic-backend/gstore.h @@ -33,14 +33,6 @@ namespace CKM { namespace Crypto { -// Data is very generic and does not say anything about content. -struct Data { - Data() {}; - Data(const DataType &t, RawBuffer d) : type(t), data(std::move(d)) {} - DataType type; - RawBuffer data; // buffer will be better? -}; - class GStore { public: virtual GObjUPtr getObject(const Token &, const Password &) = 0; diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index 9b4e1a2..1f812e0 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace CKM { namespace Crypto { @@ -65,6 +66,34 @@ Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawB return Token(backendId(), data.type, Store::pack(data.buffer, pass)); } +Token Key::unwrap(const CryptoAlgorithm ¶ms, + const Data &encryptedKey, + const Password &pass, + const RawBuffer &) +{ + auto decrypted = decrypt(params, encryptedKey.data); + + if (!encryptedKey.type.isKey()) { + ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a key"); + } + + // validate the decrypted key + if (encryptedKey.type.isSKey()) { + auto tmp = CKM::Key::createAES(decrypted); + if (!tmp) + ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid AES key"); + } else { + auto tmp = CKM::Key::create(decrypted); + if (!tmp) + ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid asymmetric key"); + + if (encryptedKey.type != DataType(tmp->getType())) + ThrowErr(Exc::Crypto::InputParam, "Wrapped key type does not match the required one"); + } + + return Token(backendId(), encryptedKey.type, Store::pack(decrypted, pass)); +} + RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) { return Internals::symmetricEncrypt(getBinary(), alg, data); @@ -189,6 +218,11 @@ Token Cert::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) ThrowErr(Exc::Crypto::OperationNotSupported); } +Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, const RawBuffer &) +{ + ThrowErr(Exc::Crypto::OperationNotSupported); +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h index 2712341..15ddb98 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -50,19 +50,26 @@ protected: DataType m_type; }; -class SKey : public BData { +class Key : public BData { + using BData::BData; + + Token unwrap(const CryptoAlgorithm ¶ms, + const Data &encryptedKey, + const Password &pass, + const RawBuffer &hash) override; +}; + +class SKey : public Key { public: - SKey(CryptoBackend backendId, RawBuffer buffer, DataType keyType) : - BData(backendId, std::move(buffer), keyType) {} + using Key::Key; RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &) override; RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &) override; }; -class AKey : public BData { +class AKey : public Key { public: - AKey(CryptoBackend backendId, RawBuffer buffer, DataType dataType) : - BData(backendId, std::move(buffer), dataType) {} + using Key::Key; RawBuffer sign(const CryptoAlgorithm &alg, const RawBuffer &message) override; int verify(const CryptoAlgorithm &alg, @@ -80,9 +87,13 @@ protected: class Cert : public AKey { public: - Cert(CryptoBackend backendId, RawBuffer buffer, DataType dataType) : - AKey(backendId, std::move(buffer), dataType) {} + using AKey::AKey; + Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override; + Token unwrap(const CryptoAlgorithm &, + const Data &, + const Password &, + const RawBuffer &) override; protected: EvpShPtr getEvpShPtr() override; diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 496b95b..bc88876 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1562,5 +1562,41 @@ RawBuffer CKMLogic::deriveKey( })); } -} // namespace CKM +RawBuffer CKMLogic::importWrappedKey( + const Credentials &cred, + const int msgId, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &encryptedKeyName, + const ClientId &encryptedKeyOwner, + const RawBuffer &encryptedKey, + const CKM::DataType encryptedKeyType, + const PolicySerializable &encryptedKeyPolicy) +{ + + return SerializeMessage(msgId, tryRet([&] { + Crypto::GObjUPtr wrappingKey; + auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, encryptedKeyName, encryptedKeyOwner); + if (retCode != CKM_API_SUCCESS) + return retCode; + + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName, + wrappingKeyOwner, wrappingKeyPassword, wrappingKey); + if (retCode != CKM_API_SUCCESS) + return retCode; + + Token token = wrappingKey->unwrap(params, + Crypto::Data(encryptedKeyType, std::move(encryptedKey)), + encryptedKeyPolicy.password, + digest); + + dbOp.finalize(std::move(token), encryptedKeyPolicy); + + return retCode; + })); +} + +} // namespace CKM diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index 8829612..ce990bb 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -230,6 +230,20 @@ public: const Policy &policy); int unlockSystemDB(); + + RawBuffer importWrappedKey( + const Credentials &cred, + const int msgId, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &encryptedKeyName, + const ClientId &encryptedKeyOwner, + const RawBuffer &encryptedKey, + const CKM::DataType encryptedKeyType, + const PolicySerializable &encryptedKeyPolicy); + private: // select private/system database depending on asking uid and owner id. // output: database handler for effective owner diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 27c90ad..8d06e64 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -458,6 +458,40 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) newKeyPolicy); } + case LogicCommand::IMPORT_WRAPPED_KEY: { + CryptoAlgorithmSerializable params; + Name wrappingKeyName; + ClientId wrappingKeyOwner; + Password wrappingKeyPassword; + Name encryptedKeyName; + RawBuffer encryptedKey; + CKM::DataType encryptedKeyType; + PolicySerializable encryptedKeyPolicy; + + buffer.Deserialize(params, + wrappingKeyPassword, + encryptedKey, + encryptedKeyType, + encryptedKeyPolicy, + encryptedKeyName, + explicitOwner, + wrappingKeyName, + wrappingKeyOwner); + + return m_logic->importWrappedKey( + cred, + msgId, + params, + wrappingKeyName, + cred.effectiveOwner(wrappingKeyOwner), + wrappingKeyPassword, + encryptedKeyName, + cred.effectiveOwner(explicitOwner), + encryptedKey, + encryptedKeyType, + encryptedKeyPolicy); + } + default: Throw(Exception::BrokenProtocol); } diff --git a/unit-tests/test_sw-backend.cpp b/unit-tests/test_sw-backend.cpp index 4de683e..a4e6077 100644 --- a/unit-tests/test_sw-backend.cpp +++ b/unit-tests/test_sw-backend.cpp @@ -75,9 +75,9 @@ void checkKey(const Token& token, KeyType keyType, const Password& pass) KeyShPtr key; if (dataType.isSKey()) - key = Key::createAES(data); + key = CKM::Key::createAES(data); else - key = Key::create(data); + key = CKM::Key::create(data); BOOST_REQUIRE(key); BOOST_REQUIRE(!key->empty()); -- 2.7.4 From dc375c06b749aba6c49413a8b51887d4f1c62dba Mon Sep 17 00:00:00 2001 From: "m.ksiezak" Date: Thu, 16 Mar 2023 11:56:02 +0100 Subject: [PATCH 15/16] Implementation of ckmc_export_wrapped_key Change-Id: I2769be74b1ad3d76537d31bc3f7ac4659946029f --- src/include/ckm/ckm-manager.h | 8 +++ src/include/ckmc/ckmc-manager.h | 14 ++--- src/manager/client-capi/ckmc-manager.cpp | 46 ++++++++++++++++ src/manager/client/client-manager-impl.cpp | 43 +++++++++++++++ src/manager/client/client-manager-impl.h | 8 +++ src/manager/client/client-manager.cpp | 21 ++++++- src/manager/common/protocols.h | 4 +- src/manager/crypto/generic-backend/gobj.h | 7 +++ src/manager/crypto/sw-backend/obj.cpp | 17 ++++++ src/manager/crypto/sw-backend/obj.h | 9 +++ src/manager/crypto/sw-backend/store.cpp | 88 +++++++++++++++--------------- src/manager/crypto/sw-backend/store.h | 1 + src/manager/service/ckm-logic.cpp | 36 +++++++++++- src/manager/service/ckm-logic.h | 12 +++- src/manager/service/ckm-service.cpp | 29 ++++++++++ 15 files changed, 287 insertions(+), 56 deletions(-) diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index defe6ce..8ce5dea 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -186,6 +186,14 @@ public: const KeyType keyType, const Policy &policy); + int exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey); + private: std::unique_ptr m_impl; }; diff --git a/src/include/ckmc/ckmc-manager.h b/src/include/ckmc/ckmc-manager.h index 54c5ab5..fd92c25 100644 --- a/src/include/ckmc/ckmc-manager.h +++ b/src/include/ckmc/ckmc-manager.h @@ -1062,18 +1062,18 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, * - #CKMC_ALGO_RSA_OAEP * @param[in] wrapping_key_alias The name of the wrapping key * @param[in] wrapping_key_password An optional password of the wrapping key - * @param[in] alias The name of the key to be wrapped and exported - * @param[in] password An optional password used to decrypt the key pointed by @a alias + * @param[in] wrapped_key_alias The name of the key to be wrapped and exported + * @param[in] wrapped_key_password An optional password used to decrypt the key pointed by @a wrapped_key_alias * @param[out] ppwrapped_key The wrapped key * * @return @c 0 on success, otherwise a negative error value * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid (missing or invalid mandatory * algorithm parameter, GCM tag authentication failed, - * @a wrapping_key_alias = NULL, @a alias = NULL, - * @a wrapped_key = NULL, @a ppwrapped_key = NULL) + * @a wrapping_key_alias = NULL, @a wrapped_key_alias = NULL, + * @a ppwrapped_key = NULL) * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN @a wrapping_key_alias or @a alias does not exist + * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN @a wrapping_key_alias or @a wrapped_key_alias does not exist * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_AUTHENTICATION_FAILED Wrapping key decryption failed because * @a wrapping_key_password is incorrect @@ -1089,8 +1089,8 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, int ckmc_export_wrapped_key(const ckmc_param_list_h params, const char *wrapping_key_alias, const char *wrapping_key_password, - const char *alias, - const char *password, + const char *wrapped_key_alias, + const char *wrapped_key_password, ckmc_key_s **ppwrapped_key); diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index 488f287..e5fa0ec 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -1049,3 +1049,49 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, EXCEPTION_GUARD_END } + +KEY_MANAGER_CAPI +int ckmc_export_wrapped_key(const ckmc_param_list_h params, + const char *wrapping_key_alias, + const char *wrapping_key_password, + const char *wrapped_key_alias, + const char *wrapped_key_password, + ckmc_key_s **ppwrapped_key) +{ + EXCEPTION_GUARD_START_CAPI + + if (params == nullptr || + wrapping_key_alias == nullptr || + wrapped_key_alias == nullptr || + ppwrapped_key == nullptr) + return CKMC_ERROR_INVALID_PARAMETER; + + const CKM::CryptoAlgorithm *ca = reinterpret_cast + (params); + + int ret = 0; + ckmc_key_s *wrapped_key = nullptr; + CKM::RawBuffer wrappedKey; + CKM::KeyType keyType; + auto mgr = CKM::Manager::create(); + + ret = to_ckmc_error(mgr->exportWrappedKey(*ca, + CKM::Alias(wrapping_key_alias), + _tostring(wrapping_key_password), + CKM::Alias(wrapped_key_alias), + _tostring(wrapped_key_password), + keyType, + wrappedKey)); + + + + if (ret == CKMC_ERROR_NONE) { + ckmc_key_type_e ckmcKeyType = static_cast(keyType); + ret = ckmc_key_new(wrappedKey.data(), wrappedKey.size(), ckmcKeyType, nullptr, &wrapped_key); + if (ret == CKMC_ERROR_NONE) + *ppwrapped_key = wrapped_key; + } + + return ret; + EXCEPTION_GUARD_END +} diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 5228f91..d2d8534 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -789,4 +789,47 @@ int Manager::Impl::importWrappedKey(const CryptoAlgorithm ¶ms, EXCEPTION_GUARD_END } +int Manager::Impl::exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey) +{ + EXCEPTION_GUARD_START_CPPAPI + + AliasSupport wrapping_helper(wrappingKeyAlias); + AliasSupport wrapped_helper(wrappedKeyAlias); + DataType *dataTypeKey = nullptr; + + int retCode = Request(*this, + LogicCommand::EXPORT_WRAPPED_KEY, + m_storageConnection, + CryptoAlgorithmSerializable(params), + wrapping_helper.getName(), + wrapping_helper.getOwner(), + wrappingKeyPassword, + wrapped_helper.getName(), + wrapped_helper.getOwner(), + wrappedKeyPassword + ).maybeDeserialize(dataTypeKey, wrappedKey); + + if (retCode != CKM_API_SUCCESS) + return retCode; + + if (dataTypeKey->isSKey()) { + keyType = KeyType::KEY_AES; + } else if (dataTypeKey->isKeyPrivate()) { + keyType = KeyType::KEY_RSA_PRIVATE; + } else { + return CKM_API_ERROR_INVALID_FORMAT; + } + + return retCode; + + EXCEPTION_GUARD_END +} + + } // namespace CKM diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 19dbcc5..91e5732 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -149,6 +149,14 @@ public: const KeyType keyType, const Policy &policy); + int exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey); + private: int saveBinaryData( const Alias &alias, diff --git a/src/manager/client/client-manager.cpp b/src/manager/client/client-manager.cpp index 2c4d1d8..8ef76bb 100644 --- a/src/manager/client/client-manager.cpp +++ b/src/manager/client/client-manager.cpp @@ -324,5 +324,24 @@ ManagerShPtr Manager::create() } } -} // namespace CKM +int Manager::exportWrappedKey( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey) +{ + return m_impl->exportWrappedKey( + params, + wrappingKeyAlias, + wrappingKeyPassword, + wrappedKeyAlias, + wrappedKeyPassword, + keyType, + wrappedKey + ); +} +} // namespace CKM diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 3670b9c..3b1cad8 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -68,7 +68,8 @@ enum class LogicCommand : int { GET_PKCS12, GET_PROTECTION_STATUS, DERIVE, - IMPORT_WRAPPED_KEY + IMPORT_WRAPPED_KEY, + EXPORT_WRAPPED_KEY }; enum class EncryptionCommand : int { @@ -138,4 +139,3 @@ struct COMMON_API CryptoAlgorithmSerializable : public CryptoAlgorithm, }; } // namespace CKM - diff --git a/src/manager/crypto/generic-backend/gobj.h b/src/manager/crypto/generic-backend/gobj.h index 7e60dab..8433e67 100644 --- a/src/manager/crypto/generic-backend/gobj.h +++ b/src/manager/crypto/generic-backend/gobj.h @@ -84,6 +84,13 @@ public: ThrowErr(Exc::Crypto::OperationNotSupported); } + virtual RawBuffer wrap(const CryptoAlgorithm &, + const Token &, + const Password &) + { + ThrowErr(Exc::Crypto::OperationNotSupported); + } + virtual ~GObj() { } diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index 1f812e0..a120cc6 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -94,6 +94,16 @@ Token Key::unwrap(const CryptoAlgorithm ¶ms, return Token(backendId(), encryptedKey.type, Store::pack(decrypted, pass)); } +RawBuffer Key::wrap(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass) +{ + + RawBuffer data = Store::unpack(keyToWrap.data, keyToWrapPass); + return encrypt(params, data); +} + + RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) { return Internals::symmetricEncrypt(getBinary(), alg, data); @@ -223,6 +233,13 @@ Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, cons ThrowErr(Exc::Crypto::OperationNotSupported); } +RawBuffer Cert::wrap(const CryptoAlgorithm &, + const Token &, + const Password &) +{ + ThrowErr(Exc::Crypto::OperationNotSupported); +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h index 15ddb98..16b801a 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -57,6 +57,11 @@ class Key : public BData { const Data &encryptedKey, const Password &pass, const RawBuffer &hash) override; + + RawBuffer wrap(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass) override; + }; class SKey : public Key { @@ -95,6 +100,10 @@ public: const Password &, const RawBuffer &) override; + RawBuffer wrap(const CryptoAlgorithm &, + const Token &, + const Password &) override; + protected: EvpShPtr getEvpShPtr() override; }; diff --git a/src/manager/crypto/sw-backend/store.cpp b/src/manager/crypto/sw-backend/store.cpp index 96a081b..7d610f7 100644 --- a/src/manager/crypto/sw-backend/store.cpp +++ b/src/manager/crypto/sw-backend/store.cpp @@ -72,50 +72,6 @@ RawBuffer passwordToKey(const Password &password, const RawBuffer &salt, return result; } -RawBuffer unpack(const RawBuffer &packed, const Password &pass) -{ - MessageBuffer buffer; - buffer.Push(RawBuffer(packed)); - int encryptionScheme = EncryptionScheme::NONE; - RawBuffer data; - buffer.Deserialize(encryptionScheme, data); - - if (encryptionScheme == EncryptionScheme::NONE) { - if (!pass.empty()) - ThrowErr(Exc::AuthenticationFailed, "Unexpected custom password."); - return data; - } - - MessageBuffer internalBuffer; - internalBuffer.Push(std::move(data)); - RawBuffer encrypted; - RawBuffer iv; - RawBuffer tag; - - // serialization exceptions will be catched as CKM::Exception and will cause - // CKM_API_ERROR_SERVER_ERROR - internalBuffer.Deserialize(encrypted, iv, tag); - - /* - * AES GCM will check data integrity and handle cases where: - * - wrong password is used - * - password is empty when it shouldn't be - */ - RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH); - - RawBuffer ret; - - try { - ret = Crypto::SW::Internals::decryptDataAesGcm(key, encrypted, iv, tag); - } catch (const Exc::Crypto::InputParam &e) { - ThrowErr(Exc::AuthenticationFailed, "Decryption with custom password failed, authentication failed"); - } catch (const Exc::Exception &e) { - ThrowErr(Exc::InternalError, "Decryption with custom password failed, internal error"); - } - - return ret; -} - std::string rawToHexString(const RawBuffer &raw) { return hexDump(raw); @@ -214,6 +170,50 @@ RawBuffer Store::pack(const RawBuffer &data, const Password &pass) return SerializeMessage(scheme, packed); } +RawBuffer Store::unpack(const RawBuffer &packed, const Password &pass) +{ + MessageBuffer buffer; + buffer.Push(RawBuffer(packed)); + int encryptionScheme = EncryptionScheme::NONE; + RawBuffer data; + buffer.Deserialize(encryptionScheme, data); + + if (encryptionScheme == EncryptionScheme::NONE) { + if (!pass.empty()) + ThrowErr(Exc::AuthenticationFailed, "Unexpected custom password."); + return data; + } + + MessageBuffer internalBuffer; + internalBuffer.Push(std::move(data)); + RawBuffer encrypted; + RawBuffer iv; + RawBuffer tag; + + // serialization exceptions will be catched as CKM::Exception and will cause + // CKM_API_ERROR_SERVER_ERROR + internalBuffer.Deserialize(encrypted, iv, tag); + + /* + * AES GCM will check data integrity and handle cases where: + * - wrong password is used + * - password is empty when it shouldn't be + */ + RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH); + + RawBuffer ret; + + try { + ret = Crypto::SW::Internals::decryptDataAesGcm(key, encrypted, iv, tag); + } catch (const Exc::Crypto::InputParam &e) { + ThrowErr(Exc::AuthenticationFailed, "Decryption with custom password failed, authentication failed"); + } catch (const Exc::Exception &e) { + ThrowErr(Exc::InternalError, "Decryption with custom password failed, internal error"); + } + + return ret; +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/store.h b/src/manager/crypto/sw-backend/store.h index eba1365..fa61e9b 100644 --- a/src/manager/crypto/sw-backend/store.h +++ b/src/manager/crypto/sw-backend/store.h @@ -45,6 +45,7 @@ public: void destroy(const Token &) override {} static RawBuffer pack(const RawBuffer &data, const Password &pass); + static RawBuffer unpack(const RawBuffer &packed, const Password &pass); }; } // namespace SW diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index bc88876..d931083 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1575,7 +1575,6 @@ RawBuffer CKMLogic::importWrappedKey( const CKM::DataType encryptedKeyType, const PolicySerializable &encryptedKeyPolicy) { - return SerializeMessage(msgId, tryRet([&] { Crypto::GObjUPtr wrappingKey; @@ -1599,4 +1598,39 @@ RawBuffer CKMLogic::importWrappedKey( })); } +RawBuffer CKMLogic::exportWrappedKey( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &wrappedKeyName, + const ClientId &wrappedKeyOwner, + const Password &wrappedKeyPassword) +{ + Crypto::GObjUPtr wrappingKey; + DB::Row wrappedKeyRow; + DataType wrappedKeyType; + RawBuffer wrappedKey; + + auto retCode = tryRet([&] { + auto retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName, + wrappingKeyOwner, wrappingKeyPassword, wrappingKey); + if (retCode != CKM_API_SUCCESS) + return retCode; + + retCode = readRowHelper(false, cred, DataType::DB_KEY_FIRST, wrappedKeyName, + wrappedKeyOwner, wrappedKeyPassword, wrappedKeyRow, wrappedKeyType); + if (retCode != CKM_API_SUCCESS) + return retCode; + + wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, wrappedKeyPassword); + + return retCode; + }); + + return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey); +} + } // namespace CKM diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index ce990bb..b87848b 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -202,6 +202,17 @@ public: const ClientId &newKeyOwner, const Policy &newKeyPolicy); + RawBuffer exportWrappedKey( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &wrappedKeyName, + const ClientId &wrappedKeyOwner, + const Password &wrappedKeyPassword); + int setPermissionHelper( const Credentials &cred, const Name &name, @@ -408,4 +419,3 @@ protected: }; } // namespace CKM - diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 8d06e64..5c52e09 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -492,6 +492,35 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) encryptedKeyPolicy); } + case LogicCommand::EXPORT_WRAPPED_KEY: { + CryptoAlgorithmSerializable params; + Name wrappingKeyName; + ClientId wrappingKeyOwner; + Password wrappingKeyPassword; + Name wrappedKeyName; + ClientId wrappedKeyOwner; + Password wrappedKeyPassword; + + buffer.Deserialize(params, + wrappingKeyName, + wrappingKeyOwner, + wrappingKeyPassword, + wrappedKeyName, + wrappedKeyOwner, + wrappedKeyPassword); + + return m_logic->exportWrappedKey( + cred, + msgId, + params, + wrappingKeyName, + cred.effectiveOwner(wrappingKeyOwner), + wrappingKeyPassword, + wrappedKeyName, + cred.effectiveOwner(wrappedKeyOwner), + wrappedKeyPassword); + } + default: Throw(Exception::BrokenProtocol); } -- 2.7.4 From 6350c707508c9ac3fa63e96053d13d7078d3adb1 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 31 Mar 2023 12:14:39 +0200 Subject: [PATCH 16/16] Change code formatting in import/export wrapped key Change-Id: If8932f5f9b3a1f2cdb2003895b348b89b7a15321 --- src/include/ckm/ckm-manager.h | 6 ++-- src/manager/client-capi/ckmc-manager.cpp | 6 ++-- src/manager/client/client-manager-impl.cpp | 15 ++++----- src/manager/client/client-manager-impl.h | 2 +- src/manager/client/client-manager.cpp | 54 +++++++++++++++--------------- src/manager/crypto/sw-backend/obj.cpp | 17 ++++------ src/manager/crypto/sw-backend/obj.h | 2 +- src/manager/service/ckm-logic.cpp | 18 +++++----- src/manager/service/ckm-logic.h | 26 +++++++------- src/manager/service/ckm-service.cpp | 28 ++++++++-------- 10 files changed, 84 insertions(+), 90 deletions(-) diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index 8ce5dea..5eb3f17 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -176,13 +176,11 @@ public: const Alias &newKeyAlias, const Policy &newKeyPolicy); - static ManagerShPtr create(); - int importWrappedKey(const CryptoAlgorithm ¶ms, const Alias &wrappingKeyAlias, const Password &wrappingKeyPassword, const Alias &alias, - const RawBuffer &encryptedKey, + const RawBuffer &wrappedKey, const KeyType keyType, const Policy &policy); @@ -194,6 +192,8 @@ public: KeyType &keyType, RawBuffer &wrappedKey); + static ManagerShPtr create(); + private: std::unique_ptr m_impl; }; diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index e5fa0ec..083ee28 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -1083,11 +1083,9 @@ int ckmc_export_wrapped_key(const ckmc_param_list_h params, keyType, wrappedKey)); - - if (ret == CKMC_ERROR_NONE) { - ckmc_key_type_e ckmcKeyType = static_cast(keyType); - ret = ckmc_key_new(wrappedKey.data(), wrappedKey.size(), ckmcKeyType, nullptr, &wrapped_key); + ckmc_key_type_e key_type = static_cast(keyType); + ret = ckmc_key_new(wrappedKey.data(), wrappedKey.size(), key_type, nullptr, &wrapped_key); if (ret == CKMC_ERROR_NONE) *ppwrapped_key = wrapped_key; } diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index d2d8534..8628daf 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -763,7 +763,7 @@ int Manager::Impl::importWrappedKey(const CryptoAlgorithm ¶ms, const Alias &wrappingKeyAlias, const Password &wrappingKeyPassword, const Alias &alias, - const RawBuffer &encryptedKey, + const RawBuffer &wrappedKey, const KeyType keyType, const Policy &policy) { @@ -776,15 +776,15 @@ int Manager::Impl::importWrappedKey(const CryptoAlgorithm ¶ms, LogicCommand::IMPORT_WRAPPED_KEY, m_storageConnection, CryptoAlgorithmSerializable(params), + wrapping_helper.getName(), + wrapping_helper.getOwner(), wrappingKeyPassword, - encryptedKey, - DataType(keyType), - PolicySerializable(policy), helper.getName(), helper.getOwner(), - wrapping_helper.getName(), - wrapping_helper.getOwner() - ).maybeDeserialize(); + wrappedKey, + DataType(keyType), + PolicySerializable(policy) + ).maybeDeserialize(); EXCEPTION_GUARD_END } @@ -831,5 +831,4 @@ int Manager::Impl::exportWrappedKey(const CryptoAlgorithm ¶ms, EXCEPTION_GUARD_END } - } // namespace CKM diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 91e5732..b63598c 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -145,7 +145,7 @@ public: const Alias &wrappingKeyAlias, const Password &wrappingKeyPassword, const Alias &alias, - const RawBuffer &encryptedKey, + const RawBuffer &wrappedKey, const KeyType keyType, const Policy &policy); diff --git a/src/manager/client/client-manager.cpp b/src/manager/client/client-manager.cpp index 8ef76bb..4d9fcd6 100644 --- a/src/manager/client/client-manager.cpp +++ b/src/manager/client/client-manager.cpp @@ -251,26 +251,6 @@ int Manager::verifySignature( cAlg); } -int Manager::importWrappedKey( - const CryptoAlgorithm ¶ms, - const Alias &wrappingKeyAlias, - const Password &wrappingKeyPassword, - const Alias &alias, - const RawBuffer &encryptedKey, - const KeyType keyType, - const Policy &policy) -{ - return m_impl->importWrappedKey( - params, - wrappingKeyAlias, - wrappingKeyPassword, - alias, - encryptedKey, - keyType, - policy - ); -} - int Manager::ocspCheck(const CertificateShPtrVector &certificateChainVector, int &ocspStatus) { @@ -314,14 +294,24 @@ int Manager::deriveKey(const CryptoAlgorithm &algo, return m_impl->deriveKey(algo, secretAlias, secretPassword, newKeyAlias, newKeyPolicy); } -ManagerShPtr Manager::create() +int Manager::importWrappedKey( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const RawBuffer &wrappedKey, + const KeyType keyType, + const Policy &policy) { - try { - return std::make_shared(); - } catch (...) { - LogError("Exception occured in Manager::create"); - throw; - } + return m_impl->importWrappedKey( + params, + wrappingKeyAlias, + wrappingKeyPassword, + alias, + wrappedKey, + keyType, + policy + ); } int Manager::exportWrappedKey( @@ -344,4 +334,14 @@ int Manager::exportWrappedKey( ); } +ManagerShPtr Manager::create() +{ + try { + return std::make_shared(); + } catch (...) { + LogError("Exception occured in Manager::create"); + throw; + } +} + } // namespace CKM diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index a120cc6..49d0616 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -67,18 +67,18 @@ Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawB } Token Key::unwrap(const CryptoAlgorithm ¶ms, - const Data &encryptedKey, + const Data &wrappedKey, const Password &pass, const RawBuffer &) { - auto decrypted = decrypt(params, encryptedKey.data); + auto decrypted = decrypt(params, wrappedKey.data); - if (!encryptedKey.type.isKey()) { + if (!wrappedKey.type.isKey()) { ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a key"); } // validate the decrypted key - if (encryptedKey.type.isSKey()) { + if (wrappedKey.type.isSKey()) { auto tmp = CKM::Key::createAES(decrypted); if (!tmp) ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid AES key"); @@ -87,18 +87,17 @@ Token Key::unwrap(const CryptoAlgorithm ¶ms, if (!tmp) ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid asymmetric key"); - if (encryptedKey.type != DataType(tmp->getType())) + if (wrappedKey.type != DataType(tmp->getType())) ThrowErr(Exc::Crypto::InputParam, "Wrapped key type does not match the required one"); } - return Token(backendId(), encryptedKey.type, Store::pack(decrypted, pass)); + return Token(backendId(), wrappedKey.type, Store::pack(decrypted, pass)); } RawBuffer Key::wrap(const CryptoAlgorithm ¶ms, const Token &keyToWrap, const Password &keyToWrapPass) { - RawBuffer data = Store::unpack(keyToWrap.data, keyToWrapPass); return encrypt(params, data); } @@ -233,9 +232,7 @@ Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, cons ThrowErr(Exc::Crypto::OperationNotSupported); } -RawBuffer Cert::wrap(const CryptoAlgorithm &, - const Token &, - const Password &) +RawBuffer Cert::wrap(const CryptoAlgorithm &, const Token &, const Password &) { ThrowErr(Exc::Crypto::OperationNotSupported); } diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h index 16b801a..945a85f 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -54,7 +54,7 @@ class Key : public BData { using BData::BData; Token unwrap(const CryptoAlgorithm ¶ms, - const Data &encryptedKey, + const Data &wrappedKey, const Password &pass, const RawBuffer &hash) override; diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index d931083..de74c47 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1569,16 +1569,16 @@ RawBuffer CKMLogic::importWrappedKey( const Name &wrappingKeyName, const ClientId &wrappingKeyOwner, const Password &wrappingKeyPassword, - const Name &encryptedKeyName, - const ClientId &encryptedKeyOwner, - const RawBuffer &encryptedKey, - const CKM::DataType encryptedKeyType, - const PolicySerializable &encryptedKeyPolicy) + const Name &keyName, + const ClientId &keyOwner, + const RawBuffer &wrappedKey, + const CKM::DataType keyType, + const PolicySerializable &policy) { return SerializeMessage(msgId, tryRet([&] { Crypto::GObjUPtr wrappingKey; - auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, encryptedKeyName, encryptedKeyOwner); + auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, keyName, keyOwner); if (retCode != CKM_API_SUCCESS) return retCode; @@ -1588,11 +1588,11 @@ RawBuffer CKMLogic::importWrappedKey( return retCode; Token token = wrappingKey->unwrap(params, - Crypto::Data(encryptedKeyType, std::move(encryptedKey)), - encryptedKeyPolicy.password, + Crypto::Data(keyType, std::move(wrappedKey)), + policy.password, digest); - dbOp.finalize(std::move(token), encryptedKeyPolicy); + dbOp.finalize(std::move(token), policy); return retCode; })); diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index b87848b..933ba08 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -202,6 +202,19 @@ public: const ClientId &newKeyOwner, const Policy &newKeyPolicy); + RawBuffer importWrappedKey( + const Credentials &cred, + const int msgId, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &keyName, + const ClientId &keyOwner, + const RawBuffer &wrappedKey, + const CKM::DataType keyType, + const PolicySerializable &policy); + RawBuffer exportWrappedKey( const Credentials &cred, const int msgID, @@ -242,19 +255,6 @@ public: int unlockSystemDB(); - RawBuffer importWrappedKey( - const Credentials &cred, - const int msgId, - const CryptoAlgorithm ¶ms, - const Name &wrappingKeyName, - const ClientId &wrappingKeyOwner, - const Password &wrappingKeyPassword, - const Name &encryptedKeyName, - const ClientId &encryptedKeyOwner, - const RawBuffer &encryptedKey, - const CKM::DataType encryptedKeyType, - const PolicySerializable &encryptedKeyPolicy); - private: // select private/system database depending on asking uid and owner id. // output: database handler for effective owner diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 5c52e09..71899ab 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -463,20 +463,20 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) Name wrappingKeyName; ClientId wrappingKeyOwner; Password wrappingKeyPassword; - Name encryptedKeyName; - RawBuffer encryptedKey; - CKM::DataType encryptedKeyType; - PolicySerializable encryptedKeyPolicy; + Name keyName; + RawBuffer wrappedKey; + CKM::DataType keyType; + PolicySerializable policy; buffer.Deserialize(params, + wrappingKeyName, + wrappingKeyOwner, wrappingKeyPassword, - encryptedKey, - encryptedKeyType, - encryptedKeyPolicy, - encryptedKeyName, + keyName, explicitOwner, - wrappingKeyName, - wrappingKeyOwner); + wrappedKey, + keyType, + policy); return m_logic->importWrappedKey( cred, @@ -485,11 +485,11 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) wrappingKeyName, cred.effectiveOwner(wrappingKeyOwner), wrappingKeyPassword, - encryptedKeyName, + keyName, cred.effectiveOwner(explicitOwner), - encryptedKey, - encryptedKeyType, - encryptedKeyPolicy); + wrappedKey, + keyType, + policy); } case LogicCommand::EXPORT_WRAPPED_KEY: { -- 2.7.4