#!/bin/sh # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (c) 2018 Petr Vorel # Copyright (c) 2016 Red Hat Inc., All Rights Reserved. # Copyright (c) 2016 Oracle and/or its affiliates. All Rights Reserved. # Author: Hangbin Liu # Authenticated encryption with associated data AEALGO="rfc4106_128" # Encryption algorithm EALGO="des3_ede" # Authentication algorithm AALGO="sha1" # Compression algorithm CALGO="deflate" IPSEC_REQUESTS="500" ipsec_lib_usage() { echo "l n n is the number of test link when tests run" echo "m x x is ipsec mode, could be transport / tunnel" echo "p x x is ipsec protocol, could be ah / esp / comp" echo "s x x is icmp message size array" echo "S n n is IPsec SPI value" echo "k x key for vti interface" echo "A x Authenticated encryption with associated data algorithm" echo "e x Encryption algorithm" echo "a x Authentication algorithm" echo "c x Compression algorithm" echo "r x Num of requests, PING_MAX or netstress' '-r' opt" } ipsec_lib_parse_args() { case "$1" in l) LINK_NUM=$2;; m) IPSEC_MODE=$2;; p) IPSEC_PROTO=$2;; s) TST_TEST_DATA="$2"; TST_TEST_DATA_IFS=":";; S) SPI=$2;; k) VTI_KEY=$2;; A) AEALGO=$2;; e) EALGO=$2;; a) AALGO=$2;; c) CALGO=$2;; r) IPSEC_REQUESTS="$2";; esac } ipsec_lib_setup() { case $AEALGO in rfc4106_128|rfc4543_128) AEALGO_KEY=$(get_key 160);; rfc4106_192|rfc4543_192) AEALGO_KEY=$(get_key 224);; rfc4106_256|rfc4543_256) AEALGO_KEY=$(get_key 288);; rfc4309_128) AEALGO_KEY=$(get_key 152);; rfc4309_192) AEALGO_KEY=$(get_key 216);; rfc4309_256) AEALGO_KEY=$(get_key 280);; esac case $EALGO in des) EALGO_KEY=$(get_key 64);; des3_ede) EALGO_KEY=$(get_key 192);; cast5) EALGO_KEY=$(get_key 128);; blowfish) EALGO_KEY=$(get_key 448);; aes|twofish|camellia|serpent) EALGO_KEY=$(get_key 256);; *) tst_brk TBROK "unknown enc alg: $EALGO";; esac case $AALGO in sha1|rmd160) AALGO_KEY=$(get_key 160);; sha256) AALGO_KEY=$(get_key 256);; sha384) AALGO_KEY=$(get_key 384);; sha512) AALGO_KEY=$(get_key 512);; *) tst_brk TBROK "unknown auth alg: $AALGO";; esac SPI=${SPI:-1000} VTI_KEY=${VTI_KEY:-10} cleanup_vti= ALG= ALGR= if [ -n "$IPSEC_MODE" ]; then tst_net_run "tst_check_drivers xfrm_user" || \ tst_brk TCONF "xfrm_user driver not available on lhost or rhost" cleanup_xfrm=1 fi } TST_OPTS="l:m:p:s:S:k:A:e:a:c:r:" TST_PARSE_ARGS=ipsec_lib_parse_args TST_SETUP=${TST_SETUP:-ipsec_lib_setup} TST_USAGE=ipsec_lib_usage . tst_net.sh get_key() { local bits=$1 local bytes=$(( $bits / 8)) echo "0x$(hexdump -vn $bytes -e '1/1 "%02x"' /dev/urandom)" } tst_ipsec_setup() { ipsec_lib_setup # Configure SAD/SPD if [ -n "$IPSEC_MODE" -a -n "$IPSEC_PROTO" ]; then tst_res TINFO "IPsec[$IPSEC_PROTO/$IPSEC_MODE]" tst_ipsec lhost $(tst_ipaddr) $(tst_ipaddr rhost) tst_ipsec rhost $(tst_ipaddr rhost) $(tst_ipaddr) fi } # tst_ipsec_cleanup: flush ipsec state and policy rules tst_ipsec_cleanup() { [ -z "$cleanup_xfrm" ] && return ip xfrm state flush ip xfrm policy flush tst_rhost_run -c "ip xfrm state flush && ip xfrm policy flush" if [ -n "$cleanup_vti" ]; then ip li del $cleanup_vti 2>/dev/null tst_rhost_run -c "ip li del $cleanup_vti 2>/dev/null" fi } ipsec_set_algoline() { case $IPSEC_PROTO in ah) ALG='auth hmac('$AALGO') '$AALGO_KEY ALGR='auth hmac\('$AALGO'\) '$AALGO_KEY ;; esp) ALG="enc $EALGO $EALGO_KEY auth "'hmac('$AALGO') '$AALGO_KEY ALGR="enc $EALGO $EALGO_KEY auth "'hmac\('$AALGO'\) '$AALGO_KEY ;; esp_aead) case $AEALGO in rfc4106_128|rfc4106_192|rfc4106_256) ALG="aead "'rfc4106(gcm(aes))'" $AEALGO_KEY 128" ALGR="aead "'rfc4106\(gcm\(aes\)\)'" $AEALGO_KEY 128" ;; rfc4309_128|rfc4309_192|rfc4309_256) ALG="aead "'rfc4309(ccm(aes))'" $AEALGO_KEY 128" ALGR="aead "'rfc4309\(ccm\(aes\)\)'" $AEALGO_KEY 128" ;; rfc4543_128|rfc4543_192|rfc4543_256) ALG="aead "'rfc4543(gcm(aes))'" $AEALGO_KEY 128" ALGR="aead "'rfc4543\(gcm\(aes\)\)'" $AEALGO_KEY 128" ;; esac ;; comp) ALG="comp $CALGO" ALGR=$ALG ;; *) tst_brk TCONF "tst_ipsec protocol mismatch" ;; esac } # tst_ipsec target src_addr dst_addr: config ipsec # # target: target of the configuration host ( lhost / rhost ) # src_addr: source IP address # dst_addr: destination IP address tst_ipsec() { if [ $# -ne 3 ]; then tst_brk TCONF "tst_ipsec parameter mismatch" fi local target=$1 local src=$2 local dst=$3 local mode=$IPSEC_MODE local p="proto $IPSEC_PROTO" [ "$IPSEC_PROTO" = "esp_aead" ] && p="proto esp" ipsec_set_algoline if [ $target = lhost ]; then local spi_1="0x$SPI" local spi_2="0x$(( $SPI + 1 ))" TST_RTNL_CHK ip xfrm state add src $src dst $dst spi $spi_1 \ $p $ALG mode $mode sel src $src dst $dst ROD ip xfrm state add src $dst dst $src spi $spi_2 \ $p $ALG mode $mode sel src $dst dst $src ROD ip xfrm policy add src $src dst $dst dir out tmpl src $src \ dst $dst $p mode $mode ROD ip xfrm policy add src $dst dst $src dir in tmpl src $dst \ dst $src $p mode $mode level use elif [ $target = rhost ]; then local spi_1="0x$(( $SPI + 1 ))" local spi_2="0x$SPI" tst_rhost_run -s -c "ip xfrm state add src $src dst $dst \ spi $spi_1 $p $ALGR mode $mode sel src $src dst $dst" tst_rhost_run -s -c "ip xfrm state add src $dst dst $src \ spi $spi_2 $p $ALGR mode $mode sel src $dst dst $src" tst_rhost_run -s -c "ip xfrm policy add src $src dst $dst \ dir out tmpl src $src dst $dst $p mode $mode" tst_rhost_run -s -c "ip xfrm policy add src $dst dst $src dir \ in tmpl src $dst dst $src $p mode $mode level use" fi } # tst_ipsec_vti target src_addr dst_addr vti_name # # target: target of the configuration host ( lhost / rhost ) # src_addr: source IP address # dst_addr: destination IP address # vti_name: name of vti interface tst_ipsec_vti() { if [ $# -ne 4 ]; then tst_brk TCONF "tst_ipsec_vti parameter mismatch" fi local target=$1 local src=$2 local dst=$3 local vti=$4 local m="mode $IPSEC_MODE" local p="proto $IPSEC_PROTO" [ "$IPSEC_PROTO" = "esp_aead" ] && p="proto esp" local key="key $VTI_KEY" local mrk="mark $VTI_KEY" local type="type vti$TST_IPV6" local d="dev $(tst_iface)" local rd="dev $(tst_iface rhost)" ip li add type vti help 2>&1 | grep -q vti || \ tst_brk TCONF "iproute doesn't support 'vti'" ipsec_set_algoline local o_dir="src $src dst $dst" local i_dir="src $dst dst $src" local ipx="ip -$TST_IPVER xf" cleanup_vti=$vti if [ $target = lhost ]; then TST_RTNL_CHK ip li add $vti $type local $src remote $dst $key $d ROD ip li set $vti up local spi_1="spi 0x$SPI" local spi_2="spi 0x$(( $SPI + 1 ))" TST_RTNL_CHK $ipx st add $o_dir $p $spi_1 $ALG $m ROD $ipx st add $i_dir $p $spi_2 $ALG $m ROD $ipx po add dir out tmpl $o_dir $p $m $mrk ROD $ipx po add dir in tmpl $i_dir $p $m $mrk elif [ $target = rhost ]; then tst_rhost_run -s -c \ "ip li add $vti $type local $src remote $dst $key $rd" tst_rhost_run -s -c "ip li set $vti up" local spi_1="spi 0x$(( $SPI + 1 ))" local spi_2="spi 0x$SPI" tst_rhost_run -s -c "$ipx st add $o_dir $p $spi_1 $ALGR $m" tst_rhost_run -s -c "$ipx st add $i_dir $p $spi_2 $ALGR $m" tst_rhost_run -s -c "$ipx po add dir out tmpl $o_dir $p $m $mrk" tst_rhost_run -s -c "$ipx po add dir in tmpl $i_dir $p $m $mrk" fi } # Setup vti/vti6 interface for IPsec tunneling # The function sets variables: # * tst_vti - vti interface name, # * ip_loc_tun - local IP address on vti interface # * ip_rmt_tun - remote IP address tst_ipsec_setup_vti() { ipsec_lib_setup if_loc=$(tst_iface) if_rmt=$(tst_iface rhost) ip_loc=$(tst_ipaddr) ip_rmt=$(tst_ipaddr rhost) tst_vti="ltp_vti0" tst_res TINFO "Test vti$TST_IPV6 + IPsec[$IPSEC_PROTO/$IPSEC_MODE]" tst_ipsec_vti lhost $ip_loc $ip_rmt $tst_vti tst_ipsec_vti rhost $ip_rmt $ip_loc $tst_vti local mask address_opt if [ "$TST_IPV6" ]; then ip_loc_tun="${IPV6_NET32_UNUSED}::1"; ip_rmt_tun="${IPV6_NET32_UNUSED}::2"; mask=64 address_opt=nodad ROD ip -6 route add ${IPV6_NET32_UNUSED}::/$mask dev $tst_vti else ip_loc_tun="${IPV4_NET16_UNUSED}.1.1"; ip_rmt_tun="${IPV4_NET16_UNUSED}.1.2"; mask=30 ROD ip route add ${IPV4_NET16_UNUSED}.1.0/$mask dev $tst_vti fi tst_res TINFO "Add IPs to vti tunnel, " \ "loc: $ip_loc_tun/$mask, rmt: $ip_rmt_tun/$mask" ROD ip a add $ip_loc_tun/$mask dev $tst_vti $address_opt tst_rhost_run -s -c "ip a add $ip_rmt_tun/$mask dev $tst_vti" }