blob: e459f288b4c0e24fe206654c659ea26121c5c605 [file] [log] [blame]
/*
* Copyright (C) 2017 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 com.android.server.locksettings.recoverablekeystore;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.security.recoverablekeystore.KeyEntryRecoveryData;
import android.security.recoverablekeystore.KeyStoreRecoveryData;
import android.security.recoverablekeystore.KeyStoreRecoveryMetadata;
import android.security.recoverablekeystore.RecoverableKeyStoreLoader;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
/**
* Class with {@link RecoverableKeyStoreLoader} API implementation and internal methods to interact
* with {@code LockSettingsService}.
*
* @hide
*/
public class RecoverableKeyStoreManager {
private static final String TAG = "RecoverableKeyStoreManager";
private static RecoverableKeyStoreManager mInstance;
private Context mContext;
/**
* Returns a new or existing instance.
*
* @hide
*/
public static synchronized RecoverableKeyStoreManager getInstance(Context mContext) {
if (mInstance == null) {
mInstance = new RecoverableKeyStoreManager(mContext);
}
return mInstance;
}
@VisibleForTesting
RecoverableKeyStoreManager(Context context) {
mContext = context;
}
public int initRecoveryService(
@NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList, int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
// TODO open /system/etc/security/... cert file
throw new UnsupportedOperationException();
}
/**
* Gets all data necessary to recover application keys on new device.
*
* @return recovery data
* @hide
*/
public KeyStoreRecoveryData getRecoveryData(@NonNull byte[] account, int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
final int callingUid = Binder.getCallingUid(); // Recovery agent uid.
final int callingUserId = UserHandle.getCallingUserId();
final long callingIdentiy = Binder.clearCallingIdentity();
try {
// TODO: Return the latest snapshot for the calling recovery agent.
} finally {
Binder.restoreCallingIdentity(callingIdentiy);
}
// KeyStoreRecoveryData without application keys and empty recovery blob.
KeyStoreRecoveryData recoveryData =
new KeyStoreRecoveryData(
/*snapshotVersion=*/ 1,
new ArrayList<KeyStoreRecoveryMetadata>(),
new ArrayList<KeyEntryRecoveryData>(),
/*encryptedRecoveryKeyBlob=*/ new byte[] {});
throw new ServiceSpecificException(
RecoverableKeyStoreLoader.UNINITIALIZED_RECOVERY_PUBLIC_KEY);
}
public void setServerParameters(long serverParameters, int userId) throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
public void setRecoveryStatus(
@NonNull String packageName, @Nullable String[] aliases, int status, int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
/**
* Sets recovery secrets list used by all recovery agents for given {@code userId}
*
* @hide
*/
public void setRecoverySecretTypes(
@NonNull @KeyStoreRecoveryMetadata.UserSecretType int[] secretTypes, int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
/**
* Gets secret types necessary to create Recovery Data.
*
* @return secret types
* @hide
*/
public int[] getRecoverySecretTypes(int userId) throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
/**
* Gets secret types RecoverableKeyStoreLoaders is waiting for to create new Recovery Data.
*
* @return secret types
* @hide
*/
public int[] getPendingRecoverySecretTypes(int userId) throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
public void recoverySecretAvailable(
@NonNull KeyStoreRecoveryMetadata recoverySecret, int userId) throws RemoteException {
final int callingUid = Binder.getCallingUid(); // Recovery agent uid.
if (recoverySecret.getLockScreenUiFormat() == KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN) {
throw new SecurityException(
"Caller " + callingUid + "is not allowed to set lock screen secret");
}
checkRecoverKeyStorePermission();
// TODO: add hook from LockSettingsService to set lock screen secret.
throw new UnsupportedOperationException();
}
/**
* Initializes recovery session.
*
* @return recovery claim
* @hide
*/
public byte[] startRecoverySession(
@NonNull String sessionId,
@NonNull byte[] verifierPublicKey,
@NonNull byte[] vaultParams,
@NonNull byte[] vaultChallenge,
@NonNull List<KeyStoreRecoveryMetadata> secrets,
int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
public void recoverKeys(
@NonNull String sessionId,
@NonNull byte[] recoveryKeyBlob,
@NonNull List<KeyEntryRecoveryData> applicationKeys,
int userId)
throws RemoteException {
checkRecoverKeyStorePermission();
throw new UnsupportedOperationException();
}
/** This function can only be used inside LockSettingsService. */
public void lockScreenSecretAvailable(
@KeyStoreRecoveryMetadata.LockScreenUiFormat int type,
String unencryptedPassword,
int userId) {
// TODO: compute SHA256 or Argon2id depending on secret type.
throw new UnsupportedOperationException();
}
/** This function can only be used inside LockSettingsService. */
public void lockScreenSecretChanged(
@KeyStoreRecoveryMetadata.LockScreenUiFormat int type,
@Nullable String unencryptedPassword,
int userId) {
throw new UnsupportedOperationException();
}
private void checkRecoverKeyStorePermission() {
mContext.enforceCallingOrSelfPermission(
RecoverableKeyStoreLoader.PERMISSION_RECOVER_KEYSTORE,
"Caller " + Binder.getCallingUid() + " doesn't have RecoverKeyStore permission.");
}
}