diff options
author | Hasini Gunasinghe <hasinitg@google.com> | 2020-12-04 17:46:20 +0000 |
---|---|---|
committer | Janis Danisevskis <jdanis@google.com> | 2021-01-14 17:09:06 -0800 |
commit | 2d29591e5151d1a705448852f4a0a32db6daa345 (patch) | |
tree | 6d1cad93bb5f70d747b2258b110fb81d6cfe94ac | |
parent | a1daeb70050ae20350d2e30982a3e53e4e31cddb (diff) |
Integrate IKeystoreAuthorization aidl's addAuthToken with Keystore SPI.
This CL introduces the Keystore SPI class for IKeystoreAuthorization
aidl interface and implements the calling code for addAuthToken method.
Bug: 166672367
Test: VTS test
Change-Id: I7893ab4520b16533b9fddc9909297856e0b523ae
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | keystore/java/android/security/AuthTokenUtils.java | 75 | ||||
-rw-r--r-- | keystore/java/android/security/Authorization.java | 78 | ||||
-rw-r--r-- | keystore/java/android/security/KeyStore.java | 1 |
4 files changed, 155 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp index 23168232b7a3..402cf1c245ab 100644 --- a/Android.bp +++ b/Android.bp @@ -483,6 +483,7 @@ java_library { "android.hardware.vibrator-V1.2-java", "android.hardware.vibrator-V1.3-java", "android.security.apc-java", + "android.security.authorization-java", "android.system.keystore2-java", "android.system.suspend.control.internal-java", "devicepolicyprotosnano", diff --git a/keystore/java/android/security/AuthTokenUtils.java b/keystore/java/android/security/AuthTokenUtils.java new file mode 100644 index 000000000000..14d6626e5e97 --- /dev/null +++ b/keystore/java/android/security/AuthTokenUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 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; + +import android.annotation.NonNull; +import android.hardware.security.keymint.HardwareAuthToken; +import android.hardware.security.keymint.Timestamp; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * @hide This Utils class provides method(s) for AuthToken conversion. + */ +public class AuthTokenUtils { + + private AuthTokenUtils(){ + } + + /** + * Build a HardwareAuthToken from a byte array + * @param array byte array representing an auth token + * @return HardwareAuthToken representation of an auth token + */ + public static @NonNull HardwareAuthToken toHardwareAuthToken(@NonNull byte[] array) { + final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken(); + + // First byte is version, which does not exist in HardwareAuthToken anymore + // Next 8 bytes is the challenge. + hardwareAuthToken.challenge = + ByteBuffer.wrap(array, 1, 8).order(ByteOrder.nativeOrder()).getLong(); + + // Next 8 bytes is the userId + hardwareAuthToken.userId = + ByteBuffer.wrap(array, 9, 8).order(ByteOrder.nativeOrder()).getLong(); + + // Next 8 bytes is the authenticatorId. + hardwareAuthToken.authenticatorId = + ByteBuffer.wrap(array, 17, 8).order(ByteOrder.nativeOrder()).getLong(); + + // while the other fields are in machine byte order, authenticatorType and timestamp + // are in network byte order. + // Next 4 bytes is the authenticatorType. + hardwareAuthToken.authenticatorType = + ByteBuffer.wrap(array, 25, 4).order(ByteOrder.BIG_ENDIAN).getInt(); + // Next 8 bytes is the timestamp. + final Timestamp timestamp = new Timestamp(); + timestamp.milliSeconds = + ByteBuffer.wrap(array, 29, 8).order(ByteOrder.BIG_ENDIAN).getLong(); + hardwareAuthToken.timestamp = timestamp; + + // Last 32 bytes is the mac, 37:69 + hardwareAuthToken.mac = new byte[32]; + System.arraycopy(array, 37 /* srcPos */, + hardwareAuthToken.mac, + 0 /* destPos */, + 32 /* length */); + + return hardwareAuthToken; + } +} diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java new file mode 100644 index 000000000000..2b76f25793ce --- /dev/null +++ b/keystore/java/android/security/Authorization.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 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; + +import android.annotation.NonNull; +import android.hardware.security.keymint.HardwareAuthToken; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.security.authorization.IKeystoreAuthorization; +import android.system.keystore2.ResponseCode; +import android.util.Log; + +/** + * @hide This is the client side for IKeystoreAuthorization AIDL. + * It shall only be used by biometric authentication providers and Gatekeeper. + */ +public class Authorization { + private static final String TAG = "KeystoreAuthorization"; + private static IKeystoreAuthorization sIKeystoreAuthorization; + + public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; + + public Authorization() { + sIKeystoreAuthorization = null; + } + + private static synchronized IKeystoreAuthorization getService() { + if (sIKeystoreAuthorization == null) { + sIKeystoreAuthorization = IKeystoreAuthorization.Stub.asInterface( + ServiceManager.getService("android.security.authorization")); + } + return sIKeystoreAuthorization; + } + + /** + * Adds an auth token to keystore2. + * + * @param authToken created by Android authenticators. + * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}. + */ + public int addAuthToken(@NonNull HardwareAuthToken authToken) { + if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0; + try { + getService().addAuthToken(authToken); + return 0; + } catch (RemoteException e) { + Log.w(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } catch (ServiceSpecificException e) { + return e.errorCode; + } + } + + /** + * Add an auth token to Keystore 2.0 in the legacy serialized auth token format. + * @param authToken + * @return 0 if successful or a {@code ResponseCode}. + */ + public int addAuthToken(@NonNull byte[] authToken) { + return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken)); + } + +} diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index c70c986fcd6b..4a67135227dd 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -996,6 +996,7 @@ public class KeyStore { */ public int addAuthToken(byte[] authToken) { try { + new Authorization().addAuthToken(authToken); return mBinder.addAuthToken(authToken); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); |