Spdk/test/sma/crypto.sh

275 lines
7.5 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2022 Intel Corporation
# All rights reserved.
#
testdir=$(readlink -f "$(dirname "$0")")
rootdir=$(readlink -f "$testdir/../..")
source "$rootdir/test/common/autotest_common.sh"
source "$testdir/common.sh"
rpc_py="$rootdir/scripts/rpc.py"
localnqn=nqn.2016-06.io.spdk:cnode0
tgtnqn=nqn.2016-06.io.spdk:tgt0
key0=1234567890abcdef1234567890abcdef
key1=deadbeefcafebabefeedbeefbabecafe
tgtsock=/var/tmp/spdk.sock2
discovery_port=8009
cleanup() {
killprocess $smapid
killprocess $hostpid
killprocess $tgtpid
}
gen_volume_params() {
local volume_id=$1 cipher=$2 key=$3 key2=$4 config
local -a params crypto
config=$(
cat <<- PARAMS
"volume_id": "$(uuid2base64 $volume_id)",
"nvmf": {
"hostnqn": "nqn.2016-06.io.spdk:host0",
"discovery": {
"discovery_endpoints": [
{
"trtype": "tcp",
"traddr": "127.0.0.1",
"trsvcid": "$discovery_port"
}
]
}
}
PARAMS
)
params+=("$config")
local IFS=","
if [[ -n "$cipher" ]]; then
crypto+=("\"cipher\": $(get_cipher $cipher)")
crypto+=("\"key\": \"$(format_key $key)\"")
if [[ -n "$key2" ]]; then
crypto+=("\"key2\": \"$(format_key $key2)\"")
fi
crypto_config=$(
cat <<- PARAMS
"crypto": {
${crypto[*]}
}
PARAMS
)
params+=("$crypto_config")
fi
cat <<- PARAMS
"volume": {
${params[*]}
}
PARAMS
}
create_device() {
"$rootdir/scripts/sma-client.py" <<- CREATE
{
"method": "CreateDevice",
"params": {
"nvmf_tcp": {
"subnqn": "$localnqn",
"adrfam": "ipv4",
"traddr": "127.0.0.1",
"trsvcid": "4420"
}
${1:+, $(gen_volume_params "$@")}
}
}
CREATE
}
delete_device() {
"$rootdir/scripts/sma-client.py" <<- DELETE
{
"method": "DeleteDevice",
"params": {
"handle": "$1"
}
}
DELETE
}
attach_volume() {
local device=$1
shift
"$rootdir/scripts/sma-client.py" <<- ATTACH
{
"method": "AttachVolume",
"params": {
"device_handle": "$device",
$(gen_volume_params "$@")
}
}
ATTACH
}
detach_volume() {
"$rootdir/scripts/sma-client.py" <<- DETACH
{
"method": "DetachVolume",
"params": {
"device_handle": "$1",
"volume_id": "$(uuid2base64 $2)"
}
}
DETACH
}
verify_crypto_volume() {
local nqn=$1 uuid=$2 ns ns_bdev
ns=$(rpc_cmd nvmf_get_subsystems $nqn | jq -r '.[0].namespaces[0]')
ns_bdev=$(jq -r '.name' <<< "$ns")
# Make sure that the namespace is a crypto bdev and that there's only a single crypto bdev
[[ $(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[0].product_name') == crypto ]]
[[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 1 ]]
# Check that the namespace's UUID/NGUID matches the one requested by the user
[[ $(jq -r '.uuid' <<< "$ns") == "$uuid" ]]
[[ $(jq -r '.nguid' <<< "$ns") == "$(uuid2nguid $uuid)" ]]
}
trap "cleanup; exit 1" SIGINT SIGTERM EXIT
"$rootdir/build/bin/spdk_tgt" -m 0x1 &
hostpid=$!
"$rootdir/build/bin/spdk_tgt" -r "$tgtsock" -m 0x2 &
tgtpid=$!
$rootdir/scripts/sma.py -c <(
cat <<- CONFIG
address: 127.0.0.1
port: 8080
devices:
- name: 'nvmf_tcp'
crypto:
name: 'bdev_crypto'
params:
driver: 'crypto_aesni_mb'
CONFIG
) &
smapid=$!
# Wait until the SMA starts listening
sma_waitforlisten
# Prepare the target
uuid=$(uuidgen)
waitforlisten "$tgtpid" "$tgtsock"
$rpc_py -s "$tgtsock" << CONFIG
bdev_malloc_create -b malloc0 32 4096 -u $uuid
nvmf_create_transport -t tcp
nvmf_create_subsystem $tgtnqn -a
nvmf_subsystem_add_listener discovery -t tcp -a 127.0.0.1 -s $discovery_port
nvmf_subsystem_add_listener -t tcp -a 127.0.0.1 -s 4421 -f ipv4 $tgtnqn
nvmf_subsystem_add_ns $tgtnqn malloc0
CONFIG
# Create an empty device first
device=$(create_device | jq -r '.handle')
# First attach a volume without crypto
attach_volume $device $uuid
ns_bdev=$(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].name')
[[ $(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[0].product_name') == 'NVMe disk' ]]
[[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 0 ]]
[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].uuid') == "$uuid" ]]
[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].nguid') == "$(uuid2nguid $uuid)" ]]
detach_volume $device $uuid
# Now attach a volume with crypto enabled
attach_volume $device $uuid AES_CBC $key0
[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 1 ]]
[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 1 ]]
# Make sure that the namespace exposed in the subsystem is a crypto bdev and is using malloc bdev's UUID
verify_crypto_volume $localnqn $uuid
# Check that it's using correct key
crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")')
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]]
# Attach the same volume again
attach_volume $device $uuid AES_CBC $key0
# Nothing should change
[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 1 ]]
[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 1 ]]
verify_crypto_volume $localnqn $uuid
crypto_bdev2=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")')
[[ $(jq -r '.name' <<< "$crypto_bdev") == $(jq -r '.name' <<< "$crypto_bdev2") ]]
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev2") == "$key0" ]]
# Try to do attach it again, but this time use a different crypto algorithm
NOT attach_volume $device $uuid AES_XTS $key0
# Check the same, this time changing the key
NOT attach_volume $device $uuid AES_CBC $key1
# Check the same, this time adding second key
NOT attach_volume $device $uuid AES_CBC $key0 $key1
# Check out-of-range cipher value
NOT attach_volume $device $uuid 8 $key0
# Make sure these failures haven't affected anything
verify_crypto_volume $localnqn $uuid
detach_volume $device $uuid
# Check that if there's something wrong with crypto params, the volume won't get attached and
# everything is cleaned up afterwards
NOT attach_volume $device $uuid 8 $key0
[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 0 ]]
[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]]
[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]]
delete_device $device
# Check that it's possible to create a device immediately specyfing a volume with crypto
device=$(create_device $uuid AES_CBC $key0 | jq -r '.handle')
verify_crypto_volume $localnqn $uuid
delete_device $device
# Try to create a device with incorrect volume crypto params, check that it fails and everything
# is cleaned up afterwards
NOT create_device $uuid 8 $key0
[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]]
[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]]
[[ $(rpc_cmd nvmf_get_subsystems | jq -r "[.[] | select(.nqn == \"$localnqn\")] | length") -eq 0 ]]
# Check that if crypto is disabled, it's not possible to attach a volume with crypto
killprocess $smapid
$rootdir/scripts/sma.py -c <(
cat <<- CONFIG
address: 127.0.0.1
port: 8080
devices:
- name: 'nvmf_tcp'
CONFIG
) &
smapid=$!
sma_waitforlisten
device=$(create_device | jq -r '.handle')
NOT attach_volume $device $uuid AES_CBC $key0
[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]]
[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]]
cleanup
trap - SIGINT SIGTERM EXIT