Merge "Support default, pattern, pin and password encryption types"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a9f387bdf0
@@ -642,12 +642,13 @@ public interface IMountService extends IInterface {
|
||||
return _result;
|
||||
}
|
||||
|
||||
public int changeEncryptionPassword(String password) throws RemoteException {
|
||||
public int changeEncryptionPassword(int type, String password) throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
int _result;
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
_data.writeInt(type);
|
||||
_data.writeString(password);
|
||||
mRemote.transact(Stub.TRANSACTION_changeEncryptionPassword, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
@@ -677,6 +678,22 @@ public interface IMountService extends IInterface {
|
||||
return _result;
|
||||
}
|
||||
|
||||
public int getPasswordType() throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
int _result;
|
||||
try {
|
||||
_data.writeInterfaceToken(DESCRIPTOR);
|
||||
mRemote.transact(Stub.TRANSACTION_getPasswordType, _data, _reply, 0);
|
||||
_reply.readException();
|
||||
_result = _reply.readInt();
|
||||
} finally {
|
||||
_reply.recycle();
|
||||
_data.recycle();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
public StorageVolume[] getVolumeList() throws RemoteException {
|
||||
Parcel _data = Parcel.obtain();
|
||||
Parcel _reply = Parcel.obtain();
|
||||
@@ -829,6 +846,8 @@ public interface IMountService extends IInterface {
|
||||
|
||||
static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
|
||||
|
||||
static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 36;
|
||||
|
||||
/**
|
||||
* Cast an IBinder object into an IMountService interface, generating a
|
||||
* proxy if needed.
|
||||
@@ -1130,8 +1149,9 @@ public interface IMountService extends IInterface {
|
||||
}
|
||||
case TRANSACTION_changeEncryptionPassword: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
int type = data.readInt();
|
||||
String password = data.readString();
|
||||
int result = changeEncryptionPassword(password);
|
||||
int result = changeEncryptionPassword(type, password);
|
||||
reply.writeNoException();
|
||||
reply.writeInt(result);
|
||||
return true;
|
||||
@@ -1181,6 +1201,13 @@ public interface IMountService extends IInterface {
|
||||
reply.writeInt(result);
|
||||
return true;
|
||||
}
|
||||
case TRANSACTION_getPasswordType: {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
int result = getPasswordType();
|
||||
reply.writeNoException();
|
||||
reply.writeInt(result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
@@ -1375,7 +1402,8 @@ public interface IMountService extends IInterface {
|
||||
/**
|
||||
* Changes the encryption password.
|
||||
*/
|
||||
public int changeEncryptionPassword(String password) throws RemoteException;
|
||||
public int changeEncryptionPassword(int type, String password)
|
||||
throws RemoteException;
|
||||
|
||||
/**
|
||||
* Verify the encryption password against the stored volume. This method
|
||||
@@ -1412,4 +1440,10 @@ public interface IMountService extends IInterface {
|
||||
* external storage data or OBB directory belonging to calling app.
|
||||
*/
|
||||
public int mkdirs(String callingPkg, String path) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Determines the type of the encryption password
|
||||
* @return PasswordType
|
||||
*/
|
||||
public int getPasswordType() throws RemoteException;
|
||||
}
|
||||
|
||||
@@ -645,4 +645,14 @@ public class StorageManager {
|
||||
return Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
|
||||
DEFAULT_FULL_THRESHOLD_BYTES);
|
||||
}
|
||||
|
||||
/// Consts to match the password types in cryptfs.h
|
||||
/** @hide */
|
||||
public static final int CRYPT_TYPE_PASSWORD = 0;
|
||||
/** @hide */
|
||||
public static final int CRYPT_TYPE_DEFAULT = 1;
|
||||
/** @hide */
|
||||
public static final int CRYPT_TYPE_PATTERN = 2;
|
||||
/** @hide */
|
||||
public static final int CRYPT_TYPE_PIN = 3;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@ import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.storage.IMountService;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@@ -498,6 +500,13 @@ public class LockPatternUtils {
|
||||
getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId());
|
||||
DevicePolicyManager dpm = getDevicePolicyManager();
|
||||
if (pattern != null) {
|
||||
|
||||
int userHandle = getCurrentOrCallingUserId();
|
||||
if (userHandle == UserHandle.USER_OWNER) {
|
||||
String stringPattern = patternToString(pattern);
|
||||
updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
|
||||
}
|
||||
|
||||
setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
|
||||
if (!isFallback) {
|
||||
deleteGallery();
|
||||
@@ -565,7 +574,7 @@ public class LockPatternUtils {
|
||||
}
|
||||
|
||||
/** Update the encryption password if it is enabled **/
|
||||
private void updateEncryptionPassword(String password) {
|
||||
private void updateEncryptionPassword(int type, String password) {
|
||||
DevicePolicyManager dpm = getDevicePolicyManager();
|
||||
if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId())
|
||||
!= DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
|
||||
@@ -580,7 +589,7 @@ public class LockPatternUtils {
|
||||
|
||||
IMountService mountService = IMountService.Stub.asInterface(service);
|
||||
try {
|
||||
mountService.changeEncryptionPassword(password);
|
||||
mountService.changeEncryptionPassword(type, password);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error changing encryption password", e);
|
||||
}
|
||||
@@ -623,12 +632,15 @@ public class LockPatternUtils {
|
||||
getLockSettings().setLockPassword(password, userHandle);
|
||||
DevicePolicyManager dpm = getDevicePolicyManager();
|
||||
if (password != null) {
|
||||
int computedQuality = computePasswordQuality(password);
|
||||
|
||||
if (userHandle == UserHandle.USER_OWNER) {
|
||||
// Update the encryption password.
|
||||
updateEncryptionPassword(password);
|
||||
int type = computedQuality == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|
||||
? StorageManager.CRYPT_TYPE_PIN : StorageManager.CRYPT_TYPE_PASSWORD;
|
||||
updateEncryptionPassword(type, password);
|
||||
}
|
||||
|
||||
int computedQuality = computePasswordQuality(password);
|
||||
if (!isFallback) {
|
||||
deleteGallery();
|
||||
setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle);
|
||||
@@ -675,8 +687,7 @@ public class LockPatternUtils {
|
||||
0, 0, 0, 0, 0, 0, 0, userHandle);
|
||||
}
|
||||
// Add the password to the password history. We assume all
|
||||
// password
|
||||
// hashes have the same length for simplicity of implementation.
|
||||
// password hashes have the same length for simplicity of implementation.
|
||||
String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle);
|
||||
if (passwordHistory == null) {
|
||||
passwordHistory = new String();
|
||||
@@ -695,6 +706,11 @@ public class LockPatternUtils {
|
||||
}
|
||||
setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle);
|
||||
} else {
|
||||
if (userHandle == UserHandle.USER_OWNER) {
|
||||
// Update the encryption password.
|
||||
updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, password);
|
||||
}
|
||||
|
||||
dpm.setActivePasswordState(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0,
|
||||
userHandle);
|
||||
|
||||
@@ -73,13 +73,16 @@ import com.android.server.pm.UserManagerService;
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.android.collect.Maps;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
@@ -189,6 +192,12 @@ class MountService extends IMountService.Stub
|
||||
public static final int FstrimCompleted = 700;
|
||||
}
|
||||
|
||||
/** List of crypto types.
|
||||
* These must match CRYPT_TYPE_XXX in cryptfs.h AND their
|
||||
* corresponding commands in CommandListener.cpp */
|
||||
public static final String[] CRYPTO_TYPES
|
||||
= { "password", "default", "pattern", "pin" };
|
||||
|
||||
private Context mContext;
|
||||
private NativeDaemonConnector mConnector;
|
||||
|
||||
@@ -2036,6 +2045,14 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private String toHex(String password) {
|
||||
if (password == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
|
||||
return new String(Hex.encodeHex(bytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decryptStorage(String password) {
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
@@ -2053,7 +2070,7 @@ class MountService extends IMountService.Stub
|
||||
|
||||
final NativeDaemonEvent event;
|
||||
try {
|
||||
event = mConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
|
||||
event = mConnector.execute("cryptfs", "checkpw", new SensitiveArg(toHex(password)));
|
||||
|
||||
final int code = Integer.parseInt(event.getMessage());
|
||||
if (code == 0) {
|
||||
@@ -2092,7 +2109,8 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
|
||||
try {
|
||||
mConnector.execute("cryptfs", "enablecrypto", "inplace", new SensitiveArg(password));
|
||||
mConnector.execute("cryptfs", "enablecrypto", "inplace",
|
||||
new SensitiveArg(toHex(password)));
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
// Encryption failed
|
||||
return e.getCode();
|
||||
@@ -2101,11 +2119,11 @@ class MountService extends IMountService.Stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int changeEncryptionPassword(String password) {
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
throw new IllegalArgumentException("password cannot be empty");
|
||||
}
|
||||
|
||||
/** Set the password for encrypting the master key.
|
||||
* @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager.
|
||||
* @param password The password to set.
|
||||
*/
|
||||
public int changeEncryptionPassword(int type, String password) {
|
||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
|
||||
"no permission to access the crypt keeper");
|
||||
|
||||
@@ -2117,7 +2135,8 @@ class MountService extends IMountService.Stub
|
||||
|
||||
final NativeDaemonEvent event;
|
||||
try {
|
||||
event = mConnector.execute("cryptfs", "changepw", new SensitiveArg(password));
|
||||
event = mConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type],
|
||||
new SensitiveArg(toHex(password)));
|
||||
return Integer.parseInt(event.getMessage());
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
// Encryption failed
|
||||
@@ -2150,7 +2169,7 @@ class MountService extends IMountService.Stub
|
||||
|
||||
final NativeDaemonEvent event;
|
||||
try {
|
||||
event = mConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
|
||||
event = mConnector.execute("cryptfs", "verifypw", new SensitiveArg(toHex(password)));
|
||||
Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
|
||||
return Integer.parseInt(event.getMessage());
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
@@ -2159,6 +2178,29 @@ class MountService extends IMountService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of encryption used to encrypt the master key.
|
||||
* @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager.
|
||||
*/
|
||||
@Override
|
||||
public int getPasswordType() throws RemoteException {
|
||||
|
||||
waitForReady();
|
||||
|
||||
final NativeDaemonEvent event;
|
||||
try {
|
||||
event = mConnector.execute("cryptfs", "getpwtype");
|
||||
for (int i = 0; i < CRYPTO_TYPES.length; ++i) {
|
||||
if (CRYPTO_TYPES[i].equals(event.getMessage()))
|
||||
return i;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("unexpected return from cryptfs");
|
||||
} catch (NativeDaemonConnectorException e) {
|
||||
throw e.rethrowAsParcelableException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mkdirs(String callingPkg, String appPath) {
|
||||
final int userId = UserHandle.getUserId(Binder.getCallingUid());
|
||||
|
||||
Reference in New Issue
Block a user