-
Notifications
You must be signed in to change notification settings - Fork 24
Add: Qualcomm User Data Encryption test script & Document #141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 ```/<user-defined-location>``` directory on the target device. | ||
|
|
||
| 2. Verify Transfer: Ensure that the repo have been successfully copied to the ```/<user-defined-location>``` directory on the target device. | ||
|
|
||
| 3. Run Scripts: Navigate to the ```/<user-defined-location>``` directory on the target device and execute the scripts as needed. | ||
|
|
||
| --- | ||
| Quick Example | ||
| ``` | ||
| git clone <this-repo> | ||
| cd <this-repo> | ||
| scp -r common Runner user@target_device_ip:/<user-defined-location> | ||
| ssh user@target_device_ip | ||
| cd /<user-defined-location>/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 `/<user-defined-location>/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. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: | ||
| - [email protected] | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| #!/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 1 | ||
| 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 1 | ||
| 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") | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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" > "$SCRIPT_DIR/$TESTNAME.res" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's nicer if every test always write the .res in test_path, not in SCRIPT_DIR |
||
| log_fail "$TESTNAME : Test case directory not found" | ||
| exit 1 | ||
| fi | ||
|
|
||
| cd "$test_path" || { | ||
| log_fail "Failed to change directory to $test_path" | ||
| echo "$TESTNAME FAIL" > "$SCRIPT_DIR/$TESTNAME.res" | ||
| exit 1 | ||
| } | ||
|
|
||
| res_file="./$TESTNAME.res" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Result file isn’t written for some early exits (e.g., not root / init_env missing).
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. only early exits where res_file is not created is script root & init_env, we cannot create res_file for these as the res_file path is created post init_env. |
||
|
|
||
| # Globals that cleanup will use | ||
| key_id="" | ||
| KEY_FILE="" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's slightly safer to inititalize globals before |
||
|
|
||
| cleanup() { | ||
| if [ -n "$MOUNT_DIR" ] && [ "$MOUNT_DIR" != "/" ]; then | ||
| log_info "Cleaning up mount directory: $MOUNT_DIR" | ||
| if [ -f "$MOUNT_DIR/file.txt" ]; then | ||
| rm -f "$MOUNT_DIR/file.txt" 2>/dev/null || true | ||
| log_info "Deleted test file: $MOUNT_DIR/file.txt" | ||
| fi | ||
|
|
||
| if [ -d "$MOUNT_DIR" ]; then | ||
| rmdir "$MOUNT_DIR" 2>/dev/null || true | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you always log "Removed mount directory" even if it failed. Better add precise logs, check the return code. |
||
| log_info "Removed 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 | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| log_info "-----------------------------------------------------------------------------------------" | ||
| log_info "-------------------Starting $TESTNAME Testcase----------------------------" | ||
| log_info "=== Test Initialization ===" | ||
|
|
||
| log_info "Checking if dependency binary is available" | ||
| check_dependencies "$FSCRYPTCTL" | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if ! command -v "$FSCRYPTCTL" >/dev/null 2>&1; then | ||
| log_fail "$FSCRYPTCTL binary was not found. Skipping $TESTNAME." | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use log_warn |
||
| 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| fi | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kernel/filesystem precheck: Add
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check for add_key success exists, key_id=$("$FSCRYPTCTL" add_key "$FS_PATH" < "$KEY_FILE" 2>/dev/null) |
||
| # 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| fi | ||
| log_info "Created unique mount directory: $MOUNT_DIR" | ||
|
|
||
|
|
||
| FS_PATH=$(df --output=target "$MOUNT_DIR" | tail -n 1) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if there's any chance of a busybox/ non-GNU environment, just be aware --output=target may not exist. Given the meta-qcom target, it's probably fine. If we want to be ultra-portable in future, this part might be abstracted into hlper, but for now it's acceptable. |
||
| if [ -z "$FS_PATH" ]; then | ||
| log_fail "$TESTNAME : Failed to determine filesystem mount point for $MOUNT_DIR" | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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) | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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) | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if [ -z "$status" ]; then | ||
| log_fail "$TESTNAME : Failed to get key status" | ||
| echo "$TESTNAME FAIL" > "$res_file" | ||
| exit 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| 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) | ||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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 1 | ||
| fi | ||
|
|
||
xbharani marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # 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 1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT |
||
| fi | ||
|
|
||
| log_info "-------------------Completed $TESTNAME Testcase----------------------------" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
exit 0as in Lava. If the script usesexit 1, it will not proceed to the remaining tests.