Loading security/keymint/support/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -62,3 +62,19 @@ cc_library { "libcrypto", ], } cc_test { name: "libkeymint_remote_prov_support_test", srcs: ["remote_prov_utils_test.cpp"], static_libs: [ "libgmock", "libgtest_main", ], shared_libs: [ "libcppbor_external", "libcppcose_rkp", "libcrypto", "libkeymaster_portable", "libkeymint_remote_prov_support", ], } security/keymint/support/include/remote_prov/remote_prov_utils.h +30 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,31 @@ using namespace cppcose; extern bytevec kTestMacKey; // The Google root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1 inline constexpr uint8_t kCoseEncodedRootCert[] = { 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x2a, 0xa4, 0x01, 0x01, 0x03, 0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0x99, 0xb9, 0xee, 0xdd, 0x5e, 0xe4, 0x52, 0xf6, 0x85, 0xc6, 0x4c, 0x62, 0xdc, 0x3e, 0x61, 0xab, 0x57, 0x48, 0x7d, 0x75, 0x37, 0x29, 0xad, 0x76, 0x80, 0x32, 0xd2, 0xb3, 0xcb, 0x63, 0x58, 0xd9, 0x58, 0x40, 0x1e, 0x22, 0x08, 0x4b, 0xa4, 0xb7, 0xa4, 0xc8, 0xd7, 0x4e, 0x03, 0x0e, 0xfe, 0xb8, 0xaf, 0x14, 0x4c, 0xa7, 0x3b, 0x6f, 0xa5, 0xcd, 0xdc, 0xda, 0x79, 0xc6, 0x2b, 0x64, 0xfe, 0x99, 0x39, 0xaf, 0x76, 0xe7, 0x80, 0xfa, 0x66, 0x00, 0x85, 0x0d, 0x07, 0x98, 0x2a, 0xac, 0x91, 0x5c, 0xa7, 0x25, 0x14, 0x49, 0x06, 0x34, 0x75, 0xca, 0x8a, 0x27, 0x7a, 0xd9, 0xe3, 0x5a, 0x49, 0xeb, 0x02, 0x03}; // The Google Endpoint Encryption Key certificate, encoded as COSE_Sign1 inline constexpr uint8_t kCoseEncodedGeekCert[] = { 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4e, 0xa5, 0x01, 0x01, 0x02, 0x58, 0x20, 0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b, 0xcc, 0xcb, 0xd1, 0x96, 0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a, 0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5, 0x99, 0xdf, 0x98, 0x08, 0x03, 0x38, 0x18, 0x20, 0x04, 0x21, 0x58, 0x20, 0xbe, 0x85, 0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c, 0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f, 0x72, 0x60, 0x58, 0x40, 0x9b, 0xcf, 0x90, 0xe2, 0x2e, 0x4b, 0xab, 0xd1, 0x18, 0xb1, 0x0e, 0x8e, 0x5d, 0x20, 0x27, 0x4b, 0x84, 0x58, 0xfe, 0xfc, 0x32, 0x90, 0x7e, 0x72, 0x05, 0x83, 0xbc, 0xd7, 0x82, 0xbe, 0xfa, 0x64, 0x78, 0x2d, 0x54, 0x10, 0x4b, 0xc0, 0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2, 0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04}; /** * Generates random bytes. */ Loading @@ -44,6 +69,11 @@ struct EekChain { */ ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId); /** * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain. */ bytevec getProdEekChain(); struct BccEntryData { bytevec pubKey; }; Loading security/keymint/support/remote_prov_utils.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include <tuple> #include <remote_prov/remote_prov_utils.h> #include <openssl/rand.h> Loading @@ -31,6 +33,10 @@ bytevec randomBytes(size_t numBytes) { } ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) { if (length < 2) { return "EEK chain must contain at least 2 certs."; } auto eekChain = cppbor::Array(); bytevec prev_priv_key; Loading Loading @@ -78,6 +84,18 @@ ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) { return EekChain{eekChain.encode(), pub_key, priv_key}; } bytevec getProdEekChain() { bytevec prodEek; prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert)); // In CBOR encoding, 0x82 indicates an array of two items prodEek.push_back(0x82); prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert)); prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert)); return prodEek; } ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, const bytevec& signingCoseKey, const bytevec& aad) { if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) { Loading security/keymint/support/remote_prov_utils_test.cpp 0 → 100644 +84 −0 Original line number Diff line number Diff line /* * Copyright 2021 The Android Open Source Project * * 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 <cppbor_parse.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <keymaster/android_keymaster_utils.h> #include <keymaster/logger.h> #include <keymaster/remote_provisioning_utils.h> #include <openssl/curve25519.h> #include <remote_prov/remote_prov_utils.h> #include <cstdint> #include "keymaster/cppcose/cppcose.h" namespace aidl::android::hardware::security::keymint::remote_prov { namespace { using ::keymaster::KeymasterBlob; using ::keymaster::validateAndExtractEekPubAndId; using ::testing::ElementsAreArray; TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) { ASSERT_FALSE(generateEekChain(1, /*eekId=*/{})); } TEST(RemoteProvUtilsTest, GenerateEekChain) { bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0}; for (size_t length : {2, 3, 31}) { auto get_eek_result = generateEekChain(length, kTestEekId); ASSERT_TRUE(get_eek_result) << get_eek_result.message(); auto& [chain, pubkey, privkey] = *get_eek_result; auto validation_result = validateAndExtractEekPubAndId( /*testMode=*/true, KeymasterBlob(chain.data(), chain.size())); ASSERT_TRUE(validation_result.isOk()); auto& [eekPub, eekId] = *validation_result; EXPECT_THAT(eekId, ElementsAreArray(kTestEekId)); EXPECT_THAT(eekPub, ElementsAreArray(pubkey)); } } TEST(RemoteProvUtilsTest, GetProdEekChain) { auto chain = getProdEekChain(); auto validation_result = validateAndExtractEekPubAndId( /*testMode=*/false, KeymasterBlob(chain.data(), chain.size())); ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError(); auto& [eekPub, eekId] = *validation_result; auto [geekCert, ignoredNewPos, error] = cppbor::parse(kCoseEncodedGeekCert, sizeof(kCoseEncodedGeekCert)); ASSERT_NE(geekCert, nullptr) << "Error: " << error; ASSERT_NE(geekCert->asArray(), nullptr); auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload); ASSERT_NE(encodedGeekCoseKey, nullptr); ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr); auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value()); ASSERT_TRUE(geek) << "Error: " << geek.message(); const std::vector<uint8_t> empty; EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty))); EXPECT_THAT(eekPub, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty))); } } // namespace } // namespace aidl::android::hardware::security::keymint::remote_prov Loading
security/keymint/support/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -62,3 +62,19 @@ cc_library { "libcrypto", ], } cc_test { name: "libkeymint_remote_prov_support_test", srcs: ["remote_prov_utils_test.cpp"], static_libs: [ "libgmock", "libgtest_main", ], shared_libs: [ "libcppbor_external", "libcppcose_rkp", "libcrypto", "libkeymaster_portable", "libkeymint_remote_prov_support", ], }
security/keymint/support/include/remote_prov/remote_prov_utils.h +30 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,31 @@ using namespace cppcose; extern bytevec kTestMacKey; // The Google root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1 inline constexpr uint8_t kCoseEncodedRootCert[] = { 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x2a, 0xa4, 0x01, 0x01, 0x03, 0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0x99, 0xb9, 0xee, 0xdd, 0x5e, 0xe4, 0x52, 0xf6, 0x85, 0xc6, 0x4c, 0x62, 0xdc, 0x3e, 0x61, 0xab, 0x57, 0x48, 0x7d, 0x75, 0x37, 0x29, 0xad, 0x76, 0x80, 0x32, 0xd2, 0xb3, 0xcb, 0x63, 0x58, 0xd9, 0x58, 0x40, 0x1e, 0x22, 0x08, 0x4b, 0xa4, 0xb7, 0xa4, 0xc8, 0xd7, 0x4e, 0x03, 0x0e, 0xfe, 0xb8, 0xaf, 0x14, 0x4c, 0xa7, 0x3b, 0x6f, 0xa5, 0xcd, 0xdc, 0xda, 0x79, 0xc6, 0x2b, 0x64, 0xfe, 0x99, 0x39, 0xaf, 0x76, 0xe7, 0x80, 0xfa, 0x66, 0x00, 0x85, 0x0d, 0x07, 0x98, 0x2a, 0xac, 0x91, 0x5c, 0xa7, 0x25, 0x14, 0x49, 0x06, 0x34, 0x75, 0xca, 0x8a, 0x27, 0x7a, 0xd9, 0xe3, 0x5a, 0x49, 0xeb, 0x02, 0x03}; // The Google Endpoint Encryption Key certificate, encoded as COSE_Sign1 inline constexpr uint8_t kCoseEncodedGeekCert[] = { 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4e, 0xa5, 0x01, 0x01, 0x02, 0x58, 0x20, 0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b, 0xcc, 0xcb, 0xd1, 0x96, 0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a, 0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5, 0x99, 0xdf, 0x98, 0x08, 0x03, 0x38, 0x18, 0x20, 0x04, 0x21, 0x58, 0x20, 0xbe, 0x85, 0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c, 0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f, 0x72, 0x60, 0x58, 0x40, 0x9b, 0xcf, 0x90, 0xe2, 0x2e, 0x4b, 0xab, 0xd1, 0x18, 0xb1, 0x0e, 0x8e, 0x5d, 0x20, 0x27, 0x4b, 0x84, 0x58, 0xfe, 0xfc, 0x32, 0x90, 0x7e, 0x72, 0x05, 0x83, 0xbc, 0xd7, 0x82, 0xbe, 0xfa, 0x64, 0x78, 0x2d, 0x54, 0x10, 0x4b, 0xc0, 0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2, 0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04}; /** * Generates random bytes. */ Loading @@ -44,6 +69,11 @@ struct EekChain { */ ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId); /** * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain. */ bytevec getProdEekChain(); struct BccEntryData { bytevec pubKey; }; Loading
security/keymint/support/remote_prov_utils.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include <tuple> #include <remote_prov/remote_prov_utils.h> #include <openssl/rand.h> Loading @@ -31,6 +33,10 @@ bytevec randomBytes(size_t numBytes) { } ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) { if (length < 2) { return "EEK chain must contain at least 2 certs."; } auto eekChain = cppbor::Array(); bytevec prev_priv_key; Loading Loading @@ -78,6 +84,18 @@ ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) { return EekChain{eekChain.encode(), pub_key, priv_key}; } bytevec getProdEekChain() { bytevec prodEek; prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert)); // In CBOR encoding, 0x82 indicates an array of two items prodEek.push_back(0x82); prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert)); prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert)); return prodEek; } ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, const bytevec& signingCoseKey, const bytevec& aad) { if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) { Loading
security/keymint/support/remote_prov_utils_test.cpp 0 → 100644 +84 −0 Original line number Diff line number Diff line /* * Copyright 2021 The Android Open Source Project * * 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 <cppbor_parse.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <keymaster/android_keymaster_utils.h> #include <keymaster/logger.h> #include <keymaster/remote_provisioning_utils.h> #include <openssl/curve25519.h> #include <remote_prov/remote_prov_utils.h> #include <cstdint> #include "keymaster/cppcose/cppcose.h" namespace aidl::android::hardware::security::keymint::remote_prov { namespace { using ::keymaster::KeymasterBlob; using ::keymaster::validateAndExtractEekPubAndId; using ::testing::ElementsAreArray; TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) { ASSERT_FALSE(generateEekChain(1, /*eekId=*/{})); } TEST(RemoteProvUtilsTest, GenerateEekChain) { bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0}; for (size_t length : {2, 3, 31}) { auto get_eek_result = generateEekChain(length, kTestEekId); ASSERT_TRUE(get_eek_result) << get_eek_result.message(); auto& [chain, pubkey, privkey] = *get_eek_result; auto validation_result = validateAndExtractEekPubAndId( /*testMode=*/true, KeymasterBlob(chain.data(), chain.size())); ASSERT_TRUE(validation_result.isOk()); auto& [eekPub, eekId] = *validation_result; EXPECT_THAT(eekId, ElementsAreArray(kTestEekId)); EXPECT_THAT(eekPub, ElementsAreArray(pubkey)); } } TEST(RemoteProvUtilsTest, GetProdEekChain) { auto chain = getProdEekChain(); auto validation_result = validateAndExtractEekPubAndId( /*testMode=*/false, KeymasterBlob(chain.data(), chain.size())); ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError(); auto& [eekPub, eekId] = *validation_result; auto [geekCert, ignoredNewPos, error] = cppbor::parse(kCoseEncodedGeekCert, sizeof(kCoseEncodedGeekCert)); ASSERT_NE(geekCert, nullptr) << "Error: " << error; ASSERT_NE(geekCert->asArray(), nullptr); auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload); ASSERT_NE(encodedGeekCoseKey, nullptr); ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr); auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value()); ASSERT_TRUE(geek) << "Error: " << geek.message(); const std::vector<uint8_t> empty; EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty))); EXPECT_THAT(eekPub, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty))); } } // namespace } // namespace aidl::android::hardware::security::keymint::remote_prov