Merge "Update Keystore with new fields for API V3"

This commit is contained in:
Shaquille Johnson
2022-12-06 17:46:46 +00:00
committed by Gerrit Code Review
4 changed files with 47 additions and 5 deletions

View File

@@ -105,7 +105,7 @@ filegroup {
":android.security.legacykeystore-java-source", ":android.security.legacykeystore-java-source",
":android.security.maintenance-java-source", ":android.security.maintenance-java-source",
":android.security.metrics-java-source", ":android.security.metrics-java-source",
":android.system.keystore2-V1-java-source", ":android.system.keystore2-V3-java-source",
":credstore_aidl", ":credstore_aidl",
":dumpstate_aidl", ":dumpstate_aidl",
":framework_native_aidl", ":framework_native_aidl",

View File

@@ -37605,6 +37605,7 @@ package android.security {
field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5 field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5
field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc
field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2 field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2
field public static final int RETRY_AFTER_NEXT_REBOOT = 4; // 0x4
field public static final int RETRY_NEVER = 1; // 0x1 field public static final int RETRY_NEVER = 1; // 0x1
field public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3; // 0x3 field public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3; // 0x3
field public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2; // 0x2 field public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2; // 0x2

View File

@@ -138,6 +138,16 @@ public class KeyStoreException extends Exception {
* provisioning server refuses key issuance, this is a permanent error.</p> * provisioning server refuses key issuance, this is a permanent error.</p>
*/ */
public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16; public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16;
/**
* This device requires a software upgrade to use the key provisioning server. The software
* is outdated and this error is returned only on devices that rely solely on
* remotely-provisioned keys (see <a href=
* "https://android-developers.googleblog.com/2022/03/upgrading-android-attestation-remote.html"
* >Remote Key Provisioning</a>).
*
* @hide
*/
public static final int ERROR_DEVICE_REQUIRES_UPGRADE_FOR_ATTESTATION = 17;
/** @hide */ /** @hide */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@@ -157,7 +167,8 @@ public class KeyStoreException extends Exception {
ERROR_INCORRECT_USAGE, ERROR_INCORRECT_USAGE,
ERROR_KEY_NOT_TEMPORALLY_VALID, ERROR_KEY_NOT_TEMPORALLY_VALID,
ERROR_KEY_OPERATION_EXPIRED, ERROR_KEY_OPERATION_EXPIRED,
ERROR_ATTESTATION_KEYS_UNAVAILABLE ERROR_ATTESTATION_KEYS_UNAVAILABLE,
ERROR_DEVICE_REQUIRES_UPGRADE_FOR_ATTESTATION,
}) })
public @interface PublicErrorCode { public @interface PublicErrorCode {
} }
@@ -184,6 +195,16 @@ public class KeyStoreException extends Exception {
* This value is returned when {@link #isTransientFailure()} is {@code true}. * This value is returned when {@link #isTransientFailure()} is {@code true}.
*/ */
public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3; public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3;
/**
* Re-try the operation that led to this error when the device has a software update
* downloaded and on the next reboot. The Remote provisioning server recognizes
* the device, but refuses issuance of attestation keys because it contains a software
* version that could potentially be vulnerable and needs an update. Re-trying after the
* device has upgraded and rebooted may alleviate the problem.
*
* <p>This value is returned when {@link #isTransientFailure()} is {@code true}.
*/
public static final int RETRY_AFTER_NEXT_REBOOT = 4;
/** @hide */ /** @hide */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@@ -191,6 +212,7 @@ public class KeyStoreException extends Exception {
RETRY_NEVER, RETRY_NEVER,
RETRY_WITH_EXPONENTIAL_BACKOFF, RETRY_WITH_EXPONENTIAL_BACKOFF,
RETRY_WHEN_CONNECTIVITY_AVAILABLE, RETRY_WHEN_CONNECTIVITY_AVAILABLE,
RETRY_AFTER_NEXT_REBOOT,
}) })
public @interface RetryPolicy { public @interface RetryPolicy {
} }
@@ -217,6 +239,13 @@ public class KeyStoreException extends Exception {
* when the device has connectivity again. * when the device has connectivity again.
* @hide */ * @hide */
public static final int RKP_FETCHING_PENDING_CONNECTIVITY = 3; public static final int RKP_FETCHING_PENDING_CONNECTIVITY = 3;
/**
* The RKP server recognizes the device, but the device may be running vulnerable software,
* and thus refusing issuance of RKP keys to it.
*
* @hide
*/
public static final int RKP_FETCHING_PENDING_SOFTWARE_REBOOT = 4;
// Constants for encoding information about the error encountered: // Constants for encoding information about the error encountered:
// Whether the error relates to the system state/implementation as a whole, or a specific key. // Whether the error relates to the system state/implementation as a whole, or a specific key.
@@ -236,7 +265,7 @@ public class KeyStoreException extends Exception {
private static int initializeRkpStatusForRegularErrors(int errorCode) { private static int initializeRkpStatusForRegularErrors(int errorCode) {
// Check if the system code mistakenly called a constructor of KeyStoreException with // Check if the system code mistakenly called a constructor of KeyStoreException with
// the OUT_OF_KEYS error code but without RKP status. // the OUT_OF_KEYS error code but without RKP status.
if (errorCode == ResponseCode.OUT_OF_KEYS) { if (isRkpRelatedError(errorCode)) {
Log.e(TAG, "RKP error code without RKP status"); Log.e(TAG, "RKP error code without RKP status");
// Set RKP status to RKP_SERVER_REFUSED_ISSUANCE so that the caller never retries. // Set RKP status to RKP_SERVER_REFUSED_ISSUANCE so that the caller never retries.
return RKP_SERVER_REFUSED_ISSUANCE; return RKP_SERVER_REFUSED_ISSUANCE;
@@ -272,7 +301,7 @@ public class KeyStoreException extends Exception {
super(message); super(message);
mErrorCode = errorCode; mErrorCode = errorCode;
mRkpStatus = rkpStatus; mRkpStatus = rkpStatus;
if (mErrorCode != ResponseCode.OUT_OF_KEYS) { if (!isRkpRelatedError(mErrorCode)) {
Log.e(TAG, "Providing RKP status for error code " + errorCode + " has no effect."); Log.e(TAG, "Providing RKP status for error code " + errorCode + " has no effect.");
} }
} }
@@ -309,10 +338,11 @@ public class KeyStoreException extends Exception {
public boolean isTransientFailure() { public boolean isTransientFailure() {
PublicErrorInformation failureInfo = getErrorInformation(mErrorCode); PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
// Special-case handling for RKP failures: // Special-case handling for RKP failures:
if (mRkpStatus != RKP_SUCCESS && mErrorCode == ResponseCode.OUT_OF_KEYS) { if (mRkpStatus != RKP_SUCCESS && isRkpRelatedError(mErrorCode)) {
switch (mRkpStatus) { switch (mRkpStatus) {
case RKP_TEMPORARILY_UNAVAILABLE: case RKP_TEMPORARILY_UNAVAILABLE:
case RKP_FETCHING_PENDING_CONNECTIVITY: case RKP_FETCHING_PENDING_CONNECTIVITY:
case RKP_FETCHING_PENDING_SOFTWARE_REBOOT:
return true; return true;
case RKP_SERVER_REFUSED_ISSUANCE: case RKP_SERVER_REFUSED_ISSUANCE:
default: default:
@@ -346,6 +376,11 @@ public class KeyStoreException extends Exception {
return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0; return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0;
} }
private static boolean isRkpRelatedError(int errorCode) {
return errorCode == ResponseCode.OUT_OF_KEYS
|| errorCode == ResponseCode.OUT_OF_KEYS_REQUIRES_UPGRADE;
}
/** /**
* Returns the re-try policy for transient failures. Valid only if * Returns the re-try policy for transient failures. Valid only if
* {@link #isTransientFailure()} returns {@code True}. * {@link #isTransientFailure()} returns {@code True}.
@@ -362,6 +397,8 @@ public class KeyStoreException extends Exception {
return RETRY_WHEN_CONNECTIVITY_AVAILABLE; return RETRY_WHEN_CONNECTIVITY_AVAILABLE;
case RKP_SERVER_REFUSED_ISSUANCE: case RKP_SERVER_REFUSED_ISSUANCE:
return RETRY_NEVER; return RETRY_NEVER;
case RKP_FETCHING_PENDING_SOFTWARE_REBOOT:
return RETRY_AFTER_NEXT_REBOOT;
default: default:
return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0 return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0
? RETRY_WITH_EXPONENTIAL_BACKOFF : RETRY_NEVER; ? RETRY_WITH_EXPONENTIAL_BACKOFF : RETRY_NEVER;
@@ -620,5 +657,8 @@ public class KeyStoreException extends Exception {
new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST)); new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
sErrorCodeToFailureInfo.put(ResponseCode.OUT_OF_KEYS, sErrorCodeToFailureInfo.put(ResponseCode.OUT_OF_KEYS,
new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_ATTESTATION_KEYS_UNAVAILABLE)); new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_ATTESTATION_KEYS_UNAVAILABLE));
sErrorCodeToFailureInfo.put(ResponseCode.OUT_OF_KEYS_REQUIRES_UPGRADE,
new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR,
ERROR_DEVICE_REQUIRES_UPGRADE_FOR_ATTESTATION));
} }
} }

View File

@@ -648,6 +648,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
// {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE}, // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE},
// {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE}, // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE},
// {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY} // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY}
// {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_SOFTWARE_REBOOT}
public final int rkpStatus; public final int rkpStatus;
@Nullable @Nullable
public final KeyPair keyPair; public final KeyPair keyPair;