Merge "Keystore: Surface service error message" am: af771eb908 am: b3612e019f am: e53fd593b5

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1969819

Change-Id: Ibbef2974a7b8b8b584fb9f1c29d8b23be43ce796
This commit is contained in:
Eran Messeri
2022-02-08 19:17:52 +00:00
committed by Automerger Merge Worker
5 changed files with 81 additions and 18 deletions

View File

@@ -108,7 +108,7 @@ public class KeyStore2 {
try { try {
return request.execute(service); return request.execute(service);
} catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) {
throw getKeyStoreException(e.errorCode); throw getKeyStoreException(e.errorCode, e.getMessage());
} catch (RemoteException e) { } catch (RemoteException e) {
if (firstTry) { if (firstTry) {
Log.w(TAG, "Looks like we may have lost connection to the Keystore " Log.w(TAG, "Looks like we may have lost connection to the Keystore "
@@ -120,7 +120,7 @@ public class KeyStore2 {
firstTry = false; firstTry = false;
} else { } else {
Log.e(TAG, "Cannot connect to Keystore daemon.", e); Log.e(TAG, "Cannot connect to Keystore daemon.", e);
throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, ""); throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
} }
} }
} }
@@ -322,26 +322,32 @@ public class KeyStore2 {
} }
} }
static KeyStoreException getKeyStoreException(int errorCode) { static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
if (errorCode > 0) { if (errorCode > 0) {
// KeyStore layer error // KeyStore layer error
switch (errorCode) { switch (errorCode) {
case ResponseCode.LOCKED: case ResponseCode.LOCKED:
return new KeyStoreException(errorCode, "User authentication required"); return new KeyStoreException(errorCode, "User authentication required",
serviceErrorMessage);
case ResponseCode.UNINITIALIZED: case ResponseCode.UNINITIALIZED:
return new KeyStoreException(errorCode, "Keystore not initialized"); return new KeyStoreException(errorCode, "Keystore not initialized",
serviceErrorMessage);
case ResponseCode.SYSTEM_ERROR: case ResponseCode.SYSTEM_ERROR:
return new KeyStoreException(errorCode, "System error"); return new KeyStoreException(errorCode, "System error", serviceErrorMessage);
case ResponseCode.PERMISSION_DENIED: case ResponseCode.PERMISSION_DENIED:
return new KeyStoreException(errorCode, "Permission denied"); return new KeyStoreException(errorCode, "Permission denied",
serviceErrorMessage);
case ResponseCode.KEY_NOT_FOUND: case ResponseCode.KEY_NOT_FOUND:
return new KeyStoreException(errorCode, "Key not found"); return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage);
case ResponseCode.VALUE_CORRUPTED: case ResponseCode.VALUE_CORRUPTED:
return new KeyStoreException(errorCode, "Key blob corrupted"); return new KeyStoreException(errorCode, "Key blob corrupted",
serviceErrorMessage);
case ResponseCode.KEY_PERMANENTLY_INVALIDATED: case ResponseCode.KEY_PERMANENTLY_INVALIDATED:
return new KeyStoreException(errorCode, "Key permanently invalidated"); return new KeyStoreException(errorCode, "Key permanently invalidated",
serviceErrorMessage);
default: default:
return new KeyStoreException(errorCode, String.valueOf(errorCode)); return new KeyStoreException(errorCode, String.valueOf(errorCode),
serviceErrorMessage);
} }
} else { } else {
// Keymaster layer error // Keymaster layer error
@@ -350,10 +356,12 @@ public class KeyStore2 {
// The name of this parameter significantly differs between Keymaster and // The name of this parameter significantly differs between Keymaster and
// framework APIs. Use the framework wording to make life easier for developers. // framework APIs. Use the framework wording to make life easier for developers.
return new KeyStoreException(errorCode, return new KeyStoreException(errorCode,
"Invalid user authentication validity duration"); "Invalid user authentication validity duration",
serviceErrorMessage);
default: default:
return new KeyStoreException(errorCode, return new KeyStoreException(errorCode,
KeymasterDefs.getErrorMessage(errorCode)); KeymasterDefs.getErrorMessage(errorCode),
serviceErrorMessage);
} }
} }
} }

View File

@@ -157,6 +157,16 @@ public class KeyStoreException extends Exception {
mErrorCode = errorCode; mErrorCode = errorCode;
} }
/**
* @hide
*/
public KeyStoreException(int errorCode, @Nullable String message,
@Nullable String keystoreErrorMessage) {
super(message + " (internal Keystore code: " + errorCode + " message: "
+ keystoreErrorMessage + ")");
mErrorCode = errorCode;
}
/** /**
* Returns the internal error code. Only for use by the platform. * Returns the internal error code. Only for use by the platform.
* *

View File

@@ -75,7 +75,7 @@ public class KeyStoreOperation {
); );
} }
default: default:
throw KeyStore2.getKeyStoreException(e.errorCode); throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
} }
} catch (RemoteException e) { } catch (RemoteException e) {
// Log exception and report invalid operation handle. // Log exception and report invalid operation handle.
@@ -85,7 +85,8 @@ public class KeyStoreOperation {
"Remote exception while advancing a KeyStoreOperation.", "Remote exception while advancing a KeyStoreOperation.",
e e
); );
throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, ""); throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "",
e.getMessage());
} }
} }

View File

@@ -54,12 +54,12 @@ public class KeyStoreSecurityLevel {
try { try {
return request.execute(); return request.execute();
} catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) {
throw KeyStore2.getKeyStoreException(e.errorCode); throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
} catch (RemoteException e) { } catch (RemoteException e) {
// Log exception and report invalid operation handle. // Log exception and report invalid operation handle.
// This should prompt the caller drop the reference to this operation and retry. // This should prompt the caller drop the reference to this operation and retry.
Log.e(TAG, "Could not connect to Keystore.", e); Log.e(TAG, "Could not connect to Keystore.", e);
throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, ""); throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
} }
} }
@@ -117,7 +117,7 @@ public class KeyStoreSecurityLevel {
break; break;
} }
default: default:
throw KeyStore2.getKeyStoreException(e.errorCode); throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
} }
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e); Log.w(TAG, "Cannot connect to keystore", e);

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 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 static org.junit.Assert.assertTrue;
import android.security.KeyStoreException;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class KeyStoreExceptionTest {
@Test
public void testKeystoreMessageIsIncluded() {
final String primaryMessage = "some_message";
final String keystoreMessage = "ks_message";
KeyStoreException exception = new KeyStoreException(-1, primaryMessage, keystoreMessage);
String exceptionMessage = exception.getMessage();
assertTrue(exceptionMessage.contains(primaryMessage));
assertTrue(exceptionMessage.contains(keystoreMessage));
String exceptionString = exception.toString();
assertTrue(exceptionString.contains(primaryMessage));
assertTrue(exceptionString.contains(keystoreMessage));
}
}