Merge "Multi-threaded keystore" am: 9f248989bf am: cbd890315e
am: 444162a57c
Change-Id: I2c09961a74c7de92d85f3d2045dd065c94bc6fac
This commit is contained in:
@@ -1320,18 +1320,6 @@ Landroid/R$styleable;->Window_windowFrame:I
|
||||
Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
|
||||
Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
|
||||
Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
|
||||
Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
|
||||
Landroid/security/IKeystoreService;->clear_uid(J)I
|
||||
Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
|
||||
Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
|
||||
Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
|
||||
Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
|
||||
Landroid/security/IKeystoreService;->getState(I)I
|
||||
Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
|
||||
Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
|
||||
Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
|
||||
Landroid/security/IKeystoreService;->reset()I
|
||||
Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
|
||||
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
|
||||
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
|
||||
Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
|
||||
@@ -1343,6 +1331,17 @@ Landroid/security/keymaster/KeymasterIntArgument;->value:I
|
||||
Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
|
||||
Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
|
||||
Landroid/security/keymaster/KeymasterLongArgument;->value:J
|
||||
Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
|
||||
Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
|
||||
Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
|
||||
Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
|
||||
Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
|
||||
Landroid/security/keystore/IKeystoreService;->getState(I)I
|
||||
Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
|
||||
Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
|
||||
Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
|
||||
Landroid/security/keystore/IKeystoreService;->reset()I
|
||||
Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
|
||||
Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
|
||||
Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
|
||||
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
|
||||
|
||||
@@ -28,6 +28,11 @@ public class ExportResult implements Parcelable {
|
||||
public final int resultCode;
|
||||
public final byte[] exportData;
|
||||
|
||||
public ExportResult(int resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
this.exportData = new byte[0];
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public static final Parcelable.Creator<ExportResult> CREATOR = new
|
||||
Parcelable.Creator<ExportResult>() {
|
||||
|
||||
@@ -52,6 +52,14 @@ public class KeyCharacteristics implements Parcelable {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a shallow copy of other by copying the other's references to the KeymasterArguments
|
||||
*/
|
||||
public void shallowCopyFrom(KeyCharacteristics other) {
|
||||
this.swEnforced = other.swEnforced;
|
||||
this.hwEnforced = other.hwEnforced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
||||
@@ -54,6 +54,14 @@ public class KeymasterCertificateChain implements Parcelable {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a shallow copy of other by copying the reference to the certificate chain list.
|
||||
* @param other
|
||||
*/
|
||||
public void shallowCopyFrom(KeymasterCertificateChain other) {
|
||||
this.mCertificates = other.mCertificates;
|
||||
}
|
||||
|
||||
public List<byte[]> getCertificates() {
|
||||
return mCertificates;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ public class OperationResult implements Parcelable {
|
||||
this.outParams = outParams;
|
||||
}
|
||||
|
||||
public OperationResult(int resultCode) {
|
||||
this(resultCode, null, 0, 0, null, null);
|
||||
}
|
||||
|
||||
protected OperationResult(Parcel in) {
|
||||
resultCode = in.readInt();
|
||||
token = in.readStrongBinder();
|
||||
|
||||
@@ -38,11 +38,13 @@ import android.security.keymaster.KeymasterBlob;
|
||||
import android.security.keymaster.KeymasterCertificateChain;
|
||||
import android.security.keymaster.KeymasterDefs;
|
||||
import android.security.keymaster.OperationResult;
|
||||
import android.security.keystore.IKeystoreService;
|
||||
import android.security.keystore.KeyExpiredException;
|
||||
import android.security.keystore.KeyNotYetValidException;
|
||||
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.security.keystore.KeyProtection;
|
||||
import android.security.keystore.KeystoreResponse;
|
||||
import android.security.keystore.StrongBoxUnavailableException;
|
||||
import android.security.keystore.UserNotAuthenticatedException;
|
||||
import android.util.Log;
|
||||
@@ -54,6 +56,8 @@ import java.io.IOException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
|
||||
@@ -451,27 +455,107 @@ public class KeyStore {
|
||||
|
||||
public boolean addRngEntropy(byte[] data, int flags) {
|
||||
try {
|
||||
return mBinder.addRngEntropy(data, flags) == NO_ERROR;
|
||||
KeystoreResultPromise promise = new KeystoreResultPromise();
|
||||
int errorCode = mBinder.addRngEntropy(promise, data, flags);
|
||||
if (errorCode == NO_ERROR) {
|
||||
return promise.getFuture().get().getErrorCode() == NO_ERROR;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return false;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "AddRngEntropy completed with exception", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyCharacteristicsCallbackResult {
|
||||
private KeystoreResponse keystoreResponse;
|
||||
private KeyCharacteristics keyCharacteristics;
|
||||
|
||||
public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
|
||||
KeyCharacteristics keyCharacteristics) {
|
||||
this.keystoreResponse = keystoreResponse;
|
||||
this.keyCharacteristics = keyCharacteristics;
|
||||
}
|
||||
|
||||
public KeystoreResponse getKeystoreResponse() {
|
||||
return keystoreResponse;
|
||||
}
|
||||
|
||||
public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
|
||||
this.keystoreResponse = keystoreResponse;
|
||||
}
|
||||
|
||||
public KeyCharacteristics getKeyCharacteristics() {
|
||||
return keyCharacteristics;
|
||||
}
|
||||
|
||||
public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
|
||||
this.keyCharacteristics = keyCharacteristics;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyCharacteristicsPromise
|
||||
extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
|
||||
final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
|
||||
new CompletableFuture<KeyCharacteristicsCallbackResult>();
|
||||
@Override
|
||||
public void onFinished(KeystoreResponse keystoreResponse,
|
||||
KeyCharacteristics keyCharacteristics)
|
||||
throws android.os.RemoteException {
|
||||
future.complete(
|
||||
new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
|
||||
}
|
||||
public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
|
||||
int flags, KeyCharacteristics outCharacteristics)
|
||||
throws RemoteException, ExecutionException, InterruptedException {
|
||||
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
|
||||
int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
|
||||
if (error != NO_ERROR) {
|
||||
Log.e(TAG, "generateKeyInternal failed on request " + error);
|
||||
return error;
|
||||
}
|
||||
|
||||
KeyCharacteristicsCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error != NO_ERROR) {
|
||||
Log.e(TAG, "generateKeyInternal failed on response " + error);
|
||||
return error;
|
||||
}
|
||||
KeyCharacteristics characteristics = result.getKeyCharacteristics();
|
||||
if (characteristics == null) {
|
||||
Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
outCharacteristics.shallowCopyFrom(characteristics);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
|
||||
int flags, KeyCharacteristics outCharacteristics) {
|
||||
try {
|
||||
entropy = entropy != null ? entropy : new byte[0];
|
||||
args = args != null ? args : new KeymasterArguments();
|
||||
int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
|
||||
int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
|
||||
if (error == KEY_ALREADY_EXISTS) {
|
||||
mBinder.del(alias, uid);
|
||||
error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
|
||||
error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
|
||||
}
|
||||
return error;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "generateKey completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,10 +569,24 @@ public class KeyStore {
|
||||
try {
|
||||
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
|
||||
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
|
||||
return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
|
||||
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
|
||||
int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristicsCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristics characteristics = result.getKeyCharacteristics();
|
||||
if (characteristics == null) return SYSTEM_ERROR;
|
||||
outCharacteristics.shallowCopyFrom(characteristics);
|
||||
return NO_ERROR;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,20 +595,40 @@ public class KeyStore {
|
||||
return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
|
||||
}
|
||||
|
||||
private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
|
||||
int uid, int flags, KeyCharacteristics outCharacteristics)
|
||||
throws RemoteException, ExecutionException, InterruptedException {
|
||||
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
|
||||
int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristicsCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristics characteristics = result.getKeyCharacteristics();
|
||||
if (characteristics == null) return SYSTEM_ERROR;
|
||||
outCharacteristics.shallowCopyFrom(characteristics);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
|
||||
int uid, int flags, KeyCharacteristics outCharacteristics) {
|
||||
try {
|
||||
int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
|
||||
int error = importKeyInternal(alias, args, format, keyData, uid, flags,
|
||||
outCharacteristics);
|
||||
if (error == KEY_ALREADY_EXISTS) {
|
||||
mBinder.del(alias, uid);
|
||||
error = mBinder.importKey(alias, args, format, keyData, uid, flags,
|
||||
error = importKeyInternal(alias, args, format, keyData, uid, flags,
|
||||
outCharacteristics);
|
||||
}
|
||||
return error;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "ImportKey completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,34 +696,79 @@ public class KeyStore {
|
||||
return true;
|
||||
}
|
||||
|
||||
private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
|
||||
String wrappingKeyAlias,
|
||||
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
|
||||
KeyCharacteristics outCharacteristics)
|
||||
throws RemoteException, ExecutionException, InterruptedException {
|
||||
KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
|
||||
int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
|
||||
maskingKey, args, rootSid, fingerprintSid);
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristicsCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error != NO_ERROR) return error;
|
||||
|
||||
KeyCharacteristics characteristics = result.getKeyCharacteristics();
|
||||
if (characteristics == null) return SYSTEM_ERROR;
|
||||
outCharacteristics.shallowCopyFrom(characteristics);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
|
||||
String wrappingKeyAlias,
|
||||
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
|
||||
KeyCharacteristics outCharacteristics) {
|
||||
// TODO b/119217337 uid parameter gets silently ignored.
|
||||
try {
|
||||
int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
|
||||
int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
|
||||
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
|
||||
if (error == KEY_ALREADY_EXISTS) {
|
||||
mBinder.del(wrappedKeyAlias, -1);
|
||||
error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
|
||||
mBinder.del(wrappedKeyAlias, UID_SELF);
|
||||
error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
|
||||
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
|
||||
}
|
||||
return error;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "ImportWrappedKey completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
private class ExportKeyPromise
|
||||
extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
|
||||
final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
|
||||
@Override
|
||||
public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
|
||||
future.complete(exportKeyResult);
|
||||
}
|
||||
public final CompletableFuture<ExportResult> getFuture() {
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
|
||||
KeymasterBlob appId, int uid) {
|
||||
try {
|
||||
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
|
||||
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
|
||||
return mBinder.exportKey(alias, format, clientId, appId, uid);
|
||||
ExportKeyPromise promise = new ExportKeyPromise();
|
||||
int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
|
||||
if (error == NO_ERROR) {
|
||||
return promise.getFuture().get();
|
||||
} else {
|
||||
return new ExportResult(error);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return null;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "ExportKey completed with exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
|
||||
@@ -613,15 +776,37 @@ public class KeyStore {
|
||||
return exportKey(alias, format, clientId, appId, UID_SELF);
|
||||
}
|
||||
|
||||
private class OperationPromise
|
||||
extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
|
||||
final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
|
||||
@Override
|
||||
public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
|
||||
future.complete(operationResult);
|
||||
}
|
||||
public final CompletableFuture<OperationResult> getFuture() {
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
public OperationResult begin(String alias, int purpose, boolean pruneable,
|
||||
KeymasterArguments args, byte[] entropy, int uid) {
|
||||
try {
|
||||
args = args != null ? args : new KeymasterArguments();
|
||||
entropy = entropy != null ? entropy : new byte[0];
|
||||
return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
|
||||
OperationPromise promise = new OperationPromise();
|
||||
int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
|
||||
entropy, uid);
|
||||
if (errorCode == NO_ERROR) {
|
||||
return promise.getFuture().get();
|
||||
} else {
|
||||
return new OperationResult(errorCode);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return null;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "Begin completed with exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,10 +821,19 @@ public class KeyStore {
|
||||
try {
|
||||
arguments = arguments != null ? arguments : new KeymasterArguments();
|
||||
input = input != null ? input : new byte[0];
|
||||
return mBinder.update(token, arguments, input);
|
||||
OperationPromise promise = new OperationPromise();
|
||||
int errorCode = mBinder.update(promise, token, arguments, input);
|
||||
if (errorCode == NO_ERROR) {
|
||||
return promise.getFuture().get();
|
||||
} else {
|
||||
return new OperationResult(errorCode);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return null;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "Update completed with exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,10 +843,19 @@ public class KeyStore {
|
||||
arguments = arguments != null ? arguments : new KeymasterArguments();
|
||||
entropy = entropy != null ? entropy : new byte[0];
|
||||
signature = signature != null ? signature : new byte[0];
|
||||
return mBinder.finish(token, arguments, signature, entropy);
|
||||
OperationPromise promise = new OperationPromise();
|
||||
int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
|
||||
if (errorCode == NO_ERROR) {
|
||||
return promise.getFuture().get();
|
||||
} else {
|
||||
return new OperationResult(errorCode);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return null;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "Finish completed with exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,12 +863,33 @@ public class KeyStore {
|
||||
return finish(token, arguments, signature, null);
|
||||
}
|
||||
|
||||
private class KeystoreResultPromise
|
||||
extends android.security.keystore.IKeystoreResponseCallback.Stub {
|
||||
final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
|
||||
@Override
|
||||
public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
|
||||
future.complete(keystoreResponse);
|
||||
}
|
||||
public final CompletableFuture<KeystoreResponse> getFuture() {
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
public int abort(IBinder token) {
|
||||
try {
|
||||
return mBinder.abort(token);
|
||||
KeystoreResultPromise promise = new KeystoreResultPromise();
|
||||
int errorCode = mBinder.abort(promise, token);
|
||||
if (errorCode == NO_ERROR) {
|
||||
return promise.getFuture().get().getErrorCode();
|
||||
} else {
|
||||
return errorCode;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "Abort completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,6 +971,47 @@ public class KeyStore {
|
||||
return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
|
||||
}
|
||||
|
||||
private class KeyAttestationCallbackResult {
|
||||
private KeystoreResponse keystoreResponse;
|
||||
private KeymasterCertificateChain certificateChain;
|
||||
|
||||
public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
|
||||
KeymasterCertificateChain certificateChain) {
|
||||
this.keystoreResponse = keystoreResponse;
|
||||
this.certificateChain = certificateChain;
|
||||
}
|
||||
|
||||
public KeystoreResponse getKeystoreResponse() {
|
||||
return keystoreResponse;
|
||||
}
|
||||
|
||||
public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
|
||||
this.keystoreResponse = keystoreResponse;
|
||||
}
|
||||
|
||||
public KeymasterCertificateChain getCertificateChain() {
|
||||
return certificateChain;
|
||||
}
|
||||
|
||||
public void setCertificateChain(KeymasterCertificateChain certificateChain) {
|
||||
this.certificateChain = certificateChain;
|
||||
}
|
||||
}
|
||||
|
||||
private class CertificateChainPromise
|
||||
extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
|
||||
final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
|
||||
@Override
|
||||
public void onFinished(KeystoreResponse keystoreResponse,
|
||||
KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
|
||||
future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
|
||||
}
|
||||
public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
|
||||
return future;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public int attestKey(
|
||||
String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
|
||||
try {
|
||||
@@ -756,10 +1021,21 @@ public class KeyStore {
|
||||
if (outChain == null) {
|
||||
outChain = new KeymasterCertificateChain();
|
||||
}
|
||||
return mBinder.attestKey(alias, params, outChain);
|
||||
CertificateChainPromise promise = new CertificateChainPromise();
|
||||
int error = mBinder.attestKey(promise, alias, params);
|
||||
if (error != NO_ERROR) return error;
|
||||
KeyAttestationCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error == NO_ERROR) {
|
||||
outChain.shallowCopyFrom(result.getCertificateChain());
|
||||
}
|
||||
return error;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "AttestKey completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,10 +1047,21 @@ public class KeyStore {
|
||||
if (outChain == null) {
|
||||
outChain = new KeymasterCertificateChain();
|
||||
}
|
||||
return mBinder.attestDeviceIds(params, outChain);
|
||||
CertificateChainPromise promise = new CertificateChainPromise();
|
||||
int error = mBinder.attestDeviceIds(promise, params);
|
||||
if (error != NO_ERROR) return error;
|
||||
KeyAttestationCallbackResult result = promise.getFuture().get();
|
||||
error = result.getKeystoreResponse().getErrorCode();
|
||||
if (error == NO_ERROR) {
|
||||
outChain.shallowCopyFrom(result.getCertificateChain());
|
||||
}
|
||||
return error;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Cannot connect to keystore", e);
|
||||
return SYSTEM_ERROR;
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Log.e(TAG, "AttestDevicdeIds completed with exception", e);
|
||||
return SYSTEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.security.keystore;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ParcelFormatException;
|
||||
|
||||
/**
|
||||
* The Java side of the KeystoreResponse.
|
||||
* <p>
|
||||
* Serialization code for this and subclasses must be kept in sync with system/security/keystore.
|
||||
* @hide
|
||||
*/
|
||||
public class KeystoreResponse implements Parcelable {
|
||||
public final int error_code_;
|
||||
public final String error_msg_;
|
||||
|
||||
public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
|
||||
Parcelable.Creator<KeystoreResponse>() {
|
||||
@Override
|
||||
public KeystoreResponse createFromParcel(Parcel in) {
|
||||
final int error_code = in.readInt();
|
||||
final String error_msg = in.readString();
|
||||
return new KeystoreResponse(error_code, error_msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeystoreResponse[] newArray(int size) {
|
||||
return new KeystoreResponse[size];
|
||||
}
|
||||
};
|
||||
|
||||
protected KeystoreResponse(int error_code, String error_msg) {
|
||||
this.error_code_ = error_code;
|
||||
this.error_msg_ = error_msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the error_code_
|
||||
*/
|
||||
public final int getErrorCode() {
|
||||
return error_code_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the error_msg_
|
||||
*/
|
||||
public final String getErrorMessage() {
|
||||
return error_msg_;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(error_code_);
|
||||
out.writeString(error_msg_);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.security.IKeystoreService;
|
||||
import android.security.keystore.IKeystoreService;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.policy.IKeyguardService;
|
||||
|
||||
Reference in New Issue
Block a user