Merge "Make Settings aware of legacy user keys with secret key prefix"

This commit is contained in:
Janis Danisevskis
2017-12-15 23:48:55 +00:00
committed by Android (Google) Code Review
2 changed files with 53 additions and 27 deletions

View File

@@ -37,6 +37,8 @@ import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.security.KeyStore;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterDefs;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseArray;
@@ -48,19 +50,15 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
public class UserCredentialsSettings extends SettingsPreferenceFragment
implements View.OnClickListener {
private static final String TAG = "UserCredentialsSettings";
@@ -254,10 +252,30 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
return credentials;
}
private boolean isAsymmetric(KeyStore keyStore, String alias, int uid)
throws UnrecoverableKeyException {
KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
int errorCode = keyStore.getKeyCharacteristics(alias, null, null, uid,
keyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw (UnrecoverableKeyException)
new UnrecoverableKeyException("Failed to obtain information about key")
.initCause(KeyStore.getKeyStoreException(errorCode));
}
Integer keymasterAlgorithm = keyCharacteristics.getEnum(
KeymasterDefs.KM_TAG_ALGORITHM);
if (keymasterAlgorithm == null) {
throw new UnrecoverableKeyException("Key algorithm unknown");
}
return keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA ||
keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC;
}
private SortedMap<String, Credential> getCredentialsForUid(KeyStore keyStore, int uid) {
final SortedMap<String, Credential> aliasMap = new TreeMap<>();
for (final Credential.Type type : Credential.Type.values()) {
for (final String alias : keyStore.list(type.prefix, uid)) {
for (final String prefix : type.prefix) {
for (final String alias : keyStore.list(prefix, uid)) {
if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
// Do not show work profile keys in user credentials
if (alias.startsWith(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT) ||
@@ -269,6 +287,15 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
continue;
}
}
try {
if (type == Credential.Type.USER_KEY &&
!isAsymmetric(keyStore, prefix + alias, uid)) {
continue;
}
} catch (UnrecoverableKeyException e) {
Log.e(TAG, "Unable to determine algorithm of key: " + prefix + alias, e);
continue;
}
Credential c = aliasMap.get(alias);
if (c == null) {
c = new Credential(alias, uid);
@@ -277,6 +304,7 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
c.storedTypes.add(type);
}
}
}
return aliasMap;
}
@@ -344,7 +372,7 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
*/
private static final SparseArray<Credential.Type> credentialViewTypes = new SparseArray<>();
static {
credentialViewTypes.put(R.id.contents_userkey, Credential.Type.USER_PRIVATE_KEY);
credentialViewTypes.put(R.id.contents_userkey, Credential.Type.USER_KEY);
credentialViewTypes.put(R.id.contents_usercrt, Credential.Type.USER_CERTIFICATE);
credentialViewTypes.put(R.id.contents_cacrt, Credential.Type.CA_CERTIFICATE);
}
@@ -380,12 +408,11 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
static enum Type {
CA_CERTIFICATE (Credentials.CA_CERTIFICATE),
USER_CERTIFICATE (Credentials.USER_CERTIFICATE),
USER_PRIVATE_KEY (Credentials.USER_PRIVATE_KEY),
USER_SECRET_KEY (Credentials.USER_SECRET_KEY);
USER_KEY(Credentials.USER_PRIVATE_KEY, Credentials.USER_SECRET_KEY);
final String prefix;
final String[] prefix;
Type(String prefix) {
Type(String... prefix) {
this.prefix = prefix;
}
}
@@ -407,8 +434,7 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
* <ul>
* <li>{@link Credentials.CA_CERTIFICATE}</li>
* <li>{@link Credentials.USER_CERTIFICATE}</li>
* <li>{@link Credentials.USER_PRIVATE_KEY}</li>
* <li>{@link Credentials.USER_SECRET_KEY}</li>
* <li>{@link Credentials.USER_KEY}</li>
* </ul>
*/
final EnumSet<Type> storedTypes = EnumSet.noneOf(Type.class);

View File

@@ -40,7 +40,7 @@ public class UserCredentialsTest extends InstrumentationTestCase {
Credential c = new Credential(alias, Process.SYSTEM_UID);
c.storedTypes.add(Credential.Type.CA_CERTIFICATE);
c.storedTypes.add(Credential.Type.USER_SECRET_KEY);
c.storedTypes.add(Credential.Type.USER_KEY);
Parcel p = Parcel.obtain();
c.writeToParcel(p, /* flags */ 0);