CKM: Add KBKDF tests 32/288832/6
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 23 Feb 2023 09:14:43 +0000 (10:14 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 20 Mar 2023 11:52:09 +0000 (12:52 +0100)
Change-Id: I8af39566757c6f3b4e9ca82184f9f99708c3271a

src/ckm/unprivileged/key-derivation.cpp

index 1a8a1fc..9955525 100644 (file)
@@ -40,12 +40,34 @@ const KeyAliasPair PEERS2 = { "peer2_ec_private", "peer2_ec_public" };
 const KeyAliasPair WRONG = { "wrong_ec_private", "wrong_ec_public" };
 const KeyAliasPair RSA = { "rsa_private", "rsa_public" };
 const std::string DERIVED = "derived";
+const std::string SECRET = "secret";
 
 const ckmc_policy_s UNEXPORTABLE { nullptr, false };
 const ckmc_policy_s EXPORTABLE { nullptr, true };
 const ckmc_policy_s UNEXPORTABLE_PW { const_cast<char*>(PASSWORD), false };
 const ckmc_policy_s EXPORTABLE_PW { const_cast<char*>(PASSWORD), true };
 
+constexpr ckmc_kdf_prf_e HMAC256 = CKMC_KDF_PRF_HMAC_SHA256;
+constexpr ckmc_kdf_prf_e HMAC384 = CKMC_KDF_PRF_HMAC_SHA384;
+constexpr ckmc_kdf_prf_e HMAC512 = CKMC_KDF_PRF_HMAC_SHA512;
+constexpr ckmc_kbkdf_counter_location_e BEFORE = CKMC_KBKDF_COUNTER_BEFORE_FIXED;
+constexpr ckmc_kbkdf_counter_location_e AFTER = CKMC_KBKDF_COUNTER_AFTER_FIXED;
+constexpr ckmc_kbkdf_counter_location_e MIDDLE = CKMC_KBKDF_COUNTER_MIDDLE_FIXED;
+constexpr ckmc_kbkdf_mode_e COUNTER = CKMC_KBKDF_MODE_COUNTER;
+constexpr uint64_t U0 = 0;
+constexpr uint64_t U1 = 1;
+constexpr uint64_t U7 = 7;
+constexpr uint64_t U8 = 8;
+constexpr uint64_t U16 = 16;
+constexpr uint64_t U24 = 24;
+constexpr uint64_t U32 = 32;
+constexpr uint64_t U64 = 64;
+
+const RawBufferPtr LAB = create_raw_buffer(createRandomBufferCAPI(16));
+const RawBufferPtr CTX = create_raw_buffer(createRandomBufferCAPI(12));
+const RawBufferPtr FIX = create_raw_buffer(createRandomBufferCAPI(36));
+const RawBufferPtr ONE = create_raw_buffer(createRandomBufferCAPI(1));
+
 class EcdhGroupFixture: public DPL::Test::TestGroup
 {
 private:
@@ -167,6 +189,114 @@ void invalidDerive(const ParamListPtr& params)
                          EXPORTABLE);
 }
 
+
+class KbkdfParamTester {
+public:
+    void Ok(const uint64_t* len,
+            const ckmc_kdf_prf_e* prf,
+            const ckmc_kbkdf_mode_e* mode,
+            const ckmc_kbkdf_counter_location_e* location,
+            const RawBufferPtr context,
+            const RawBufferPtr label,
+            const RawBufferPtr fixed,
+            const uint64_t* rlen,
+            const uint64_t* llen,
+            bool noSeparator = false)
+    {
+        return Test(true, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+    }
+
+    void Fail(const uint64_t* len,
+              const ckmc_kdf_prf_e* prf,
+              const ckmc_kbkdf_mode_e* mode,
+              const ckmc_kbkdf_counter_location_e* location,
+              const RawBufferPtr context,
+              const RawBufferPtr label,
+              const RawBufferPtr fixed,
+              const uint64_t* rlen,
+              const uint64_t* llen,
+              bool noSeparator = false)
+    {
+        return Test(
+            false, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+    }
+private:
+    void Test(bool ok,
+              const uint64_t* len,
+              const ckmc_kdf_prf_e* prf,
+              const ckmc_kbkdf_mode_e* mode,
+              const ckmc_kbkdf_counter_location_e* location,
+              const RawBufferPtr context,
+              const RawBufferPtr label,
+              const RawBufferPtr fixed,
+              const uint64_t* rlen,
+              const uint64_t* llen,
+              bool noSeparator = false)
+    {
+        auto derive = createParamListPtr();
+        setParam(derive, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+        if (len)
+            setParam(derive, CKMC_PARAM_KDF_LEN, *len);
+        if (prf)
+            setParam(derive, CKMC_PARAM_KDF_PRF, *prf);
+        if (mode)
+            setParam(derive, CKMC_PARAM_KBKDF_MODE, *mode);
+        if (location)
+            setParam(derive, CKMC_PARAM_KBKDF_COUNTER_LOCATION, *location);
+        if (context)
+            setParam(derive, CKMC_PARAM_KBKDF_CONTEXT, context.get());
+        if (label)
+            setParam(derive, CKMC_PARAM_KBKDF_LABEL, label.get());
+        if (fixed)
+            setParam(derive, CKMC_PARAM_KBKDF_FIXED_INPUT, fixed.get());
+        if (rlen)
+            setParam(derive, CKMC_PARAM_KBKDF_RLEN, *rlen);
+        if (llen)
+            setParam(derive, CKMC_PARAM_KBKDF_LLEN, *llen);
+        if (noSeparator)
+            setParam(derive, CKMC_PARAM_KBKDF_NO_SEPARATOR, 1);
+
+        if (ok) {
+            assert_positive(ckmc_key_derive,
+                            derive.get(),
+                            SECRET.c_str(),
+                            "",
+                            DERIVED.c_str(),
+                            EXPORTABLE);
+
+            ckmc_key_s *derived = nullptr;
+            assert_positive(ckmc_get_key, DERIVED.c_str(), "", &derived);
+            size_t derived_size = derived->key_size;
+            ckmc_key_free(derived);
+
+            RUNNER_ASSERT(derived_size == *len);
+
+            assert_positive(ckmc_remove_alias, DERIVED.c_str());
+        } else {
+            assert_result(CKMC_ERROR_INVALID_PARAMETER,
+                          ckmc_key_derive,
+                          derive.get(),
+                          SECRET.c_str(),
+                          "",
+                          DERIVED.c_str(),
+                          EXPORTABLE);
+        }
+    }
+};
+
+ParamListPtr getDefaultKBKDFParams()
+{
+    auto kbkdfParams = createParamListPtr();
+    setParam(kbkdfParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+    setParam(kbkdfParams, CKMC_PARAM_KDF_LEN, 32);
+    setParam(kbkdfParams, CKMC_PARAM_KDF_PRF, CKMC_KDF_PRF_HMAC_SHA256);
+    setParam(kbkdfParams, CKMC_PARAM_KBKDF_MODE, CKMC_KBKDF_MODE_COUNTER);
+    setParam(kbkdfParams, CKMC_PARAM_KBKDF_LABEL, LAB.get());
+    setParam(kbkdfParams, CKMC_PARAM_KBKDF_CONTEXT, CTX.get());
+    setParam(kbkdfParams, CKMC_PARAM_KBKDF_COUNTER_LOCATION, CKMC_KBKDF_COUNTER_BEFORE_FIXED);
+    return kbkdfParams;
+}
+
 } // namespace anonymous
 
 RUNNER_TEST_GROUP_INIT_ENV(CKM_DERIVE_ECDH, EcdhGroupFixture);
@@ -347,3 +477,226 @@ RUNNER_TEST(TECDH_0230_wrong_key_types, DerivedFixture)
 {
     deriveEcdh(RSA.prv, "", RSA.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
 }
+
+
+class KbkdfGroupFixture: public DPL::Test::TestGroup
+{
+public:
+    void Init() override
+    {
+        remove_user_data(UID);
+        assert_positive(ckmc_unlock_user_key, UID, "db-pass");
+
+        ckmc_raw_buffer_s* secret = createRandomBufferCAPI(12);
+
+        assert_positive(ckmc_save_data, SECRET.c_str(), *secret, UNEXPORTABLE);
+    }
+
+    void Finish() override
+    {
+        int ret = ckmc_lock_user_key(UID);
+        if (ret != CKMC_ERROR_NONE)
+            RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+        remove_user_data(UID);
+    }
+};
+
+RUNNER_TEST_GROUP_INIT_ENV(CKM_DERIVE_KBKDF, KbkdfGroupFixture);
+
+RUNNER_TEST(TKBKDF_0010_positive, DerivedFixture)
+{
+    KbkdfParamTester test;
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    test.Ok(&U16, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Ok(&U24, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC384, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Ok(&U32, &HMAC512, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &AFTER,  CTX, LAB, nullptr, nullptr, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &MIDDLE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, ONE, LAB, nullptr, nullptr, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, ONE, nullptr, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, nullptr, FIX, nullptr, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &AFTER,  nullptr, nullptr, FIX, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, nullptr, ONE, nullptr, nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U32, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U24, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U16, nullptr);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U8,  nullptr);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U32);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U24);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U16);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U8);
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U0);
+
+    test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr, true);
+    test.Ok(&U32, &HMAC256, &COUNTER, &MIDDLE, CTX, LAB, nullptr, nullptr, nullptr, true);
+}
+
+RUNNER_TEST(TKBKDF_0020_derive_from_derived, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    SECRET.c_str(),
+                    "",
+                    DERIVED.c_str(),
+                    UNEXPORTABLE);
+
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    DERIVED.c_str(),
+                    "",
+                    "derived2",
+                    EXPORTABLE);
+
+    ckmc_key_s *derived2 = nullptr;
+    assert_positive(ckmc_get_key, "derived2", "", &derived2);
+    ckmc_key_free(derived2);
+}
+
+RUNNER_TEST(TKBKDF_0030_unknown_alias, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                  ckmc_key_derive,
+                  kbkdfParams.get(),
+                  "nonexistent-alias",
+                  "",
+                  DERIVED.c_str(),
+                  EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0040_wrong_password, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                  ckmc_key_derive,
+                  kbkdfParams.get(),
+                  SECRET.c_str(),
+                  "wrong-password",
+                  DERIVED.c_str(),
+                  EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0050_alias_exists, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    SECRET.c_str(),
+                    "",
+                    DERIVED.c_str(),
+                    EXPORTABLE);
+
+    assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+                  ckmc_key_derive,
+                  kbkdfParams.get(),
+                  SECRET.c_str(),
+                  "",
+                  DERIVED.c_str(),
+                  EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0060_derived_password, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    SECRET.c_str(),
+                    "",
+                    DERIVED.c_str(),
+                    EXPORTABLE);
+
+    ckmc_key_s *derived = nullptr;
+    assert_result(
+            CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_key, DERIVED.c_str(), PASSWORD, &derived);
+
+    assert_positive(ckmc_remove_alias, DERIVED.c_str());
+
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    SECRET.c_str(),
+                    "",
+                    DERIVED.c_str(),
+                    EXPORTABLE_PW);
+
+    assert_result(
+            CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_key, DERIVED.c_str(), "", &derived);
+    assert_positive(ckmc_get_key, DERIVED.c_str(), PASSWORD, &derived);
+    ckmc_key_free(derived);
+}
+
+RUNNER_TEST(TKBKDF_0070_unexportable, DerivedFixture)
+{
+    auto kbkdfParams = getDefaultKBKDFParams();
+    assert_positive(ckmc_key_derive,
+                    kbkdfParams.get(),
+                    SECRET.c_str(),
+                    "",
+                    DERIVED.c_str(),
+                    UNEXPORTABLE);
+
+    ckmc_key_s *derived = nullptr;
+    assert_result(CKMC_ERROR_NOT_EXPORTABLE, ckmc_get_key, DERIVED.c_str(), "", &derived);
+}
+
+RUNNER_TEST(TKBKDF_0100_wrong_params, DerivedFixture)
+{
+    KbkdfParamTester test;
+
+    // missing parameters
+    test.Fail(nullptr, &HMAC256, &COUNTER, &BEFORE, CTX,     LAB,     nullptr, nullptr, nullptr);
+    test.Fail(&U32,    nullptr,  &COUNTER, &BEFORE, CTX,     LAB,     nullptr, nullptr, nullptr);
+    test.Fail(&U32,    &HMAC256, nullptr,  &BEFORE, CTX,     LAB,     nullptr, nullptr, nullptr);
+    test.Fail(&U32,    &HMAC256, &COUNTER, nullptr, CTX,     LAB,     nullptr, nullptr, nullptr);
+    test.Fail(&U32,    &HMAC256, &COUNTER, &BEFORE, nullptr, LAB,     nullptr, nullptr, nullptr);
+    test.Fail(&U32,    &HMAC256, &COUNTER, &BEFORE, CTX,     nullptr, nullptr, nullptr, nullptr);
+
+    // conflicting parameters
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX,     LAB,     FIX, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, LAB,     FIX, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX,     nullptr, FIX, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, &U32);
+    test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, &U0);
+    test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, nullptr, true);
+
+    // invalid values
+    test.Fail(&U0,  &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U1,  &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U8,  &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U64, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    auto wrongPrf1 = static_cast<ckmc_kdf_prf_e>(0);
+    auto wrongPrf2 = static_cast<ckmc_kdf_prf_e>(4);
+    test.Fail(&U32, &wrongPrf1, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U32, &wrongPrf2, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    auto wrongMode1 = static_cast<ckmc_kbkdf_mode_e>(0);
+    auto wrongMode2 = static_cast<ckmc_kbkdf_mode_e>(2);
+    test.Fail(&U32, &HMAC256, &wrongMode1, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &wrongMode2, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+    auto wrongLocation1 = static_cast<ckmc_kbkdf_counter_location_e>(0);
+    auto wrongLocation2 = static_cast<ckmc_kbkdf_counter_location_e>(4);
+    test.Fail(&U32, &HMAC256, &COUNTER, &wrongLocation1, CTX, LAB, nullptr, nullptr, nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &wrongLocation2, CTX, LAB, nullptr, nullptr, nullptr);
+
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U0,  nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U1,  nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U7,  nullptr);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U64, nullptr);
+
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U1);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U7);
+    test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U64);
+}