Loading identity/aidl/aidl_api/android.hardware.identity/2/.hash +1 −1 Original line number Diff line number Diff line 3b0b10b618dbc4bf283aa2bf78833ad3de0a5928 194e04be642728623d65ec8321a3764fdea52ae0 identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredential.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -28,4 +28,5 @@ interface IIdentityCredential { 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); } identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -28,4 +28,5 @@ interface IIdentityCredential { 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); } identity/aidl/android/hardware/identity/IIdentityCredential.aidl +30 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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 { Loading Loading @@ -71,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. */ Loading @@ -83,7 +85,8 @@ interface IIdentityCredential { /** * Start an entry retrieval process. * * The setRequestedNamespaces() method will be called before this method. * 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 Loading @@ -96,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. Loading Loading @@ -179,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. Loading Loading @@ -358,4 +374,13 @@ interface IIdentityCredential { * @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); } identity/aidl/default/IdentityCredential.cpp +22 −21 Original line number Diff line number Diff line Loading @@ -198,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 Loading @@ -214,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"; Loading @@ -227,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: // // "[...] 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. // 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. // 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 << ")"; Loading @@ -261,6 +255,12 @@ ndk::ScopedAStatus IdentityCredential::setRequestedNamespaces( 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<uint8_t>& itemsRequest, Loading Loading @@ -483,7 +483,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) { Loading Loading
identity/aidl/aidl_api/android.hardware.identity/2/.hash +1 −1 Original line number Diff line number Diff line 3b0b10b618dbc4bf283aa2bf78833ad3de0a5928 194e04be642728623d65ec8321a3764fdea52ae0
identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredential.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -28,4 +28,5 @@ interface IIdentityCredential { 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); }
identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -28,4 +28,5 @@ interface IIdentityCredential { 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); }
identity/aidl/android/hardware/identity/IIdentityCredential.aidl +30 −5 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ 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 { Loading Loading @@ -71,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. */ Loading @@ -83,7 +85,8 @@ interface IIdentityCredential { /** * Start an entry retrieval process. * * The setRequestedNamespaces() method will be called before this method. * 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 Loading @@ -96,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. Loading Loading @@ -179,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. Loading Loading @@ -358,4 +374,13 @@ interface IIdentityCredential { * @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); }
identity/aidl/default/IdentityCredential.cpp +22 −21 Original line number Diff line number Diff line Loading @@ -198,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 Loading @@ -214,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"; Loading @@ -227,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: // // "[...] 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. // 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. // 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 << ")"; Loading @@ -261,6 +255,12 @@ ndk::ScopedAStatus IdentityCredential::setRequestedNamespaces( 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<uint8_t>& itemsRequest, Loading Loading @@ -483,7 +483,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) { Loading