Identity: Move signingKeyBlob from finishRetrieval() to startRetrieval().
The implementation of the Identity Credential TA in constrained environments may need to incrementally update the HMAC-SHA256 of DeviceAuthencation CBOR to avoid keeping the entire CBOR structure in memory. To do this they need to calculate the derived key before starting to build the CBOR so they need access to the signingKey earlier on. Bug: 150390415 Test: atest android.security.identity.cts Test: VtsHalIdentityTargetTest Merged-In: I72ad30ec3ccec0b8161cbea360ef8c9212f8cbbc Change-Id: I95e28dd46b35bc31dec8d77ee14b5a1b3b5c0391
This commit is contained in:
parent
c5a652431f
commit
b790d97f45
4 changed files with 25 additions and 26 deletions
|
@ -176,6 +176,10 @@ interface IIdentityCredential {
|
|||
* @param itemsRequest
|
||||
* If non-empty, contains request data that is signed by the reader. See above.
|
||||
*
|
||||
* @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
|
||||
* below) containing the signing key to use to sign the data retrieved. If this
|
||||
* is not in the right format the call fails with STATUS_INVALID_DATA.
|
||||
*
|
||||
* @param sessionTranscript
|
||||
* Either empty or the CBOR of the SessionTranscript. See above.
|
||||
*
|
||||
|
@ -195,8 +199,7 @@ interface IIdentityCredential {
|
|||
* and remove the corresponding requests from the counts.
|
||||
*/
|
||||
void startRetrieval(in SecureAccessControlProfile[] accessControlProfiles,
|
||||
in HardwareAuthToken authToken,
|
||||
in byte[] itemsRequest,
|
||||
in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
|
||||
in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
|
||||
|
||||
/**
|
||||
|
@ -254,10 +257,6 @@ interface IIdentityCredential {
|
|||
* If signingKeyBlob or the sessionTranscript parameter passed to startRetrieval() is
|
||||
* empty then the returned MAC will be empty.
|
||||
*
|
||||
* @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
|
||||
* below) containing the signing key to use to sign the data retrieved. If this
|
||||
* is not in the right format the call fails with STATUS_INVALID_DATA.
|
||||
*
|
||||
* @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
|
||||
* startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
|
||||
* and the detached content is set to DeviceAuthentication as defined below.
|
||||
|
@ -304,7 +303,7 @@ interface IIdentityCredential {
|
|||
*
|
||||
* @param out deviceNameSpaces the bytes of DeviceNameSpaces.
|
||||
*/
|
||||
void finishRetrieval(in byte[] signingKeyBlob, out byte[] mac, out byte[] deviceNameSpaces);
|
||||
void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
|
||||
|
||||
/**
|
||||
* Generate a key pair to be used for signing session data and retrieved data items.
|
||||
|
|
|
@ -256,8 +256,8 @@ bool checkUserAuthentication(const SecureAccessControlProfile& profile,
|
|||
ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
||||
const vector<SecureAccessControlProfile>& accessControlProfiles,
|
||||
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
|
||||
const vector<int8_t>& sessionTranscriptS, const vector<int8_t>& readerSignatureS,
|
||||
const vector<int32_t>& requestCounts) {
|
||||
const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
|
||||
const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
|
||||
auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
|
||||
auto itemsRequest = byteStringToUnsigned(itemsRequestS);
|
||||
auto readerSignature = byteStringToUnsigned(readerSignatureS);
|
||||
|
@ -498,6 +498,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
|||
currentNameSpace_ = "";
|
||||
|
||||
itemsRequest_ = itemsRequest;
|
||||
signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
|
||||
|
||||
numStartRetrievalCalls_ += 1;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
|
@ -650,11 +651,8 @@ ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<int8_t>&
|
|||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus IdentityCredential::finishRetrieval(const vector<int8_t>& signingKeyBlobS,
|
||||
vector<int8_t>* outMac,
|
||||
ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
|
||||
vector<int8_t>* outDeviceNameSpaces) {
|
||||
auto signingKeyBlob = byteStringToUnsigned(signingKeyBlobS);
|
||||
|
||||
if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
|
||||
deviceNameSpacesMap_.add(currentNameSpace_,
|
||||
std::move(currentNameSpaceDeviceNameSpacesMap_));
|
||||
|
@ -664,7 +662,8 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(const vector<int8_t>& sig
|
|||
// If there's no signing key or no sessionTranscript or no reader ephemeral
|
||||
// public key, we return the empty MAC.
|
||||
optional<vector<uint8_t>> mac;
|
||||
if (signingKeyBlob.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) {
|
||||
if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
|
||||
readerPublicKey_.size() > 0) {
|
||||
cppbor::Array array;
|
||||
array.add("DeviceAuthentication");
|
||||
array.add(sessionTranscriptItem_->clone());
|
||||
|
@ -674,7 +673,7 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(const vector<int8_t>& sig
|
|||
|
||||
vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
|
||||
optional<vector<uint8_t>> signingKey =
|
||||
support::decryptAes128Gcm(storageKey_, signingKeyBlob, docTypeAsBlob);
|
||||
support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
|
||||
if (!signingKey) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IIdentityCredentialStore::STATUS_INVALID_DATA,
|
||||
|
|
|
@ -54,14 +54,14 @@ class IdentityCredential : public BnIdentityCredential {
|
|||
ndk::ScopedAStatus startRetrieval(
|
||||
const vector<SecureAccessControlProfile>& accessControlProfiles,
|
||||
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
|
||||
const vector<int8_t>& sessionTranscript, const vector<int8_t>& readerSignature,
|
||||
const vector<int32_t>& requestCounts) override;
|
||||
const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
|
||||
const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
|
||||
ndk::ScopedAStatus startRetrieveEntryValue(
|
||||
const string& nameSpace, const string& name, int32_t entrySize,
|
||||
const vector<int32_t>& accessControlProfileIds) override;
|
||||
ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
|
||||
vector<int8_t>* outContent) override;
|
||||
ndk::ScopedAStatus finishRetrieval(const vector<int8_t>& signingKeyBlob, vector<int8_t>* outMac,
|
||||
ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
|
||||
vector<int8_t>* outDeviceNameSpaces) override;
|
||||
ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
|
||||
Certificate* outSigningKeyCertificate) override;
|
||||
|
@ -88,6 +88,7 @@ class IdentityCredential : public BnIdentityCredential {
|
|||
|
||||
// Set at startRetrieval() time.
|
||||
map<int32_t, int> profileIdToAccessCheckResult_;
|
||||
vector<uint8_t> signingKeyBlob_;
|
||||
vector<uint8_t> sessionTranscript_;
|
||||
std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
|
||||
vector<uint8_t> itemsRequest_;
|
||||
|
|
|
@ -352,10 +352,15 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
|
|||
readerCertificate.value());
|
||||
ASSERT_TRUE(readerSignature);
|
||||
|
||||
// Generate the key that will be used to sign AuthenticatedData.
|
||||
vector<uint8_t> signingKeyBlob;
|
||||
Certificate signingKeyCertificate;
|
||||
ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
|
||||
|
||||
ASSERT_TRUE(credential
|
||||
->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
|
||||
sessionTranscriptBytes, readerSignature.value(),
|
||||
testEntriesEntryCounts)
|
||||
signingKeyBlob, sessionTranscriptBytes,
|
||||
readerSignature.value(), testEntriesEntryCounts)
|
||||
.isOk());
|
||||
|
||||
for (const auto& entry : testEntries) {
|
||||
|
@ -377,14 +382,9 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
|
|||
EXPECT_EQ(content, entry.valueCbor);
|
||||
}
|
||||
|
||||
// Generate the key that will be used to sign AuthenticatedData.
|
||||
vector<uint8_t> signingKeyBlob;
|
||||
Certificate signingKeyCertificate;
|
||||
ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
|
||||
|
||||
vector<uint8_t> mac;
|
||||
vector<uint8_t> deviceNameSpacesBytes;
|
||||
ASSERT_TRUE(credential->finishRetrieval(signingKeyBlob, &mac, &deviceNameSpacesBytes).isOk());
|
||||
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
|
||||
cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
|
||||
ASSERT_EQ(
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in a new issue