Merge changes I36d1e494,I65a74ac6 into main
* changes:
Add missing supportedEnumValues
Add missing status codes
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
index 15de48f..4787f0b 100644
--- a/automotive/evs/OWNERS
+++ b/automotive/evs/OWNERS
@@ -1,2 +1,2 @@
ankitarora@google.com
-jwhpryor@google.com
+changyeon@google.com
diff --git a/automotive/evs/aidl/impl/default/Android.bp b/automotive/evs/aidl/impl/default/Android.bp
index 70c523b..79ee956 100644
--- a/automotive/evs/aidl/impl/default/Android.bp
+++ b/automotive/evs/aidl/impl/default/Android.bp
@@ -60,12 +60,15 @@
"libyuv",
],
static_libs: [
- "android.frameworks.automotive.display-V1-ndk",
+ "android.frameworks.automotive.display-V2-ndk",
"android.hardware.automotive.evs-V2-ndk",
"android.hardware.common-V2-ndk",
"libaidlcommonsupport",
"libcutils",
],
+ header_libs: [
+ "libgui_aidl_headers",
+ ],
local_include_dirs: ["include"],
include_dirs: ["frameworks/native/include/"],
required: ["evs_mock_hal_configuration.xml"],
diff --git a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h b/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
index 259c266..3897b4e 100644
--- a/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
+++ b/automotive/evs/aidl/impl/default/include/EvsEnumerator.h
@@ -27,6 +27,7 @@
#include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
#include <aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.h>
#include <aidl/android/hardware/automotive/evs/Stream.h>
+#include <android-base/thread_annotations.h>
#include <utils/Thread.h>
#include <atomic>
diff --git a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h b/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
index ceabd9e..0865a04 100644
--- a/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
+++ b/automotive/evs/aidl/impl/default/include/EvsGlDisplay.h
@@ -23,6 +23,7 @@
#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
#include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
#include <aidl/android/hardware/automotive/evs/DisplayState.h>
+#include <android-base/thread_annotations.h>
#include <thread>
diff --git a/automotive/evs/aidl/impl/default/include/GlWrapper.h b/automotive/evs/aidl/impl/default/include/GlWrapper.h
index adb250c..7ff6104 100644
--- a/automotive/evs/aidl/impl/default/include/GlWrapper.h
+++ b/automotive/evs/aidl/impl/default/include/GlWrapper.h
@@ -25,7 +25,7 @@
#include <aidl/android/frameworks/automotive/display/ICarDisplayProxy.h>
#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
#include <android-base/logging.h>
-#include <bufferqueueconverter/BufferQueueConverter.h>
+#include <cutils/native_handle.h>
namespace aidl::android::hardware::automotive::evs::implementation {
@@ -33,7 +33,6 @@
class GlWrapper {
public:
- GlWrapper() : mSurfaceHolder(::android::SurfaceHolderUniquePtr(nullptr, nullptr)) {}
bool initialize(const std::shared_ptr<automotivedisplay::ICarDisplayProxy>& svc,
uint64_t displayId);
void shutdown();
@@ -53,9 +52,6 @@
unsigned getHeight() { return mHeight; };
private:
- ::android::sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
- mGfxBufferProducer;
-
EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;
@@ -71,9 +67,6 @@
// Opaque handle for a native hardware buffer defined in
// frameworks/native/opengl/include/EGL/eglplatform.h
ANativeWindow* mWindow;
-
- // Pointer to a Surface wrapper.
- ::android::SurfaceHolderUniquePtr mSurfaceHolder;
};
} // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
index e5f8e4c..5b5cbcc 100644
--- a/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsGlDisplay.cpp
@@ -352,8 +352,8 @@
BufferDesc bufferDescToSend = {
.buffer =
{
- .handle = std::move(::android::dupToAidl(mBuffer.handle)),
.description = mBuffer.description,
+ .handle = std::move(::android::dupToAidl(mBuffer.handle)),
},
.pixelSizeBytes = 4, // RGBA_8888 is 4-byte-per-pixel format
.bufferId = mBuffer.fingerprint,
diff --git a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp b/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
index 0ee5ecb..a9d0213 100644
--- a/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
+++ b/automotive/evs/aidl/impl/default/src/GlWrapper.cpp
@@ -19,6 +19,7 @@
#include <aidl/android/frameworks/automotive/display/DisplayDesc.h>
#include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <gui/view/Surface.h>
#include <ui/DisplayMode.h>
#include <ui/DisplayState.h>
#include <ui/GraphicBuffer.h>
@@ -183,20 +184,6 @@
return program;
}
-::android::sp<HGraphicBufferProducer> convertNativeHandleToHGBP(const NativeHandle& aidlHandle) {
- native_handle_t* handle = ::android::dupFromAidl(aidlHandle);
- if (handle->numFds != 0 || handle->numInts < std::ceil(sizeof(size_t) / sizeof(int))) {
- LOG(ERROR) << "Invalid native handle";
- return nullptr;
- }
- ::android::hardware::hidl_vec<uint8_t> halToken;
- halToken.setToExternal(reinterpret_cast<uint8_t*>(const_cast<int*>(&(handle->data[1]))),
- handle->data[0]);
- ::android::sp<HGraphicBufferProducer> hgbp =
- HGraphicBufferProducer::castFrom(::android::retrieveHalInterface(halToken));
- return std::move(hgbp);
-}
-
} // namespace
namespace aidl::android::hardware::automotive::evs::implementation {
@@ -226,30 +213,19 @@
}
LOG(INFO) << "Display resolution is " << mWidth << "x" << mHeight;
- NativeHandle aidlHandle;
- status = pWindowProxy->getHGraphicBufferProducer(displayId, &aidlHandle);
+ aidl::android::view::Surface shimSurface;
+ status = pWindowProxy->getSurface(displayId, &shimSurface);
if (!status.isOk()) {
- LOG(ERROR) << "Failed to get IGraphicBufferProducer from ICarDisplayProxy.";
+ LOG(ERROR) << "Failed to obtain the surface.";
return false;
}
- mGfxBufferProducer = convertNativeHandleToHGBP(aidlHandle);
- if (!mGfxBufferProducer) {
- LOG(ERROR) << "Failed to convert a NativeHandle to HGBP.";
- return false;
- }
-
- mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer);
- if (mSurfaceHolder == nullptr) {
- LOG(ERROR) << "Failed to get a Surface from HGBP.";
- return false;
- }
-
- mWindow = getNativeWindow(mSurfaceHolder.get());
+ mWindow = shimSurface.get();
if (mWindow == nullptr) {
LOG(ERROR) << "Failed to get a native window from Surface.";
return false;
}
+ ANativeWindow_acquire(mWindow);
// Set up our OpenGL ES context associated with the default display
mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -350,7 +326,12 @@
mDisplay = EGL_NO_DISPLAY;
// Release the window
- mSurfaceHolder = nullptr;
+ if (mWindow == nullptr) {
+ return;
+ }
+
+ ANativeWindow_release(mWindow);
+ mWindow = nullptr;
}
void GlWrapper::showWindow(const std::shared_ptr<ICarDisplayProxy>& pWindowProxy, uint64_t id) {
diff --git a/bluetooth/aidl/vts/Android.bp b/bluetooth/aidl/vts/Android.bp
index 5fc0b2e..ade3bef 100644
--- a/bluetooth/aidl/vts/Android.bp
+++ b/bluetooth/aidl/vts/Android.bp
@@ -16,10 +16,6 @@
srcs: [
"VtsHalBluetoothTargetTest.cpp",
":BluetoothPacketSources",
- ":BluetoothHciPacketSources",
- ],
- generated_headers: [
- "BluetoothGeneratedPackets_h",
],
include_dirs: [
"packages/modules/Bluetooth/system/gd",
@@ -31,7 +27,7 @@
],
static_libs: [
"android.hardware.bluetooth-V1-ndk",
- "libbluetooth-types",
+ "libbluetooth_hci_pdl",
],
test_config: "VtsHalBluetoothTargetTest.xml",
test_suites: [
@@ -57,6 +53,5 @@
],
tidy_disabled_srcs: [
":BluetoothPacketSources",
- ":BluetoothHciPacketSources",
],
}
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 08ad0bb..5f9d605 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -120,7 +120,7 @@
ABinderProcess_startThreadPool();
SpAIBinder cameraProviderBinder =
- SpAIBinder(AServiceManager_getService(serviceDescriptor.c_str()));
+ SpAIBinder(AServiceManager_waitForService(serviceDescriptor.c_str()));
ASSERT_NE(cameraProviderBinder.get(), nullptr);
std::shared_ptr<ICameraProvider> cameraProvider =
diff --git a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
index 12bc441..0d1a094 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
@@ -24,35 +24,47 @@
@Backing(type="long")
enum BufferUsage {
/** bit 0-3 is an enum */
- CPU_READ_MASK = 0xf,
+ CPU_READ_MASK = 0xf,
/** buffer is never read by CPU */
- CPU_READ_NEVER = 0,
+ CPU_READ_NEVER = 0,
/** buffer is rarely read by CPU */
- CPU_READ_RARELY = 2,
+ CPU_READ_RARELY = 2,
/** buffer is often read by CPU */
- CPU_READ_OFTEN = 3,
+ CPU_READ_OFTEN = 3,
/** bit 4-7 is an enum */
- CPU_WRITE_MASK = 0xf << 4,
+ CPU_WRITE_MASK = 0xf << 4,
/** buffer is never written by CPU */
- CPU_WRITE_NEVER = 0 << 4,
+ CPU_WRITE_NEVER = 0 << 4,
/** buffer is rarely written by CPU */
- CPU_WRITE_RARELY = 2 << 4,
+ CPU_WRITE_RARELY = 2 << 4,
/** buffer is often written by CPU */
- CPU_WRITE_OFTEN = 3 << 4,
+ CPU_WRITE_OFTEN = 3 << 4,
- /** buffer is used as a GPU texture */
- GPU_TEXTURE = 1 << 8,
+ /**
+ * Buffer may be used as a GPU texture
+ *
+ * Buffers allocated with this flag must be
+ * texturable both in EGL/GL & Vulkan via
+ * their respective external memory extensions
+ */
+ GPU_TEXTURE = 1 << 8,
- /** buffer is used as a GPU render target */
- GPU_RENDER_TARGET = 1 << 9,
+ /**
+ * Buffer may be used as a GPU render target
+ *
+ * Buffers allocated with this flag must be
+ * renderable both in EGL/GL & Vulkan via
+ * their respective external memory extensions
+ */
+ GPU_RENDER_TARGET = 1 << 9,
/** bit 10 must be zero */
/** buffer is used as a composer HAL overlay layer */
- COMPOSER_OVERLAY = 1 << 11,
+ COMPOSER_OVERLAY = 1 << 11,
/** buffer is used as a composer HAL client target */
- COMPOSER_CLIENT_TARGET = 1 << 12,
+ COMPOSER_CLIENT_TARGET = 1 << 12,
/** bit 13 must be zero */
@@ -61,86 +73,86 @@
* contents (or information derived from the contents) into unprotected
* memory.
*/
- PROTECTED = 1 << 14,
+ PROTECTED = 1 << 14,
/** buffer is used as a hwcomposer HAL cursor layer */
- COMPOSER_CURSOR = 1 << 15,
+ COMPOSER_CURSOR = 1 << 15,
/** buffer is used as a video encoder input */
- VIDEO_ENCODER = 1 << 16,
+ VIDEO_ENCODER = 1 << 16,
/** buffer is used as a camera HAL output */
- CAMERA_OUTPUT = 1 << 17,
+ CAMERA_OUTPUT = 1 << 17,
/** buffer is used as a camera HAL input */
- CAMERA_INPUT = 1 << 18,
+ CAMERA_INPUT = 1 << 18,
/** bit 19 must be zero */
/** buffer is used as a renderscript allocation */
- RENDERSCRIPT = 1 << 20,
+ RENDERSCRIPT = 1 << 20,
/** bit 21 must be zero */
/** buffer is used as a video decoder output */
- VIDEO_DECODER = 1 << 22,
+ VIDEO_DECODER = 1 << 22,
/** buffer is used as a sensor direct report output */
- SENSOR_DIRECT_DATA = 1 << 23,
+ SENSOR_DIRECT_DATA = 1 << 23,
/**
* buffer is used as as an OpenGL shader storage or uniform
* buffer object
*/
- GPU_DATA_BUFFER = 1 << 24,
+ GPU_DATA_BUFFER = 1 << 24,
/** buffer is used as a cube map texture */
- GPU_CUBE_MAP = 1 << 25,
+ GPU_CUBE_MAP = 1 << 25,
/** buffer contains a complete mipmap hierarchy */
- GPU_MIPMAP_COMPLETE = 1 << 26,
+ GPU_MIPMAP_COMPLETE = 1 << 26,
/**
* Buffer is used as input for HEIC encoder.
*/
- HW_IMAGE_ENCODER = 1 << 27,
+ HW_IMAGE_ENCODER = 1 << 27,
/* Bits 28-31 are reserved for vendor usage */
/**
- * Buffer is used for front-buffer rendering.
- *
- * To satisfy an allocation with this usage, the resulting buffer
- * must operate as equivalent to shared memory for all targets.
- *
- * For CPU_USAGE_* other than NEVER, this means the buffer must
- * "lock in place". The buffers must be directly accessible via mapping.
- *
- * For GPU_RENDER_TARGET the buffer must behave equivalent to a
- * single-buffered EGL surface. For example glFlush must perform
- * a flush, same as if the default framebuffer was single-buffered.
- *
- * For COMPOSER_* the HWC must not perform any caching for this buffer
- * when submitted for composition. HWCs do not need to do any form
- * of auto-refresh, and they are allowed to cache composition results between
- * presents from SF (such as for panel self-refresh), but for any given
- * present the buffer must be composited from even if it otherwise appears
- * to be the same as a previous composition.
- *
- * If the GPU & HWC supports EGL_SINGLE_BUFFER, then it is recommended that
- * FRONT_BUFFER usage is supported for the same formats as supported by
- * EGL_SINGLE_BUFFER. In particular, it is recommended that the following
- * combination is supported when possible:
- * Format = RGBA_8888
- * Usage = FRONT_BUFFER | GPU_RENDER_TARGET | COMPOSER_OVERLAY
- *
- */
- FRONT_BUFFER = 1L << 32,
+ * Buffer is used for front-buffer rendering.
+ *
+ * To satisfy an allocation with this usage, the resulting buffer
+ * must operate as equivalent to shared memory for all targets.
+ *
+ * For CPU_USAGE_* other than NEVER, this means the buffer must
+ * "lock in place". The buffers must be directly accessible via mapping.
+ *
+ * For GPU_RENDER_TARGET the buffer must behave equivalent to a
+ * single-buffered EGL surface. For example glFlush must perform
+ * a flush, same as if the default framebuffer was single-buffered.
+ *
+ * For COMPOSER_* the HWC must not perform any caching for this buffer
+ * when submitted for composition. HWCs do not need to do any form
+ * of auto-refresh, and they are allowed to cache composition results between
+ * presents from SF (such as for panel self-refresh), but for any given
+ * present the buffer must be composited from even if it otherwise appears
+ * to be the same as a previous composition.
+ *
+ * If the GPU & HWC supports EGL_SINGLE_BUFFER, then it is recommended that
+ * FRONT_BUFFER usage is supported for the same formats as supported by
+ * EGL_SINGLE_BUFFER. In particular, it is recommended that the following
+ * combination is supported when possible:
+ * Format = RGBA_8888
+ * Usage = FRONT_BUFFER | GPU_RENDER_TARGET | COMPOSER_OVERLAY
+ *
+ */
+ FRONT_BUFFER = 1L << 32,
/** bits 28-31 are reserved for vendor extensions */
- VENDOR_MASK = 0xf << 28,
+ VENDOR_MASK = 0xf << 28,
/** bits 33-47 must be zero and are reserved for future versions */
/** bits 48-63 are reserved for vendor extensions */
- VENDOR_MASK_HI = (1L * 0xffff) << 48,
+ VENDOR_MASK_HI = (1L * 0xffff) << 48,
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
index 7377b4b..bb2569f 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -42,7 +42,7 @@
int averageRefreshPeriodNs;
}
parcelable NotifyExpectedPresentConfig {
- int headsUpNs;
- int timeoutNs;
+ int notifyExpectedPresentHeadsUpNs;
+ int notifyExpectedPresentTimeoutNs;
}
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index ec54f2a..725c947 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -895,9 +895,9 @@
*
* The framework will call this function based on the parameters specified in
* DisplayConfiguration.VrrConfig:
- * - timeoutNs specifies the idle time from the previous present command
+ * - notifyExpectedPresentTimeoutNs specifies the idle time from the previous present command
* where the framework must send the early hint for the next frame.
- * - headsUpNs specifies minimal time that framework must send
+ * - notifyExpectedPresentHeadsUpNs specifies minimal time that framework must send
* the early hint before the next frame.
*
* The framework can omit calling this API when the next present command matches
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
index 93667e0..3b241ba 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/VrrConfig.aidl
@@ -45,7 +45,7 @@
* The minimal time in nanoseconds that IComposerClient.notifyExpectedPresent needs to be
* called ahead of an expectedPresentTime provided on a presentDisplay command.
*/
- int headsUpNs;
+ int notifyExpectedPresentHeadsUpNs;
/**
* The time in nanoseconds that represents a timeout from the previous presentDisplay, which
@@ -53,7 +53,7 @@
* sending the next frame. If set to 0, there is no need to call
* IComposerClient.notifyExpectedPresent for timeout.
*/
- int timeoutNs;
+ int notifyExpectedPresentTimeoutNs;
}
/**
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 4a8e3b4..1e6f34b 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1274,8 +1274,8 @@
if (vrrConfig.notifyExpectedPresentConfig) {
const auto& notifyExpectedPresentConfig =
*vrrConfig.notifyExpectedPresentConfig;
- EXPECT_GT(0, notifyExpectedPresentConfig.headsUpNs);
- EXPECT_GE(0, notifyExpectedPresentConfig.timeoutNs);
+ EXPECT_GT(0, notifyExpectedPresentConfig.notifyExpectedPresentHeadsUpNs);
+ EXPECT_GE(0, notifyExpectedPresentConfig.notifyExpectedPresentTimeoutNs);
}
}
}
diff --git a/security/README.md b/security/README.md
new file mode 100644
index 0000000..c5b5ba8
--- /dev/null
+++ b/security/README.md
@@ -0,0 +1,109 @@
+# Security-Related HALs
+
+The `security/` subdirectory holds various security-related HALs. (The final two sections of this
+document also describe security-related HALs that are in other places under `hardware/interfaces/`.)
+
+The most significant HAL is KeyMint (**`IKeyMintDevice`** in the
+`hardware/interfaces/security/keymint/` directory), which allows access to cryptographic
+functionality where the key material is restricted to a secure environment. This functionality is
+used by Android system services, and is also made available to apps via Android Keystore.
+
+A KeyMint implementation (or an implementation of its predecessor, Keymaster) that runs in an
+isolated execution environment (e.g. ARM TrustZone) is required for most Android devices; see [CDD
+9.11](https://source.android.com/docs/compatibility/13/android-13-cdd#911_keys_and_credentials).
+
+A device may optionally also support a second KeyMint instance, running in a dedicated secure
+processor; this is known as StrongBox ([CDD
+9.11.2](https://source.android.com/docs/compatibility/13/android-13-cdd#9112_strongbox)).
+
+Two specific features of KeyMint are worth highlighting, as they have an impact on the other
+security-related HALs:
+
+- KeyMint supports keys that can only be used when the operation is authenticated by the user,
+ either by their lock screen knowledge factor (LSKF, e.g. PIN or pattern) or by a strong biometric
+ (e.g. fingerprint).
+- KeyMint supports *attestation* of public keys: when an asymmetric keypair is created, the secure
+ environment produces a chain of signed certificates:
+ - starting from a trusted root certificate
+ - terminating in a leaf certificate that holds the public key; this leaf certificate may also
+ describe the state of the device and the policies attached to the key.
+
+## Authentication Verification
+
+User authentication must also take place in a secure environment (see the final section below), but
+the results of that authentication are communicated to KeyMint via Android. As such, the
+authentication result (a *hardware auth token*) is signed with a per-boot shared HMAC key known only
+to the secure components, so that it's authenticity can be verified.
+
+If an authenticator, for example GateKeeper (described by the **`IGatekeeper`** HAL in
+`hardware/interfaces/gatekeeper/`), is co-located in the same secure environment as KeyMint, it can
+use a local, vendor-specific, method to communicate the shared HMAC key.
+
+However, if the authenticator is in a different environment than the KeyMint instance then a local
+communication mechanism may not be possible. For example, a StrongBox KeyMint instance running in a
+separate secure processor may not have a communication channel with a TEE on the main processor.
+
+To allow for this, the **`ISharedSecret`** HAL (in `hardware/interfaces/security/sharedsecret`)
+describes an N-party shared key agreement protocol for per-boot derivation of the shared HMAC key,
+based on a pre-provisioned shared secret. This HAL can be implemented by any security component
+– whether KeyMint instance or authenticator – that needs access to the shared HMAC key.
+
+User authentication operations are also timestamped, but a StrongBox KeyMint instance may not have
+access to a secure time source that is aligned with the authenticator's time source.
+
+To allow for this, the **`ISecureClock`** HAL (in `hardware/interfaces/secureclock`) describes a
+challenge-based timestamp authentication protocol. This HAL is optional; it need only be
+implemented if there is a KeyMint instance without a secure source of time.
+
+## Attestation Key Provisioning
+
+As noted above, key generation may also generate an attestation certificate chain, which requires
+that the secure environment have access to a signing key which in turn chains back to the Google
+root.
+
+Historically these signing keys were created by Google and provided to vendors for installation in
+batches of devices (to prevent their use as unique device identifiers). However, this mechanism had
+significant disadvantages, as it required secure handling of key material and only allowed for
+coarse-grained revocation.
+
+The remote key provisioning HAL (**`IRemotelyProvisionedComponent`** in
+`hardware/interfaces/security/rkp/`) provides a mechanism whereby signing certificates for
+attestation can be retrieved at runtime from Google servers based on pre-registered device identity
+information. This mechanism is used to provision certificates for KeyMint's signing keys, but is
+not restricted to that purpose; it can also be used in other scenarios where keys need to be
+provisioned (for example, for [Widevine](https://developers.google.com/widevine/drm/overview)).
+
+## Keymaster
+
+The Keymaster HAL (**`IKeymasterDevice`** in `hardware/interfaces/keymaster/`) is the historical
+ancestor of many of the HALs here (and may still be present on older devices). Its functionality is
+effectively the union of the following current HALs:
+
+- **`IKeyMintDevice`**
+- **`ISharedSecret`**
+- **`ISecureClock`**
+
+## Related Authentication HALs
+
+Authentication of users needs to happen in a secure environment, using vendor-specific
+functionality, and so involves the use of one of the following HALs (all of which are outside the
+`security/` subdirectory).
+
+- The **`IGatekeeper`** HAL (in `hardware/interfaces/gatekeeper/`) provides user authentication
+ functionality based on the user's lock-screen knowledge factor (LSKF), including throttling
+ behaviour to prevent attacks. Authentication tokens produced by this HAL are consumed by KeyMint,
+ validated using the shared HMAC key described above.
+ - The optional **`IWeaver`** HAL (in `hardware/interfaces/weaver`) improves the security of LSKF
+ authentication by converting the user's LSKF into a *synthetic password* via hashing and
+ stretching. This is required to be implemented on a separate secure element, which prevents
+ offline attacks on Gatekeeper storage. Note that Weaver does not directly interact with KeyMint;
+ the synthetic password is fed into Gatekeeper in place of the plain user password, and then
+ Gatekeeper interacts with KeyMint as normal.
+- The **`IFingerprint`** and **`IFace`** HAL definitions (under `hardware/interfaces/biometrics/`)
+ allow access to biometric authentication functionality that is implemented in a secure
+ environment. Authentication tokens produced by these HALs are consumed by KeyMint, validated
+ using the shared HMAC key described above.
+- The optional **`IConfirmationUI`** HAL (in `hardware/interfaces/confirmationui`) supports
+ functionality where the user confirms that they have seen a specific message in a secure manner.
+ Confirmation tokens produced by this HAL are consumed by KeyMint, validated using the shared HMAC
+ key described above.
diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp
index dc0c618..10cbf07 100644
--- a/security/keymint/aidl/default/service.cpp
+++ b/security/keymint/aidl/default/service.cpp
@@ -44,6 +44,8 @@
}
int main() {
+ // The global logger object required by keymaster's logging macros in keymaster/logger.h.
+ keymaster::SoftKeymasterLogger km_logger;
// Zero threads seems like a useless pool, but below we'll join this thread to it, increasing
// the pool size to 1.
ABinderProcess_setThreadPoolMaxThreadCount(0);
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index c9c3e4d..780c3d2 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <iomanip>
#include <iterator>
#include <memory>
#include <set>
@@ -420,6 +421,36 @@
return entryName + " has an invalid value.\n";
}
+std::string checkMapPatchLevelEntry(bool isFactory, const cppbor::Map& devInfo,
+ const std::string& entryName) {
+ std::string error = checkMapEntry(isFactory, devInfo, cppbor::UINT, entryName);
+ if (!error.empty()) {
+ return error;
+ }
+
+ if (isFactory) {
+ return "";
+ }
+
+ const std::unique_ptr<cppbor::Item>& val = devInfo.get(entryName);
+ std::string dateString = std::to_string(val->asUint()->unsignedValue());
+ if (dateString.size() == 6) {
+ dateString += "01";
+ }
+ if (dateString.size() != 8) {
+ return entryName + " should in the format YYYYMMDD or YYYYMM\n";
+ }
+
+ std::tm t;
+ std::istringstream ss(dateString);
+ ss >> std::get_time(&t, "%Y%m%d");
+ if (!ss) {
+ return entryName + " should in the format YYYYMMDD or YYYYMM\n";
+ }
+
+ return "";
+}
+
bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
return devInfo.get("security_level") && devInfo.get("security_level")->asTstr() &&
devInfo.get("security_level")->asTstr()->value() == "tee";
@@ -520,6 +551,10 @@
error += "Err: Unrecognized key entry: <" + key->asTstr()->value() + ">,\n";
}
}
+ // Checks that only apply to v3.
+ error += checkMapPatchLevelEntry(isFactory, *parsed, "system_patch_level");
+ error += checkMapPatchLevelEntry(isFactory, *parsed, "boot_patch_level");
+ error += checkMapPatchLevelEntry(isFactory, *parsed, "vendor_patch_level");
FALLTHROUGH_INTENDED;
case 2:
for (const auto& entry : kAttestationIdEntrySet) {
diff --git a/security/rkp/aidl/Android.bp b/security/rkp/aidl/Android.bp
index e2ce649..e9e2021 100644
--- a/security/rkp/aidl/Android.bp
+++ b/security/rkp/aidl/Android.bp
@@ -28,6 +28,10 @@
},
rust: {
enabled: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
},
},
versions_with_info: [
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index f8a5540..21c5315 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -185,77 +185,7 @@
*
* In either case, the root is self-signed.
*
- * EekChain = [ + SignedSignatureKey, SignedEek ]
- *
- * SignedSignatureKey = [ ; COSE_Sign1
- * protected: bstr .cbor {
- * 1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
- * },
- * unprotected: {},
- * payload: bstr .cbor SignatureKeyEd25519 /
- * bstr .cbor SignatureKeyP256,
- * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
- * bstr ECDSA(.cbor SignatureKeySignatureInput)
- * ]
- *
- * SignatureKeyEd25519 = { ; COSE_Key
- * 1 : 1, ; Key type : Octet Key Pair
- * 3 : AlgorithmEdDSA, ; Algorithm
- * -1 : 6, ; Curve : Ed25519
- * -2 : bstr ; Ed25519 public key
- * }
- *
- * SignatureKeyP256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 3 : AlgorithmES256, ; Algorithm
- * -1 : 1, ; Curve: P256
- * -2 : bstr, ; X coordinate
- * -3 : bstr ; Y coordinate
- * }
- *
- * SignatureKeySignatureInput = [
- * context: "Signature1",
- * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor SignatureKeyEd25519 /
- * bstr .cbor SignatureKeyP256
- * ]
- *
- * ; COSE_Sign1
- * SignedEek = [
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * unprotected: {},
- * payload: bstr .cbor EekX25519 / .cbor EekP256,
- * signature: bstr PureEd25519(.cbor EekSignatureInput) /
- * bstr ECDSA(.cbor EekSignatureInput)
- * ]
- *
- * EekX25519 = { ; COSE_Key
- * 1 : 1, ; Key type : Octet Key Pair
- * 2 : bstr ; KID : EEK ID
- * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
- * -1 : 4, ; Curve : X25519
- * -2 : bstr ; X25519 public key, little-endian
- * }
- *
- * EekP256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 2 : bstr ; KID : EEK ID
- * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
- * -1 : 1, ; Curve : P256
- * -2 : bstr ; Sender X coordinate
- * -3 : bstr ; Sender Y coordinate
- * }
- *
- * EekSignatureInput = [
- * context: "Signature1",
- * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor EekX25519 / .cbor EekP256
- * ]
- *
- * AlgorithmES256 = -7 ; RFC 8152 section 8.1
- * AlgorithmEdDSA = -8 ; RFC 8152 section 8.2
+ * See generateCertificateRequest.cddl for CDDL definitions.
*
* If the contents of endpointEncryptionKey do not match the SignedEek structure above,
* the method must return STATUS_INVALID_EEK.
@@ -283,25 +213,9 @@
* HMAC-256(EK_mac, .cbor KeysToMacStructure)
*
* Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below). The MACed
- * data is the "tag" field of a COSE_Mac0 structure like:
+ * data is the "tag" field of a MacedKeys COSE_Mac0 structure.
*
- * MacedKeys = [ ; COSE_Mac0
- * protected : bstr .cbor {
- * 1 : 5, ; Algorithm : HMAC-256
- * },
- * unprotected : {},
- * ; Payload is PublicKeys from keysToSign argument, in provided order.
- * payload: bstr .cbor [ * PublicKey ],
- * tag: bstr
- * ]
- *
- * KeysToMacStructure = [
- * context : "MAC0",
- * protected : bstr .cbor { 1 : 5 }, ; Algorithm : HMAC-256
- * external_aad : bstr .size 0,
- * ; Payload is PublicKeys from keysToSign argument, in provided order.
- * payload : bstr .cbor [ * PublicKey ]
- * ]
+ * See generateCertificateRequest.cddl for CDDL definitions.
*/
byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
@@ -322,168 +236,9 @@
* use different semantic data for this field, but the supported sizes must be between 0
* and 64 bytes, inclusive.
*
- * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
+ * @return a CBOR Certificate Signing Request (Csr) serialized into a byte array.
*
- * Csr = AuthenticatedRequest<CsrPayload>
- *
- * CsrPayload = [ ; CBOR Array defining the payload for Csr
- * version: 3, ; The CsrPayload CDDL Schema version.
- * CertificateType, ; The type of certificate being requested.
- * DeviceInfo, ; Defined in DeviceInfo.aidl
- * KeysToSign, ; Provided by the method parameters
- * ]
- *
- * ; A tstr identifying the type of certificate. The set of supported certificate types may
- * ; be extended without requiring a version bump of the HAL. Custom certificate types may
- * ; be used, but the provisioning server may reject the request for an unknown certificate
- * ; type. The currently defined certificate types are:
- * ; - "widevine"
- * ; - "keymint"
- * CertificateType = tstr
- *
- * KeysToSign = [ * PublicKey ] ; Please see MacedPublicKey.aidl for the PublicKey definition.
- *
- * AuthenticatedRequest<T> = [
- * version: 1, ; The AuthenticatedRequest CDDL Schema version.
- * UdsCerts,
- * DiceCertChain,
- * SignedData<[
- * challenge: bstr .size (0..64), ; Provided by the method parameters
- * bstr .cbor T,
- * ]>,
- * ]
- *
- * ; COSE_Sign1 (untagged)
- * SignedData<Data> = [
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
- * unprotected: {},
- * payload: bstr .cbor Data / nil,
- * signature: bstr ; PureEd25519(CDI_Leaf_Priv, SignedDataSigStruct<Data>) /
- * ; ECDSA(CDI_Leaf_Priv, SignedDataSigStruct<Data>)
- * ]
- *
- * ; Sig_structure for SignedData
- * SignedDataSigStruct<Data> = [
- * context: "Signature1",
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor Data / nil,
- * ]
- *
- * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
- * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
- * ; The SignerName is a free-form string describing who generated the signature. The root
- * ; certificate will need to be communicated to the verifier out of band, along with the
- * ; SignerName that is expected for the given root certificate.
- * UdsCerts = {
- * * SignerName => UdsCertChain
- * }
- *
- * ; SignerName is a string identifier that indicates both the signing authority as
- * ; well as the format of the UdsCertChain
- * SignerName = tstr
- *
- * UdsCertChain = [
- * 2* X509Certificate ; Root -> ... -> Leaf. "Root" is the vendor self-signed
- * ; cert, "Leaf" contains UDS_Public. There may also be
- * ; intermediate certificates between Root and Leaf.
- * ]
- *
- * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
- * X509Certificate = bstr
- *
- * ; The DICE Chain contains measurements about the device firmware.
- * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
- * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
- * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
- * DiceCertChain = [
- * PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384, ; UDS_Pub
- * + DiceChainEntry, ; First CDI_Certificate -> Last CDI_Certificate
- * ; Last certificate corresponds to KeyMint's DICE key.
- * ]
- *
- * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
- * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
- * ; defines its own configuration values for the Configuration Descriptor field. See
- * ; the Open Profile for DICE for more details on the fields. SHA256, SHA384 and SHA512 are
- * ; acceptable hash algorithms. The digest bstr values in the payload are the digest values
- * ; without any padding. Note that this implies that the digest is a 32-byte bstr for SHA256
- * ; and a 48-byte bstr for SHA384. This is an intentional, minor deviation from Open Profile
- * ; for DICE, which specifies all digests are 64 bytes.
- * DiceChainEntryPayload = { ; CWT [RFC8392]
- * 1 : tstr, ; Issuer
- * 2 : tstr, ; Subject
- * -4670552 : bstr .cbor PubKeyEd25519 /
- * bstr .cbor PubKeyECDSA256 /
- * bstr .cbor PubKeyECDSA384, ; Subject Public Key
- * -4670553 : bstr ; Key Usage
- *
- * ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
- * ; described above.
- * -4670545 : bstr, ; Code Hash
- * ? -4670546 : bstr, ; Code Descriptor
- * -4670547 : bstr, ; Configuration Hash
- * -4670548 : bstr .cbor { ; Configuration Descriptor
- * ? -70002 : tstr, ; Component name
- * ? -70003 : int / tstr, ; Component version
- * ? -70004 : null, ; Resettable
- * ? -70005 : uint, ; Security version
- * },
- * -4670549 : bstr, ; Authority Hash
- * ? -4670550 : bstr, ; Authority Descriptor
- * -4670551 : bstr, ; Mode
- * }
- *
- * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
- * ; entry in the DICE chain array.
- * DiceChainEntry = [ ; COSE_Sign1 (untagged)
- * protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
- * unprotected: {},
- * payload: bstr .cbor DiceChainEntryPayload,
- * signature: bstr ; PureEd25519(SigningKey, DiceChainEntryInput) /
- * ; ECDSA(SigningKey, DiceChainEntryInput)
- * ; See RFC 8032 for details of how to encode the signature value
- * ; for Ed25519.
- * ]
- *
- * DiceChainEntryInput = [
- * context: "Signature1",
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor DiceChainEntryPayload
- * ]
- *
- * ; The following section defines some types that are reused throughout the above
- * ; data structures.
- * ; NOTE: Integer encoding is different for Ed25519 and P256 keys:
- * ; - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
- * ; - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
- * PubKeyEd25519 = { ; COSE_Key
- * 1 : 1, ; Key type : octet key pair
- * 3 : AlgorithmEdDSA, ; Algorithm : EdDSA
- * -1 : 6, ; Curve : Ed25519
- * -2 : bstr ; X coordinate, little-endian
- * }
- *
- * PubKeyECDSA256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 3 : AlgorithmES256, ; Algorithm : ECDSA w/ SHA-256
- * -1 : 1, ; Curve: P256
- * -2 : bstr, ; X coordinate, big-endian
- * -3 : bstr ; Y coordinate, big-endian
- * }
- *
- * PubKeyECDSA384 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 3 : AlgorithmES384, ; Algorithm : ECDSA w/ SHA-384
- * -1 : 2, ; Curve: P384
- * -2 : bstr, ; X coordinate
- * -3 : bstr ; Y coordinate
- * }
- *
- * AlgorithmES256 = -7
- * AlgorithmES384 = -35
- * AlgorithmEdDSA = -8
+ * See generateCertificateRequestV2.cddl for CDDL definitions.
*/
byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
}
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl
new file mode 100644
index 0000000..82930bc
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequest.cddl
@@ -0,0 +1,92 @@
+; CDDL for the deprecated version 1 generateCertificateRequest method
+; in IRemotelyProvisionedComponent.aidl
+
+EekChain = [ + SignedSignatureKey, SignedEek ]
+
+SignedSignatureKey = [ ; COSE_Sign1
+ protected: bstr .cbor {
+ 1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
+ },
+ unprotected: {},
+ payload: bstr .cbor SignatureKeyEd25519 /
+ bstr .cbor SignatureKeyP256,
+ signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
+ bstr ECDSA(.cbor SignatureKeySignatureInput)
+]
+
+SignatureKeyEd25519 = { ; COSE_Key
+ 1 : 1, ; Key type : Octet Key Pair
+ 3 : AlgorithmEdDSA, ; Algorithm
+ -1 : 6, ; Curve : Ed25519
+ -2 : bstr ; Ed25519 public key
+}
+
+SignatureKeyP256 = { ; COSE_Key
+ 1 : 2, ; Key type : EC2
+ 3 : AlgorithmES256, ; Algorithm
+ -1 : 1, ; Curve: P256
+ -2 : bstr, ; X coordinate
+ -3 : bstr ; Y coordinate
+}
+
+SignatureKeySignatureInput = [
+ context: "Signature1",
+ body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ external_aad: bstr .size 0,
+ payload: bstr .cbor SignatureKeyEd25519 /
+ bstr .cbor SignatureKeyP256
+]
+
+; COSE_Sign1
+SignedEek = [
+ protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ unprotected: {},
+ payload: bstr .cbor EekX25519 / .cbor EekP256,
+ signature: bstr PureEd25519(.cbor EekSignatureInput) /
+ bstr ECDSA(.cbor EekSignatureInput)
+]
+
+EekX25519 = { ; COSE_Key
+ 1 : 1, ; Key type : Octet Key Pair
+ 2 : bstr ; KID : EEK ID
+ 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
+ -1 : 4, ; Curve : X25519
+ -2 : bstr ; X25519 public key, little-endian
+}
+
+EekP256 = { ; COSE_Key
+ 1 : 2, ; Key type : EC2
+ 2 : bstr ; KID : EEK ID
+ 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
+ -1 : 1, ; Curve : P256
+ -2 : bstr ; Sender X coordinate
+ -3 : bstr ; Sender Y coordinate
+}
+
+EekSignatureInput = [
+ context: "Signature1",
+ body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ external_aad: bstr .size 0,
+ payload: bstr .cbor EekX25519 / .cbor EekP256
+]
+
+AlgorithmES256 = -7 ; RFC 8152 section 8.1
+AlgorithmEdDSA = -8 ; RFC 8152 section 8.2
+
+MacedKeys = [ ; COSE_Mac0
+ protected : bstr .cbor {
+ 1 : 5, ; Algorithm : HMAC-256
+ },
+ unprotected : {},
+ ; Payload is PublicKeys from keysToSign argument, in provided order.
+ payload: bstr .cbor [ * PublicKey ],
+ tag: bstr
+]
+
+KeysToMacStructure = [
+ context : "MAC0",
+ protected : bstr .cbor { 1 : 5 }, ; Algorithm : HMAC-256
+ external_aad : bstr .size 0,
+ ; Payload is PublicKeys from keysToSign argument, in provided order.
+ payload : bstr .cbor [ * PublicKey ]
+]
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
new file mode 100644
index 0000000..ea71f98
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -0,0 +1,163 @@
+; CDDL for the generateCertificateRequestV2 method in
+; IRemotelyProvisionedComponent.aidl
+
+Csr = AuthenticatedRequest<CsrPayload>
+
+CsrPayload = [ ; CBOR Array defining the payload for Csr
+ version: 3, ; The CsrPayload CDDL Schema version.
+ CertificateType, ; The type of certificate being requested.
+ DeviceInfo, ; Defined in DeviceInfo.aidl
+ KeysToSign, ; Provided by the method parameters
+]
+
+; A tstr identifying the type of certificate. The set of supported certificate types may
+; be extended without requiring a version bump of the HAL. Custom certificate types may
+; be used, but the provisioning server may reject the request for an unknown certificate
+; type. The currently defined certificate types are:
+; - "widevine"
+; - "keymint"
+CertificateType = tstr
+
+KeysToSign = [ * PublicKey ] ; Please see MacedPublicKey.aidl for the PublicKey definition.
+
+AuthenticatedRequest<T> = [
+ version: 1, ; The AuthenticatedRequest CDDL Schema version.
+ UdsCerts,
+ DiceCertChain,
+ SignedData<[
+ challenge: bstr .size (0..64), ; Provided by the method parameters
+ bstr .cbor T,
+ ]>,
+]
+
+; COSE_Sign1 (untagged)
+SignedData<Data> = [
+ protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+ unprotected: {},
+ payload: bstr .cbor Data / nil,
+ signature: bstr ; PureEd25519(CDI_Leaf_Priv, SignedDataSigStruct<Data>) /
+ ; ECDSA(CDI_Leaf_Priv, SignedDataSigStruct<Data>)
+]
+
+; Sig_structure for SignedData
+SignedDataSigStruct<Data> = [
+ context: "Signature1",
+ protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+ external_aad: bstr .size 0,
+ payload: bstr .cbor Data / nil,
+]
+
+; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
+; example, this could be provided by the hardware vendor, who certifies all of their chips.
+; The SignerName is a free-form string describing who generated the signature. The root
+; certificate will need to be communicated to the verifier out of band, along with the
+; SignerName that is expected for the given root certificate.
+UdsCerts = {
+ * SignerName => UdsCertChain
+}
+
+; SignerName is a string identifier that indicates both the signing authority as
+; well as the format of the UdsCertChain
+SignerName = tstr
+
+UdsCertChain = [
+ 2* X509Certificate ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+ ; cert, "Leaf" contains UDS_Public. There may also be
+ ; intermediate certificates between Root and Leaf.
+]
+
+; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
+X509Certificate = bstr
+
+; The DICE Chain contains measurements about the device firmware.
+; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
+; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
+; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+DiceCertChain = [
+ PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384, ; UDS_Pub
+ + DiceChainEntry, ; First CDI_Certificate -> Last CDI_Certificate
+ ; Last certificate corresponds to KeyMint's DICE key.
+]
+
+; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
+; defines its own configuration values for the Configuration Descriptor field. See
+; the Open Profile for DICE for more details on the fields. SHA256, SHA384 and SHA512 are
+; acceptable hash algorithms. The digest bstr values in the payload are the digest values
+; without any padding. Note that this implies that the digest is a 32-byte bstr for SHA256
+; and a 48-byte bstr for SHA384. This is an intentional, minor deviation from Open Profile
+; for DICE, which specifies all digests are 64 bytes.
+DiceChainEntryPayload = { ; CWT [RFC8392]
+ 1 : tstr, ; Issuer
+ 2 : tstr, ; Subject
+ -4670552 : bstr .cbor PubKeyEd25519 /
+ bstr .cbor PubKeyECDSA256 /
+ bstr .cbor PubKeyECDSA384, ; Subject Public Key
+ -4670553 : bstr ; Key Usage
+
+ ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
+ ; described above.
+ -4670545 : bstr, ; Code Hash
+ ? -4670546 : bstr, ; Code Descriptor
+ -4670547 : bstr, ; Configuration Hash
+ -4670548 : bstr .cbor { ; Configuration Descriptor
+ ? -70002 : tstr, ; Component name
+ ? -70003 : int / tstr, ; Component version
+ ? -70004 : null, ; Resettable
+ ? -70005 : uint, ; Security version
+ },
+ -4670549 : bstr, ; Authority Hash
+ ? -4670550 : bstr, ; Authority Descriptor
+ -4670551 : bstr, ; Mode
+}
+
+; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+; entry in the DICE chain array.
+DiceChainEntry = [ ; COSE_Sign1 (untagged)
+ protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+ unprotected: {},
+ payload: bstr .cbor DiceChainEntryPayload,
+ signature: bstr ; PureEd25519(SigningKey, DiceChainEntryInput) /
+ ; ECDSA(SigningKey, DiceChainEntryInput)
+ ; See RFC 8032 for details of how to encode the signature value
+ ; for Ed25519.
+]
+
+DiceChainEntryInput = [
+ context: "Signature1",
+ protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 / AlgorithmES384 },
+ external_aad: bstr .size 0,
+ payload: bstr .cbor DiceChainEntryPayload
+]
+
+; The following section defines some types that are reused throughout the above
+; data structures.
+; NOTE: Integer encoding is different for Ed25519 and P256 keys:
+; - Ed25519 is LE: https://www.rfc-editor.org/rfc/rfc8032#section-3.1
+; - P256 is BE: https://www.secg.org/sec1-v2.pdf#page=19 (section 2.3.7)
+PubKeyEd25519 = { ; COSE_Key
+ 1 : 1, ; Key type : octet key pair
+ 3 : AlgorithmEdDSA, ; Algorithm : EdDSA
+ -1 : 6, ; Curve : Ed25519
+ -2 : bstr ; X coordinate, little-endian
+}
+
+PubKeyECDSA256 = { ; COSE_Key
+ 1 : 2, ; Key type : EC2
+ 3 : AlgorithmES256, ; Algorithm : ECDSA w/ SHA-256
+ -1 : 1, ; Curve: P256
+ -2 : bstr, ; X coordinate, big-endian
+ -3 : bstr ; Y coordinate, big-endian
+}
+
+PubKeyECDSA384 = { ; COSE_Key
+ 1 : 2, ; Key type : EC2
+ 3 : AlgorithmES384, ; Algorithm : ECDSA w/ SHA-384
+ -1 : 2, ; Curve: P384
+ -2 : bstr, ; X coordinate
+ -3 : bstr ; Y coordinate
+}
+
+AlgorithmES256 = -7
+AlgorithmES384 = -35
+AlgorithmEdDSA = -8
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 02f8209..fae30c0 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -89,6 +89,24 @@
ChipModeId mode_id;
return configureChipToSupportIfaceTypeInternal(wifi_chip, type, &mode_id);
}
+
+bool doesChipSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
+ IfaceType type) {
+ ChipModeId mode_id;
+ if (!wifi_chip.get()) {
+ return false;
+ }
+ const auto& status_and_modes = HIDL_INVOKE(wifi_chip, getAvailableModes);
+ if (status_and_modes.first.code != WifiStatusCode::SUCCESS) {
+ return false;
+ }
+ if (!findAnyModeSupportingIfaceType(type, status_and_modes.second,
+ &mode_id)) {
+ return false;
+ }
+
+ return true;
+}
} // namespace
sp<IWifi> getWifi(const std::string& instance_name) {
@@ -205,6 +223,11 @@
configured_mode_id);
}
+bool doesChipSupportIfaceType(const sp<IWifiChip>& wifi_chip,
+ IfaceType type) {
+ return doesChipSupportIfaceTypeInternal(wifi_chip, type);
+}
+
void stopWifi(const std::string& instance_name) {
sp<IWifi> wifi = IWifi::getService(instance_name);
ASSERT_NE(wifi, nullptr);
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index 62c015c..876c316 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -49,6 +49,10 @@
const android::sp<android::hardware::wifi::V1_0::IWifiChip>& wifi_chip,
android::hardware::wifi::V1_0::IfaceType type,
android::hardware::wifi::V1_0::ChipModeId* configured_mode_id);
+// Check whether wifi chip supports given interface type mode
+bool doesChipSupportIfaceType(
+ const android::sp<android::hardware::wifi::V1_0::IWifiChip>& wifi_chip,
+ android::hardware::wifi::V1_0::IfaceType type);
// Used to trigger IWifi.stop() at the end of every test.
void stopWifi(const std::string& instance_name);
uint32_t getChipCapabilitiesLatest(
diff --git a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
index 424f934..c3bd4d7 100644
--- a/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.5/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -58,12 +58,16 @@
"wifi_softap_bridged_ap_supported");
// Make sure to start with a clean state
stopWifi(GetInstanceName());
+ // Read AP mode capabilities from the wifi chip modes
+ sp<IWifiChip> wifi_chip_ = getWifiChip_1_5(GetInstanceName());
+ isApModeSupport_ = doesChipSupportIfaceType(wifi_chip_, IfaceType::AP);
}
virtual void TearDown() override { stopWifi(GetInstanceName()); }
protected:
bool isBridgedSupport_ = false;
+ bool isApModeSupport_ = false;
std::string GetInstanceName() { return GetParam(); }
};
@@ -83,6 +87,7 @@
* resetToFactoryMacAddress in non-bridged mode
*/
TEST_P(WifiApIfaceHidlTest, resetToFactoryMacAddressTest) {
+ if (!isApModeSupport_) GTEST_SKIP() << "Missing AP support";
sp<IWifiApIface> wifi_ap_iface = getWifiApIface_1_5(GetInstanceName());
ASSERT_NE(nullptr, wifi_ap_iface.get());
const auto& status = HIDL_INVOKE(wifi_ap_iface, resetToFactoryMacAddress);
@@ -93,6 +98,7 @@
* getBridgedInstances in non-bridged mode
*/
TEST_P(WifiApIfaceHidlTest, getBridgedInstancesTest) {
+ if (!isApModeSupport_) GTEST_SKIP() << "Missing AP support";
sp<IWifiApIface> wifi_ap_iface = getWifiApIface_1_5(GetInstanceName());
ASSERT_NE(nullptr, wifi_ap_iface.get());
const auto& status_and_instances =
diff --git a/wifi/aidl/default/wifi_feature_flags.cpp b/wifi/aidl/default/wifi_feature_flags.cpp
index 3c9f042..35b4b4a 100644
--- a/wifi/aidl/default/wifi_feature_flags.cpp
+++ b/wifi/aidl/default/wifi_feature_flags.cpp
@@ -122,6 +122,7 @@
#define AP IfaceConcurrencyType::AP
#define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED
#define P2P IfaceConcurrencyType::P2P
+#undef NAN // undefine NAN from math.h
#define NAN IfaceConcurrencyType::NAN_IFACE
static const std::vector<IWifiChip::ChipMode> kChipModesPrimary{
{kMainModeId, legacyToChipConcurrencyComboList({WIFI_HAL_INTERFACE_COMBINATIONS})},
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 75d6252..56f285d 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -41,10 +41,9 @@
using ::android::wifi_system::HostapdManager;
using ::android::wifi_system::SupplicantManager;
-namespace {
// Helper function to initialize the driver and firmware to AP mode
// using the vendor HAL HIDL interface.
-void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+void initializeDriverAndFirmware(const std::string& wifi_instance_name) {
if (getWifi(wifi_instance_name) != nullptr) {
sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
ChipModeId mode_id;
@@ -57,21 +56,20 @@
// Helper function to deinitialize the driver and firmware
// using the vendor HAL HIDL interface.
-void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name) {
if (getWifi(wifi_instance_name) != nullptr) {
stopWifi(wifi_instance_name);
} else {
LOG(WARNING) << __func__ << ": Vendor HAL not supported";
}
}
-} // namespace
void stopSupplicantIfNeeded(const std::string& instance_name) {
SupplicantManager supplicant_manager;
if (supplicant_manager.IsSupplicantRunning()) {
LOG(INFO) << "Supplicant is running, stop supplicant first.";
ASSERT_TRUE(supplicant_manager.StopSupplicant());
- deInitilializeDriverAndFirmware(instance_name);
+ deInitializeDriverAndFirmware(instance_name);
ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
}
}
@@ -80,13 +78,13 @@
HostapdManager hostapd_manager;
ASSERT_TRUE(hostapd_manager.StopHostapd());
- deInitilializeDriverAndFirmware(instance_name);
+ deInitializeDriverAndFirmware(instance_name);
}
void startHostapdAndWaitForHidlService(
const std::string& wifi_instance_name,
const std::string& hostapd_instance_name) {
- initilializeDriverAndFirmware(wifi_instance_name);
+ initializeDriverAndFirmware(wifi_instance_name);
HostapdManager hostapd_manager;
ASSERT_TRUE(hostapd_manager.StartHostapd());
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
index 5cb4f01..893de1e 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -33,5 +33,9 @@
bool is_1_1(const android::sp<android::hardware::wifi::hostapd::V1_0::IHostapd>&
hostapd);
+// Used to initialize/deinitialize the driver and firmware at the
+// beginning and end of each test.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name);
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name);
#endif /* HOSTAPD_HIDL_TEST_UTILS_H */
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index 33318a4..ff35056 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -37,6 +37,7 @@
"android.hardware.wifi@1.5",
"android.hardware.wifi@1.6",
"android.hardware.wifi-V1-ndk",
+ "libwifi-system",
"libwifi-system-iface",
"VtsHalWifiTargetTestUtil",
],
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index efd1538..137537d 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -32,6 +32,7 @@
#include <wifi_hidl_test_utils_1_5.h>
#include <wifi_hidl_test_utils_1_6.h>
+#include "hostapd_test_utils.h"
#include "wifi_aidl_test_utils.h"
using aidl::android::hardware::wifi::hostapd::BandMask;
@@ -56,10 +57,7 @@
const int kIfaceChannel = 6;
const int kIfaceInvalidChannel = 567;
const std::vector<uint8_t> kTestZeroMacAddr(6, 0x0);
-const Ieee80211ReasonCode kTestDisconnectReasonCode =
- Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
-const std::string kWifiAidlInstanceNameStr = std::string() + IWifi::descriptor + "/default";
-const char* kWifiAidlInstanceName = kWifiAidlInstanceNameStr.c_str();
+const Ieee80211ReasonCode kTestDisconnectReasonCode = Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
inline BandMask operator|(BandMask a, BandMask b) {
return static_cast<BandMask>(static_cast<int32_t>(a) |
@@ -70,10 +68,13 @@
class HostapdAidl : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
- hostapd = IHostapd::fromBinder(ndk::SpAIBinder(
- AServiceManager_waitForService(GetParam().c_str())));
+ disableHalsAndFramework();
+ initializeHostapdAndVendorHal(GetParam());
+
+ hostapd = getHostapd(GetParam());
ASSERT_NE(hostapd, nullptr);
EXPECT_TRUE(hostapd->setDebugParams(DebugLevel::EXCESSIVE).isOk());
+
isAcsSupport = testing::checkSubstringInCommandOutput(
"/system/bin/cmd wifi get-softap-supported-features",
"wifi_softap_acs_supported");
@@ -81,81 +82,23 @@
"/system/bin/cmd wifi get-softap-supported-features",
"wifi_softap_wpa3_sae_supported");
isBridgedSupport = testing::checkSubstringInCommandOutput(
- "/system/bin/cmd wifi get-softap-supported-features",
- "wifi_softap_bridged_ap_supported");
- if (!isAidlServiceAvailable(kWifiAidlInstanceName)) {
- const std::vector<std::string> instances = android::hardware::getAllHalInstanceNames(
- ::android::hardware::wifi::V1_0::IWifi::descriptor);
- EXPECT_NE(0, instances.size());
- wifiHidlInstanceName = instances[0];
- }
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
}
virtual void TearDown() override {
- stopVendorHal();
hostapd->terminate();
// Wait 3 seconds to allow terminate to complete
sleep(3);
+ stopHostapdAndVendorHal();
+ startWifiFramework();
}
std::shared_ptr<IHostapd> hostapd;
- std::string wifiHidlInstanceName;
bool isAcsSupport;
bool isWpa3SaeSupport;
bool isBridgedSupport;
- void stopVendorHal() {
- if (isAidlServiceAvailable(kWifiAidlInstanceName)) {
- // HIDL and AIDL versions of getWifi() take different arguments
- // i.e. const char* vs string
- if (getWifi(kWifiAidlInstanceName) != nullptr) {
- stopWifiService(kWifiAidlInstanceName);
- }
- } else {
- if (getWifi(wifiHidlInstanceName) != nullptr) {
- stopWifi(wifiHidlInstanceName);
- }
- }
- }
-
- std::string setupApIfaceAndGetName(bool isBridged) {
- if (isAidlServiceAvailable(kWifiAidlInstanceName)) {
- return setupApIfaceAndGetNameAidl(isBridged);
- } else {
- return setupApIfaceAndGetNameHidl(isBridged);
- }
- }
-
- std::string setupApIfaceAndGetNameAidl(bool isBridged) {
- std::shared_ptr<IWifiApIface> wifi_ap_iface;
- if (isBridged) {
- wifi_ap_iface = getBridgedWifiApIface(kWifiAidlInstanceName);
- } else {
- wifi_ap_iface = getWifiApIface(kWifiAidlInstanceName);
- }
- EXPECT_NE(nullptr, wifi_ap_iface.get());
-
- std::string ap_iface_name;
- auto status = wifi_ap_iface->getName(&ap_iface_name);
- EXPECT_TRUE(status.isOk());
- return ap_iface_name;
- }
-
- std::string setupApIfaceAndGetNameHidl(bool isBridged) {
- android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface;
- if (isBridged) {
- wifi_ap_iface = getBridgedWifiApIface_1_6(wifiHidlInstanceName);
- } else {
- wifi_ap_iface = getWifiApIface_1_5(wifiHidlInstanceName);
- }
- EXPECT_NE(nullptr, wifi_ap_iface.get());
-
- const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
- EXPECT_EQ(android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS,
- status_and_name.first.code);
- return status_and_name.second;
- }
-
IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
IfaceParams iface_params;
ChannelParams channelParams;
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
new file mode 100644
index 0000000..93540b2
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_aidl_test_utils.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+#include <android-base/logging.h>
+
+#include "wifi_aidl_test_utils.h"
+
+namespace {
+
+const std::string kWifiInstanceNameStr = std::string() + IWifi::descriptor + "/default";
+const char* kWifiInstanceName = kWifiInstanceNameStr.c_str();
+
+} // namespace
+
+namespace HostapdAidlTestUtils {
+
+bool useAidlService() {
+ return isAidlServiceAvailable(kWifiInstanceName);
+}
+
+void startAndConfigureVendorHal() {
+ if (getWifi(kWifiInstanceName) != nullptr) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(kWifiInstanceName);
+ int mode_id;
+ EXPECT_TRUE(configureChipToSupportConcurrencyType(wifi_chip, IfaceConcurrencyType::AP,
+ &mode_id));
+ } else {
+ LOG(ERROR) << "Unable to initialize Vendor HAL";
+ }
+}
+
+void stopVendorHal() {
+ if (getWifi(kWifiInstanceName) != nullptr) {
+ stopWifiService(kWifiInstanceName);
+ } else {
+ LOG(ERROR) << "Unable to stop Vendor HAL";
+ }
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface;
+ if (isBridged) {
+ wifi_ap_iface = getBridgedWifiApIface(kWifiInstanceName);
+ } else {
+ wifi_ap_iface = getWifiApIface(kWifiInstanceName);
+ }
+
+ EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
+ if (!wifi_ap_iface.get()) {
+ LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged;
+ return "";
+ }
+
+ std::string ap_iface_name;
+ auto status = wifi_ap_iface->getName(&ap_iface_name);
+ EXPECT_TRUE(status.isOk());
+ if (!status.isOk()) {
+ LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged;
+ return "";
+ }
+ return ap_iface_name;
+}
+
+} // namespace HostapdAidlTestUtils
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h
new file mode 100644
index 0000000..fb59dc2
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_legacy_test_utils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+#include "hostapd_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::hardware::wifi::V1_0::WifiStatus;
+
+namespace {
+
+std::string getWifiInstanceName() {
+ const std::vector<std::string> instances = android::hardware::getAllHalInstanceNames(
+ ::android::hardware::wifi::V1_0::IWifi::descriptor);
+ EXPECT_NE(0, instances.size());
+ return instances.size() != 0 ? instances[0] : "";
+}
+
+} // namespace
+
+namespace HostapdLegacyTestUtils {
+
+void startAndConfigureVendorHal() {
+ initializeDriverAndFirmware(getWifiInstanceName());
+}
+
+void stopVendorHal() {
+ deInitializeDriverAndFirmware(getWifiInstanceName());
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+ android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface;
+ if (isBridged) {
+ wifi_ap_iface = getBridgedWifiApIface_1_6(getWifiInstanceName());
+ } else {
+ wifi_ap_iface = getWifiApIface_1_5(getWifiInstanceName());
+ }
+
+ EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
+ if (!wifi_ap_iface.get()) {
+ LOG(ERROR) << "Unable to create iface. isBridged=" << isBridged;
+ return "";
+ }
+
+ const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
+ EXPECT_TRUE(status_and_name.first.code ==
+ android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS);
+ if (status_and_name.first.code != android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS) {
+ LOG(ERROR) << "Unable to retrieve iface name. isBridged=" << isBridged;
+ return "";
+ }
+ return status_and_name.second;
+}
+
+} // namespace HostapdLegacyTestUtils
diff --git a/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h
new file mode 100644
index 0000000..feee2c8
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/hostapd_test_utils.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
+#include <android-base/logging.h>
+#include <wifi_system/hostapd_manager.h>
+#include <wifi_system/supplicant_manager.h>
+
+#include "hostapd_aidl_test_utils.h"
+#include "hostapd_legacy_test_utils.h"
+
+using aidl::android::hardware::wifi::hostapd::IHostapd;
+using android::wifi_system::HostapdManager;
+using android::wifi_system::SupplicantManager;
+
+namespace {
+
+void startAndConfigureVendorHal() {
+ if (HostapdAidlTestUtils::useAidlService()) {
+ HostapdAidlTestUtils::startAndConfigureVendorHal();
+ } else {
+ HostapdLegacyTestUtils::startAndConfigureVendorHal();
+ }
+}
+
+void stopVendorHal() {
+ if (HostapdAidlTestUtils::useAidlService()) {
+ HostapdAidlTestUtils::stopVendorHal();
+ } else {
+ HostapdLegacyTestUtils::stopVendorHal();
+ }
+}
+
+void stopHostapd() {
+ HostapdManager hostapd_manager;
+ ASSERT_TRUE(hostapd_manager.StopHostapd());
+}
+
+void waitForSupplicantState(bool enable) {
+ SupplicantManager supplicant_manager;
+ int count = 50; // wait at most 5 seconds
+ while (count-- > 0) {
+ if (supplicant_manager.IsSupplicantRunning() == enable) {
+ return;
+ }
+ usleep(100000); // 100 ms
+ }
+ LOG(ERROR) << "Unable to " << (enable ? "start" : "stop") << " supplicant";
+}
+
+void toggleWifiFramework(bool enable) {
+ if (enable) {
+ std::system("svc wifi enable");
+ std::system("cmd wifi set-scan-always-available enabled");
+ waitForSupplicantState(true);
+ } else {
+ std::system("svc wifi disable");
+ std::system("cmd wifi set-scan-always-available disabled");
+ waitForSupplicantState(false);
+ }
+}
+
+} // namespace
+
+std::shared_ptr<IHostapd> getHostapd(const std::string& hostapd_instance_name) {
+ return IHostapd::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(hostapd_instance_name.c_str())));
+}
+
+/**
+ * Disable the Wifi framework, hostapd, and vendor HAL.
+ *
+ * Note: The framework should be disabled to avoid having
+ * any other clients to the HALs during testing.
+ */
+void disableHalsAndFramework() {
+ toggleWifiFramework(false);
+ stopHostapd();
+ stopVendorHal();
+
+ // Wait for the services to stop.
+ sleep(3);
+}
+
+void initializeHostapdAndVendorHal(const std::string& hostapd_instance_name) {
+ startAndConfigureVendorHal();
+ HostapdManager hostapd_manager;
+ ASSERT_TRUE(hostapd_manager.StartHostapd());
+ getHostapd(hostapd_instance_name);
+}
+
+void stopHostapdAndVendorHal() {
+ stopHostapd();
+ stopVendorHal();
+}
+
+void startWifiFramework() {
+ toggleWifiFramework(true);
+}
+
+std::string setupApIfaceAndGetName(bool isBridged) {
+ if (HostapdAidlTestUtils::useAidlService()) {
+ return HostapdAidlTestUtils::setupApIfaceAndGetName(isBridged);
+ } else {
+ return HostapdLegacyTestUtils::setupApIfaceAndGetName(isBridged);
+ }
+}