Loading core/java/android/security/attestationverification/AttestationVerificationManager.java +57 −45 Original line number Diff line number Diff line Loading @@ -79,9 +79,7 @@ public class AttestationVerificationManager { * is also associated with a particular connection. * * <p>The {@code callback} is called with a result and {@link VerificationToken} (which may be * null). The result is an integer (see constants in this class with the prefix {@code RESULT_}. * The result is {@link #RESULT_SUCCESS} when at least one verifier has passed its checks. The * token may be used in calls to other parts of the system. * null). The result is an integer (see constants in {@link VerificationResultFlags}). * * <p>It's expected that a verifier will be able to decode and understand the passed values, * otherwise fail to verify. {@code attestation} should contain some type data to prevent parse Loading @@ -108,7 +106,7 @@ public class AttestationVerificationManager { @NonNull Bundle requirements, @NonNull byte[] attestation, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<@VerificationResult Integer, VerificationToken> callback) { @NonNull BiConsumer<@VerificationResultFlags Integer, VerificationToken> callback) { try { AndroidFuture<IVerificationResult> resultCallback = new AndroidFuture<>(); resultCallback.thenAccept(result -> { Loading Loading @@ -155,7 +153,7 @@ public class AttestationVerificationManager { */ @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE) @CheckResult @VerificationResult @VerificationResultFlags public int verifyToken( @NonNull AttestationProfile profile, @LocalBindingType int localBindingType, Loading Loading @@ -280,30 +278,66 @@ public class AttestationVerificationManager { */ public static final int TYPE_CHALLENGE = 3; /** @hide */ @IntDef( prefix = {"RESULT_"}, /** * Verification result returned from {@link #verifyAttestation}. * * A value of {@code 0} indicates success. Otherwise, a bit flag is set from first failing stage * below: * <ol> * <li> The received attestation's integrity (e.g. the certificate signatures) is validated. * If this fails, {@link #FLAG_FAILURE_CERTS} will be returned with all other bits unset. * <li> The local binding requirements are checked. If this fails, * {@link #FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS} is returned with all other bits unset. * <li> The profile requirements are checked. If this fails, a bit flag will be returned with * some of the these bits set to indicate the type of profile requirement failure: * {@link #FLAG_FAILURE_UNSUPPORTED_PROFILE}, {@link #FLAG_FAILURE_KEYSTORE_REQUIREMENTS}, * {@link #FLAG_FAILURE_BOOT_STATE}, and {@link #FLAG_FAILURE_PATCH_LEVEL_DIFF}. * </ol> * * Note: The reason of the failure must be not be provided to the remote device. * * @hide */ @IntDef(flag = true, prefix = {"FLAG_FAILURE_"}, value = { RESULT_UNKNOWN, RESULT_SUCCESS, RESULT_FAILURE, FLAG_FAILURE_UNKNOWN, FLAG_FAILURE_UNSUPPORTED_PROFILE, FLAG_FAILURE_CERTS, FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS, FLAG_FAILURE_KEYSTORE_REQUIREMENTS, FLAG_FAILURE_BOOT_STATE, FLAG_FAILURE_PATCH_LEVEL_DIFF, }) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface VerificationResult { } @Retention(RetentionPolicy.SOURCE) public @interface VerificationResultFlags{} /** Flag: If there are unknown failures e.g. runtime exception. 0 = no, 1 = yes. */ public static final int FLAG_FAILURE_UNKNOWN = 1; /** The result of the verification is unknown because it has a value unknown to this SDK. */ public static final int RESULT_UNKNOWN = 0; /** Flag: If the AVF profile is supported. 0 = supported, 1 = not supported */ public static final int FLAG_FAILURE_UNSUPPORTED_PROFILE = 1 << 1; /** * Flag: Result bit for certs verification e.g. loading, generating, parsing certs. * 0 = success, 1 = failure */ public static final int FLAG_FAILURE_CERTS = 1 << 2; /** The result of the verification was successful. */ public static final int RESULT_SUCCESS = 1; /** Flag: Result bit for local binding requirements verification. 0 = success, 1 = failure. */ public static final int FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS = 1 << 3; /** * The result of the attestation verification was failure. The attestation could not be * verified. * Flag: Result bit for KeyStore requirements verification. * 0 = success, 1 = failure. */ public static final int RESULT_FAILURE = 2; public static final int FLAG_FAILURE_KEYSTORE_REQUIREMENTS = 1 << 4; /** Flag: Result bit for boot state verification. 0 = success, 1 = failure */ public static final int FLAG_FAILURE_BOOT_STATE = 1 << 5; /** Flag: Result bit for patch level diff checks. 0 = success, 1 = failure. */ public static final int FLAG_FAILURE_PATCH_LEVEL_DIFF = 1 << 6; /** * Requirements bundle parameter key for a public key, a byte array. Loading Loading @@ -351,26 +385,4 @@ public class AttestationVerificationManager { } return text + "(" + localBindingType + ")"; } /** @hide */ public static String verificationResultCodeToString(@VerificationResult int resultCode) { final String text; switch (resultCode) { case RESULT_UNKNOWN: text = "UNKNOWN"; break; case RESULT_SUCCESS: text = "SUCCESS"; break; case RESULT_FAILURE: text = "FAILURE"; break; default: return Integer.toString(resultCode); } return text + "(" + resultCode + ")"; } } core/java/android/security/attestationverification/AttestationVerificationService.java +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.annotation.CheckResult; import android.annotation.NonNull; import android.app.Service; import android.os.Bundle; import android.security.attestationverification.AttestationVerificationManager.VerificationResult; import android.security.attestationverification.AttestationVerificationManager.VerificationResultFlags; /** * A verifier which can be implemented by apps to verify an attestation (as described in {@link Loading Loading @@ -93,7 +93,7 @@ public abstract class AttestationVerificationService extends Service { * byte[], java.util.concurrent.Executor, java.util.function.BiConsumer) */ @CheckResult @VerificationResult @VerificationResultFlags public abstract int onVerifyPeerDeviceAttestation( @NonNull Bundle requirements, @NonNull byte[] attestation); Loading core/java/android/security/attestationverification/VerificationToken.java +63 −142 File changed.Preview size limit exceeded, changes collapsed. Show changes services/companion/java/com/android/server/companion/securechannel/SecureChannel.java +4 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.companion.securechannel; import static android.security.attestationverification.AttestationVerificationManager.RESULT_SUCCESS; import android.annotation.NonNull; import android.content.Context; import android.os.Build; Loading Loading @@ -498,7 +496,7 @@ public class SecureChannel { private void exchangeAttestation() throws IOException, GeneralSecurityException, BadHandleException, CryptoException { if (mVerificationResult == RESULT_SUCCESS) { if (mVerificationResult == 0) { Slog.d(TAG, "Remote attestation was already verified."); return; } Loading Loading @@ -530,11 +528,11 @@ public class SecureChannel { sendMessage(MessageType.AVF_RESULT, verificationResult); byte[] remoteVerificationResult = readMessage(MessageType.AVF_RESULT); if (ByteBuffer.wrap(remoteVerificationResult).getInt() != RESULT_SUCCESS) { if (ByteBuffer.wrap(remoteVerificationResult).getInt() != 0) { throw new SecureChannelException("Remote device failed to verify local attestation."); } if (mVerificationResult != RESULT_SUCCESS) { if (mVerificationResult != 0) { throw new SecureChannelException("Failed to verify remote attestation."); } Loading @@ -549,7 +547,7 @@ public class SecureChannel { return false; } // Is authenticated return mPskVerified || mVerificationResult == RESULT_SUCCESS; return mPskVerified || mVerificationResult == 0; } // First byte indicates message type; 0 = CLIENT INIT, 1 = SERVER INIT Loading services/core/java/com/android/server/security/AttestationVerificationManagerService.java +9 −9 Original line number Diff line number Diff line Loading @@ -17,10 +17,10 @@ package com.android.server.security; import static android.Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE; import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_CERTS; import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_UNSUPPORTED_PROFILE; import static android.security.attestationverification.AttestationVerificationManager.PROFILE_PEER_DEVICE; import static android.security.attestationverification.AttestationVerificationManager.PROFILE_SELF_TRUSTED; import static android.security.attestationverification.AttestationVerificationManager.RESULT_FAILURE; import static android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -88,8 +88,8 @@ public class AttestationVerificationManagerService extends SystemService { public void verifyToken(VerificationToken token, ParcelDuration parcelDuration, AndroidFuture resultCallback) throws RemoteException { enforceUsePermission(); // TODO(b/201696614): Implement resultCallback.complete(RESULT_UNKNOWN); throw new UnsupportedOperationException(); } private void enforceUsePermission() { Loading Loading @@ -123,9 +123,9 @@ public class AttestationVerificationManagerService extends SystemService { AttestationProfile profile, int localBindingType, Bundle requirements, byte[] attestation, AndroidFuture<IVerificationResult> resultCallback) { IVerificationResult result = new IVerificationResult(); // TODO(b/201696614): Implement result.token = null; switch (profile.getAttestationProfileId()) { int profileId = profile.getAttestationProfileId(); switch (profileId) { case PROFILE_SELF_TRUSTED: Slog.d(TAG, "Verifying Self Trusted profile."); try { Loading @@ -133,7 +133,7 @@ public class AttestationVerificationManagerService extends SystemService { AttestationVerificationSelfTrustedVerifierForTesting.getInstance() .verifyAttestation(localBindingType, requirements, attestation); } catch (Throwable t) { result.resultCode = RESULT_FAILURE; result.resultCode = FLAG_FAILURE_CERTS; } break; case PROFILE_PEER_DEVICE: Loading @@ -142,8 +142,8 @@ public class AttestationVerificationManagerService extends SystemService { localBindingType, requirements, attestation); break; default: Slog.d(TAG, "No profile found, defaulting."); result.resultCode = RESULT_UNKNOWN; Slog.e(TAG, "Profile [" + profileId + "] is not supported."); result.resultCode = FLAG_FAILURE_UNSUPPORTED_PROFILE; } resultCallback.complete(result); } Loading Loading
core/java/android/security/attestationverification/AttestationVerificationManager.java +57 −45 Original line number Diff line number Diff line Loading @@ -79,9 +79,7 @@ public class AttestationVerificationManager { * is also associated with a particular connection. * * <p>The {@code callback} is called with a result and {@link VerificationToken} (which may be * null). The result is an integer (see constants in this class with the prefix {@code RESULT_}. * The result is {@link #RESULT_SUCCESS} when at least one verifier has passed its checks. The * token may be used in calls to other parts of the system. * null). The result is an integer (see constants in {@link VerificationResultFlags}). * * <p>It's expected that a verifier will be able to decode and understand the passed values, * otherwise fail to verify. {@code attestation} should contain some type data to prevent parse Loading @@ -108,7 +106,7 @@ public class AttestationVerificationManager { @NonNull Bundle requirements, @NonNull byte[] attestation, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<@VerificationResult Integer, VerificationToken> callback) { @NonNull BiConsumer<@VerificationResultFlags Integer, VerificationToken> callback) { try { AndroidFuture<IVerificationResult> resultCallback = new AndroidFuture<>(); resultCallback.thenAccept(result -> { Loading Loading @@ -155,7 +153,7 @@ public class AttestationVerificationManager { */ @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE) @CheckResult @VerificationResult @VerificationResultFlags public int verifyToken( @NonNull AttestationProfile profile, @LocalBindingType int localBindingType, Loading Loading @@ -280,30 +278,66 @@ public class AttestationVerificationManager { */ public static final int TYPE_CHALLENGE = 3; /** @hide */ @IntDef( prefix = {"RESULT_"}, /** * Verification result returned from {@link #verifyAttestation}. * * A value of {@code 0} indicates success. Otherwise, a bit flag is set from first failing stage * below: * <ol> * <li> The received attestation's integrity (e.g. the certificate signatures) is validated. * If this fails, {@link #FLAG_FAILURE_CERTS} will be returned with all other bits unset. * <li> The local binding requirements are checked. If this fails, * {@link #FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS} is returned with all other bits unset. * <li> The profile requirements are checked. If this fails, a bit flag will be returned with * some of the these bits set to indicate the type of profile requirement failure: * {@link #FLAG_FAILURE_UNSUPPORTED_PROFILE}, {@link #FLAG_FAILURE_KEYSTORE_REQUIREMENTS}, * {@link #FLAG_FAILURE_BOOT_STATE}, and {@link #FLAG_FAILURE_PATCH_LEVEL_DIFF}. * </ol> * * Note: The reason of the failure must be not be provided to the remote device. * * @hide */ @IntDef(flag = true, prefix = {"FLAG_FAILURE_"}, value = { RESULT_UNKNOWN, RESULT_SUCCESS, RESULT_FAILURE, FLAG_FAILURE_UNKNOWN, FLAG_FAILURE_UNSUPPORTED_PROFILE, FLAG_FAILURE_CERTS, FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS, FLAG_FAILURE_KEYSTORE_REQUIREMENTS, FLAG_FAILURE_BOOT_STATE, FLAG_FAILURE_PATCH_LEVEL_DIFF, }) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface VerificationResult { } @Retention(RetentionPolicy.SOURCE) public @interface VerificationResultFlags{} /** Flag: If there are unknown failures e.g. runtime exception. 0 = no, 1 = yes. */ public static final int FLAG_FAILURE_UNKNOWN = 1; /** The result of the verification is unknown because it has a value unknown to this SDK. */ public static final int RESULT_UNKNOWN = 0; /** Flag: If the AVF profile is supported. 0 = supported, 1 = not supported */ public static final int FLAG_FAILURE_UNSUPPORTED_PROFILE = 1 << 1; /** * Flag: Result bit for certs verification e.g. loading, generating, parsing certs. * 0 = success, 1 = failure */ public static final int FLAG_FAILURE_CERTS = 1 << 2; /** The result of the verification was successful. */ public static final int RESULT_SUCCESS = 1; /** Flag: Result bit for local binding requirements verification. 0 = success, 1 = failure. */ public static final int FLAG_FAILURE_LOCAL_BINDING_REQUIREMENTS = 1 << 3; /** * The result of the attestation verification was failure. The attestation could not be * verified. * Flag: Result bit for KeyStore requirements verification. * 0 = success, 1 = failure. */ public static final int RESULT_FAILURE = 2; public static final int FLAG_FAILURE_KEYSTORE_REQUIREMENTS = 1 << 4; /** Flag: Result bit for boot state verification. 0 = success, 1 = failure */ public static final int FLAG_FAILURE_BOOT_STATE = 1 << 5; /** Flag: Result bit for patch level diff checks. 0 = success, 1 = failure. */ public static final int FLAG_FAILURE_PATCH_LEVEL_DIFF = 1 << 6; /** * Requirements bundle parameter key for a public key, a byte array. Loading Loading @@ -351,26 +385,4 @@ public class AttestationVerificationManager { } return text + "(" + localBindingType + ")"; } /** @hide */ public static String verificationResultCodeToString(@VerificationResult int resultCode) { final String text; switch (resultCode) { case RESULT_UNKNOWN: text = "UNKNOWN"; break; case RESULT_SUCCESS: text = "SUCCESS"; break; case RESULT_FAILURE: text = "FAILURE"; break; default: return Integer.toString(resultCode); } return text + "(" + resultCode + ")"; } }
core/java/android/security/attestationverification/AttestationVerificationService.java +2 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.annotation.CheckResult; import android.annotation.NonNull; import android.app.Service; import android.os.Bundle; import android.security.attestationverification.AttestationVerificationManager.VerificationResult; import android.security.attestationverification.AttestationVerificationManager.VerificationResultFlags; /** * A verifier which can be implemented by apps to verify an attestation (as described in {@link Loading Loading @@ -93,7 +93,7 @@ public abstract class AttestationVerificationService extends Service { * byte[], java.util.concurrent.Executor, java.util.function.BiConsumer) */ @CheckResult @VerificationResult @VerificationResultFlags public abstract int onVerifyPeerDeviceAttestation( @NonNull Bundle requirements, @NonNull byte[] attestation); Loading
core/java/android/security/attestationverification/VerificationToken.java +63 −142 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/companion/java/com/android/server/companion/securechannel/SecureChannel.java +4 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.companion.securechannel; import static android.security.attestationverification.AttestationVerificationManager.RESULT_SUCCESS; import android.annotation.NonNull; import android.content.Context; import android.os.Build; Loading Loading @@ -498,7 +496,7 @@ public class SecureChannel { private void exchangeAttestation() throws IOException, GeneralSecurityException, BadHandleException, CryptoException { if (mVerificationResult == RESULT_SUCCESS) { if (mVerificationResult == 0) { Slog.d(TAG, "Remote attestation was already verified."); return; } Loading Loading @@ -530,11 +528,11 @@ public class SecureChannel { sendMessage(MessageType.AVF_RESULT, verificationResult); byte[] remoteVerificationResult = readMessage(MessageType.AVF_RESULT); if (ByteBuffer.wrap(remoteVerificationResult).getInt() != RESULT_SUCCESS) { if (ByteBuffer.wrap(remoteVerificationResult).getInt() != 0) { throw new SecureChannelException("Remote device failed to verify local attestation."); } if (mVerificationResult != RESULT_SUCCESS) { if (mVerificationResult != 0) { throw new SecureChannelException("Failed to verify remote attestation."); } Loading @@ -549,7 +547,7 @@ public class SecureChannel { return false; } // Is authenticated return mPskVerified || mVerificationResult == RESULT_SUCCESS; return mPskVerified || mVerificationResult == 0; } // First byte indicates message type; 0 = CLIENT INIT, 1 = SERVER INIT Loading
services/core/java/com/android/server/security/AttestationVerificationManagerService.java +9 −9 Original line number Diff line number Diff line Loading @@ -17,10 +17,10 @@ package com.android.server.security; import static android.Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE; import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_CERTS; import static android.security.attestationverification.AttestationVerificationManager.FLAG_FAILURE_UNSUPPORTED_PROFILE; import static android.security.attestationverification.AttestationVerificationManager.PROFILE_PEER_DEVICE; import static android.security.attestationverification.AttestationVerificationManager.PROFILE_SELF_TRUSTED; import static android.security.attestationverification.AttestationVerificationManager.RESULT_FAILURE; import static android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -88,8 +88,8 @@ public class AttestationVerificationManagerService extends SystemService { public void verifyToken(VerificationToken token, ParcelDuration parcelDuration, AndroidFuture resultCallback) throws RemoteException { enforceUsePermission(); // TODO(b/201696614): Implement resultCallback.complete(RESULT_UNKNOWN); throw new UnsupportedOperationException(); } private void enforceUsePermission() { Loading Loading @@ -123,9 +123,9 @@ public class AttestationVerificationManagerService extends SystemService { AttestationProfile profile, int localBindingType, Bundle requirements, byte[] attestation, AndroidFuture<IVerificationResult> resultCallback) { IVerificationResult result = new IVerificationResult(); // TODO(b/201696614): Implement result.token = null; switch (profile.getAttestationProfileId()) { int profileId = profile.getAttestationProfileId(); switch (profileId) { case PROFILE_SELF_TRUSTED: Slog.d(TAG, "Verifying Self Trusted profile."); try { Loading @@ -133,7 +133,7 @@ public class AttestationVerificationManagerService extends SystemService { AttestationVerificationSelfTrustedVerifierForTesting.getInstance() .verifyAttestation(localBindingType, requirements, attestation); } catch (Throwable t) { result.resultCode = RESULT_FAILURE; result.resultCode = FLAG_FAILURE_CERTS; } break; case PROFILE_PEER_DEVICE: Loading @@ -142,8 +142,8 @@ public class AttestationVerificationManagerService extends SystemService { localBindingType, requirements, attestation); break; default: Slog.d(TAG, "No profile found, defaulting."); result.resultCode = RESULT_UNKNOWN; Slog.e(TAG, "Profile [" + profileId + "] is not supported."); result.resultCode = FLAG_FAILURE_UNSUPPORTED_PROFILE; } resultCallback.complete(result); } Loading