aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_keygen.sh
blob: 7afff271cbd26462fcc1298cf729db0148499d28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
#!/bin/sh

# Note: some of this code is lifted from zero_length_keys.sh, and could be
# unified.

umask 077
set -e

if [ $# -eq 0 ] || [ ! -f ${1} ] || [ ! -x ${1} ]; then
  if [ "$TESTING_TOR_BINARY" = "" ] ; then
    echo "Usage: ${0} PATH_TO_TOR [case-number]"
    exit 1
  fi
fi

UNAME_OS=`uname -s | cut -d_ -f1`
if test "$UNAME_OS" = 'CYGWIN' || \
   test "$UNAME_OS" = 'MSYS' || \
   test "$UNAME_OS" = 'MINGW'; then
  echo "This test is unreliable on Windows. See trac #26076. Skipping." >&2
  exit 77
fi

if [ $# -ge 1 ]; then
  TOR_BINARY="${1}"
  shift
else
  TOR_BINARY="${TESTING_TOR_BINARY}"
fi



  if [ $# -ge 1 ]; then
      dflt=0
  else
      dflt=1
  fi

  CASE2A=$dflt
  CASE2B=$dflt
  CASE3A=$dflt
  CASE3B=$dflt
  CASE3C=$dflt
  CASE4=$dflt
  CASE5=$dflt
  CASE6=$dflt
  CASE7=$dflt
  CASE8=$dflt
  CASE9=$dflt
  CASE10=$dflt
  CASE11A=$dflt
  CASE11B=$dflt
  CASE11C=$dflt
  CASE11D=$dflt
  CASE11E=$dflt
  CASE11F=$dflt

  if [ $# -ge 1 ]; then
     eval "CASE${1}"=1
  fi


dump() { xxd -p "$1" | tr -d '\n '; }
die() { echo "$1" >&2 ; exit 5; }
check_dir() { [ -d "$1" ] || die "$1 did not exist"; }
check_file() { [ -e "$1" ] || die "$1 did not exist"; }
check_no_file() { [ -e "$1" ] && die "$1 was not supposed to exist" || true; }
check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: `dump $1` vs `dump $2`"; }
check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; }

DATA_DIR=`mktemp -d -t tor_keygen_tests.XXXXXX`
if [ -z "$DATA_DIR" ]; then
  echo "Failure: mktemp invocation returned empty string" >&2
  exit 3
fi
if [ ! -d "$DATA_DIR" ]; then
  echo "Failure: mktemp invocation result doesn't point to directory" >&2
  exit 3
fi
trap "rm -rf '$DATA_DIR'" 0

# Use an absolute path for this or Tor will complain
DATA_DIR=`cd "${DATA_DIR}" && pwd`

touch "${DATA_DIR}/empty_torrc"
touch "${DATA_DIR}/empty_defaults_torrc"

QUIETLY="--hush"
SILENTLY="--quiet"
TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc --defaults-torrc ${DATA_DIR}/empty_defaults_torrc"

##### SETUP
#
# Here we create three sets of keys: one using "tor", one using "tor
# --keygen", and one using "tor --keygen" and encryption.  We'll be
# copying them into different keys directories in order to simulate
# different kinds of configuration problems/issues.

# Step 1: Start Tor with --list-fingerprint --quiet.  Make sure everything is there.
mkdir "${DATA_DIR}/orig"
${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint ${SILENTLY} > /dev/null

check_dir "${DATA_DIR}/orig/keys"
check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key"
check_file "${DATA_DIR}/orig/keys/ed25519_master_id_secret_key"
check_file "${DATA_DIR}/orig/keys/ed25519_signing_cert"
check_file "${DATA_DIR}/orig/keys/ed25519_signing_secret_key"

# Step 2: Start Tor with --keygen.  Make sure everything is there.
mkdir "${DATA_DIR}/keygen"
${TOR} --DataDirectory "${DATA_DIR}/keygen" --keygen --no-passphrase 2>"${DATA_DIR}/keygen/stderr"
grep "Not encrypting the secret key" "${DATA_DIR}/keygen/stderr" >/dev/null || die "Tor didn't declare that there would be no encryption"

check_dir "${DATA_DIR}/keygen/keys"
check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_public_key"
check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_secret_key"
check_file "${DATA_DIR}/keygen/keys/ed25519_signing_cert"
check_file "${DATA_DIR}/keygen/keys/ed25519_signing_secret_key"

# Step 3: Start Tor with --keygen and a passphrase.
#         Make sure everything is there.
mkdir "${DATA_DIR}/encrypted"
echo "passphrase" | ${TOR} --DataDirectory "${DATA_DIR}/encrypted" --keygen --passphrase-fd 0

check_dir "${DATA_DIR}/encrypted/keys"
check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_public_key"
check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_secret_key_encrypted"
check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert"
check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key"


echo "=== Starting keygen tests."

#
# The "case X" numbers below come from s7r's email on
#   https://lists.torproject.org/pipermail/tor-dev/2015-August/009204.html


# Case 2a: Missing secret key, public key exists, start tor.

if [ "$CASE2A" = 1 ]; then

ME="${DATA_DIR}/case2a"
SRC="${DATA_DIR}/orig"
mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Somehow succeeded when missing secret key, certs: `cat ${ME}/stdout`" || true
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"

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"

echo "==== Case 2A ok"
fi

# Case 2b: Encrypted secret key, public key exists, start tor.

if [ "$CASE2B" = 1 ]; then

ME="${DATA_DIR}/case2b"
SRC="${DATA_DIR}/encrypted"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && dir "Somehow succeeded with encrypted secret key, missing certs"

check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"

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."

echo "==== Case 2B ok"

fi

# Case 3a: Start Tor with only master key.

if [ "$CASE3A" = 1 ]; then

ME="${DATA_DIR}/case3a"
SRC="${DATA_DIR}/orig"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Tor failed when starting with only master key"
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
check_file "${ME}/keys/ed25519_signing_cert"
check_file "${ME}/keys/ed25519_signing_secret_key"

echo "==== Case 3A ok"

fi

# Case 3b: Call keygen with only unencrypted master key.

if [ "$CASE3B" = 1 ]; then

ME="${DATA_DIR}/case3b"
SRC="${DATA_DIR}/orig"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --keygen || die "Keygen failed with only master key"
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
check_file "${ME}/keys/ed25519_signing_cert"
check_file "${ME}/keys/ed25519_signing_secret_key"

echo "==== Case 3B ok"

fi

# Case 3c: Call keygen with only encrypted master key.

if [ "$CASE3C" = 1 ]; then

ME="${DATA_DIR}/case3c"
SRC="${DATA_DIR}/encrypted"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
echo "passphrase" | ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 0 || die "Keygen failed with only encrypted master key"
check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
check_file "${ME}/keys/ed25519_signing_cert"
check_file "${ME}/keys/ed25519_signing_secret_key"

echo "==== Case 3C ok"

fi

# Case 4: Make a new data directory with only an unencrypted secret key.
#         Then start tor.  The rest should become correct.

if [ "$CASE4" = 1 ]; then

ME="${DATA_DIR}/case4"
SRC="${DATA_DIR}/orig"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key"
check_file "${ME}/keys/ed25519_master_id_public_key"
check_file "${ME}/keys/ed25519_signing_cert"
check_file "${ME}/keys/ed25519_signing_secret_key"
${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key."

check_files_eq "${ME}/fp1" "${ME}/fp2"

echo "==== Case 4 ok"

fi

# Case 5: Make a new data directory with only an encrypted secret key.

if [ "$CASE5" = 1 ]; then

ME="${DATA_DIR}/case5"
SRC="${DATA_DIR}/encrypted"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Tor started with only encrypted secret key!"
check_no_file "${ME}/keys/ed25519_master_id_public_key"
check_no_file "${ME}/keys/ed25519_master_id_public_key"

grep "but not public key file" "${ME}/stdout" >/dev/null || die "Tor didn't declare it couldn't find a public key."

echo "==== Case 5 ok"

fi

# Case 6: Make a new data directory with encrypted secret key and public key

if [ "$CASE6" = 1 ]; then

ME="${DATA_DIR}/case6"
SRC="${DATA_DIR}/encrypted"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && die "Tor started with encrypted secret key and no certs" || true
check_no_file "${ME}/keys/ed25519_signing_cert"
check_no_file "${ME}/keys/ed25519_signing_secret_key"

grep "but it was encrypted" "${ME}/stdout" >/dev/null || die "Tor didn't declare that the secret key was encrypted."

echo "==== Case 6 ok"

fi

# Case 7: Make a new data directory with unencrypted secret key and
# certificates; missing master public.

if [ "$CASE7" = 1 ]; then

ME="${DATA_DIR}/case7"
SRC="${DATA_DIR}/keygen"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"

${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with missing public key"
check_keys_eq ed25519_master_id_secret_key
check_keys_eq ed25519_master_id_public_key
check_keys_eq ed25519_signing_secret_key
check_keys_eq ed25519_signing_cert

echo "==== Case 7 ok"

fi

# Case 8: offline master secret key.

if [ "$CASE8" = 1 ]; then

ME="${DATA_DIR}/case8"
SRC="${DATA_DIR}/keygen"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"

${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with offline secret key"
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
check_keys_eq ed25519_master_id_public_key
check_keys_eq ed25519_signing_secret_key
check_keys_eq ed25519_signing_cert

echo "==== Case 8 ok"

fi

# Case 9: signing cert and secret key provided; could infer master key.

if [ "$CASE9" = 1 ]; then

ME="${DATA_DIR}/case9"
SRC="${DATA_DIR}/keygen"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"

${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with only signing material"
check_no_file "${ME}/keys/ed25519_master_id_secret_key"
check_file "${ME}/keys/ed25519_master_id_public_key"
check_keys_eq ed25519_signing_secret_key
check_keys_eq ed25519_signing_cert

echo "==== Case 9 ok"

fi


# Case 10: master key mismatch.

if [ "$CASE10" = 1 ]; then

ME="${DATA_DIR}/case10"
SRC="${DATA_DIR}/keygen"
OTHER="${DATA_DIR}/orig"

mkdir -p "${ME}/keys"
cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
cp "${OTHER}/keys/ed25519_master_id_secret_key" "${ME}/keys/"

${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Successfully started with mismatched keys!?" || true

grep "public_key does not match.*secret_key" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a key mismatch"

echo "==== Case 10 ok"

fi

# Case 11a: -passphrase-fd without --keygen

if [ "$CASE11A" = 1 ]; then

ME="${DATA_DIR}/case11a"

mkdir -p "${ME}/keys"

${TOR} --DataDirectory "${ME}" --passphrase-fd 1 > "${ME}/stdout" && die "Successfully started with passphrase-fd but no keygen?" || true

grep "passphrase-fd specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

echo "==== Case 11A ok"

fi

# Case 11b: --no-passphrase without --keygen

if [ "$CASE11B" = 1 ]; then

ME="${DATA_DIR}/case11b"

mkdir -p "${ME}/keys"

${TOR} --DataDirectory "${ME}" --no-passphrase > "${ME}/stdout" && die "Successfully started with no-passphrase but no keygen?" || true

grep "no-passphrase specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

echo "==== Case 11B ok"

fi

# Case 11c: --newpass without --keygen

if [ "$CASE11C" = 1 ]; then

ME="${DATA_DIR}/case11C"

mkdir -p "${ME}/keys"

${TOR} --DataDirectory "${ME}" --newpass > "${ME}/stdout" && die "Successfully started with newpass but no keygen?" || true

grep "newpass specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

echo "==== Case 11C ok"

fi

######## --master-key does not work yet, but this will test the error case
########  when it does.
#
# Case 11d: --master-key without --keygen
#
if [ "$CASE11D" = 1 ]; then
#
# ME="${DATA_DIR}/case11d"
#
# mkdir -p "${ME}/keys"
#
# ${TOR} --DataDirectory "${ME}" --master-key "${ME}/foobar" > "${ME}/stdout" && die "Successfully started with master-key but no keygen?" || true
#
# cat "${ME}/stdout"
#
# grep "master-key without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

    echo "==== Case 11D skipped"

fi


# Case 11E: Silly passphrase-fd

if [ "$CASE11E" = 1 ]; then

ME="${DATA_DIR}/case11E"

mkdir -p "${ME}/keys"

${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd ewigeblumenkraft > "${ME}/stdout" && die "Successfully started with bogus passphrase-fd?" || true

grep "Invalid --passphrase-fd value" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

echo "==== Case 11E ok"

fi


# Case 11F: --no-passphrase with --passphrase-fd

if [ "$CASE11F" = 1 ]; then

ME="${DATA_DIR}/case11F"

mkdir -p "${ME}/keys"

${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 1 --no-passphrase > "${ME}/stdout" && die "Successfully started with bogus passphrase-fd combination?" || true

grep "no-passphrase specified with --passphrase-fd" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."

echo "==== Case 11F ok"

fi


# Check cert-only.