Skip to content

Commit 70e1cd2

Browse files
committed
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 <bbharani@qti.qualcomm.com>
1 parent 34562ed commit 70e1cd2

3 files changed

Lines changed: 397 additions & 0 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
2+
SPDX-License-Identifier: BSD-3-Clause-Clear
3+
4+
# Qualcomm UserDataEncryption Functionality Test Script
5+
## Overview
6+
7+
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.
8+
9+
## Features
10+
11+
- **Dependency Check**: Verifies the presence of the `fscryptctl` binary.
12+
- **Key Management**: Generates a 64-byte key and adds it to the filesystem.
13+
- **Encryption Policy**: Applies and verifies encryption policy on a mount directory.
14+
- **Functional Validation**: Creates and reads a test file to confirm encryption functionality.
15+
- **Automated Result Logging**: Outputs test results to a `.res` file for automated result collection.
16+
17+
## Prerequisites
18+
19+
Ensure the following components are present on the target device:
20+
21+
- `fscryptctl` binary available in `/data/`
22+
- Sufficient permissions to create and mount directories
23+
24+
## Directory Structure
25+
```
26+
Runner/
27+
├── suites/
28+
│ ├── Kernel/
29+
│ │ │ ├── baseport/
30+
│ │ │ │ ├── UserDataEncryption/
31+
│ │ │ │ │ ├── run.sh
32+
```
33+
## Usage
34+
35+
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.
36+
37+
2. Verify Transfer: Ensure that the repo have been successfully copied to the ```/<user-defined-location>``` directory on the target device.
38+
39+
3. Run Scripts: Navigate to the ```/<user-defined-location>``` directory on the target device and execute the scripts as needed.
40+
41+
---
42+
Quick Example
43+
```
44+
git clone <this-repo>
45+
cd <this-repo>
46+
scp -r common Runner user@target_device_ip:/<user-defined-location>
47+
ssh user@target_device_ip
48+
cd /<user-defined-location>/Runner && ./run-test.sh UserDataEncryption
49+
50+
Sample output:
51+
sh-5.2# ./run-test.sh UserDataEncryption
52+
[Executing test case: UserDataEncryption] 2025-12-22 15:52:23 -
53+
[INFO] 2025-12-22 15:52:23 - Running as root. Continuing...
54+
[INFO] 2025-12-22 15:52:23 - -----------------------------------------------------------------------------------------
55+
[INFO] 2025-12-22 15:52:23 - -------------------Starting UserDataEncryption Testcase----------------------------
56+
[INFO] 2025-12-22 15:52:23 - === Test Initialization ===
57+
[INFO] 2025-12-22 15:52:23 - Kernel supports fscrypt (CONFIG_FS_ENCRYPTION=y/m).
58+
[INFO] 2025-12-22 15:52:23 - Checking if dependency binary is available
59+
[INFO] 2025-12-22 15:52:23 - Temporary key file created: /tmp/tmp.sdmKJUpwF4
60+
[INFO] 2025-12-22 15:52:23 - Generating 64-byte encryption key
61+
[INFO] 2025-12-22 15:52:23 - Using existing writable /mnt for mount directory base
62+
[INFO] 2025-12-22 15:52:23 - Creating unique mount folder under /mnt
63+
[INFO] 2025-12-22 15:52:23 - Created unique mount directory: /mnt/testing.RMclob
64+
[INFO] 2025-12-22 15:52:23 - Derived filesystem mount point: /var
65+
[INFO] 2025-12-22 15:52:23 - Filesystem at /var: ext4
66+
[INFO] 2025-12-22 15:52:23 - Adding encryption key to the filesystem
67+
[INFO] 2025-12-22 15:52:23 - Key ID: ad3bb8b705299ff24470de8531241334
68+
[INFO] 2025-12-22 15:52:23 - Checking key status
69+
[INFO] 2025-12-22 15:52:23 - Key Status: Present (user_count=1, added_by_self)
70+
[INFO] 2025-12-22 15:52:23 - Setting encryption policy on /mnt/testing.RMclob
71+
[INFO] 2025-12-22 15:52:23 - Verifying encryption policy
72+
[INFO] 2025-12-22 15:52:23 - Policy verification successful: Master key identifier matches key_id
73+
[INFO] 2025-12-22 15:52:23 - Creating test file in encrypted directory
74+
[INFO] 2025-12-22 15:52:23 - Reading test file
75+
[PASS] 2025-12-22 15:52:23 - UserDataEncryption : Test Passed
76+
[INFO] 2025-12-22 15:52:23 - Cleaning up mount directory: /mnt/testing.RMclob
77+
[INFO] 2025-12-22 15:52:24 - No relevant, non-benign errors for modules [fscrypt] in recent dmesg.
78+
[PASS] 2025-12-22 15:52:24 - UserDataEncryption passed
79+
80+
[INFO] 2025-12-22 15:52:24 - ========== Test Summary ==========
81+
PASSED:
82+
UserDataEncryption
83+
84+
FAILED:
85+
None
86+
87+
SKIPPED:
88+
None
89+
[INFO] 2025-12-22 15:52:24 - ==================================
90+
4. Results will be available in the `/<user-defined-location>/Runner/suites/Kernel/baseport/UserDataEncryption/` directory.
91+
92+
## Notes
93+
94+
- The script uses /data/UserDataEncryption for all operations.
95+
- Temporary files such as the encryption key are cleaned up after the test.
96+
- If any test fails, the script logs the error and exits with a failure code.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
metadata:
2+
format: Lava-Test Test Definition 1.0
3+
name: UserDataEncryption
4+
description: "Validates fscrypt-based user data encryption on supported filesystems"
5+
maintainer:
6+
- bbharani@qti.qualcomm.com
7+
os:
8+
- openembedded
9+
scope:
10+
- functional
11+
devices:
12+
- rb3gen2
13+
- ridesx
14+
- lemans evk
15+
- monaco evk
16+
17+
run:
18+
steps:
19+
- cd Runner
20+
- $PWD/suites/Kernel/Baseport/UserDataEncryption/run.sh || true
21+
- $PWD/utils/send-to-lava.sh $PWD/suites/Kernel/Baseport/UserDataEncryption/UserDataEncryption.res || true
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
#!/bin/sh
2+
3+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4+
# SPDX-License-Identifier: BSD-3-Clause-Clear
5+
# Robustly find and source init_env
6+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7+
INIT_ENV=""
8+
SEARCH="$SCRIPT_DIR"
9+
while [ "$SEARCH" != "/" ]; do
10+
if [ -f "$SEARCH/init_env" ]; then
11+
INIT_ENV="$SEARCH/init_env"
12+
break
13+
fi
14+
SEARCH=$(dirname "$SEARCH")
15+
done
16+
17+
if [ -z "${INIT_ENV:-}" ]; then
18+
echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2
19+
exit 0
20+
fi
21+
22+
if [ -z "${__INIT_ENV_LOADED:-}" ]; then
23+
# shellcheck disable=SC1090
24+
. "$INIT_ENV"
25+
fi
26+
27+
# shellcheck disable=SC1090,SC1091
28+
. "$TOOLS/functestlib.sh"
29+
30+
FSCRYPTCTL="${FSCRYPTCTL:-fscryptctl}"
31+
TESTNAME="UserDataEncryption"
32+
test_path=$(find_test_case_by_name "$TESTNAME")
33+
34+
if [ -z "${test_path:-}" ]; then
35+
log_warn "Path not found for $TESTNAME test. Falling back to SCRIPT_DIR: $SCRIPT_DIR"
36+
test_path="$SCRIPT_DIR"
37+
fi
38+
39+
res_file="$test_path/$TESTNAME.res"
40+
41+
# Ensure script runs as root
42+
if [ "$(id -u)" -ne 0 ]; then
43+
log_skip "This script must be run as root."
44+
echo "$TESTNAME SKIP" > "$res_file"
45+
exit 0
46+
else
47+
log_info "Running as root. Continuing..."
48+
fi
49+
50+
if ! cd "${test_path:-}"; then
51+
log_fail "Failed to change directory to $test_path"
52+
echo "$TESTNAME FAIL" > "$res_file"
53+
exit 0
54+
fi
55+
56+
# Globals that cleanup will use
57+
MOUNT_DIR=""
58+
FS_PATH=""
59+
key_id=""
60+
KEY_FILE=""
61+
62+
cleanup() {
63+
64+
if [ -n "${MOUNT_DIR:-}" ] && [ "${MOUNT_DIR:-}" != "/" ]; then
65+
log_info "Cleaning up mount directory: $MOUNT_DIR"
66+
67+
if ! rm -f "$MOUNT_DIR/file.txt" 2>/dev/null; then
68+
log_warn "Failed to remove test file: $MOUNT_DIR/file.txt"
69+
fi
70+
71+
if ! rmdir "$MOUNT_DIR" 2>/dev/null; then
72+
log_warn "Failed to remove mount directory: $MOUNT_DIR"
73+
fi
74+
fi
75+
76+
if [ -n "${key_id:-}" ] && [ -n "${FS_PATH:-}" ]; then
77+
"$FSCRYPTCTL" remove_key "$key_id" "$FS_PATH" >/dev/null 2>&1 || true
78+
fi
79+
80+
81+
if [ -n "${KEY_FILE:-}" ]; then
82+
if ! rm -f "$KEY_FILE" 2>/dev/null; then
83+
log_warn "Failed to remove key file: $KEY_FILE"
84+
fi
85+
fi
86+
87+
scan_dmesg_errors "$SCRIPT_DIR" "fscrypt" ""
88+
}
89+
90+
# Run cleanup on normal exit, Ctrl-C, or SIGTERM
91+
trap cleanup EXIT INT TERM
92+
93+
log_info "-----------------------------------------------------------------------------------------"
94+
log_info "-------------------Starting $TESTNAME Testcase----------------------------"
95+
log_info "=== Test Initialization ==="
96+
97+
98+
## kernel config check
99+
if [ -r /proc/config.gz ]; then
100+
if zcat /proc/config.gz 2>/dev/null | grep -q '^CONFIG_FS_ENCRYPTION=[ym]'; then
101+
log_info "Kernel supports fscrypt (CONFIG_FS_ENCRYPTION=y/m)."
102+
else
103+
log_skip "$TESTNAME : Kernel lacks CONFIG_FS_ENCRYPTION. Skipping."
104+
echo "$TESTNAME SKIP" > "$res_file"
105+
exit 0
106+
fi
107+
else
108+
log_warn "/proc/config.gz not available; cannot verify kernel config. Proceeding"
109+
fi
110+
111+
log_info "Checking if dependency binary is available"
112+
113+
114+
if ! check_dependencies "${FSCRYPTCTL:-}"; then
115+
log_skip "$TESTNAME : Dependency check failed (missing or unusable: $FSCRYPTCTL). Skipping."
116+
echo "$TESTNAME SKIP" > "$res_file"
117+
exit 0
118+
fi
119+
120+
121+
# Create a secure temporary file for the key
122+
if KEY_FILE="$(mktemp)"; then
123+
log_info "Temporary key file created: $KEY_FILE"
124+
chmod 600 "$KEY_FILE"
125+
else
126+
log_fail "$TESTNAME : Failed to create temporary key file"
127+
echo "[ERROR] Failed to create temporary key file" > "$res_file"
128+
exit 0
129+
fi
130+
131+
# Step 1: Generate a 64-byte key
132+
log_info "Generating 64-byte encryption key"
133+
if ! head -c 64 /dev/urandom > "${KEY_FILE:-}"; then
134+
log_fail "$TESTNAME : Failed to generate encryption key"
135+
echo "$TESTNAME FAIL" > "$res_file"
136+
exit 0
137+
fi
138+
139+
BASE_MNT="/mnt"
140+
141+
# Ensure /mnt exists
142+
if [ -d "$BASE_MNT" ] && [ -w "$BASE_MNT" ]; then
143+
log_info "Using existing writable $BASE_MNT for mount directory base"
144+
else
145+
BASE_MNT="/UDE"
146+
log_info "/mnt not usable; falling back to separate base directory: $BASE_MNT"
147+
148+
if ! mkdir -p "$BASE_MNT"; then
149+
log_fail "Failed to create base directory $BASE_MNT; cannot proceed with FBE test"
150+
echo "$TESTNAME FAIL" > "$res_file"
151+
exit 0
152+
fi
153+
154+
if [ ! -w "$BASE_MNT" ]; then
155+
log_fail "Base directory $BASE_MNT is not writable; cannot proceed with FBE test"
156+
echo "$TESTNAME FAIL" > "$res_file"
157+
exit 0
158+
fi
159+
fi
160+
161+
# Step 2: Create mount folder (this will create an unique folder under mnt)
162+
log_info "Creating unique mount folder under $BASE_MNT"
163+
164+
MOUNT_DIR=$(mktemp -d "${BASE_MNT:-}/testing.XXXXXX")
165+
if [ ! -d "${MOUNT_DIR:-}" ]; then
166+
log_fail "$TESTNAME : Failed to create mount directory"
167+
echo "$TESTNAME FAIL" > "$res_file"
168+
exit 0
169+
fi
170+
log_info "Created unique mount directory: $MOUNT_DIR"
171+
172+
173+
FS_PATH=$(df --output=target "$MOUNT_DIR" | tail -n 1)
174+
if [ -z "${FS_PATH:-}" ]; then
175+
log_fail "$TESTNAME : Failed to determine filesystem mount point for $MOUNT_DIR"
176+
echo "$TESTNAME FAIL" > "$res_file"
177+
exit 0
178+
fi
179+
log_info "Derived filesystem mount point: $FS_PATH"
180+
181+
182+
#file-system check
183+
if fs_type="$(df -Th "${FS_PATH:-}" 2>/dev/null | awk 'NR==2{print $2}')"; then
184+
if [ -n "${fs_type:-}" ]; then
185+
log_info "Filesystem at $FS_PATH: $fs_type"
186+
else
187+
log_warn "df -Th succeeded but could not parse filesystem type for $FS_PATH"
188+
fi
189+
else
190+
log_warn "df -Th failed for $FS_PATH"
191+
fi
192+
193+
# Step 3: Add the key to the filesystem
194+
log_info "Adding encryption key to the filesystem"
195+
key_id=$("$FSCRYPTCTL" add_key "$FS_PATH" < "$KEY_FILE" 2>/dev/null)
196+
197+
if [ -z "${key_id:-}" ]; then
198+
log_fail "$TESTNAME : Failed to add encryption key"
199+
echo "$TESTNAME FAIL" > "$res_file"
200+
exit 0
201+
fi
202+
203+
log_info "Key ID: $key_id"
204+
205+
# Step 4: Check key status
206+
log_info "Checking key status"
207+
status=$("$FSCRYPTCTL" key_status "$key_id" "$FS_PATH" 2>/dev/null)
208+
if [ -z "${status:-}" ]; then
209+
log_fail "$TESTNAME : Failed to get key status"
210+
echo "$TESTNAME FAIL" > "$res_file"
211+
exit 0
212+
fi
213+
log_info "Key Status: $status"
214+
215+
if ! echo "${status:-}" | grep -q "^Present"; then
216+
log_fail "$TESTNAME : Key is not usable (status: $status)"
217+
echo "$TESTNAME FAIL" > "$res_file"
218+
exit 0
219+
fi
220+
221+
222+
# Step 5: Set encryption policy
223+
log_info "Setting encryption policy on $MOUNT_DIR"
224+
225+
if ! "${FSCRYPTCTL:-}" set_policy "$key_id" "$MOUNT_DIR"; then
226+
log_fail "$TESTNAME : Failed to set encryption policy"
227+
echo "$TESTNAME FAIL" > "$res_file"
228+
exit 0
229+
fi
230+
231+
# Step 6: Verify policy
232+
log_info "Verifying encryption policy"
233+
234+
if ! policy_output=$("$FSCRYPTCTL" get_policy "$MOUNT_DIR" 2>/dev/null); then
235+
log_fail "fscryptctl get_policy failed for $MOUNT_DIR: $policy_output"
236+
echo "$TESTNAME FAIL" > "$res_file"
237+
exit 0
238+
fi
239+
240+
not_encrypted=$(echo "$policy_output" | awk '/file or directory not encrypted/ {print 1}')
241+
242+
if [ -n "$not_encrypted" ]; then
243+
log_fail "$MOUNT_DIR is not encrypted (fscryptctl reports 'file or directory not encrypted')"
244+
echo "$TESTNAME FAIL" > "$res_file"
245+
exit 0
246+
fi
247+
248+
policy_key=$(echo "$policy_output" | awk -F': ' '/Master key identifier/ {print $2}' | tr -d '[:space:]')
249+
250+
if [ -z "${policy_key:-}" ]; then
251+
log_fail "$TESTNAME : fscryptctl get_policy did not return a Master key identifier line"
252+
echo "$TESTNAME FAIL" > "$res_file"
253+
exit 0
254+
fi
255+
256+
if [ "${policy_key:-}" = "${key_id:-}" ]; then
257+
log_info "Policy verification successful: Master key identifier matches key_id"
258+
else
259+
log_fail "$TESTNAME : Policy verification failed (expected $key_id, got $policy_key)"
260+
echo "$TESTNAME FAIL" > "$res_file"
261+
exit 0
262+
fi
263+
264+
# Step 7: Create and read a test file
265+
log_info "Creating test file in encrypted directory"
266+
echo "file" > "$MOUNT_DIR/file.txt"
267+
268+
log_info "Reading test file"
269+
file_content=$(cat "$MOUNT_DIR/file.txt")
270+
if [ "${file_content:-}" = "file" ]; then
271+
log_pass "$TESTNAME : Test Passed"
272+
echo "$TESTNAME PASS" > "$res_file"
273+
exit 0
274+
else
275+
log_fail "$TESTNAME : Test Failed"
276+
echo "$TESTNAME FAIL" > "$res_file"
277+
exit 0
278+
fi
279+
280+
log_info "-------------------Completed $TESTNAME Testcase----------------------------"

0 commit comments

Comments
 (0)