Merge changes from topic "ic-hal-v2-rvc" into rvc-dev
* changes: Identity Credential: Add method to accept verification token. Identity Credential: Pass additional information to HAL.
This commit is contained in:
commit
fc7b29c5a0
41 changed files with 1070 additions and 53 deletions
|
@ -18,5 +18,8 @@ aidl_interface {
|
|||
},
|
||||
},
|
||||
},
|
||||
versions: ["1"],
|
||||
versions: [
|
||||
"1",
|
||||
"2",
|
||||
],
|
||||
}
|
||||
|
|
1
identity/aidl/aidl_api/android.hardware.identity/2/.hash
Normal file
1
identity/aidl/aidl_api/android.hardware.identity/2/.hash
Normal file
|
@ -0,0 +1 @@
|
|||
194e04be642728623d65ec8321a3764fdea52ae0
|
|
@ -0,0 +1,22 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable Certificate {
|
||||
byte[] encodedCertificate;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum CipherSuite {
|
||||
CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1,
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable HardwareInformation {
|
||||
@utf8InCpp String credentialStoreName;
|
||||
@utf8InCpp String credentialStoreAuthorName;
|
||||
int dataChunkSize;
|
||||
boolean isDirectAccess;
|
||||
@utf8InCpp String[] supportedDocTypes;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
interface IIdentityCredential {
|
||||
byte[] deleteCredential();
|
||||
byte[] createEphemeralKeyPair();
|
||||
void setReaderEphemeralPublicKey(in byte[] publicKey);
|
||||
long createAuthChallenge();
|
||||
void startRetrieval(in android.hardware.identity.SecureAccessControlProfile[] accessControlProfiles, in android.hardware.keymaster.HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob, in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
|
||||
void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds);
|
||||
byte[] retrieveEntryValue(in byte[] encryptedContent);
|
||||
void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
|
||||
android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
|
||||
void setRequestedNamespaces(in android.hardware.identity.RequestNamespace[] requestNamespaces);
|
||||
void setVerificationToken(in android.hardware.keymaster.VerificationToken verificationToken);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
interface IIdentityCredentialStore {
|
||||
android.hardware.identity.HardwareInformation getHardwareInformation();
|
||||
android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
|
||||
android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
|
||||
const int STATUS_OK = 0;
|
||||
const int STATUS_FAILED = 1;
|
||||
const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
|
||||
const int STATUS_INVALID_DATA = 3;
|
||||
const int STATUS_INVALID_AUTH_TOKEN = 4;
|
||||
const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5;
|
||||
const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6;
|
||||
const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7;
|
||||
const int STATUS_USER_AUTHENTICATION_FAILED = 8;
|
||||
const int STATUS_READER_AUTHENTICATION_FAILED = 9;
|
||||
const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10;
|
||||
const int STATUS_NOT_IN_REQUEST_MESSAGE = 11;
|
||||
const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
interface IWritableIdentityCredential {
|
||||
android.hardware.identity.Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
|
||||
void startPersonalization(in int accessControlProfileCount, in int[] entryCounts);
|
||||
android.hardware.identity.SecureAccessControlProfile addAccessControlProfile(in int id, in android.hardware.identity.Certificate readerCertificate, in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
|
||||
void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
|
||||
byte[] addEntryValue(in byte[] content);
|
||||
void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
|
||||
void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable RequestDataItem {
|
||||
@utf8InCpp String name;
|
||||
long size;
|
||||
int[] accessControlProfileIds;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable RequestNamespace {
|
||||
@utf8InCpp String namespaceName;
|
||||
android.hardware.identity.RequestDataItem[] items;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable SecureAccessControlProfile {
|
||||
int id;
|
||||
android.hardware.identity.Certificate readerCertificate;
|
||||
boolean userAuthenticationRequired;
|
||||
long timeoutMillis;
|
||||
long secureUserId;
|
||||
byte[] mac;
|
||||
}
|
|
@ -27,4 +27,6 @@ interface IIdentityCredential {
|
|||
byte[] retrieveEntryValue(in byte[] encryptedContent);
|
||||
void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
|
||||
android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
|
||||
void setRequestedNamespaces(in android.hardware.identity.RequestNamespace[] requestNamespaces);
|
||||
void setVerificationToken(in android.hardware.keymaster.VerificationToken verificationToken);
|
||||
}
|
||||
|
|
|
@ -24,4 +24,5 @@ interface IWritableIdentityCredential {
|
|||
void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
|
||||
byte[] addEntryValue(in byte[] content);
|
||||
void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
|
||||
void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable RequestDataItem {
|
||||
@utf8InCpp String name;
|
||||
long size;
|
||||
int[] accessControlProfileIds;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.identity;
|
||||
@VintfStability
|
||||
parcelable RequestNamespace {
|
||||
@utf8InCpp String namespaceName;
|
||||
android.hardware.identity.RequestDataItem[] items;
|
||||
}
|
|
@ -17,8 +17,10 @@
|
|||
package android.hardware.identity;
|
||||
|
||||
import android.hardware.identity.Certificate;
|
||||
import android.hardware.identity.RequestNamespace;
|
||||
import android.hardware.identity.SecureAccessControlProfile;
|
||||
import android.hardware.keymaster.HardwareAuthToken;
|
||||
import android.hardware.keymaster.VerificationToken;
|
||||
|
||||
@VintfStability
|
||||
interface IIdentityCredential {
|
||||
|
@ -70,10 +72,11 @@ interface IIdentityCredential {
|
|||
|
||||
/**
|
||||
* Creates a challenge value to be used for proving successful user authentication. This
|
||||
* is included in the authToken passed to the startRetrieval() method.
|
||||
* is included in the authToken passed to the startRetrieval() method and the
|
||||
* verificationToken passed to the setVerificationToken() method.
|
||||
*
|
||||
* This method may only be called once per instance. If called more than once, STATUS_FAILED
|
||||
* will be returned.
|
||||
* will be returned. If user authentication is not needed, this method may not be called.
|
||||
*
|
||||
* @return challenge, a non-zero number.
|
||||
*/
|
||||
|
@ -82,6 +85,9 @@ interface IIdentityCredential {
|
|||
/**
|
||||
* Start an entry retrieval process.
|
||||
*
|
||||
* The setRequestedNamespaces() and setVerificationToken() methods will be called before
|
||||
* this method is called.
|
||||
*
|
||||
* This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
|
||||
* createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
|
||||
* multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
|
||||
|
@ -93,7 +99,19 @@ interface IIdentityCredential {
|
|||
* must be identical for each startRetrieval() invocation. If this is not the case, this call
|
||||
* fails with the STATUS_SESSION_TRANSCRIPT_MISMATCH error.
|
||||
*
|
||||
* If the provided authToken is not valid this method fails with STATUS_INVALID_AUTH_TOKEN.
|
||||
* If either authToken or verificationToken (as passed with setVerificationToken())
|
||||
* is not valid this method fails with STATUS_INVALID_AUTH_TOKEN. Note that valid tokens
|
||||
* are only passed if they are actually needed and available (this can be detected by
|
||||
* the timestamp being set to zero). For example, if no data items with access control
|
||||
* profiles using user authentication are requested, the tokens are not filled in.
|
||||
* It's also possible that no usable auth token is actually available (it could be the user
|
||||
* never unlocked the device within the timeouts in the access control profiles) and
|
||||
* in this case the tokens aren't filled in either.
|
||||
*
|
||||
* For test credentials (identified by the testCredential boolean in the CredentialData
|
||||
* CBOR created at provisioning time), the |mac| field in both the authToken and
|
||||
* verificationToken should not be checked against the shared HMAC key (see IKeyMasterDevice
|
||||
* for details). This is to enable VTS tests to check for correct behavior.
|
||||
*
|
||||
* Each of the provided accessControlProfiles is checked in this call. If they are not
|
||||
* all valid, the call fails with STATUS_INVALID_DATA.
|
||||
|
@ -176,7 +194,8 @@ interface IIdentityCredential {
|
|||
*
|
||||
* @param authToken
|
||||
* The authentication token that proves the user was authenticated, as required
|
||||
* by one or more of the provided accessControlProfiles. See above.
|
||||
* by one or more of the provided accessControlProfiles. This token is only valid
|
||||
* if the timestamp field is non-zero. See above.
|
||||
*
|
||||
* @param itemsRequest
|
||||
* If non-empty, contains request data that is signed by the reader. See above.
|
||||
|
@ -274,7 +293,7 @@ interface IIdentityCredential {
|
|||
* "DeviceAuthentication",
|
||||
* SessionTranscript,
|
||||
* DocType,
|
||||
* DeviceNameSpaceBytes,
|
||||
* DeviceNameSpacesBytes,
|
||||
* ]
|
||||
*
|
||||
* DocType = tstr
|
||||
|
@ -343,4 +362,25 @@ interface IIdentityCredential {
|
|||
* @return an X.509 certificate for the new signing key, signed by the credential key.
|
||||
*/
|
||||
Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
|
||||
|
||||
/**
|
||||
* Sets the namespaces and data items (including their size and access control profiles)
|
||||
* which will be requested. This method must be called before startRetrieval() is called.
|
||||
*
|
||||
* This information is provided to make it possible for a HAL implementation to
|
||||
* incrementally build up cryptographically authenticated data which includes the
|
||||
* DeviceNameSpaces CBOR.
|
||||
*
|
||||
* @param requestNamespaces Namespaces and data items which will be requested.
|
||||
*/
|
||||
void setRequestedNamespaces(in RequestNamespace[] requestNamespaces);
|
||||
|
||||
/**
|
||||
* Sets the VerificationToken. This method must be called before startRetrieval() is
|
||||
* called. This token uses the same challenge as returned by createAuthChallenge().
|
||||
*
|
||||
* @param verificationToken
|
||||
* The verification token. This token is only valid if the timestamp field is non-zero.
|
||||
*/
|
||||
void setVerificationToken(in VerificationToken verificationToken);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ interface IWritableIdentityCredential {
|
|||
*
|
||||
* startPersonalization must not be called more than once.
|
||||
*
|
||||
* The setExpectedProofOfProvisioningSize() method will be called before this method.
|
||||
*
|
||||
* @param accessControlProfileCount specifies the number of access control profiles that will
|
||||
* be provisioned with addAccessControlProfile().
|
||||
*
|
||||
|
@ -288,4 +290,16 @@ interface IWritableIdentityCredential {
|
|||
*/
|
||||
void finishAddingEntries(out byte[] credentialData,
|
||||
out byte[] proofOfProvisioningSignature);
|
||||
|
||||
/**
|
||||
* Sets the expected size of the ProofOfProvisioning returned by finishAddingEntries(). This
|
||||
* method must be called before startPersonalization() is called.
|
||||
*
|
||||
* This information is provided to make it possible for a HAL implementation to
|
||||
* incrementally build up cryptographically authenticated data which includes the
|
||||
* ProofOfProvisioning CBOR.
|
||||
*
|
||||
* @param expectedProofOfProvisioningSize the expected size of ProofOfProvisioning.
|
||||
*/
|
||||
void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
|
||||
}
|
||||
|
|
38
identity/aidl/android/hardware/identity/RequestDataItem.aidl
Normal file
38
identity/aidl/android/hardware/identity/RequestDataItem.aidl
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2020 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.identity;
|
||||
|
||||
@VintfStability
|
||||
parcelable RequestDataItem {
|
||||
/**
|
||||
* The data item name being requested, for example "driving_privileges".
|
||||
*/
|
||||
@utf8InCpp String name;
|
||||
|
||||
/**
|
||||
* The size of the data item value.
|
||||
*
|
||||
* Data item values are always encoded as CBOR so this is the length of
|
||||
* the CBOR encoding of the value.
|
||||
*/
|
||||
long size;
|
||||
|
||||
/**
|
||||
* The access control profile ids this data item is configured with.
|
||||
*/
|
||||
int[] accessControlProfileIds;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2020 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.identity;
|
||||
|
||||
import android.hardware.identity.RequestDataItem;
|
||||
|
||||
@VintfStability
|
||||
parcelable RequestNamespace {
|
||||
/**
|
||||
* The name of the namespace that items are being requested from, for
|
||||
* example "org.iso.18013.5.1".
|
||||
*/
|
||||
@utf8InCpp String namespaceName;
|
||||
|
||||
/**
|
||||
* The data items requested.
|
||||
*/
|
||||
RequestDataItem[] items;
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <cppbor.h>
|
||||
#include <cppbor_parse.h>
|
||||
|
@ -32,6 +33,7 @@
|
|||
namespace aidl::android::hardware::identity {
|
||||
|
||||
using ::aidl::android::hardware::keymaster::Timestamp;
|
||||
using ::android::base::StringPrintf;
|
||||
using ::std::optional;
|
||||
|
||||
using namespace ::android::hardware::identity;
|
||||
|
@ -196,15 +198,8 @@ bool checkReaderAuthentication(const SecureAccessControlProfile& profile,
|
|||
return false;
|
||||
}
|
||||
|
||||
Timestamp clockGetTime() {
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
Timestamp ts;
|
||||
ts.milliSeconds = time.tv_sec * 1000 + time.tv_nsec / 1000000;
|
||||
return ts;
|
||||
}
|
||||
|
||||
bool checkUserAuthentication(const SecureAccessControlProfile& profile,
|
||||
const VerificationToken& verificationToken,
|
||||
const HardwareAuthToken& authToken, uint64_t authChallenge) {
|
||||
if (profile.secureUserId != authToken.userId) {
|
||||
LOG(ERROR) << "secureUserId in profile (" << profile.secureUserId
|
||||
|
@ -212,6 +207,15 @@ bool checkUserAuthentication(const SecureAccessControlProfile& profile,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (verificationToken.timestamp.milliSeconds == 0) {
|
||||
LOG(ERROR) << "VerificationToken is not set";
|
||||
return false;
|
||||
}
|
||||
if (authToken.timestamp.milliSeconds == 0) {
|
||||
LOG(ERROR) << "AuthToken is not set";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (profile.timeoutMillis == 0) {
|
||||
if (authToken.challenge == 0) {
|
||||
LOG(ERROR) << "No challenge in authToken";
|
||||
|
@ -225,19 +229,11 @@ bool checkUserAuthentication(const SecureAccessControlProfile& profile,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Note that the Epoch for timestamps in HardwareAuthToken is at the
|
||||
// discretion of the vendor:
|
||||
// Timeout-based user auth follows. The verification token conveys what the
|
||||
// time is right now in the environment which generated the auth token. This
|
||||
// is what makes it possible to do timeout-based checks.
|
||||
//
|
||||
// "[...] since some starting point (generally the most recent device
|
||||
// boot) which all of the applications within one secure environment
|
||||
// must agree upon."
|
||||
//
|
||||
// Therefore, if this software implementation is used on a device which isn't
|
||||
// the emulator then the assumption that the epoch is the same as used in
|
||||
// clockGetTime above will not hold. This is OK as this software
|
||||
// implementation should never be used on a real device.
|
||||
//
|
||||
Timestamp now = clockGetTime();
|
||||
const Timestamp now = verificationToken.timestamp;
|
||||
if (authToken.timestamp.milliSeconds > now.milliSeconds) {
|
||||
LOG(ERROR) << "Timestamp in authToken (" << authToken.timestamp.milliSeconds
|
||||
<< ") is in the future (now: " << now.milliSeconds << ")";
|
||||
|
@ -253,6 +249,18 @@ bool checkUserAuthentication(const SecureAccessControlProfile& profile,
|
|||
return true;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus IdentityCredential::setRequestedNamespaces(
|
||||
const vector<RequestNamespace>& requestNamespaces) {
|
||||
requestNamespaces_ = requestNamespaces;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus IdentityCredential::setVerificationToken(
|
||||
const VerificationToken& verificationToken) {
|
||||
verificationToken_ = verificationToken;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
||||
const vector<SecureAccessControlProfile>& accessControlProfiles,
|
||||
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
|
||||
|
@ -451,7 +459,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
|||
"Type mismatch in nameSpaces map"));
|
||||
}
|
||||
string requestedNamespace = nsKey->value();
|
||||
vector<string> requestedKeys;
|
||||
set<string> requestedKeys;
|
||||
for (size_t m = 0; m < nsInnerMap->size(); m++) {
|
||||
const auto& [innerMapKeyItem, innerMapValueItem] = (*nsInnerMap)[m];
|
||||
const cppbor::Tstr* nameItem = innerMapKeyItem->asTstr();
|
||||
|
@ -463,13 +471,13 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
|||
IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
|
||||
"Type mismatch in value in nameSpaces map"));
|
||||
}
|
||||
requestedKeys.push_back(nameItem->value());
|
||||
requestedKeys.insert(nameItem->value());
|
||||
}
|
||||
requestedNameSpacesAndNames_[requestedNamespace] = requestedKeys;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, validate all the access control profiles in the requestData.
|
||||
// Validate all the access control profiles in the requestData.
|
||||
bool haveAuthToken = (authToken.mac.size() > 0);
|
||||
for (const auto& profile : accessControlProfiles) {
|
||||
if (!secureAccessControlProfileCheckMac(profile, storageKey_)) {
|
||||
|
@ -479,7 +487,8 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
|||
}
|
||||
int accessControlCheck = IIdentityCredentialStore::STATUS_OK;
|
||||
if (profile.userAuthenticationRequired) {
|
||||
if (!haveAuthToken || !checkUserAuthentication(profile, authToken, authChallenge_)) {
|
||||
if (!haveAuthToken ||
|
||||
!checkUserAuthentication(profile, verificationToken_, authToken, authChallenge_)) {
|
||||
accessControlCheck = IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED;
|
||||
}
|
||||
} else if (profile.readerCertificate.encodedCertificate.size() > 0) {
|
||||
|
@ -500,10 +509,118 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
|
|||
itemsRequest_ = itemsRequest;
|
||||
signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
|
||||
|
||||
// Finally, calculate the size of DeviceNameSpaces. We need to know it ahead of time.
|
||||
expectedDeviceNameSpacesSize_ = calcDeviceNameSpacesSize();
|
||||
|
||||
numStartRetrievalCalls_ += 1;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
size_t cborNumBytesForLength(size_t length) {
|
||||
if (length < 24) {
|
||||
return 0;
|
||||
} else if (length <= 0xff) {
|
||||
return 1;
|
||||
} else if (length <= 0xffff) {
|
||||
return 2;
|
||||
} else if (length <= 0xffffffff) {
|
||||
return 4;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
|
||||
size_t cborNumBytesForTstr(const string& value) {
|
||||
return 1 + cborNumBytesForLength(value.size()) + value.size();
|
||||
}
|
||||
|
||||
size_t IdentityCredential::calcDeviceNameSpacesSize() {
|
||||
/*
|
||||
* This is how DeviceNameSpaces is defined:
|
||||
*
|
||||
* DeviceNameSpaces = {
|
||||
* * NameSpace => DeviceSignedItems
|
||||
* }
|
||||
* DeviceSignedItems = {
|
||||
* + DataItemName => DataItemValue
|
||||
* }
|
||||
*
|
||||
* Namespace = tstr
|
||||
* DataItemName = tstr
|
||||
* DataItemValue = any
|
||||
*
|
||||
* This function will calculate its length using knowledge of how CBOR is
|
||||
* encoded.
|
||||
*/
|
||||
size_t ret = 0;
|
||||
size_t numNamespacesWithValues = 0;
|
||||
for (const RequestNamespace& rns : requestNamespaces_) {
|
||||
vector<RequestDataItem> itemsToInclude;
|
||||
|
||||
for (const RequestDataItem& rdi : rns.items) {
|
||||
// If we have a CBOR request message, skip if item isn't in it
|
||||
if (itemsRequest_.size() > 0) {
|
||||
const auto& it = requestedNameSpacesAndNames_.find(rns.namespaceName);
|
||||
if (it == requestedNameSpacesAndNames_.end()) {
|
||||
continue;
|
||||
}
|
||||
const set<string>& dataItemNames = it->second;
|
||||
if (dataItemNames.find(rdi.name) == dataItemNames.end()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Access is granted if at least one of the profiles grants access.
|
||||
//
|
||||
// If an item is configured without any profiles, access is denied.
|
||||
//
|
||||
bool authorized = false;
|
||||
for (auto id : rdi.accessControlProfileIds) {
|
||||
auto it = profileIdToAccessCheckResult_.find(id);
|
||||
if (it != profileIdToAccessCheckResult_.end()) {
|
||||
int accessControlForProfile = it->second;
|
||||
if (accessControlForProfile == IIdentityCredentialStore::STATUS_OK) {
|
||||
authorized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!authorized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
itemsToInclude.push_back(rdi);
|
||||
}
|
||||
|
||||
// If no entries are to be in the namespace, we don't include it...
|
||||
if (itemsToInclude.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Key: NameSpace
|
||||
ret += cborNumBytesForTstr(rns.namespaceName);
|
||||
|
||||
// Value: Open the DeviceSignedItems map
|
||||
ret += 1 + cborNumBytesForLength(itemsToInclude.size());
|
||||
|
||||
for (const RequestDataItem& item : itemsToInclude) {
|
||||
// Key: DataItemName
|
||||
ret += cborNumBytesForTstr(item.name);
|
||||
|
||||
// Value: DataItemValue - entryData.size is the length of serialized CBOR so we use
|
||||
// that.
|
||||
ret += item.size;
|
||||
}
|
||||
|
||||
numNamespacesWithValues++;
|
||||
}
|
||||
|
||||
// Now that we now the nunber of namespaces with values, we know how many
|
||||
// bytes the DeviceNamespaces map in the beginning is going to take up.
|
||||
ret += 1 + cborNumBytesForLength(numNamespacesWithValues);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
|
||||
const string& nameSpace, const string& name, int32_t entrySize,
|
||||
const vector<int32_t>& accessControlProfileIds) {
|
||||
|
@ -562,8 +679,8 @@ ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
|
|||
IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE,
|
||||
"Name space was not requested in startRetrieval"));
|
||||
}
|
||||
const auto& dataItemNames = it->second;
|
||||
if (std::find(dataItemNames.begin(), dataItemNames.end(), name) == dataItemNames.end()) {
|
||||
const set<string>& dataItemNames = it->second;
|
||||
if (dataItemNames.find(name) == dataItemNames.end()) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE,
|
||||
"Data item name in name space was not requested in startRetrieval"));
|
||||
|
@ -608,7 +725,6 @@ ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
|
|||
ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<int8_t>& encryptedContentS,
|
||||
vector<int8_t>* outContent) {
|
||||
auto encryptedContent = byteStringToUnsigned(encryptedContentS);
|
||||
|
||||
optional<vector<uint8_t>> content =
|
||||
support::decryptAes128Gcm(storageKey_, encryptedContent, entryAdditionalData_);
|
||||
if (!content) {
|
||||
|
@ -659,6 +775,17 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
|
|||
}
|
||||
vector<uint8_t> encodedDeviceNameSpaces = deviceNameSpacesMap_.encode();
|
||||
|
||||
if (encodedDeviceNameSpaces.size() != expectedDeviceNameSpacesSize_) {
|
||||
LOG(ERROR) << "encodedDeviceNameSpaces is " << encodedDeviceNameSpaces.size() << " bytes, "
|
||||
<< "was expecting " << expectedDeviceNameSpacesSize_;
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IIdentityCredentialStore::STATUS_INVALID_DATA,
|
||||
StringPrintf(
|
||||
"Unexpected CBOR size %zd for encodedDeviceNameSpaces, was expecting %zd",
|
||||
encodedDeviceNameSpaces.size(), expectedDeviceNameSpacesSize_)
|
||||
.c_str()));
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <aidl/android/hardware/identity/BnIdentityCredential.h>
|
||||
#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
|
||||
#include <aidl/android/hardware/keymaster/VerificationToken.h>
|
||||
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
|
||||
|
||||
#include <map>
|
||||
|
@ -31,16 +32,19 @@
|
|||
namespace aidl::android::hardware::identity {
|
||||
|
||||
using ::aidl::android::hardware::keymaster::HardwareAuthToken;
|
||||
using ::aidl::android::hardware::keymaster::VerificationToken;
|
||||
using ::std::map;
|
||||
using ::std::set;
|
||||
using ::std::string;
|
||||
using ::std::vector;
|
||||
|
||||
using MapStringToVectorOfStrings = map<string, vector<string>>;
|
||||
|
||||
class IdentityCredential : public BnIdentityCredential {
|
||||
public:
|
||||
IdentityCredential(const vector<uint8_t>& credentialData)
|
||||
: credentialData_(credentialData), numStartRetrievalCalls_(0), authChallenge_(0) {}
|
||||
: credentialData_(credentialData),
|
||||
numStartRetrievalCalls_(0),
|
||||
authChallenge_(0),
|
||||
expectedDeviceNameSpacesSize_(0) {}
|
||||
|
||||
// Parses and decrypts credentialData_, return a status code from
|
||||
// IIdentityCredentialStore. Must be called right after construction.
|
||||
|
@ -51,6 +55,9 @@ class IdentityCredential : public BnIdentityCredential {
|
|||
ndk::ScopedAStatus createEphemeralKeyPair(vector<int8_t>* outKeyPair) override;
|
||||
ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<int8_t>& publicKey) override;
|
||||
ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
|
||||
ndk::ScopedAStatus setRequestedNamespaces(
|
||||
const vector<RequestNamespace>& requestNamespaces) override;
|
||||
ndk::ScopedAStatus setVerificationToken(const VerificationToken& verificationToken) override;
|
||||
ndk::ScopedAStatus startRetrieval(
|
||||
const vector<SecureAccessControlProfile>& accessControlProfiles,
|
||||
const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
|
||||
|
@ -86,6 +93,12 @@ class IdentityCredential : public BnIdentityCredential {
|
|||
// Set by createAuthChallenge()
|
||||
uint64_t authChallenge_;
|
||||
|
||||
// Set by setRequestedNamespaces()
|
||||
vector<RequestNamespace> requestNamespaces_;
|
||||
|
||||
// Set by setVerificationToken().
|
||||
VerificationToken verificationToken_;
|
||||
|
||||
// Set at startRetrieval() time.
|
||||
map<int32_t, int> profileIdToAccessCheckResult_;
|
||||
vector<uint8_t> signingKeyBlob_;
|
||||
|
@ -93,16 +106,21 @@ class IdentityCredential : public BnIdentityCredential {
|
|||
std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
|
||||
vector<uint8_t> itemsRequest_;
|
||||
vector<int32_t> requestCountsRemaining_;
|
||||
MapStringToVectorOfStrings requestedNameSpacesAndNames_;
|
||||
map<string, set<string>> requestedNameSpacesAndNames_;
|
||||
cppbor::Map deviceNameSpacesMap_;
|
||||
cppbor::Map currentNameSpaceDeviceNameSpacesMap_;
|
||||
|
||||
// Calculated at startRetrieval() time.
|
||||
size_t expectedDeviceNameSpacesSize_;
|
||||
|
||||
// Set at startRetrieveEntryValue() time.
|
||||
string currentNameSpace_;
|
||||
string currentName_;
|
||||
size_t entryRemainingBytes_;
|
||||
vector<uint8_t> entryValue_;
|
||||
vector<uint8_t> entryAdditionalData_;
|
||||
|
||||
size_t calcDeviceNameSpacesSize();
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::identity
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <cppbor/cppbor.h>
|
||||
#include <cppbor/cppbor_parse.h>
|
||||
|
@ -34,6 +35,7 @@
|
|||
|
||||
namespace aidl::android::hardware::identity {
|
||||
|
||||
using ::android::base::StringPrintf;
|
||||
using ::std::optional;
|
||||
using namespace ::android::hardware::identity;
|
||||
|
||||
|
@ -105,6 +107,12 @@ ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
|
|||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WritableIdentityCredential::setExpectedProofOfProvisioningSize(
|
||||
int32_t expectedProofOfProvisioningSize) {
|
||||
expectedProofOfProvisioningSize_ = expectedProofOfProvisioningSize;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WritableIdentityCredential::startPersonalization(
|
||||
int32_t accessControlProfileCount, const vector<int32_t>& entryCounts) {
|
||||
if (startPersonalizationCalled_) {
|
||||
|
@ -255,7 +263,7 @@ ndk::ScopedAStatus WritableIdentityCredential::beginAddEntry(
|
|||
}
|
||||
|
||||
ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t>& contentS,
|
||||
vector<int8_t>* outEncryptedContent) {
|
||||
vector<int8_t>* outEncryptedContentS) {
|
||||
auto content = byteStringToUnsigned(contentS);
|
||||
size_t contentSize = content.size();
|
||||
|
||||
|
@ -311,7 +319,7 @@ ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t
|
|||
signedDataCurrentNamespace_.add(std::move(entryMap));
|
||||
}
|
||||
|
||||
*outEncryptedContent = byteStringToSigned(encryptedContent.value());
|
||||
*outEncryptedContentS = byteStringToSigned(encryptedContent.value());
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
|
@ -384,6 +392,16 @@ ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
|
|||
.add(testCredential_);
|
||||
vector<uint8_t> encodedCbor = popArray.encode();
|
||||
|
||||
if (encodedCbor.size() != expectedProofOfProvisioningSize_) {
|
||||
LOG(ERROR) << "CBOR for proofOfProvisioning is " << encodedCbor.size() << " bytes, "
|
||||
<< "was expecting " << expectedProofOfProvisioningSize_;
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IIdentityCredentialStore::STATUS_INVALID_DATA,
|
||||
StringPrintf("Unexpected CBOR size %zd for proofOfProvisioning, was expecting %zd",
|
||||
encodedCbor.size(), expectedProofOfProvisioningSize_)
|
||||
.c_str()));
|
||||
}
|
||||
|
||||
optional<vector<uint8_t>> signature = support::coseSignEcDsa(credentialPrivKey_,
|
||||
encodedCbor, // payload
|
||||
{}, // additionalData
|
||||
|
|
|
@ -43,6 +43,9 @@ class WritableIdentityCredential : public BnWritableIdentityCredential {
|
|||
const vector<int8_t>& attestationChallenge,
|
||||
vector<Certificate>* outCertificateChain) override;
|
||||
|
||||
ndk::ScopedAStatus setExpectedProofOfProvisioningSize(
|
||||
int32_t expectedProofOfProvisioningSize) override;
|
||||
|
||||
ndk::ScopedAStatus startPersonalization(int32_t accessControlProfileCount,
|
||||
const vector<int32_t>& entryCounts) override;
|
||||
|
||||
|
@ -62,7 +65,7 @@ class WritableIdentityCredential : public BnWritableIdentityCredential {
|
|||
vector<int8_t>* outCredentialData,
|
||||
vector<int8_t>* outProofOfProvisioningSignature) override;
|
||||
|
||||
// private:
|
||||
private:
|
||||
string docType_;
|
||||
bool testCredential_;
|
||||
|
||||
|
@ -82,6 +85,7 @@ class WritableIdentityCredential : public BnWritableIdentityCredential {
|
|||
cppbor::Array signedDataAccessControlProfiles_;
|
||||
cppbor::Map signedDataNamespaces_;
|
||||
cppbor::Array signedDataCurrentNamespace_;
|
||||
size_t expectedProofOfProvisioningSize_;
|
||||
|
||||
// This field is initialized in addAccessControlProfile
|
||||
set<int32_t> accessControlProfileIds_;
|
||||
|
|
|
@ -22,9 +22,14 @@
|
|||
|
||||
#include "IdentityCredentialStore.h"
|
||||
|
||||
using ::android::base::InitLogging;
|
||||
using ::android::base::StderrLogger;
|
||||
|
||||
using aidl::android::hardware::identity::IdentityCredentialStore;
|
||||
|
||||
int main() {
|
||||
int main(int /*argc*/, char* argv[]) {
|
||||
InitLogging(argv, StderrLogger);
|
||||
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<IdentityCredentialStore> store =
|
||||
ndk::SharedRefBase::make<IdentityCredentialStore>();
|
||||
|
|
|
@ -43,6 +43,7 @@ using ::android::String16;
|
|||
using ::android::binder::Status;
|
||||
|
||||
using ::android::hardware::keymaster::HardwareAuthToken;
|
||||
using ::android::hardware::keymaster::VerificationToken;
|
||||
|
||||
class IdentityAidl : public testing::TestWithParam<std::string> {
|
||||
public:
|
||||
|
@ -82,7 +83,20 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
|
|||
// Profile 1 (no authentication)
|
||||
{1, {}, false, 0}};
|
||||
|
||||
// It doesn't matter since no user auth is needed in this particular test,
|
||||
// but for good measure, clear out the tokens we pass to the HAL.
|
||||
HardwareAuthToken authToken;
|
||||
VerificationToken verificationToken;
|
||||
authToken.challenge = 0;
|
||||
authToken.userId = 0;
|
||||
authToken.authenticatorId = 0;
|
||||
authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
|
||||
authToken.timestamp.milliSeconds = 0;
|
||||
authToken.mac.clear();
|
||||
verificationToken.challenge = 0;
|
||||
verificationToken.timestamp.milliSeconds = 0;
|
||||
verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
|
||||
verificationToken.mac.clear();
|
||||
|
||||
// Here's the actual test data:
|
||||
const vector<test_utils::TestEntryData> testEntries = {
|
||||
|
@ -112,6 +126,11 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
|
|||
// TODO: set it to something random and check it's in the cert chain
|
||||
ASSERT_GE(attData.attestationCertificate.size(), 2);
|
||||
|
||||
// This is kinda of a hack but we need to give the size of
|
||||
// ProofOfProvisioning that we'll expect to receive.
|
||||
const int32_t expectedProofOfProvisioningSize = 262861 - 326 + readerCertificate.value().size();
|
||||
// OK to fail, not available in v1 HAL
|
||||
writableCredential->setExpectedProofOfProvisioningSize(expectedProofOfProvisioningSize);
|
||||
ASSERT_TRUE(
|
||||
writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
|
||||
.isOk());
|
||||
|
@ -268,6 +287,11 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
|
|||
Certificate signingKeyCertificate;
|
||||
ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
|
||||
|
||||
vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
|
||||
// OK to fail, not available in v1 HAL
|
||||
credential->setRequestedNamespaces(requestedNamespaces).isOk();
|
||||
// OK to fail, not available in v1 HAL
|
||||
credential->setVerificationToken(verificationToken);
|
||||
ASSERT_TRUE(credential
|
||||
->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
|
||||
signingKeyBlob, sessionTranscriptBytes,
|
||||
|
|
|
@ -279,14 +279,17 @@ TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
|
|||
EXPECT_TRUE(attData.result.isOk())
|
||||
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
|
||||
|
||||
const vector<int32_t> entryCounts = {1u};
|
||||
writableCredential->startPersonalization(1, entryCounts);
|
||||
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
|
||||
<< endl;
|
||||
|
||||
optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
|
||||
ASSERT_TRUE(readerCertificate1);
|
||||
|
||||
const vector<int32_t> entryCounts = {1u};
|
||||
size_t expectedPoPSize = 186 + readerCertificate1.value().size();
|
||||
// OK to fail, not available in v1 HAL
|
||||
writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
|
||||
result = writableCredential->startPersonalization(1, entryCounts);
|
||||
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
|
||||
<< endl;
|
||||
|
||||
const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
|
||||
|
||||
optional<vector<SecureAccessControlProfile>> secureProfiles =
|
||||
|
@ -374,7 +377,11 @@ TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
|
|||
{2, readerCertificate2.value(), true, 2},
|
||||
};
|
||||
const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
|
||||
writableCredential->startPersonalization(testProfiles.size(), entryCounts);
|
||||
size_t expectedPoPSize =
|
||||
525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
|
||||
// OK to fail, not available in v1 HAL
|
||||
writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
|
||||
result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
|
||||
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
|
||||
<< endl;
|
||||
|
||||
|
@ -518,11 +525,6 @@ TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
|
|||
ASSERT_TRUE(attData.result.isOk())
|
||||
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
|
||||
|
||||
const vector<int32_t> entryCounts = {2u, 2u};
|
||||
writableCredential->startPersonalization(3, entryCounts);
|
||||
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
|
||||
<< endl;
|
||||
|
||||
optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
|
||||
ASSERT_TRUE(readerCertificate1);
|
||||
|
||||
|
@ -530,6 +532,16 @@ TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
|
|||
test_utils::GenerateReaderCertificate("123456987987987987987987");
|
||||
ASSERT_TRUE(readerCertificate2);
|
||||
|
||||
const vector<int32_t> entryCounts = {2u, 2u};
|
||||
size_t expectedPoPSize =
|
||||
377 + readerCertificate1.value().size() + readerCertificate2.value().size();
|
||||
;
|
||||
// OK to fail, not available in v1 HAL
|
||||
writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
|
||||
writableCredential->startPersonalization(3, entryCounts);
|
||||
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
|
||||
<< endl;
|
||||
|
||||
const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
|
||||
{1, readerCertificate2.value(), true, 1},
|
||||
{2, {}, false, 0}};
|
||||
|
|
|
@ -176,4 +176,28 @@ void SetImageData(vector<uint8_t>& image) {
|
|||
}
|
||||
}
|
||||
|
||||
vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
|
||||
vector<RequestNamespace> ret;
|
||||
RequestNamespace curNs;
|
||||
for (const TestEntryData& testEntry : entries) {
|
||||
if (testEntry.nameSpace != curNs.namespaceName) {
|
||||
if (curNs.namespaceName.size() > 0) {
|
||||
ret.push_back(curNs);
|
||||
}
|
||||
curNs.namespaceName = testEntry.nameSpace;
|
||||
curNs.items.clear();
|
||||
}
|
||||
|
||||
RequestDataItem item;
|
||||
item.name = testEntry.name;
|
||||
item.size = testEntry.valueCbor.size();
|
||||
item.accessControlProfileIds = testEntry.profileIds;
|
||||
curNs.items.push_back(item);
|
||||
}
|
||||
if (curNs.namespaceName.size() > 0) {
|
||||
ret.push_back(curNs);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace android::hardware::identity::test_utils
|
||||
|
|
|
@ -113,6 +113,8 @@ bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates);
|
|||
|
||||
void SetImageData(vector<uint8_t>& image);
|
||||
|
||||
vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
|
||||
|
||||
} // namespace android::hardware::identity::test_utils
|
||||
|
||||
#endif // VTS_IDENTITY_TEST_UTILS_H
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_UTILS_H_
|
||||
|
||||
#include <android/hardware/keymaster/4.0/types.h>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
@ -52,6 +54,15 @@ inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) {
|
|||
HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer);
|
||||
hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token);
|
||||
|
||||
// Serializes and deserializes a verification token. This format is private and
|
||||
// not stable between releases and should not be persisted to disk.
|
||||
//
|
||||
// Currently doesn't support the |parametersVerified| field, will fail if set.
|
||||
//
|
||||
std::optional<VerificationToken> deserializeVerificationToken(
|
||||
const std::vector<uint8_t>& serializedToken);
|
||||
std::optional<std::vector<uint8_t>> serializeVerificationToken(const VerificationToken& token);
|
||||
|
||||
uint32_t getOsVersion();
|
||||
uint32_t getOsPatchlevel();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <regex.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <hardware/hw_auth_token.h>
|
||||
#include <keymasterV4_0/keymaster_utils.h>
|
||||
|
@ -110,6 +111,80 @@ HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer) {
|
|||
return token;
|
||||
}
|
||||
|
||||
void appendUint64(std::vector<uint8_t>& vec, uint64_t value) {
|
||||
for (size_t n = 0; n < sizeof(uint64_t); n++) {
|
||||
uint8_t byte = (value >> (n * 8)) & 0xff;
|
||||
vec.push_back(byte);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t extractUint64(const std::vector<uint8_t>& data, size_t offset) {
|
||||
uint64_t value = 0;
|
||||
for (size_t n = 0; n < sizeof(uint64_t); n++) {
|
||||
uint8_t byte = data[offset + n];
|
||||
value |= byte << (n * 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void appendUint32(std::vector<uint8_t>& vec, uint32_t value) {
|
||||
for (size_t n = 0; n < sizeof(uint32_t); n++) {
|
||||
uint8_t byte = (value >> (n * 8)) & 0xff;
|
||||
vec.push_back(byte);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t extractUint32(const std::vector<uint8_t>& data, size_t offset) {
|
||||
uint32_t value = 0;
|
||||
for (size_t n = 0; n < sizeof(uint32_t); n++) {
|
||||
uint8_t byte = data[offset + n];
|
||||
value |= byte << (n * 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8_t>> serializeVerificationToken(const VerificationToken& token) {
|
||||
if (token.parametersVerified.size() > 0) {
|
||||
LOG(ERROR) << "Serializing verification tokens with parametersVerified is not supported";
|
||||
return {};
|
||||
}
|
||||
if (!(token.mac.size() == 0 || token.mac.size() == 32)) {
|
||||
LOG(ERROR) << "Unexpected MAC size " << token.mac.size() << ", expected 0 or 32";
|
||||
return {};
|
||||
}
|
||||
std::vector<uint8_t> serializedToken;
|
||||
appendUint64(serializedToken, token.challenge);
|
||||
appendUint64(serializedToken, token.timestamp);
|
||||
appendUint32(serializedToken, uint32_t(token.securityLevel));
|
||||
appendUint32(serializedToken, token.mac.size());
|
||||
serializedToken.insert(serializedToken.end(), token.mac.begin(), token.mac.end());
|
||||
return serializedToken;
|
||||
}
|
||||
|
||||
std::optional<VerificationToken> deserializeVerificationToken(
|
||||
const std::vector<uint8_t>& serializedToken) {
|
||||
if (serializedToken.size() < 24) {
|
||||
LOG(ERROR) << "Unexpected serialized VerificationToken size " << serializedToken.size()
|
||||
<< ", expected at least 24 bytes";
|
||||
return {};
|
||||
}
|
||||
VerificationToken token;
|
||||
token.challenge = extractUint64(serializedToken, 0);
|
||||
token.timestamp = extractUint64(serializedToken, 8);
|
||||
token.securityLevel = SecurityLevel(extractUint32(serializedToken, 16));
|
||||
size_t macSize = extractUint32(serializedToken, 20);
|
||||
size_t expectedSerializedSize = 24 + macSize;
|
||||
if (serializedToken.size() != expectedSerializedSize) {
|
||||
LOG(ERROR) << "Unexpected serialized VerificationToken size " << serializedToken.size()
|
||||
<< ", expected " << expectedSerializedSize;
|
||||
return {};
|
||||
}
|
||||
if (macSize > 0) {
|
||||
token.mac = std::vector<uint8_t>(serializedToken.begin() + 24, serializedToken.end());
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kPlatformVersionProp[] = "ro.build.version.release";
|
||||
|
|
|
@ -15,5 +15,8 @@ aidl_interface {
|
|||
},
|
||||
},
|
||||
},
|
||||
versions: ["1"],
|
||||
versions: [
|
||||
"1",
|
||||
"2",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
91ab0be1887410935f564e3938ff12c5f5f8c59d
|
|
@ -0,0 +1,27 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@VintfStability
|
||||
parcelable HardwareAuthToken {
|
||||
long challenge;
|
||||
long userId;
|
||||
long authenticatorId;
|
||||
android.hardware.keymaster.HardwareAuthenticatorType authenticatorType;
|
||||
android.hardware.keymaster.Timestamp timestamp;
|
||||
byte[] mac;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum HardwareAuthenticatorType {
|
||||
NONE = 0,
|
||||
PASSWORD = 1,
|
||||
FINGERPRINT = 2,
|
||||
ANY = -1,
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum SecurityLevel {
|
||||
SOFTWARE = 0,
|
||||
TRUSTED_ENVIRONMENT = 1,
|
||||
STRONGBOX = 2,
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@VintfStability
|
||||
parcelable Timestamp {
|
||||
long milliSeconds;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@VintfStability
|
||||
parcelable VerificationToken {
|
||||
long challenge;
|
||||
android.hardware.keymaster.Timestamp timestamp;
|
||||
android.hardware.keymaster.SecurityLevel securityLevel;
|
||||
byte[] mac;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum SecurityLevel {
|
||||
SOFTWARE = 0,
|
||||
TRUSTED_ENVIRONMENT = 1,
|
||||
STRONGBOX = 2,
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
|
||||
// edit this file. It looks like you are doing that because you have modified
|
||||
// an AIDL interface in a backward-incompatible way, e.g., deleting a function
|
||||
// from an interface or a field from a parcelable and it broke the build. That
|
||||
// breakage is intended.
|
||||
//
|
||||
// You must not make a backward incompatible changes to the AIDL files 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.keymaster;
|
||||
@VintfStability
|
||||
parcelable VerificationToken {
|
||||
long challenge;
|
||||
android.hardware.keymaster.Timestamp timestamp;
|
||||
android.hardware.keymaster.SecurityLevel securityLevel;
|
||||
byte[] mac;
|
||||
}
|
32
keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
Normal file
32
keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2020 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.keymaster;
|
||||
|
||||
/**
|
||||
* Device security levels.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type="int")
|
||||
enum SecurityLevel {
|
||||
SOFTWARE = 0,
|
||||
TRUSTED_ENVIRONMENT = 1,
|
||||
/**
|
||||
* STRONGBOX specifies that the secure hardware satisfies the requirements specified in CDD
|
||||
* 9.11.2.
|
||||
*/
|
||||
STRONGBOX = 2,
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2020 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.keymaster;
|
||||
|
||||
import android.hardware.keymaster.SecurityLevel;
|
||||
import android.hardware.keymaster.Timestamp;
|
||||
import android.hardware.keymaster.HardwareAuthenticatorType;
|
||||
|
||||
/**
|
||||
* VerificationToken instances are used for secure environments to authenticate one another.
|
||||
*
|
||||
* This version of the parcelable currently don't use the parametersVerified field since it's not
|
||||
* needed for time-based verification. This can be added in a later version, if needed.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable VerificationToken {
|
||||
/**
|
||||
* The operation handle, used to ensure freshness.
|
||||
*/
|
||||
long challenge;
|
||||
|
||||
/**
|
||||
* The current time of the secure environment that generates the VerificationToken. This can be
|
||||
* checked against auth tokens generated by the same secure environment, which avoids needing to
|
||||
* synchronize clocks.
|
||||
*/
|
||||
Timestamp timestamp;
|
||||
|
||||
/**
|
||||
* SecurityLevel of the secure environment that generated the token.
|
||||
*/
|
||||
SecurityLevel securityLevel;
|
||||
|
||||
/**
|
||||
* 32-byte HMAC-SHA256 of the above values, computed as:
|
||||
*
|
||||
* HMAC(H,
|
||||
* "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified)
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeymaster).
|
||||
*
|
||||
* ``||'' represents concatenation
|
||||
*
|
||||
* The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
|
||||
* order. securityLevel is represented as a 32-bit unsigned integer in big-endian order.
|
||||
*
|
||||
* If parametersVerified is non-empty, the representation of parametersVerified is an ASN.1 DER
|
||||
* encoded representation of the values. The ASN.1 schema used is the AuthorizationList schema
|
||||
* from the Keystore attestation documentation. If parametersVerified is empty, it is simply
|
||||
* omitted from the HMAC computation.
|
||||
*/
|
||||
byte[] mac;
|
||||
}
|
Loading…
Reference in a new issue