test_keygen.sh 14 KB

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