From 8f294378e28f12235e61be6fa38016a7f662258a Mon Sep 17 00:00:00 2001 From: Bharani Bhuvanagiri Date: Mon, 11 Aug 2025 17:28:44 +0530 Subject: [PATCH] Add: Qualcomm User Data Encryption test script & Document - Checks for fscryptctl binary presence - Creates a random sw encryption key - Applies and verifies encryption policy - Confirms functionality with a test file - Added yaml config Signed-off-by: Bharani Bhuvanagiri --- .../README_UserDataEncryption.md | 99 ++++++++ .../UserDataEncryption.yaml | 21 ++ .../Kernel/Baseport/UserDataEncryption/run.sh | 216 ++++++++++++++++++ 3 files changed, 336 insertions(+) create mode 100644 Runner/suites/Kernel/Baseport/UserDataEncryption/README_UserDataEncryption.md create mode 100644 Runner/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.yaml create mode 100755 Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh diff --git a/Runner/suites/Kernel/Baseport/UserDataEncryption/README_UserDataEncryption.md b/Runner/suites/Kernel/Baseport/UserDataEncryption/README_UserDataEncryption.md new file mode 100644 index 00000000..22cdc922 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/README_UserDataEncryption.md @@ -0,0 +1,99 @@ +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause-Clear + +# Qualcomm UserDataEncryption Functionality Test Script +## Overview + +The `UserDataEncryption` test script verifies basic filesystem encryption functionality. It generates a 64-byte key, adds it to the system, applies an encryption policy to a mount directory, and confirms the setup by creating and reading a test file. This ensures that key management and encryption policies work as expected. + +## Features + +- **Dependency Check**: Verifies the presence of the `fscryptctl` binary. +- **Key Management**: Generates a 64-byte key and adds it to the filesystem. +- **Encryption Policy**: Applies and verifies encryption policy on a mount directory. +- **Functional Validation**: Creates and reads a test file to confirm encryption functionality. +- **Automated Result Logging**: Outputs test results to a `.res` file for automated result collection. + +## Prerequisites + +Ensure the following components are present on the target device: + +- `fscryptctl` binary available in `/data/` +- Sufficient permissions to create and mount directories + +## Directory Structure +``` +Runner/ +├── suites/ +│ ├── Kernel/ +│ │ │ ├── baseport/ +│ │ │ │ ├── UserDataEncryption/ +│ │ │ │ │ ├── run.sh +``` +## Usage + +1. Copy repo to Target Device: Use scp to transfer the scripts from the host to the target device. The scripts should be copied to the ```/``` directory on the target device. + +2. Verify Transfer: Ensure that the repo have been successfully copied to the ```/``` directory on the target device. + +3. Run Scripts: Navigate to the ```/``` directory on the target device and execute the scripts as needed. + +--- +Quick Example +``` +git clone +cd +scp -r common Runner user@target_device_ip:/ +ssh user@target_device_ip +cd //Runner && ./run-test.sh UserDataEncryption + +Sample output: +sh-5.2# ./run-test.sh UserDataEncryption +[Executing test case: UserDataEncryption] 2025-11-18 15:03:05 - +[INFO] Running as root. Continuing... +[INFO] 2025-11-18 15:03:05 - ----------------------------------------------------------------------------------------- +[INFO] 2025-11-18 15:03:05 - -------------------Starting UserDataEncryption Testcase---------------------------- +[INFO] 2025-11-18 15:03:05 - === Test Initialization === +[INFO] 2025-11-18 15:03:05 - Checking if dependency binary is available +[INFO] 2025-11-18 15:03:05 - Temporary key file created: /tmp/tmp.yV9Fgr7z7T +[INFO] 2025-11-18 15:03:05 - Generating 64-byte encryption key +[INFO] 2025-11-18 15:03:05 - Creating unique mount folder under /mnt +[INFO] 2025-11-18 15:03:05 - Created unique mount directory: /mnt/testing.pb1KIn +[INFO] 2025-11-18 15:03:05 - Derived filesystem mount point: /var +[INFO] 2025-11-18 15:03:05 - Adding encryption key to the filesystem +[INFO] 2025-11-18 15:03:05 - No relevant, non-benign errors for modules [fscrypt] in recent dmesg. +[INFO] 2025-11-18 15:03:05 - Key ID: 80ae0d678e52fb126ea6eda7d32861eb +[INFO] 2025-11-18 15:03:05 - Checking key status +[INFO] 2025-11-18 15:03:05 - Key Status: Present (user_count=1, added_by_self) +[INFO] 2025-11-18 15:03:05 - Setting encryption policy on /mnt/testing.pb1KIn +[INFO] 2025-11-18 15:03:06 - No relevant, non-benign errors for modules [fscrypt] in recent dmesg. +[INFO] 2025-11-18 15:03:06 - Verifying encryption policy +[INFO] 2025-11-18 15:03:06 - No relevant, non-benign errors for modules [fscrypt] in recent dmesg. +[INFO] 2025-11-18 15:03:06 - Policy verification successful: Master key identifier matches key_id +[INFO] 2025-11-18 15:03:06 - Creating test file in encrypted directory +[INFO] 2025-11-18 15:03:06 - Reading test file +[PASS] 2025-11-18 15:03:06 - UserDataEncryption : Test Passed +[INFO] 2025-11-18 15:03:06 - -------------------Completed UserDataEncryption Testcase---------------------------- +[INFO] 2025-11-18 15:03:06 - Cleaning up mount directory: /mnt/testing.pb1KIn +[INFO] 2025-11-18 15:03:06 - Deleted test file: /mnt/testing.pb1KIn/file.txt +[INFO] 2025-11-18 15:03:06 - Removed mount directory: /mnt/testing.pb1KIn +[PASS] 2025-11-18 15:03:06 - UserDataEncryption passed + +[INFO] 2025-11-18 15:03:06 - ========== Test Summary ========== +PASSED: +UserDataEncryption + +FAILED: + None + +SKIPPED: + None +[INFO] 2025-11-18 15:03:06 - ================================== +``` +4. Results will be available in the `//Runner/suites/Kernel/baseport/UserDataEncryption/` directory. + +## Notes + +- The script uses /data/UserDataEncryption for all operations. +- Temporary files such as the encryption key are cleaned up after the test. +- If any test fails, the script logs the error and exits with a failure code. diff --git a/Runner/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.yaml b/Runner/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.yaml new file mode 100644 index 00000000..942594d8 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.yaml @@ -0,0 +1,21 @@ +metadata: + format: Lava-Test Test Definition 1.0 + name: UserDataEncryption + description: "Validates fscrypt-based user data encryption on supported filesystems" + maintainer: + - bbharani@qti.qualcomm.com + os: + - openembedded + scope: + - functional + devices: + - rb3gen2 + - ridesx + - lemans evk + - monaco evk + +run: + steps: + - cd Runner + - $PWD/suites/Kernel/Baseport/UserDataEncryption/run.sh || true + - $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.res || true diff --git a/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh b/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh new file mode 100755 index 00000000..e131f044 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh @@ -0,0 +1,216 @@ +#!/bin/sh + +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# Ensure script runs as root +if [ "$(id -u)" -ne 0 ]; then + echo "[ERROR] This script must be run as root." >&2 + exit 0 +else + echo "[INFO] Running as root. Continuing..." +fi + +# Robustly find and source init_env +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then + INIT_ENV="$SEARCH/init_env" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 0 +fi + +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi + +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +FSCRYPTCTL="${FSCRYPTCTL:-fscryptctl}" +TESTNAME="UserDataEncryption" +test_path=$(find_test_case_by_name "$TESTNAME") + +if [ -z "$test_path" ]; then + log_fail "Path not found for $TESTNAME test. Falling back to SCRIPT_DIR: $SCRIPT_DIR" + test_path="$SCRIPT_DIR" + + echo "$TESTNAME FAIL" > "$test_path/$TESTNAME.res" + log_fail "$TESTNAME : Test case directory not found" + exit 0 +fi + +cd "$test_path" || { + log_fail "Failed to change directory to $test_path" + log_fail "Path not found for $TESTNAME test. Falling back to SCRIPT_DIR: $SCRIPT_DIR" + test_path="$SCRIPT_DIR" + echo "$TESTNAME FAIL" > "$test_path/$TESTNAME.res" + exit 0 +} + +res_file="./$TESTNAME.res" + +# Globals that cleanup will use +MOUNT_DIR="" +FS_PATH="" +key_id="" +KEY_FILE="" + +cleanup() { + if [ -n "$MOUNT_DIR" ] && [ "$MOUNT_DIR" != "/" ]; then + log_info "Cleaning up mount directory: $MOUNT_DIR" + + if rm -f "$MOUNT_DIR/file.txt" 2>/dev/null; then + log_info "Deleted test file: $MOUNT_DIR/file.txt" + else + log_warn "Failed to delete test file: $MOUNT_DIR/file.txt" + fi + + if rmdir "$MOUNT_DIR" 2>/dev/null; then + log_info "Removed mount directory: $MOUNT_DIR" + else + log_warn "Failed to remove mount directory: $MOUNT_DIR" + fi + fi + + if [ -n "$key_id" ]; then + "$FSCRYPTCTL" remove_key "$key_id" "$FS_PATH" >/dev/null 2>&1 || true + fi + [ -n "$KEY_FILE" ] && rm -f "$KEY_FILE" 2>/dev/null || true +} + +# Run cleanup on normal exit, Ctrl-C, or SIGTERM +trap cleanup EXIT INT TERM + +log_info "-----------------------------------------------------------------------------------------" +log_info "-------------------Starting $TESTNAME Testcase----------------------------" +log_info "=== Test Initialization ===" + +log_info "Checking if dependency binary is available" +check_dependencies "$FSCRYPTCTL" + +if ! command -v "$FSCRYPTCTL" >/dev/null 2>&1; then + log_warn "$FSCRYPTCTL binary was not found. Skipping $TESTNAME." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +# Create a secure temporary file for the key +if KEY_FILE="$(mktemp)"; then + log_info "Temporary key file created: $KEY_FILE" + chmod 600 "$KEY_FILE" +else + log_fail "$TESTNAME : Failed to create temporary key file" + echo "[ERROR] Failed to create temporary key file" >&2 + exit 0 +fi + +# Step 1: Generate a 64-byte key +log_info "Generating 64-byte encryption key" +if ! head -c 64 /dev/urandom > "$KEY_FILE"; then + log_fail "$TESTNAME : Failed to generate encryption key" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +# Step 2: Create mount folder (this will create an unique folder under mnt) +log_info "Creating unique mount folder under /mnt" +MOUNT_DIR=$(mktemp -d /mnt/testing.XXXXXX) +if [ ! -d "$MOUNT_DIR" ]; then + log_fail "$TESTNAME : Failed to create mount directory" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Created unique mount directory: $MOUNT_DIR" + + +FS_PATH=$(df --output=target "$MOUNT_DIR" | tail -n 1) +if [ -z "$FS_PATH" ]; then + log_fail "$TESTNAME : Failed to determine filesystem mount point for $MOUNT_DIR" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Derived filesystem mount point: $FS_PATH" + +# Step 3: Add the key to the filesystem +log_info "Adding encryption key to the filesystem" +key_id=$("$FSCRYPTCTL" add_key "$FS_PATH" < "$KEY_FILE" 2>/dev/null) +scan_dmesg_errors "$SCRIPT_DIR" "fscrypt" "" + +if [ -z "$key_id" ]; then + log_fail "$TESTNAME : Failed to add encryption key" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +log_info "Key ID: $key_id" + +# Step 4: Check key status +log_info "Checking key status" +status=$("$FSCRYPTCTL" key_status "$key_id" "$FS_PATH" 2>/dev/null) +if [ -z "$status" ]; then + log_fail "$TESTNAME : Failed to get key status" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Key Status: $status" + +if ! echo "$status" | grep -q "^Present"; then + log_fail "$TESTNAME : Key is not usable (status: $status)" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + + +# Step 5: Set encryption policy +log_info "Setting encryption policy on $MOUNT_DIR" + +if ! "$FSCRYPTCTL" set_policy "$key_id" "$MOUNT_DIR"; then + log_fail "$TESTNAME : Failed to set encryption policy" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +scan_dmesg_errors "$SCRIPT_DIR" "fscrypt" "" + + +# Step 6: Verify policy +log_info "Verifying encryption policy" +policy_output=$("$FSCRYPTCTL" get_policy "$MOUNT_DIR" 2>/dev/null) +scan_dmesg_errors "$SCRIPT_DIR" "fscrypt" "" + + +policy_key=$(echo "$policy_output" | awk -F': ' '/Master key identifier/ {print $2}' | tr -d '[:space:]') + +if [ "$policy_key" = "$key_id" ]; then + log_info "Policy verification successful: Master key identifier matches key_id" +else + log_fail "$TESTNAME : Policy verification failed (expected $key_id, got $policy_key)" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +# Step 7: Create and read a test file +log_info "Creating test file in encrypted directory" +echo "file" > "$MOUNT_DIR/file.txt" + +log_info "Reading test file" +file_content=$(cat "$MOUNT_DIR/file.txt") +if [ "$file_content" = "file" ]; then + log_pass "$TESTNAME : Test Passed" + echo "$TESTNAME PASS" > "$res_file" +else + log_fail "$TESTNAME : Test Failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +log_info "-------------------Completed $TESTNAME Testcase----------------------------"