1#	$NetBSD: t_ipsec_transport.sh,v 1.8 2023/06/19 08:28:09 knakahara Exp $
2#
3# Copyright (c) 2017 Internet Initiative Japan Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27
28SOCK_LOCAL=unix://ipsec_local
29SOCK_PEER=unix://ipsec_peer
30BUS=./bus_ipsec
31
32DEBUG=${DEBUG:-false}
33
34check_packets()
35{
36	local outfile=$1
37	local src=$2
38	local dst=$3
39	local pktproto=$4
40
41	atf_check -s exit:0 -o match:"$src > $dst: $pktproto" cat $outfile
42	atf_check -s exit:0 -o match:"$dst > $src: $pktproto" cat $outfile
43}
44
45test_ipsec4_transport()
46{
47	local proto=$1
48	local algo=$2
49	local ip_local=10.0.0.1
50	local ip_peer=10.0.0.2
51	local tmpfile=./tmp
52	local outfile=./out
53	local pktproto=$(generate_pktproto $proto)
54	local algo_args="$(generate_algo_args $proto $algo)"
55	local pktsize=
56
57	rump_server_crypto_start $SOCK_LOCAL netipsec
58	rump_server_crypto_start $SOCK_PEER netipsec
59	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
60	rump_server_add_iface $SOCK_PEER shmif0 $BUS
61
62	export RUMP_SERVER=$SOCK_LOCAL
63	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
64	atf_check -s exit:0 rump.ifconfig -w 10
65
66	export RUMP_SERVER=$SOCK_PEER
67	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
68	atf_check -s exit:0 rump.ifconfig -w 10
69
70	extract_new_packets $BUS > $outfile
71
72	export RUMP_SERVER=$SOCK_LOCAL
73	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
74
75	extract_new_packets $BUS > $outfile
76	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: ICMP echo request" \
77	    cat $outfile
78	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: ICMP echo reply" \
79	    cat $outfile
80
81	export RUMP_SERVER=$SOCK_LOCAL
82	# from https://www.netbsd.org/docs/network/ipsec/
83	cat > $tmpfile <<-EOF
84	add $ip_local $ip_peer $proto 10000 $algo_args;
85	add $ip_peer $ip_local $proto 10001 $algo_args;
86	spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require;
87	EOF
88	$DEBUG && cat $tmpfile
89	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
90	check_sa_entries $SOCK_LOCAL $ip_local $ip_peer
91
92	export RUMP_SERVER=$SOCK_PEER
93	cat > $tmpfile <<-EOF
94	add $ip_local $ip_peer $proto 10000 $algo_args;
95	add $ip_peer $ip_local $proto 10001 $algo_args;
96	spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require;
97	EOF
98	$DEBUG && cat $tmpfile
99	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
100	check_sa_entries $SOCK_PEER $ip_local $ip_peer
101
102	export RUMP_SERVER=$SOCK_LOCAL
103	if [ $proto = ipcomp ]; then
104		# IPComp sends a packet as-is if a compressed payload of
105		# the packet is greater than or equal to the original payload.
106		# So we have to fill a payload with 1 to let IPComp always send
107		# a compressed packet.
108
109		# pktsize == minlen - 1
110		pktsize=$(($(get_minlen $algo) - 8 - 1))
111		atf_check -s exit:0 -o ignore \
112		    rump.ping -c 1 -n -w 3 -s $pktsize -p ff $ip_peer
113		extract_new_packets $BUS > $outfile
114		check_packets $outfile $ip_local $ip_peer ICMP
115
116		# pktsize == minlen
117		pktsize=$(($(get_minlen $algo) - 8))
118		atf_check -s exit:0 -o ignore \
119		    rump.ping -c 1 -n -w 3 -s $pktsize -p ff $ip_peer
120		extract_new_packets $BUS > $outfile
121		check_packets $outfile $ip_local $ip_peer $pktproto
122	else
123		atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
124		extract_new_packets $BUS > $outfile
125		check_packets $outfile $ip_local $ip_peer $pktproto
126	fi
127
128	test_flush_entries $SOCK_LOCAL
129	test_flush_entries $SOCK_PEER
130}
131
132test_ipsec6_transport()
133{
134	local proto=$1
135	local algo=$2
136	local ip_local=fd00::1
137	local ip_peer=fd00::2
138	local tmpfile=./tmp
139	local outfile=./out
140	local pktproto=$(generate_pktproto $proto)
141	local algo_args="$(generate_algo_args $proto $algo)"
142
143	rump_server_crypto_start $SOCK_LOCAL netinet6 netipsec
144	rump_server_crypto_start $SOCK_PEER netinet6 netipsec
145	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
146	rump_server_add_iface $SOCK_PEER shmif0 $BUS
147
148	export RUMP_SERVER=$SOCK_LOCAL
149	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_local
150	atf_check -s exit:0 rump.ifconfig -w 10
151
152	export RUMP_SERVER=$SOCK_PEER
153	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_peer
154	atf_check -s exit:0 rump.ifconfig -w 10
155
156	extract_new_packets $BUS > $outfile
157
158	export RUMP_SERVER=$SOCK_LOCAL
159	atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_peer
160
161	extract_new_packets $BUS > $outfile
162	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: ICMP6, echo request" \
163	    cat $outfile
164	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: ICMP6, echo reply" \
165	    cat $outfile
166
167	export RUMP_SERVER=$SOCK_LOCAL
168	# from https://www.netbsd.org/docs/network/ipsec/
169	cat > $tmpfile <<-EOF
170	add $ip_local $ip_peer $proto 10000 $algo_args;
171	add $ip_peer $ip_local $proto 10001 $algo_args;
172	spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require;
173	EOF
174	$DEBUG && cat $tmpfile
175	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
176	check_sa_entries $SOCK_LOCAL $ip_local $ip_peer
177
178	export RUMP_SERVER=$SOCK_PEER
179	cat > $tmpfile <<-EOF
180	add $ip_local $ip_peer $proto 10000 $algo_args;
181	add $ip_peer $ip_local $proto 10001 $algo_args;
182	spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require;
183	EOF
184	$DEBUG && cat $tmpfile
185	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
186	check_sa_entries $SOCK_PEER $ip_local $ip_peer
187
188	export RUMP_SERVER=$SOCK_LOCAL
189	if [ $proto = ipcomp ]; then
190		# IPComp sends a packet as-is if a compressed payload of
191		# the packet is greater than or equal to the original payload.
192		# So we have to fill a payload with 1 to let IPComp always send
193		# a compressed packet.
194
195		# pktsize == minlen - 1
196		pktsize=$(($(get_minlen $algo) - 8 - 1))
197		atf_check -s exit:0 -o ignore \
198		    rump.ping6 -c 1 -n -X 3 -s $pktsize -p ff $ip_peer
199		extract_new_packets $BUS > $outfile
200		check_packets $outfile $ip_local $ip_peer ICMP6
201
202		# pktsize == minlen
203		pktsize=$(($(get_minlen $algo) - 8))
204		atf_check -s exit:0 -o ignore \
205		    rump.ping6 -c 1 -n -X 3 -s $pktsize -p ff $ip_peer
206		extract_new_packets $BUS > $outfile
207		check_packets $outfile $ip_local $ip_peer $pktproto
208	else
209		atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_peer
210		extract_new_packets $BUS > $outfile
211		check_packets $outfile $ip_local $ip_peer $pktproto
212	fi
213
214	test_flush_entries $SOCK_LOCAL
215	test_flush_entries $SOCK_PEER
216}
217
218test_transport_common()
219{
220	local ipproto=$1
221	local proto=$2
222	local algo=$3
223
224	if [ $ipproto = ipv4 ]; then
225		test_ipsec4_transport $proto $algo
226	else
227		test_ipsec6_transport $proto $algo
228	fi
229}
230
231add_test_transport_mode()
232{
233	local ipproto=$1
234	local proto=$2
235	local algo=$3
236	local _algo=$(echo $algo | sed 's/-//g')
237	local name= desc=
238
239	name="ipsec_transport_${ipproto}_${proto}_${_algo}"
240	desc="Tests of IPsec ($ipproto) transport mode with $proto ($algo)"
241
242	atf_test_case ${name} cleanup
243	eval "
244	    ${name}_head() {
245	        atf_set descr \"$desc\"
246	        atf_set require.progs rump_server setkey
247	    }
248	    ${name}_body() {
249	        test_transport_common $ipproto $proto $algo
250	        rump_server_destroy_ifaces
251	    }
252	    ${name}_cleanup() {
253	        \$DEBUG && dump
254	        cleanup
255	    }
256	"
257	atf_add_test_case ${name}
258}
259
260atf_init_test_cases()
261{
262	local algo=
263
264	for algo in $ESP_ENCRYPTION_ALGORITHMS; do
265		add_test_transport_mode ipv4 esp $algo
266		add_test_transport_mode ipv6 esp $algo
267	done
268	for algo in $AH_AUTHENTICATION_ALGORITHMS; do
269		add_test_transport_mode ipv4 ah $algo
270		add_test_transport_mode ipv6 ah $algo
271	done
272	for algo in $IPCOMP_COMPRESSION_ALGORITHMS; do
273		add_test_transport_mode ipv4 ipcomp $algo
274		add_test_transport_mode ipv6 ipcomp $algo
275	done
276}
277