identity: Check freshness of verification token in TA.

A problem where credstore didn't always use the TA-generated challenge
in the verification token was fixed in aosp/1619825. With this bug-fix
we can now reliably check that the passed-in verification token is
always fresh.

Bug: 181893400
Test: atest android.security.identity.cts on emulator
Test: atest VtsHalIdentityTargetTest
Change-Id: Iffdf026475da6321764561972aae27a82ab94530
This commit is contained in:
David Zeuthen
2021-03-04 16:39:42 -05:00
parent 620ad1ca3f
commit c6c950b55b
2 changed files with 25 additions and 19 deletions

View File

@@ -253,14 +253,17 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
}
}
// Feed the auth token to secure hardware.
if (!hwProxy_->setAuthToken(authToken.challenge, authToken.userId, authToken.authenticatorId,
int(authToken.authenticatorType), authToken.timestamp.milliSeconds,
authToken.mac, verificationToken_.challenge,
verificationToken_.timestamp.milliSeconds,
int(verificationToken_.securityLevel), verificationToken_.mac)) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Invalid Auth Token"));
// Feed the auth token to secure hardware only if they're valid.
if (authToken.timestamp.milliSeconds != 0) {
if (!hwProxy_->setAuthToken(
authToken.challenge, authToken.userId, authToken.authenticatorId,
int(authToken.authenticatorType), authToken.timestamp.milliSeconds,
authToken.mac, verificationToken_.challenge,
verificationToken_.timestamp.milliSeconds,
int(verificationToken_.securityLevel), verificationToken_.mac)) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Invalid Auth Token"));
}
}
// We'll be feeding ACPs interleaved with certificates from the reader

View File

@@ -336,6 +336,18 @@ bool eicPresentationSetAuthToken(EicPresentation* ctx, uint64_t challenge, uint6
int verificationTokenSecurityLevel,
const uint8_t* verificationTokenMac,
size_t verificationTokenMacSize) {
// It doesn't make sense to accept any tokens if eicPresentationCreateAuthChallenge()
// was never called.
if (ctx->authChallenge == 0) {
eicDebug("Trying validate tokens when no auth-challenge was previously generated");
return false;
}
// At least the verification-token must have the same challenge as what was generated.
if (verificationTokenChallenge != ctx->authChallenge) {
eicDebug("Challenge in verification token does not match the challenge "
"previously generated");
return false;
}
if (!eicOpsValidateAuthToken(
challenge, secureUserId, authenticatorId, hardwareAuthenticatorType, timeStamp, mac,
macSize, verificationTokenChallenge, verificationTokenTimestamp,
@@ -360,18 +372,9 @@ static bool checkUserAuth(EicPresentation* ctx, bool userAuthenticationRequired,
return false;
}
// Only ACP with auth-on-every-presentation - those with timeout == 0 - need the
// challenge to match...
if (timeoutMillis == 0) {
if (ctx->authTokenChallenge == 0) {
eicDebug("No challenge in authToken");
return false;
}
// If we didn't create a challenge, too bad but user auth with
// timeoutMillis set to 0 needs it.
if (ctx->authChallenge == 0) {
eicDebug("No challenge was created for this session");
return false;
}
if (ctx->authTokenChallenge != ctx->authChallenge) {
eicDebug("Challenge in authToken (%" PRIu64
") doesn't match the challenge "