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..82e6fa70 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/README_UserDataEncryption.md @@ -0,0 +1,96 @@ +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 is available +- 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-12-24 06:19:59 - +[INFO] 2025-12-24 06:19:59 - Running as root. Continuing... +[INFO] 2025-12-24 06:19:59 - ----------------------------------------------------------------------------------------- +[INFO] 2025-12-24 06:19:59 - -------------------Starting UserDataEncryption Testcase---------------------------- +[INFO] 2025-12-24 06:19:59 - === Test Initialization === +[PASS] 2025-12-24 06:20:00 - Kernel config CONFIG_FS_ENCRYPTION is enabled +[INFO] 2025-12-24 06:20:00 - Checking if dependency binary is available +[INFO] 2025-12-24 06:20:00 - Temporary key file created: /tmp/tmp.wZdZ0ladk0 +[INFO] 2025-12-24 06:20:00 - Generating 64-byte encryption key +[INFO] 2025-12-24 06:20:00 - Using existing writable /mnt for mount directory base +[INFO] 2025-12-24 06:20:00 - Creating unique mount folder under /mnt +[INFO] 2025-12-24 06:20:00 - Created unique mount directory: /mnt/testing.jkttLK +[INFO] 2025-12-24 06:20:00 - Derived filesystem mount point: /var +[INFO] 2025-12-24 06:20:00 - Filesystem at /var: ext4 +[INFO] 2025-12-24 06:20:00 - Adding encryption key to the filesystem +[INFO] 2025-12-24 06:20:00 - Key ID: 6acffc5b7e670c7f841ef20c37027b52 +[INFO] 2025-12-24 06:20:00 - Checking key status +[INFO] 2025-12-24 06:20:00 - Key Status: Present (user_count=1, added_by_self) +[INFO] 2025-12-24 06:20:00 - Setting encryption policy on /mnt/testing.jkttLK +[INFO] 2025-12-24 06:20:00 - Verifying encryption policy +[INFO] 2025-12-24 06:20:00 - Policy verification successful: Master key identifier matches key_id +[INFO] 2025-12-24 06:20:00 - Creating test file in encrypted directory +[INFO] 2025-12-24 06:20:00 - Reading test file +[PASS] 2025-12-24 06:20:00 - UserDataEncryption : Test Passed +[INFO] 2025-12-24 06:20:00 - Cleaning up mount directory: /mnt/testing.jkttLK +[INFO] 2025-12-24 06:20:00 - No relevant, non-benign errors for modules [fscrypt] in recent dmesg. +[PASS] 2025-12-24 06:20:00 - UserDataEncryption passed + +[INFO] 2025-12-24 06:20:00 - ========== Test Summary ========== +PASSED: +UserDataEncryption + +FAILED: + None + +SKIPPED: + None +[INFO] 2025-12-24 06:20:00 - ================================== +4. Results will be available in the `//Runner/suites/Kernel/baseport/UserDataEncryption/` directory. + +## Notes + +- The script uses /mnt as the base directory (with /UDE as a fallback) 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..d5600470 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/UserDataEncryption/run.sh @@ -0,0 +1,286 @@ +#!/bin/sh + +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear +# 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" + __INIT_ENV_LOADED=1 +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_warn "Path not found for $TESTNAME test. Falling back to SCRIPT_DIR: $SCRIPT_DIR" + test_path="$SCRIPT_DIR" +fi + +res_file="$test_path/$TESTNAME.res" + +# Ensure script runs as root +if [ "$(id -u)" -ne 0 ]; then + log_skip "This script must be run as root." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +else + log_info "Running as root. Continuing..." +fi + +if ! cd "${test_path:-}"; then + log_fail "Failed to change directory to $test_path" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +# 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_warn "Failed to remove test file: $MOUNT_DIR/file.txt" + fi + + if ! rmdir "$MOUNT_DIR" 2>/dev/null; then + log_warn "Failed to remove mount directory: $MOUNT_DIR" + fi + fi + + if [ -n "${key_id:-}" ] && [ -n "${FS_PATH:-}" ]; then + "$FSCRYPTCTL" remove_key "$key_id" "$FS_PATH" >/dev/null 2>&1 || true + fi + + + if [ -n "${KEY_FILE:-}" ]; then + if ! rm -f "$KEY_FILE" 2>/dev/null; then + log_warn "Failed to remove key file: $KEY_FILE" + fi + fi + + scan_dmesg_errors "$SCRIPT_DIR" "fscrypt" "" +} + +# 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 ===" + + +## kernel config check + +if ! check_kernel_config "CONFIG_FS_ENCRYPTION"; then + log_skip "$TESTNAME : Kernel lacks CONFIG_FS_ENCRYPTION. Skipping." + echo "$TESTNAME SKIP" > "$res_file" + exit 0 +fi + +log_info "Checking if dependency binary is available" + + +if ! check_dependencies "${FSCRYPTCTL:-}"; then + log_skip "$TESTNAME : Dependency check failed (missing or unusable: $FSCRYPTCTL). Skipping." + 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" > "$res_file" + 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 + +BASE_MNT="/mnt" + +# Ensure /mnt exists +if [ -d "$BASE_MNT" ] && [ -w "$BASE_MNT" ]; then + log_info "Using existing writable $BASE_MNT for mount directory base" +else + BASE_MNT="/UDE" + log_info "/mnt not usable; falling back to separate base directory: $BASE_MNT" + + if ! mkdir -p "$BASE_MNT"; then + log_fail "Failed to create base directory $BASE_MNT; cannot proceed with FBE test" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 + fi + + if [ ! -w "$BASE_MNT" ]; then + log_fail "Base directory $BASE_MNT is not writable; cannot proceed with FBE test" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 + fi +fi + +# Step 2: Create mount folder (this will create an unique folder under mnt) +log_info "Creating unique mount folder under $BASE_MNT" + +MOUNT_DIR=$(mktemp -d "${BASE_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" + + +#file-system check +if fs_type="$(df -Th "${FS_PATH:-}" 2>/dev/null | awk 'NR==2{print $2}')"; then + if [ -n "${fs_type:-}" ]; then + log_info "Filesystem at $FS_PATH: $fs_type" + else + log_warn "df -Th succeeded but could not parse filesystem type for $FS_PATH" + fi +else + log_warn "df -Th failed for $FS_PATH" +fi + +# Step 3: Add the key to the filesystem +log_info "Adding encryption key to the filesystem" + +add_key_output=$("$FSCRYPTCTL" add_key "$FS_PATH" < "$KEY_FILE" 2>&1) +rc=$? +key_id=$(printf '%s\n' "$add_key_output" | head -n1) + +if [ "$rc" -ne 0 ] || [ -z "${key_id:-}" ]; then + log_fail "$TESTNAME : Failed to add encryption key. fscryptctl output: $add_key_output" + 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>&1) +rc=$? + +if [ "$rc" -ne 0 ] || [ -z "${status:-}" ]; then + log_fail "$TESTNAME : Failed to get key status. key status output : $status" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +if ! echo "${status:-}" | grep -q "^Present"; then + log_fail "$TESTNAME : Key is not usable (status: $status)" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi +log_info "Key Status: $status" + +# Step 5: Set encryption policy +log_info "Setting encryption policy on $MOUNT_DIR" + +set_policy_output=$("$FSCRYPTCTL" set_policy "$key_id" "$MOUNT_DIR" 2>&1) +rc=$? + +if [ "$rc" -ne 0 ]; then + log_fail "$TESTNAME : Failed to set encryption policy, set policy output : $set_policy_output" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +# Step 6: Verify policy +log_info "Verifying encryption policy" + +policy_output=$("$FSCRYPTCTL" get_policy "$MOUNT_DIR" 2>&1) +rc=$? + +if [ "$rc" -ne 0 ] || [ -z "${policy_output:-}" ]; then + log_fail "fscryptctl get_policy failed for $MOUNT_DIR: $policy_output" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +not_encrypted=$(echo "$policy_output" | awk '/file or directory not encrypted/ {print 1}') + +if [ -n "$not_encrypted" ]; then + log_fail "$MOUNT_DIR is not encrypted (fscryptctl reports 'file or directory not encrypted')" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +policy_key=$(echo "$policy_output" | awk -F': ' '/Master key identifier/ {print $2}' | tr -d '[:space:]') + +if [ -z "${policy_key:-}" ]; then + log_fail "$TESTNAME : fscryptctl get_policy did not return a Master key identifier line" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +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" + exit 0 +else + log_fail "$TESTNAME : Test Failed" + echo "$TESTNAME FAIL" > "$res_file" + exit 0 +fi + +log_info "-------------------Completed $TESTNAME Testcase----------------------------"