test_keygen.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #!/bin/sh
  2. # Note: some of this code is lifted from zero_length_keys.sh, and could be
  3. # unified.
  4. umask 077
  5. set -e
  6. if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then
  7. if [ "$TESTING_TOR_BINARY" = "" ] ; then
  8. echo "Usage: ${0} PATH_TO_TOR [case-number]"
  9. exit 1
  10. fi
  11. fi
  12. UNAME_OS=$(uname -s | cut -d_ -f1)
  13. if test "$UNAME_OS" = 'CYGWIN' || \
  14. test "$UNAME_OS" = 'MSYS' || \
  15. test "$UNAME_OS" = 'MINGW'; then
  16. echo "This test is unreliable on Windows. See trac #26076. Skipping." >&2
  17. exit 77
  18. fi
  19. if [ $# -ge 1 ]; then
  20. TOR_BINARY="${1}"
  21. shift
  22. else
  23. TOR_BINARY="${TESTING_TOR_BINARY}"
  24. fi
  25. if [ $# -ge 1 ]; then
  26. dflt=0
  27. else
  28. dflt=1
  29. fi
  30. CASE2A=$dflt
  31. CASE2B=$dflt
  32. CASE3A=$dflt
  33. CASE3B=$dflt
  34. CASE3C=$dflt
  35. CASE4=$dflt
  36. CASE5=$dflt
  37. CASE6=$dflt
  38. CASE7=$dflt
  39. CASE8=$dflt
  40. CASE9=$dflt
  41. CASE10=$dflt
  42. CASE11A=$dflt
  43. CASE11B=$dflt
  44. CASE11C=$dflt
  45. CASE11D=$dflt
  46. CASE11E=$dflt
  47. CASE11F=$dflt
  48. if [ $# -ge 1 ]; then
  49. eval "CASE${1}"=1
  50. fi
  51. dump() { xxd -p "$1" | tr -d '\n '; }
  52. die() { echo "$1" >&2 ; exit 5; }
  53. check_dir() { [ -d "$1" ] || die "$1 did not exist"; }
  54. check_file() { [ -e "$1" ] || die "$1 did not exist"; }
  55. check_no_file() { if [ -e "$1" ]; then die "$1 was not supposed to exist"; fi }
  56. check_files_eq() { cmp "$1" "$2" || die "$1 and $2 did not match: $(dump "$1") vs $(dump "$2")"; }
  57. check_keys_eq() { check_files_eq "${SRC}/keys/${1}" "${ME}/keys/${1}"; }
  58. DATA_DIR=$(mktemp -d -t tor_keygen_tests.XXXXXX)
  59. if [ -z "$DATA_DIR" ]; then
  60. echo "Failure: mktemp invocation returned empty string" >&2
  61. exit 3
  62. fi
  63. if [ ! -d "$DATA_DIR" ]; then
  64. echo "Failure: mktemp invocation result doesn't point to directory" >&2
  65. exit 3
  66. fi
  67. trap 'rm -rf "$DATA_DIR"' 0
  68. # Use an absolute path for this or Tor will complain
  69. DATA_DIR=$(cd "${DATA_DIR}" && pwd)
  70. touch "${DATA_DIR}/empty_torrc"
  71. touch "${DATA_DIR}/empty_defaults_torrc"
  72. QUIETLY="--hush"
  73. SILENTLY="--quiet"
  74. TOR="${TOR_BINARY} ${QUIETLY} --DisableNetwork 1 --ShutdownWaitLength 0 --ORPort 12345 --ExitRelay 0 -f ${DATA_DIR}/empty_torrc --defaults-torrc ${DATA_DIR}/empty_defaults_torrc"
  75. ##### SETUP
  76. #
  77. # Here we create three sets of keys: one using "tor", one using "tor
  78. # --keygen", and one using "tor --keygen" and encryption. We'll be
  79. # copying them into different keys directories in order to simulate
  80. # different kinds of configuration problems/issues.
  81. # Step 1: Start Tor with --list-fingerprint --quiet. Make sure everything is there.
  82. mkdir "${DATA_DIR}/orig"
  83. ${TOR} --DataDirectory "${DATA_DIR}/orig" --list-fingerprint ${SILENTLY} > /dev/null
  84. check_dir "${DATA_DIR}/orig/keys"
  85. check_file "${DATA_DIR}/orig/keys/ed25519_master_id_public_key"
  86. check_file "${DATA_DIR}/orig/keys/ed25519_master_id_secret_key"
  87. check_file "${DATA_DIR}/orig/keys/ed25519_signing_cert"
  88. check_file "${DATA_DIR}/orig/keys/ed25519_signing_secret_key"
  89. # Step 2: Start Tor with --keygen. Make sure everything is there.
  90. mkdir "${DATA_DIR}/keygen"
  91. ${TOR} --DataDirectory "${DATA_DIR}/keygen" --keygen --no-passphrase 2>"${DATA_DIR}/keygen/stderr"
  92. grep "Not encrypting the secret key" "${DATA_DIR}/keygen/stderr" >/dev/null || die "Tor didn't declare that there would be no encryption"
  93. check_dir "${DATA_DIR}/keygen/keys"
  94. check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_public_key"
  95. check_file "${DATA_DIR}/keygen/keys/ed25519_master_id_secret_key"
  96. check_file "${DATA_DIR}/keygen/keys/ed25519_signing_cert"
  97. check_file "${DATA_DIR}/keygen/keys/ed25519_signing_secret_key"
  98. # Step 3: Start Tor with --keygen and a passphrase.
  99. # Make sure everything is there.
  100. mkdir "${DATA_DIR}/encrypted"
  101. echo "passphrase" | ${TOR} --DataDirectory "${DATA_DIR}/encrypted" --keygen --passphrase-fd 0
  102. check_dir "${DATA_DIR}/encrypted/keys"
  103. check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_public_key"
  104. check_file "${DATA_DIR}/encrypted/keys/ed25519_master_id_secret_key_encrypted"
  105. check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_cert"
  106. check_file "${DATA_DIR}/encrypted/keys/ed25519_signing_secret_key"
  107. echo "=== Starting keygen tests."
  108. #
  109. # The "case X" numbers below come from s7r's email on
  110. # https://lists.torproject.org/pipermail/tor-dev/2015-August/009204.html
  111. # Case 2a: Missing secret key, public key exists, start tor.
  112. if [ "$CASE2A" = 1 ]; then
  113. ME="${DATA_DIR}/case2a"
  114. SRC="${DATA_DIR}/orig"
  115. mkdir -p "${ME}/keys"
  116. cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
  117. if ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout"; then
  118. die "Somehow succeeded when missing secret key, certs: $(cat "${ME}/stdout")"
  119. fi
  120. check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
  121. 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"
  122. echo "==== Case 2A ok"
  123. fi
  124. # Case 2b: Encrypted secret key, public key exists, start tor.
  125. if [ "$CASE2B" = 1 ]; then
  126. ME="${DATA_DIR}/case2b"
  127. SRC="${DATA_DIR}/encrypted"
  128. mkdir -p "${ME}/keys"
  129. cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
  130. cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
  131. ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout" && dir "Somehow succeeded with encrypted secret key, missing certs"
  132. check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
  133. check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
  134. 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."
  135. echo "==== Case 2B ok"
  136. fi
  137. # Case 3a: Start Tor with only master key.
  138. if [ "$CASE3A" = 1 ]; then
  139. ME="${DATA_DIR}/case3a"
  140. SRC="${DATA_DIR}/orig"
  141. mkdir -p "${ME}/keys"
  142. cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
  143. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Tor failed when starting with only master key"
  144. check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
  145. check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
  146. check_file "${ME}/keys/ed25519_signing_cert"
  147. check_file "${ME}/keys/ed25519_signing_secret_key"
  148. echo "==== Case 3A ok"
  149. fi
  150. # Case 3b: Call keygen with only unencrypted master key.
  151. if [ "$CASE3B" = 1 ]; then
  152. ME="${DATA_DIR}/case3b"
  153. SRC="${DATA_DIR}/orig"
  154. mkdir -p "${ME}/keys"
  155. cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
  156. ${TOR} --DataDirectory "${ME}" --keygen || die "Keygen failed with only master key"
  157. check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
  158. check_files_eq "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/ed25519_master_id_secret_key"
  159. check_file "${ME}/keys/ed25519_signing_cert"
  160. check_file "${ME}/keys/ed25519_signing_secret_key"
  161. echo "==== Case 3B ok"
  162. fi
  163. # Case 3c: Call keygen with only encrypted master key.
  164. if [ "$CASE3C" = 1 ]; then
  165. ME="${DATA_DIR}/case3c"
  166. SRC="${DATA_DIR}/encrypted"
  167. mkdir -p "${ME}/keys"
  168. cp "${SRC}/keys/ed25519_master_id_"* "${ME}/keys/"
  169. echo "passphrase" | ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 0 || die "Keygen failed with only encrypted master key"
  170. check_files_eq "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/ed25519_master_id_public_key"
  171. check_files_eq "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/ed25519_master_id_secret_key_encrypted"
  172. check_file "${ME}/keys/ed25519_signing_cert"
  173. check_file "${ME}/keys/ed25519_signing_secret_key"
  174. echo "==== Case 3C ok"
  175. fi
  176. # Case 4: Make a new data directory with only an unencrypted secret key.
  177. # Then start tor. The rest should become correct.
  178. if [ "$CASE4" = 1 ]; then
  179. ME="${DATA_DIR}/case4"
  180. SRC="${DATA_DIR}/orig"
  181. mkdir -p "${ME}/keys"
  182. cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
  183. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp1" || die "Tor wouldn't start with only unencrypted secret key"
  184. check_file "${ME}/keys/ed25519_master_id_public_key"
  185. check_file "${ME}/keys/ed25519_signing_cert"
  186. check_file "${ME}/keys/ed25519_signing_secret_key"
  187. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} > "${ME}/fp2" || die "Tor wouldn't start again after starting once with only unencrypted secret key."
  188. check_files_eq "${ME}/fp1" "${ME}/fp2"
  189. echo "==== Case 4 ok"
  190. fi
  191. # Case 5: Make a new data directory with only an encrypted secret key.
  192. if [ "$CASE5" = 1 ]; then
  193. ME="${DATA_DIR}/case5"
  194. SRC="${DATA_DIR}/encrypted"
  195. mkdir -p "${ME}/keys"
  196. cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
  197. ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout" && die "Tor started with only encrypted secret key!"
  198. check_no_file "${ME}/keys/ed25519_master_id_public_key"
  199. check_no_file "${ME}/keys/ed25519_master_id_public_key"
  200. grep "but not public key file" "${ME}/stdout" >/dev/null || die "Tor didn't declare it couldn't find a public key."
  201. echo "==== Case 5 ok"
  202. fi
  203. # Case 6: Make a new data directory with encrypted secret key and public key
  204. if [ "$CASE6" = 1 ]; then
  205. ME="${DATA_DIR}/case6"
  206. SRC="${DATA_DIR}/encrypted"
  207. mkdir -p "${ME}/keys"
  208. cp "${SRC}/keys/ed25519_master_id_secret_key_encrypted" "${ME}/keys/"
  209. cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
  210. if ${TOR} --DataDirectory "${ME}" --list-fingerprint > "${ME}/stdout"; then
  211. die "Tor started with encrypted secret key and no certs"
  212. fi
  213. check_no_file "${ME}/keys/ed25519_signing_cert"
  214. check_no_file "${ME}/keys/ed25519_signing_secret_key"
  215. grep "but it was encrypted" "${ME}/stdout" >/dev/null || die "Tor didn't declare that the secret key was encrypted."
  216. echo "==== Case 6 ok"
  217. fi
  218. # Case 7: Make a new data directory with unencrypted secret key and
  219. # certificates; missing master public.
  220. if [ "$CASE7" = 1 ]; then
  221. ME="${DATA_DIR}/case7"
  222. SRC="${DATA_DIR}/keygen"
  223. mkdir -p "${ME}/keys"
  224. cp "${SRC}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
  225. cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
  226. cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
  227. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with missing public key"
  228. check_keys_eq ed25519_master_id_secret_key
  229. check_keys_eq ed25519_master_id_public_key
  230. check_keys_eq ed25519_signing_secret_key
  231. check_keys_eq ed25519_signing_cert
  232. echo "==== Case 7 ok"
  233. fi
  234. # Case 8: offline master secret key.
  235. if [ "$CASE8" = 1 ]; then
  236. ME="${DATA_DIR}/case8"
  237. SRC="${DATA_DIR}/keygen"
  238. mkdir -p "${ME}/keys"
  239. cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
  240. cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
  241. cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
  242. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with offline secret key"
  243. check_no_file "${ME}/keys/ed25519_master_id_secret_key"
  244. check_keys_eq ed25519_master_id_public_key
  245. check_keys_eq ed25519_signing_secret_key
  246. check_keys_eq ed25519_signing_cert
  247. echo "==== Case 8 ok"
  248. fi
  249. # Case 9: signing cert and secret key provided; could infer master key.
  250. if [ "$CASE9" = 1 ]; then
  251. ME="${DATA_DIR}/case9"
  252. SRC="${DATA_DIR}/keygen"
  253. mkdir -p "${ME}/keys"
  254. cp "${SRC}/keys/ed25519_signing_cert" "${ME}/keys/"
  255. cp "${SRC}/keys/ed25519_signing_secret_key" "${ME}/keys/"
  256. ${TOR} --DataDirectory "${ME}" --list-fingerprint ${SILENTLY} >/dev/null || die "Failed when starting with only signing material"
  257. check_no_file "${ME}/keys/ed25519_master_id_secret_key"
  258. check_file "${ME}/keys/ed25519_master_id_public_key"
  259. check_keys_eq ed25519_signing_secret_key
  260. check_keys_eq ed25519_signing_cert
  261. echo "==== Case 9 ok"
  262. fi
  263. # Case 10: master key mismatch.
  264. if [ "$CASE10" = 1 ]; then
  265. ME="${DATA_DIR}/case10"
  266. SRC="${DATA_DIR}/keygen"
  267. OTHER="${DATA_DIR}/orig"
  268. mkdir -p "${ME}/keys"
  269. cp "${SRC}/keys/ed25519_master_id_public_key" "${ME}/keys/"
  270. cp "${OTHER}/keys/ed25519_master_id_secret_key" "${ME}/keys/"
  271. if ${TOR} --DataDirectory "${ME}" --list-fingerprint >"${ME}/stdout"; then
  272. die "Successfully started with mismatched keys!?"
  273. fi
  274. grep "public_key does not match.*secret_key" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a key mismatch"
  275. echo "==== Case 10 ok"
  276. fi
  277. # Case 11a: -passphrase-fd without --keygen
  278. if [ "$CASE11A" = 1 ]; then
  279. ME="${DATA_DIR}/case11a"
  280. mkdir -p "${ME}/keys"
  281. if ${TOR} --DataDirectory "${ME}" --passphrase-fd 1 > "${ME}/stdout"; then
  282. die "Successfully started with passphrase-fd but no keygen?"
  283. fi
  284. grep "passphrase-fd specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  285. echo "==== Case 11A ok"
  286. fi
  287. # Case 11b: --no-passphrase without --keygen
  288. if [ "$CASE11B" = 1 ]; then
  289. ME="${DATA_DIR}/case11b"
  290. mkdir -p "${ME}/keys"
  291. if ${TOR} --DataDirectory "${ME}" --no-passphrase > "${ME}/stdout"; then
  292. die "Successfully started with no-passphrase but no keygen?"
  293. fi
  294. grep "no-passphrase specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  295. echo "==== Case 11B ok"
  296. fi
  297. # Case 11c: --newpass without --keygen
  298. if [ "$CASE11C" = 1 ]; then
  299. ME="${DATA_DIR}/case11C"
  300. mkdir -p "${ME}/keys"
  301. if ${TOR} --DataDirectory "${ME}" --newpass > "${ME}/stdout"; then
  302. die "Successfully started with newpass but no keygen?"
  303. fi
  304. grep "newpass specified without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  305. echo "==== Case 11C ok"
  306. fi
  307. ######## --master-key does not work yet, but this will test the error case
  308. ######## when it does.
  309. #
  310. # Case 11d: --master-key without --keygen
  311. #
  312. if [ "$CASE11D" = 1 ]; then
  313. #
  314. # ME="${DATA_DIR}/case11d"
  315. #
  316. # mkdir -p "${ME}/keys"
  317. #
  318. # ${TOR} --DataDirectory "${ME}" --master-key "${ME}/foobar" > "${ME}/stdout" && die "Successfully started with master-key but no keygen?" || true
  319. #
  320. # cat "${ME}/stdout"
  321. #
  322. # grep "master-key without --keygen" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  323. echo "==== Case 11D skipped"
  324. fi
  325. # Case 11E: Silly passphrase-fd
  326. if [ "$CASE11E" = 1 ]; then
  327. ME="${DATA_DIR}/case11E"
  328. mkdir -p "${ME}/keys"
  329. if ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd ewigeblumenkraft > "${ME}/stdout"; then
  330. die "Successfully started with bogus passphrase-fd?"
  331. fi
  332. grep "Invalid --passphrase-fd value" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  333. echo "==== Case 11E ok"
  334. fi
  335. # Case 11F: --no-passphrase with --passphrase-fd
  336. if [ "$CASE11F" = 1 ]; then
  337. ME="${DATA_DIR}/case11F"
  338. mkdir -p "${ME}/keys"
  339. if ${TOR} --DataDirectory "${ME}" --keygen --passphrase-fd 1 --no-passphrase > "${ME}/stdout"; then
  340. die "Successfully started with bogus passphrase-fd combination?"
  341. fi
  342. grep "no-passphrase specified with --passphrase-fd" "${ME}/stdout" >/dev/null || die "Tor didn't declare that there was a problem with the arguments."
  343. echo "==== Case 11F ok"
  344. fi
  345. # Check cert-only.