Merge "Identity Credential: Require passing applicationId when generating attestation." am: 7175150e3f
am: 396315d92f
Change-Id: Idca7bf3e5cbe681dc8f1ccccda414dd23d637fee
This commit is contained in:
commit
ef23d7de41
5 changed files with 70 additions and 14 deletions
|
@ -626,7 +626,7 @@ db47f4ceceb1f06c656f39caa70c557b0f8471ef59fd58611bea667ffca20101 android.hardwar
|
||||||
0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
|
0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
|
||||||
bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
|
bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
|
||||||
96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
|
96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
|
||||||
6e1e28a96c90ba78d47257faea3f3bb4e6360affbbfa5822f0dc31211f9266ff android.hardware.identity@1.0::IWritableIdentityCredential
|
8da9c938e58f7d636ddd2f92c646f99d9a9e79612e6441b6380ab12744251873 android.hardware.identity@1.0::IWritableIdentityCredential
|
||||||
27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
|
27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
|
||||||
adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
|
adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
|
||||||
ac429fca0da4ce91218768ec31b64ded88251f8a26d8c4f27c06abdc5b1926d9 android.hardware.keymaster@4.1::types
|
ac429fca0da4ce91218768ec31b64ded88251f8a26d8c4f27c06abdc5b1926d9 android.hardware.keymaster@4.1::types
|
||||||
|
|
|
@ -26,20 +26,56 @@ interface IWritableIdentityCredential {
|
||||||
* characteristics to an issuing authority. Must not be called more than once.
|
* characteristics to an issuing authority. Must not be called more than once.
|
||||||
*
|
*
|
||||||
* The certificate chain must be generated using Keymaster Attestation
|
* The certificate chain must be generated using Keymaster Attestation
|
||||||
* (see https://source.android.com/security/keystore/attestation) and must also
|
* (see https://source.android.com/security/keystore/attestation) with the
|
||||||
* have the Tag::IDENTITY_CREDENTIAL_KEY tag from KeyMaster 4.1 set. This tag indicates
|
* following additional requirements:
|
||||||
* that this key is an Identity Credential key (which can only sign/MAC very
|
*
|
||||||
* specific messages) and not an Android Keystore key (which can be used to sign/MAC
|
* - The attestationVersion field in the attestation extension must be at least 3.
|
||||||
* anything).
|
*
|
||||||
|
* - The attestationSecurityLevel field must be set to either Software (0),
|
||||||
|
* TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
|
||||||
|
* implemented. Only the default AOSP implementation of this HAL may use
|
||||||
|
* value 0 (additionally, this implementation must not be used on production
|
||||||
|
* devices).
|
||||||
|
*
|
||||||
|
* - The keymasterVersion field in the attestation extension must be set to (10*major + minor)
|
||||||
|
* where major and minor are the Identity Credential interface major and minor versions.
|
||||||
|
* Specifically for this version of the interface (1.0) this value is 10.
|
||||||
|
*
|
||||||
|
* - The keymasterSecurityLevel field in the attestation extension must be set to
|
||||||
|
* either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
|
||||||
|
* the Trusted Application backing the HAL implementation is implemented. Only
|
||||||
|
* the default AOSP implementation of this HAL may use value 0 (additionally, this
|
||||||
|
* implementation must not be used on production devices)
|
||||||
|
*
|
||||||
|
* - The attestationChallenge field must be set to the passed-in challenge.
|
||||||
|
*
|
||||||
|
* - The uniqueId field must be empty.
|
||||||
|
*
|
||||||
|
* - The softwareEnforced field in the attestation extension must include
|
||||||
|
* Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
|
||||||
|
* attestationApplicationId.
|
||||||
|
*
|
||||||
|
* - The teeEnforced field in the attestation extension must include
|
||||||
|
* Tag::IDENTITY_CREDENTIAL_KEY. This tag indicates that the key is an Identity
|
||||||
|
* Credential key (which can only sign/MAC very specific messages) and not an Android
|
||||||
|
* Keystore key (which can be used to sign/MAC anything).
|
||||||
|
*
|
||||||
|
* Additional authorizations may be needed in the softwareEnforced and teeEnforced
|
||||||
|
* fields - the above is not an exhaustive list.
|
||||||
|
*
|
||||||
|
* @param attestationApplicationId is the DER encoded value to be stored
|
||||||
|
* in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
|
||||||
|
* https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
|
||||||
*
|
*
|
||||||
* @param attestationChallenge a challenge set by the issuer to ensure freshness.
|
* @param attestationChallenge a challenge set by the issuer to ensure freshness.
|
||||||
*
|
*
|
||||||
* @return result is OK on success, FAILED if an error occurred.
|
* @return result is OK on success, FAILED if an error occurred.
|
||||||
*
|
*
|
||||||
* @return certificate is the X.509 certificate chain for the credentialKey
|
* @return certificateChain is the X.509 certificate chain for the credentialKey
|
||||||
*/
|
*/
|
||||||
getAttestationCertificate(vec<uint8_t> attestationChallenge)
|
getAttestationCertificate(vec<uint8_t> attestationApplicationId,
|
||||||
generates(Result result, vec<uint8_t> certificate);
|
vec<uint8_t> attestationChallenge)
|
||||||
|
generates(Result result, vec<vec<uint8_t>> certificateChain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the personalization process.
|
* Start the personalization process.
|
||||||
|
|
|
@ -108,7 +108,12 @@ bool WritableIdentityCredential::initialize() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use |attestationApplicationId| and |attestationChallenge| and also
|
||||||
|
// ensure the returned certificate chain satisfy the requirements listed in
|
||||||
|
// the docs for IWritableIdentityCredential::getAttestationCertificate()
|
||||||
|
//
|
||||||
Return<void> WritableIdentityCredential::getAttestationCertificate(
|
Return<void> WritableIdentityCredential::getAttestationCertificate(
|
||||||
|
const hidl_vec<uint8_t>& /* attestationApplicationId */,
|
||||||
const hidl_vec<uint8_t>& /* attestationChallenge */,
|
const hidl_vec<uint8_t>& /* attestationChallenge */,
|
||||||
getAttestationCertificate_cb _hidl_cb) {
|
getAttestationCertificate_cb _hidl_cb) {
|
||||||
// For now, we dynamically generate an attestion key on each and every
|
// For now, we dynamically generate an attestion key on each and every
|
||||||
|
@ -181,7 +186,16 @@ Return<void> WritableIdentityCredential::getAttestationCertificate(
|
||||||
certificateChain.insert(certificateChain.end(), attestationKeyCertificate.value().begin(),
|
certificateChain.insert(certificateChain.end(), attestationKeyCertificate.value().begin(),
|
||||||
attestationKeyCertificate.value().end());
|
attestationKeyCertificate.value().end());
|
||||||
|
|
||||||
_hidl_cb(support::resultOK(), certificateChain);
|
optional<vector<vector<uint8_t>>> splitCertChain =
|
||||||
|
support::certificateChainSplit(certificateChain);
|
||||||
|
if (!splitCertChain) {
|
||||||
|
_hidl_cb(support::result(ResultCode::FAILED, "Error splitting certificate chain"), {});
|
||||||
|
return Void();
|
||||||
|
}
|
||||||
|
hidl_vec<hidl_vec<uint8_t>> ret;
|
||||||
|
ret.resize(splitCertChain.value().size());
|
||||||
|
std::copy(splitCertChain.value().begin(), splitCertChain.value().end(), ret.begin());
|
||||||
|
_hidl_cb(support::resultOK(), ret);
|
||||||
return Void();
|
return Void();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ class WritableIdentityCredential : public IWritableIdentityCredential {
|
||||||
|
|
||||||
// Methods from ::android::hardware::identity::IWritableIdentityCredential
|
// Methods from ::android::hardware::identity::IWritableIdentityCredential
|
||||||
// follow.
|
// follow.
|
||||||
Return<void> getAttestationCertificate(const hidl_vec<uint8_t>& attestationChallenge,
|
Return<void> getAttestationCertificate(const hidl_vec<uint8_t>& attestationApplicationId,
|
||||||
|
const hidl_vec<uint8_t>& attestationChallenge,
|
||||||
getAttestationCertificate_cb _hidl_cb) override;
|
getAttestationCertificate_cb _hidl_cb) override;
|
||||||
|
|
||||||
Return<void> startPersonalization(uint16_t accessControlProfileCount,
|
Return<void> startPersonalization(uint16_t accessControlProfileCount,
|
||||||
|
|
|
@ -201,13 +201,18 @@ TEST_P(IdentityCredentialStoreHidlTest, createAndRetrieveCredential) {
|
||||||
ASSERT_NE(writableCredential, nullptr);
|
ASSERT_NE(writableCredential, nullptr);
|
||||||
|
|
||||||
string challenge = "attestationChallenge";
|
string challenge = "attestationChallenge";
|
||||||
|
// TODO: set it to something random and check it's in the cert chain
|
||||||
|
vector<uint8_t> attestationApplicationId = {};
|
||||||
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
|
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
|
||||||
vector<uint8_t> attestationCertificate;
|
vector<uint8_t> attestationCertificate;
|
||||||
writableCredential->getAttestationCertificate(
|
writableCredential->getAttestationCertificate(
|
||||||
attestationChallenge,
|
attestationApplicationId, attestationChallenge,
|
||||||
[&](const Result& _result, const hidl_vec<uint8_t>& _attestationCertificate) {
|
[&](const Result& _result, const hidl_vec<hidl_vec<uint8_t>>& _splitCertChain) {
|
||||||
result = _result;
|
result = _result;
|
||||||
attestationCertificate = _attestationCertificate;
|
vector<vector<uint8_t>> splitCerts;
|
||||||
|
std::copy(_splitCertChain.begin(), _splitCertChain.end(),
|
||||||
|
std::back_inserter(splitCerts));
|
||||||
|
attestationCertificate = support::certificateChainJoin(splitCerts);
|
||||||
});
|
});
|
||||||
EXPECT_EQ("", result.message);
|
EXPECT_EQ("", result.message);
|
||||||
ASSERT_EQ(ResultCode::OK, result.code);
|
ASSERT_EQ(ResultCode::OK, result.code);
|
||||||
|
|
Loading…
Reference in a new issue