diff options
author | 2024-12-02 19:45:27 +0000 | |
---|---|---|
committer | 2024-12-02 19:45:27 +0000 | |
commit | 924d8b1345cf97ecf7f7905e86d6b16ff72d5b93 (patch) | |
tree | 1314e6392a67b8d1510507cee31eba1e39c160e7 | |
parent | f54003ae01986bb7d83f8fad75ba85f4964bfaf2 (diff) | |
parent | 761f2c8102b47f08e0ab0cf5873e3d2a06839cd1 (diff) |
Merge "Revert "ArrayUtils: add secure zeroization support"" into main am: 761f2c8102
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/3387622
Change-Id: Ibacb9b5260a686695cdc645cd7432ca218078802
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | core/java/com/android/internal/util/ArrayUtils.java | 45 | ||||
-rw-r--r-- | core/jni/Android.bp | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/com_android_internal_util_ArrayUtils.cpp | 122 | ||||
-rw-r--r-- | core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java | 47 |
5 files changed, 0 insertions, 217 deletions
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 9b8551bf134c..1e965c5db7ae 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -85,51 +85,6 @@ public class ArrayUtils { } /** - * This is like <code>new byte[length]</code>, but it allocates the array as non-movable. This - * prevents copies of the data from being left on the Java heap as a result of heap compaction. - * Use this when the array will contain sensitive data such as a password or cryptographic key - * that needs to be wiped from memory when no longer needed. The owner of the array is still - * responsible for the zeroization; {@link #zeroize(byte[])} should be used to do so. - * - * @param length the length of the array to allocate - * @return the new array - */ - public static byte[] newNonMovableByteArray(int length) { - return (byte[]) VMRuntime.getRuntime().newNonMovableArray(byte.class, length); - } - - /** - * Like {@link #newNonMovableByteArray(int)}, but allocates a char array. - * - * @param length the length of the array to allocate - * @return the new array - */ - public static char[] newNonMovableCharArray(int length) { - return (char[]) VMRuntime.getRuntime().newNonMovableArray(char.class, length); - } - - /** - * Zeroizes a byte array as securely as possible. Use this when the array contains sensitive - * data such as a password or cryptographic key. - * <p> - * This zeroizes the array in a way that is guaranteed to not be optimized out by the compiler. - * If supported by the architecture, it zeroizes the data not just in the L1 data cache but also - * in other levels of the memory hierarchy up to and including main memory (but not above that). - * <p> - * This works on any <code>byte[]</code>, but to ensure that copies of the array aren't left on - * the Java heap the array should have been allocated with {@link #newNonMovableByteArray(int)}. - * Use on other arrays might also introduce performance anomalies. - * - * @param array the array to zeroize - */ - public static native void zeroize(byte[] array); - - /** - * Like {@link #zeroize(byte[])}, but for char arrays. - */ - public static native void zeroize(char[] array); - - /** * Checks if the beginnings of two byte arrays are equal. * * @param array1 the first byte array diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 179966ff16a9..9a4ff8fc264f 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -90,7 +90,6 @@ cc_library_shared_for_libandroid_runtime { "android_view_VelocityTracker.cpp", "android_view_VerifiedKeyEvent.cpp", "android_view_VerifiedMotionEvent.cpp", - "com_android_internal_util_ArrayUtils.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", "core_jni_helpers.cpp", ":deviceproductinfoconstants_aidl", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 3bfc1028dd6a..9715829254ee 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -216,7 +216,6 @@ extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_ZygoteCommandBuffer(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_security_VerityUtils(JNIEnv* env); -extern int register_com_android_internal_util_ArrayUtils(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); extern int register_android_window_WindowInfosListener(JNIEnv* env); extern int register_android_window_ScreenCapture(JNIEnv* env); @@ -1616,7 +1615,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_ZygoteCommandBuffer), REG_JNI(register_com_android_internal_os_ZygoteInit), REG_JNI(register_com_android_internal_security_VerityUtils), - REG_JNI(register_com_android_internal_util_ArrayUtils), REG_JNI(register_com_android_internal_util_VirtualRefBasePtr), REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_camera2_CameraMetadata), diff --git a/core/jni/com_android_internal_util_ArrayUtils.cpp b/core/jni/com_android_internal_util_ArrayUtils.cpp deleted file mode 100644 index c69e6c903ee5..000000000000 --- a/core/jni/com_android_internal_util_ArrayUtils.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2024 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. - */ - -#define LOG_TAG "ArrayUtils" - -#include <android-base/logging.h> -#include <jni.h> -#include <nativehelper/JNIHelp.h> -#include <string.h> -#include <unistd.h> -#include <utils/Log.h> - -namespace android { - -static size_t GetCacheLineSize() { - long size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); - if (size <= 0) { - ALOGE("Unable to determine L1 data cache line size. Assuming 32 bytes"); - return 32; - } - return size; -} - -#ifdef __aarch64__ -static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) { - // Execute 'dc cvac' at least once on each cache line in the memory region. - // - // 'dc cvac' stands for "Data Cache line Clean by Virtual Address to point-of-Coherency". - // It writes the cache line back to the "point-of-coherency", i.e. main memory. - // - // Since the memory region is not guaranteed to be cache-line-aligned, we use an "extra" - // instruction after the loop to make sure the last cache line gets covered. - for (size_t i = 0; i < size; i += cache_line_size) { - asm volatile("dc cvac, %0" ::"r"(p + i)); - } - asm volatile("dc cvac, %0" ::"r"(p + size - 1)); -} -#elif defined(__i386__) || defined(__x86_64__) -static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) { - for (size_t i = 0; i < size; i += cache_line_size) { - asm volatile("clflush (%0)" ::"r"(p + i)); - } - asm volatile("clflush (%0)" ::"r"(p + size - 1)); -} -#elif defined(__riscv) -static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) { - // This should eventually work, but it is not ready to be enabled yet: - // 1.) The Android emulator needs to add support for zicbom. - // 2.) Kernel needs to enable zicbom in usermode. - // 3.) Android clang needs to add zicbom to the target. -#if 0 - for (size_t i = 0; i < size; i += cache_line_size) { - asm volatile("cbo.clean (%0)" ::"r"(p + i)); - } - asm volatile("cbo.clean (%0)" ::"r"(p + size - 1)); -#endif -} -#elif defined(__arm__) -// arm32 has a cacheflush() syscall, but it is undocumented and only flushes the icache. -// It is not the same as cacheflush(2) as documented in the Linux man-pages project. -static void CleanDataCache(const uint8_t* p, size_t size, size_t cache_line_size) {} -#else -#error "Unknown architecture" -#endif - -static void ZeroizePrimitiveArray(JNIEnv* env, jclass clazz, jarray array, size_t component_len) { - static const size_t cache_line_size = GetCacheLineSize(); - - size_t size = env->GetArrayLength(array) * component_len; - if (size == 0) { - return; - } - - // ART guarantees that GetPrimitiveArrayCritical never copies. - jboolean isCopy; - void* elems = env->GetPrimitiveArrayCritical(array, &isCopy); - CHECK(!isCopy); - -#ifdef __BIONIC__ - memset_explicit(elems, 0, size); -#else - memset(elems, 0, size); -#endif - // Clean the data cache so that the data gets zeroized in main memory right away. Without this, - // it might not be written to main memory until the cache line happens to be evicted. - CleanDataCache(static_cast<const uint8_t*>(elems), size, cache_line_size); - - env->ReleasePrimitiveArrayCritical(array, elems, /* mode= */ 0); -} - -static void ZeroizeByteArray(JNIEnv* env, jclass clazz, jbyteArray array) { - ZeroizePrimitiveArray(env, clazz, array, sizeof(jbyte)); -} - -static void ZeroizeCharArray(JNIEnv* env, jclass clazz, jcharArray array) { - ZeroizePrimitiveArray(env, clazz, array, sizeof(jchar)); -} - -static const JNINativeMethod sMethods[] = { - {"zeroize", "([B)V", (void*)ZeroizeByteArray}, - {"zeroize", "([C)V", (void*)ZeroizeCharArray}, -}; - -int register_com_android_internal_util_ArrayUtils(JNIEnv* env) { - return jniRegisterNativeMethods(env, "com/android/internal/util/ArrayUtils", sMethods, - NELEM(sMethods)); -} - -} // namespace android diff --git a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java index 3c264f15abd3..3b9f35b1eb68 100644 --- a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java @@ -496,51 +496,4 @@ public class ArrayUtilsTest { // expected } } - - // Note: the zeroize() tests only test the behavior that can be tested from a Java test. - // They do not verify that no copy of the data is left anywhere. - - @Test - @SmallTest - public void testZeroizeNonMovableByteArray() { - final int length = 10; - byte[] array = ArrayUtils.newNonMovableByteArray(length); - assertArrayEquals(array, new byte[length]); - Arrays.fill(array, (byte) 0xff); - ArrayUtils.zeroize(array); - assertArrayEquals(array, new byte[length]); - } - - @Test - @SmallTest - public void testZeroizeRegularByteArray() { - final int length = 10; - byte[] array = new byte[length]; - assertArrayEquals(array, new byte[length]); - Arrays.fill(array, (byte) 0xff); - ArrayUtils.zeroize(array); - assertArrayEquals(array, new byte[length]); - } - - @Test - @SmallTest - public void testZeroizeNonMovableCharArray() { - final int length = 10; - char[] array = ArrayUtils.newNonMovableCharArray(length); - assertArrayEquals(array, new char[length]); - Arrays.fill(array, (char) 0xff); - ArrayUtils.zeroize(array); - assertArrayEquals(array, new char[length]); - } - - @Test - @SmallTest - public void testZeroizeRegularCharArray() { - final int length = 10; - char[] array = new char[length]; - assertArrayEquals(array, new char[length]); - Arrays.fill(array, (char) 0xff); - ArrayUtils.zeroize(array); - assertArrayEquals(array, new char[length]); - } } |