Edit changelog a little for clarity and conciseness
[tor.git] / src / test / test_keygen.sh
blob87012cd2830f4c5f0c48c67d58e8735712d8cf79
1 #!/bin/sh
3 # Note: some of this code is lifted from zero_length_keys.sh, and could be
4 # unified.
6 umask 077
7 set -e
9 if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then
10 if [ "$TESTING_TOR_BINARY" = "" ] ; then
11 echo "Usage: ${0} PATH_TO_TOR [case-number]"
12 exit 1
16 if [ $# -ge 1 ]; then
17 TOR_BINARY="${1}"
18 shift
19 else
20 TOR_BINARY="${TESTING_TOR_BINARY}"
25 if [ $# -ge 1 ]; then
26 dflt=0
27 else
28 dflt=1
31 CASE2A=$dflt
32 CASE2B=$dflt
33 CASE3A=$dflt
34 CASE3B=$dflt
35 CASE3C=$dflt
36 CASE4=$dflt
37 CASE5=$dflt
38 CASE6=$dflt
39 CASE7=$dflt
40 CASE8=$dflt
41 CASE9=$dflt
42 CASE10=$dflt
44 if [ $# -ge 1 ]; then
45 eval "CASE${1}"=1
49 dump() { xxd -p "$1" | tr -d '\n '; }
50 die() { echo "$1" >&2 ; exit 5; }
51 check_dir() { [ -d "$1" ] || die "$1 did not exist"; }
52 check_file() { [ -e "$1" ] || die "$1 did not exist"; }
53 check_no_file() { [ -e "$1" ] && die "$1 was not supposed to exist" || true; }
54 check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: `dump $1` vs `dump $2`"; }
55 check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; }
57 DATA_DIR=`mktemp -d -t tor_keygen_tests.XXXXXX`
58 if [ -z "$DATA_DIR" ]; then
59 echo "Failure: mktemp invocation returned empty string" >&2
60 exit 3
62 if [ ! -d "$DATA_DIR" ]; then
63 echo "Failure: mktemp invocation result doesn't point to directory" >&2
64 exit 3
66 trap "rm -rf '$DATA_DIR'" 0
68 # Use an absolute path for this or Tor will complain
69 DATA_DIR=`cd "${DATA_DIR}" && pwd`
71 touch "${DATA_DIR}/empty_torrc"
73 QUIETLY="--hush"
74 SILENTLY="--quiet"
75 TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc"
77 ##### SETUP
79 # Here we create three sets of keys: one using "tor", one using "tor
80 # --keygen", and one using "tor --keygen" and encryption. We'll be
81 # copying them into different keys directories in order to simulate
82 # different kinds of configuration problems/issues.
84 # Step 1: Start Tor with --list-fingerprint --quiet. Make sure everything is there.
85 mkdir "${DATA_DIR}/orig"
86 ${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint ${SILENTLY} > /dev/null
88 check_dir "${DATA_DIR}/orig/keys"
89 check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key"
90 check_file "${DATA_DIR}/orig/keys/ed25519_master_id_secret_key"
91 check_file "${DATA_DIR}/orig/keys/ed25519_signing_cert"
92 check_file "${DATA_DIR}/orig/keys/ed25519_signing_secret_key"
94 # Step 2: Start Tor with --keygen. Make sure everything is there.
95 mkdir "${DATA_DIR}/keygen"
96 ${TOR} --DataDirectory "${DATA_DIR}/keygen" --keygen --no-passphrase 2>"${DATA_DIR}/keygen/stderr"
97 grep "Not encrypting the secret key" "${DATA_DIR}/keygen/stderr" >/dev/null || die "Tor didn't declare that there would be no encryption"
99 check_dir "${DATA_DIR}/keygen/keys"
100 check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_public_key"
101 check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_secret_key"
102 check_file "${DATA_DIR}/keygen/keys/ed25519_signing_cert"
103 check_file "${DATA_DIR}/keygen/keys/ed25519_signing_secret_key"
105 # Step 3: Start Tor with --keygen and a passphrase.
106 # Make sure everything is there.
107 mkdir "${DATA_DIR}/encrypted"
108 echo "passphrase" | ${TOR} --DataDirectory "${DATA_DIR}/encrypted" --keygen --passphrase-fd 0
110 check_dir "${DATA_DIR}/encrypted/keys"
111 check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_public_key"
112 check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_secret_key_encrypted"
113 check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert"
114 check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key"
117 echo "=== Starting keygen tests."
120 # The "case X" numbers below come from s7r's email on
121 # https://lists.torproject.org/pipermail/tor-dev/2015-August/009204.html
124 # Case 2a: Missing secret key, public key exists, start tor.
126 if [ "$CASE2A" = 1 ]; then
128 ME="${DATA_DIR}/case2a"
129 SRC="${DATA_DIR}/orig"
130 mkdir -p "${ME}/keys"
131 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
132 ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Somehow succeeded when missing secret key, certs: `cat ${ME}/stdout`" || true
133 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
135 grep "We needed to load a secret key.*but couldn't find it" "${ME}/stdout" >/dev/null || die "Tor didn't declare that it was missing a secret key"
137 echo "==== Case 2A ok"
140 # Case 2b: Encrypted secret key, public key exists, start tor.
142 if [ "$CASE2B" = 1 ]; then
144 ME="${DATA_DIR}/case2b"
145 SRC="${DATA_DIR}/encrypted"
147 mkdir -p "${ME}/keys"
148 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
149 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
150 ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && dir "Somehow succeeded with encrypted secret key, missing certs"
152 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
153 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
155 grep "We needed to load a secret key.*but it was encrypted.*--keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that it was missing a secret key and suggest --keygen."
157 echo "==== Case 2B ok"
161 # Case 3a: Start Tor with only master key.
163 if [ "$CASE3A" = 1 ]; then
165 ME="${DATA_DIR}/case3a"
166 SRC="${DATA_DIR}/orig"
168 mkdir -p "${ME}/keys"
169 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
170 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Tor failed when starting with only master key"
171 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
172 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
173 check_file "${ME}/keys/ed25519_signing_cert"
174 check_file "${ME}/keys/ed25519_signing_secret_key"
176 echo "==== Case 3A ok"
180 # Case 3b: Call keygen with only unencrypted master key.
182 if [ "$CASE3B" = 1 ]; then
184 ME="${DATA_DIR}/case3b"
185 SRC="${DATA_DIR}/orig"
187 mkdir -p "${ME}/keys"
188 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
189 ${TOR} --DataDirectory "${ME}" --keygen || die "Keygen failed with only master key"
190 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
191 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
192 check_file "${ME}/keys/ed25519_signing_cert"
193 check_file "${ME}/keys/ed25519_signing_secret_key"
195 echo "==== Case 3B ok"
199 # Case 3c: Call keygen with only encrypted master key.
201 if [ "$CASE3C" = 1 ]; then
203 ME="${DATA_DIR}/case3c"
204 SRC="${DATA_DIR}/encrypted"
206 mkdir -p "${ME}/keys"
207 cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
208 echo "passphrase" | ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 0 || die "Keygen failed with only encrypted master key"
209 check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
210 check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
211 check_file "${ME}/keys/ed25519_signing_cert"
212 check_file "${ME}/keys/ed25519_signing_secret_key"
214 echo "==== Case 3C ok"
218 # Case 4: Make a new data directory with only an unencrypted secret key.
219 # Then start tor. The rest should become correct.
221 if [ "$CASE4" = 1 ]; then
223 ME="${DATA_DIR}/case4"
224 SRC="${DATA_DIR}/orig"
226 mkdir -p "${ME}/keys"
227 cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
228 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key"
229 check_file "${ME}/keys/ed25519_master_id_public_key"
230 check_file "${ME}/keys/ed25519_signing_cert"
231 check_file "${ME}/keys/ed25519_signing_secret_key"
232 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key."
234 check_files_eq "${ME}/fp1" "${ME}/fp2"
236 echo "==== Case 4 ok"
240 # Case 5: Make a new data directory with only an encrypted secret key.
242 if [ "$CASE5" = 1 ]; then
244 ME="${DATA_DIR}/case5"
245 SRC="${DATA_DIR}/encrypted"
247 mkdir -p "${ME}/keys"
248 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
249 ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Tor started with only encrypted secret key!"
250 check_no_file "${ME}/keys/ed25519_master_id_public_key"
251 check_no_file "${ME}/keys/ed25519_master_id_public_key"
253 grep "but not public key file" "${ME}/stdout" >/dev/null || die "Tor didn't declare it couldn't find a public key."
255 echo "==== Case 5 ok"
259 # Case 6: Make a new data directory with encrypted secret key and public key
261 if [ "$CASE6" = 1 ]; then
263 ME="${DATA_DIR}/case6"
264 SRC="${DATA_DIR}/encrypted"
266 mkdir -p "${ME}/keys"
267 cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
268 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
269 ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Tor started with encrypted secret key and no certs" || true
270 check_no_file "${ME}/keys/ed25519_signing_cert"
271 check_no_file "${ME}/keys/ed25519_signing_secret_key"
273 grep "but it was encrypted" "${ME}/stdout" >/dev/null || die "Tor didn't declare that the secret key was encrypted."
275 echo "==== Case 6 ok"
279 # Case 7: Make a new data directory with unencrypted secret key and
280 # certificates; missing master public.
282 if [ "$CASE7" = 1 ]; then
284 ME="${DATA_DIR}/case7"
285 SRC="${DATA_DIR}/keygen"
287 mkdir -p "${ME}/keys"
288 cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
289 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
290 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
292 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with missing public key"
293 check_keys_eq ed25519_master_id_secret_key
294 check_keys_eq ed25519_master_id_public_key
295 check_keys_eq ed25519_signing_secret_key
296 check_keys_eq ed25519_signing_cert
298 echo "==== Case 7 ok"
302 # Case 8: offline master secret key.
304 if [ "$CASE8" = 1 ]; then
306 ME="${DATA_DIR}/case8"
307 SRC="${DATA_DIR}/keygen"
309 mkdir -p "${ME}/keys"
310 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
311 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
312 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
314 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with offline secret key"
315 check_no_file "${ME}/keys/ed25519_master_id_secret_key"
316 check_keys_eq ed25519_master_id_public_key
317 check_keys_eq ed25519_signing_secret_key
318 check_keys_eq ed25519_signing_cert
320 echo "==== Case 8 ok"
324 # Case 9: signing cert and secret key provided; could infer master key.
326 if [ "$CASE9" = 1 ]; then
328 ME="${DATA_DIR}/case9"
329 SRC="${DATA_DIR}/keygen"
331 mkdir -p "${ME}/keys"
332 cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
333 cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
335 ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with only signing material"
336 check_no_file "${ME}/keys/ed25519_master_id_secret_key"
337 check_file "${ME}/keys/ed25519_master_id_public_key"
338 check_keys_eq ed25519_signing_secret_key
339 check_keys_eq ed25519_signing_cert
341 echo "==== Case 9 ok"
346 # Case 10: master key mismatch.
348 if [ "$CASE10" = 1 ]; then
350 ME="${DATA_DIR}/case10"
351 SRC="${DATA_DIR}/keygen"
352 OTHER="${DATA_DIR}/orig"
354 mkdir -p "${ME}/keys"
355 cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
356 cp "${OTHER}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
358 ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Successfully started with mismatched keys!?" || true
360 grep "public_key does not match.*secret_key" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a key mismatch"
362 echo "==== Case 10 ok"
367 # Check cert-only.