Merge "IRemotelyProvisionedComponent returns DeviceInfo" am: 459bf52740 am: 081ed8f3c4

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1650665

Change-Id: Ie4c088aba3e0bb332153e01671c1151e4f955504
This commit is contained in:
Max Bires
2021-03-25 01:13:29 +00:00
committed by Automerger Merge Worker
7 changed files with 118 additions and 22 deletions

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 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.
*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
// two cases:
// 1). this is a frozen version file - do not edit this in any case.
// 2). this is a 'current' file. If you make a backwards compatible change to
// the interface (from the latest frozen version), the build system will
// prompt you to update this file with `m <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
/* @hide */
@VintfStability
parcelable DeviceInfo {
byte[] deviceInfo;
}

View File

@@ -36,7 +36,7 @@ package android.hardware.security.keymint;
@VintfStability
interface IRemotelyProvisionedComponent {
byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
void generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac, out android.hardware.security.keymint.ProtectedData protectedData);
byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData);
const int STATUS_FAILED = 1;
const int STATUS_INVALID_MAC = 2;
const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 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.
*/
package android.hardware.security.keymint;
/**
* DeviceInfo contains information about the device that's fed in as AAD in the signature of the
* device private key over the MAC key used for the bundle of public keys. These values are intended
* to be checked by the server to verify that the certificate signing request crafted by
* an IRemotelyProvisionedComponent HAL instance is coming from the expected device based
* on values initially uploaded during device manufacture in the factory.
* @hide
*/
@VintfStability
parcelable DeviceInfo {
/**
* DeviceInfo is a CBOR Map structure described by the following CDDL.
*
* DeviceInfo = {
* ? "brand" : tstr,
* ? "manufacturer" : tstr,
* ? "product" : tstr,
* ? "model" : tstr,
* ? "board" : tstr,
* ? "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values
* ? "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values
* ? "os_version" : tstr, // Same as android.os.Build.VERSION.release
* ? "system_patch_level" : uint, // YYYYMMDD
* ? "boot_patch_level" : uint, // YYYYMMDD
* ? "vendor_patch_level" : uint, // YYYYMMDD
* }
*/
byte[] deviceInfo;
}

View File

@@ -16,6 +16,7 @@
package android.hardware.security.keymint;
import android.hardware.security.keymint.DeviceInfo;
import android.hardware.security.keymint.MacedPublicKey;
import android.hardware.security.keymint.ProtectedData;
@@ -257,7 +258,7 @@ interface IRemotelyProvisionedComponent {
* @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
* authenticate the keysToSign (see keysToSignMac output argument).
*/
void generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac,
byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
out ProtectedData protectedData);
}

View File

@@ -322,8 +322,8 @@ ScopedAStatus RemotelyProvisionedComponent::generateEcdsaP256KeyPair(bool testMo
ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest(
bool testMode, const vector<MacedPublicKey>& keysToSign,
const bytevec& endpointEncCertChain, const bytevec& challenge, bytevec* keysToSignMac,
ProtectedData* protectedData) {
const bytevec& endpointEncCertChain, const bytevec& challenge, DeviceInfo* deviceInfo,
ProtectedData* protectedData, bytevec* keysToSignMac) {
auto pubKeysToSign = validateAndExtractPubkeys(testMode, keysToSign,
testMode ? remote_prov::kTestMacKey : macKey_);
if (!pubKeysToSign.isOk()) return pubKeysToSign.moveError();
@@ -343,11 +343,12 @@ ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest(
bcc = bcc_.clone();
}
deviceInfo->deviceInfo = createDeviceInfo();
auto signedMac = constructCoseSign1(devicePrivKey /* Signing key */, //
ephemeralMacKey /* Payload */,
cppbor::Array() /* AAD */
.add(challenge)
.add(createDeviceInfo())
.add(deviceInfo->deviceInfo)
.encode());
if (!signedMac) return Status(signedMac.moveMessage());

View File

@@ -39,8 +39,8 @@ class RemotelyProvisionedComponent : public BnRemotelyProvisionedComponent {
const std::vector<MacedPublicKey>& keysToSign,
const std::vector<uint8_t>& endpointEncCertChain,
const std::vector<uint8_t>& challenge,
std::vector<uint8_t>* keysToSignMac,
ProtectedData* protectedData) override;
DeviceInfo* deviceInfo, ProtectedData* protectedData,
std::vector<uint8_t>* keysToSignMac) override;
private:
// TODO(swillden): Move these into an appropriate Context class.

View File

@@ -227,11 +227,12 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
bool testMode = true;
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
eekChain_.chain, challenge,
&keysToSignMac, &protectedData);
auto status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
&keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -297,11 +298,12 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
TEST_P(CertificateRequestTest, EmptyRequest_prodMode) {
bool testMode = false;
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
eekChain_.chain, challenge,
&keysToSignMac, &protectedData);
auto status = provisionable_->generateCertificateRequest(
testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
&keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
}
@@ -314,10 +316,12 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
generateKeys(testMode, 4 /* numKeys */);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
auto status = provisionable_->generateCertificateRequest(
testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
challenge, &deviceInfo, &protectedData,
&keysToSignMac);
ASSERT_TRUE(status.isOk()) << status.getMessage();
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -384,10 +388,12 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) {
generateKeys(testMode, 4 /* numKeys */);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
auto status = provisionable_->generateCertificateRequest(
testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
challenge, &deviceInfo, &protectedData,
&keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
}
@@ -400,11 +406,12 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
generateKeys(false /* testMode */, 2 /* numKeys */);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto challenge = randomBytes(32);
auto status = provisionable_->generateCertificateRequest(true /* testMode */, keysToSign_,
eekChain_.chain, challenge,
&keysToSignMac, &protectedData);
auto status = provisionable_->generateCertificateRequest(
true /* testMode */, keysToSign_, eekChain_.chain, challenge, &deviceInfo,
&protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
@@ -418,10 +425,11 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
generateKeys(true /* testMode */, 2 /* numKeys */);
bytevec keysToSignMac;
DeviceInfo deviceInfo;
ProtectedData protectedData;
auto status = provisionable_->generateCertificateRequest(
false /* testMode */, keysToSign_, eekChain_.chain, randomBytes(32) /* challenge */,
&keysToSignMac, &protectedData);
&deviceInfo, &protectedData, &keysToSignMac);
ASSERT_FALSE(status.isOk());
ASSERT_EQ(status.getServiceSpecificError(),
BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);