pkcs11.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #
  2. # Copyright (c) 2017 Red Hat
  3. #
  4. # Authors: Jakub Jelen <jjelen@redhat.com>
  5. #
  6. # Permission to use, copy, modify, and distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. tid="pkcs11 tests with soft token"
  18. try_token_libs()
  19. {
  20. for _lib in "$@"; do
  21. if test -f "$_lib"; then
  22. verbose "Using token library $_lib"
  23. TEST_SSH_PKCS11="$_lib"
  24. return
  25. fi
  26. done
  27. echo "skipped: Unable to find PKCS#11 token library"
  28. exit 0
  29. }
  30. try_token_libs \
  31. /usr/local/lib/softhsm/libsofthsm2.so \
  32. /usr/lib64/pkcs11/libsofthsm2.so \
  33. /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
  34. TEST_SSH_PIN=1234
  35. TEST_SSH_SOPIN=12345678
  36. if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then
  37. SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}"
  38. export SSH_PKCS11_HELPER
  39. fi
  40. test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"
  41. # setup environment for softhsm token
  42. DIR=$OBJ/SOFTHSM
  43. rm -rf $DIR
  44. TOKEN=$DIR/tokendir
  45. mkdir -p $TOKEN
  46. SOFTHSM2_CONF=$DIR/softhsm2.conf
  47. export SOFTHSM2_CONF
  48. cat > $SOFTHSM2_CONF << EOF
  49. # SoftHSM v2 configuration file
  50. directories.tokendir = ${TOKEN}
  51. objectstore.backend = file
  52. # ERROR, WARNING, INFO, DEBUG
  53. log.level = DEBUG
  54. # If CKF_REMOVABLE_DEVICE flag should be set
  55. slots.removable = false
  56. EOF
  57. out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN")
  58. slot=$(echo -- $out | sed 's/.* //')
  59. # prevent ssh-agent from calling ssh-askpass
  60. SSH_ASKPASS=/usr/bin/true
  61. export SSH_ASKPASS
  62. unset DISPLAY
  63. # We need interactive access to test PKCS# since it prompts for PIN
  64. sed -i 's/.*BatchMode.*//g' $OBJ/ssh_proxy
  65. # start command w/o tty, so ssh accepts pin from stdin (from agent-pkcs11.sh)
  66. notty()
  67. {
  68. perl -e 'use POSIX; POSIX::setsid();
  69. if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@"
  70. }
  71. trace "generating keys"
  72. ID1="02"
  73. ID2="04"
  74. RSA=${DIR}/RSA
  75. EC=${DIR}/EC
  76. openssl genpkey -algorithm rsa > $RSA
  77. openssl pkcs8 -nocrypt -in $RSA |
  78. softhsm2-util --slot "$slot" --label "SSH RSA Key $ID1" --id $ID1 \
  79. --pin "$TEST_SSH_PIN" --import /dev/stdin
  80. openssl genpkey \
  81. -genparam \
  82. -algorithm ec \
  83. -pkeyopt ec_paramgen_curve:prime256v1 |
  84. openssl genpkey \
  85. -paramfile /dev/stdin > $EC
  86. openssl pkcs8 -nocrypt -in $EC |
  87. softhsm2-util --slot "$slot" --label "SSH ECDSA Key $ID2" --id $ID2 \
  88. --pin "$TEST_SSH_PIN" --import /dev/stdin
  89. trace "List the keys in the ssh-keygen with PKCS#11 URIs"
  90. ${SSHKEYGEN} -D ${TEST_SSH_PKCS11} > $OBJ/token_keys
  91. if [ $? -ne 0 ]; then
  92. fail "FAIL: keygen fails to enumerate keys on PKCS#11 token"
  93. fi
  94. grep "pkcs11:" $OBJ/token_keys > /dev/null
  95. if [ $? -ne 0 ]; then
  96. fail "FAIL: The keys from ssh-keygen do not contain PKCS#11 URI as a comment"
  97. fi
  98. # Set the ECDSA key to authorized keys
  99. grep "ECDSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER
  100. trace "Simple connect with ssh (without PKCS#11 URI)"
  101. echo ${TEST_SSH_PIN} | notty ${SSH} -I ${TEST_SSH_PKCS11} \
  102. -F $OBJ/ssh_proxy somehost exit 5
  103. r=$?
  104. if [ $r -ne 5 ]; then
  105. fail "FAIL: ssh connect with pkcs11 failed (exit code $r)"
  106. fi
  107. trace "Connect with PKCS#11 URI"
  108. trace " (ECDSA key should succeed)"
  109. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  110. -i "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  111. r=$?
  112. if [ $r -ne 5 ]; then
  113. fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)"
  114. fi
  115. trace " (RSA key should fail)"
  116. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  117. -i "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  118. r=$?
  119. if [ $r -eq 5 ]; then
  120. fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)"
  121. fi
  122. trace "Connect with PKCS#11 URI including PIN should not prompt"
  123. trace " (ECDSA key should succeed)"
  124. ${SSH} -F $OBJ/ssh_proxy -i \
  125. "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5
  126. r=$?
  127. if [ $r -ne 5 ]; then
  128. fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)"
  129. fi
  130. trace " (RSA key should fail)"
  131. ${SSH} -F $OBJ/ssh_proxy -i \
  132. "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5
  133. r=$?
  134. if [ $r -eq 5 ]; then
  135. fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)"
  136. fi
  137. trace "Connect with various filtering options in PKCS#11 URI"
  138. trace " (by object label, ECDSA should succeed)"
  139. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  140. -i "pkcs11:object=SSH%20ECDSA%20Key%2004?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  141. r=$?
  142. if [ $r -ne 5 ]; then
  143. fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)"
  144. fi
  145. trace " (by object label, RSA key should fail)"
  146. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  147. -i "pkcs11:object=SSH%20RSA%20Key%2002?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  148. r=$?
  149. if [ $r -eq 5 ]; then
  150. fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)"
  151. fi
  152. trace " (by token label, ECDSA key should succeed)"
  153. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  154. -i "pkcs11:id=%${ID2};token=token-slot-0?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  155. r=$?
  156. if [ $r -ne 5 ]; then
  157. fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)"
  158. fi
  159. trace " (by wrong token label, should fail)"
  160. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  161. -i "pkcs11:token=token-slot-99?module-path=${TEST_SSH_PKCS11}" somehost exit 5
  162. r=$?
  163. if [ $r -eq 5 ]; then
  164. fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)"
  165. fi
  166. trace "Test PKCS#11 URI specification in configuration files"
  167. echo "IdentityFile \"pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}\"" \
  168. >> $OBJ/ssh_proxy
  169. trace " (ECDSA key should succeed)"
  170. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  171. r=$?
  172. if [ $r -ne 5 ]; then
  173. fail "FAIL: ssh connect with PKCS#11 URI in config failed (exit code $r)"
  174. fi
  175. # Set the RSA key as authorized
  176. grep "RSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER
  177. trace " (RSA key should fail)"
  178. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  179. r=$?
  180. if [ $r -eq 5 ]; then
  181. fail "FAIL: ssh connect with PKCS#11 URI in config succeeded (should fail)"
  182. fi
  183. sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy
  184. trace "Test PKCS#11 URI specification in configuration files with bogus spaces"
  185. echo "IdentityFile \" pkcs11:?module-path=${TEST_SSH_PKCS11} \"" \
  186. >> $OBJ/ssh_proxy
  187. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  188. r=$?
  189. if [ $r -ne 5 ]; then
  190. fail "FAIL: ssh connect with PKCS#11 URI with bogus spaces in config failed" \
  191. "(exit code $r)"
  192. fi
  193. sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy
  194. trace "Combination of PKCS11Provider and PKCS11URI on commandline"
  195. trace " (RSA key should succeed)"
  196. echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \
  197. -i "pkcs11:id=%${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5
  198. r=$?
  199. if [ $r -ne 5 ]; then
  200. fail "FAIL: ssh connect with PKCS#11 URI and provider combination" \
  201. "failed (exit code $r)"
  202. fi
  203. trace "Regress: Missing provider in PKCS11URI option"
  204. ${SSH} -F $OBJ/ssh_proxy \
  205. -o IdentityFile=\"pkcs11:token=segfault\" somehost exit 5
  206. r=$?
  207. if [ $r -eq 139 ]; then
  208. fail "FAIL: ssh connect with missing provider_id from configuration option" \
  209. "crashed (exit code $r)"
  210. fi
  211. trace "SSH Agent can work with PKCS#11 URI"
  212. trace "start the agent"
  213. eval $(${SSHAGENT} -s) > /dev/null
  214. r=$?
  215. if [ $r -ne 0 ]; then
  216. fail "could not start ssh-agent: exit code $r"
  217. else
  218. trace "add whole provider to agent"
  219. echo ${TEST_SSH_PIN} | notty ${SSHADD} \
  220. "pkcs11:?module-path=${TEST_SSH_PKCS11}" #> /dev/null 2>&1
  221. r=$?
  222. if [ $r -ne 0 ]; then
  223. fail "FAIL: ssh-add failed with whole provider: exit code $r"
  224. fi
  225. trace " pkcs11 list via agent (all keys)"
  226. ${SSHADD} -l > /dev/null 2>&1
  227. r=$?
  228. if [ $r -ne 0 ]; then
  229. fail "FAIL: ssh-add -l failed with whole provider: exit code $r"
  230. fi
  231. trace " pkcs11 connect via agent (all keys)"
  232. ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  233. r=$?
  234. if [ $r -ne 5 ]; then
  235. fail "FAIL: ssh connect failed with whole provider (exit code $r)"
  236. fi
  237. trace " remove pkcs11 keys (all keys)"
  238. ${SSHADD} -d "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1
  239. r=$?
  240. if [ $r -ne 0 ]; then
  241. fail "FAIL: ssh-add -d failed with whole provider: exit code $r"
  242. fi
  243. trace "add only RSA key to the agent"
  244. echo ${TEST_SSH_PIN} | notty ${SSHADD} \
  245. "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1
  246. r=$?
  247. if [ $r -ne 0 ]; then
  248. fail "FAIL ssh-add failed with RSA key: exit code $r"
  249. fi
  250. trace " pkcs11 connect via agent (RSA key)"
  251. ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  252. r=$?
  253. if [ $r -ne 5 ]; then
  254. fail "FAIL: ssh connect failed with RSA key (exit code $r)"
  255. fi
  256. trace " remove RSA pkcs11 key"
  257. ${SSHADD} -d "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" \
  258. > /dev/null 2>&1
  259. r=$?
  260. if [ $r -ne 0 ]; then
  261. fail "FAIL: ssh-add -d failed with RSA key: exit code $r"
  262. fi
  263. trace "add only ECDSA key to the agent"
  264. echo ${TEST_SSH_PIN} | notty ${SSHADD} \
  265. "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1
  266. r=$?
  267. if [ $r -ne 0 ]; then
  268. fail "FAIL: ssh-add failed with second key: exit code $r"
  269. fi
  270. trace " pkcs11 connect via agent (ECDSA key should fail)"
  271. ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  272. r=$?
  273. if [ $r -eq 5 ]; then
  274. fail "FAIL: ssh connect passed with ECDSA key (should fail)"
  275. fi
  276. trace "add also the RSA key to the agent"
  277. echo ${TEST_SSH_PIN} | notty ${SSHADD} \
  278. "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1
  279. r=$?
  280. if [ $r -ne 0 ]; then
  281. fail "FAIL: ssh-add failed with first key: exit code $r"
  282. fi
  283. trace " remove ECDSA pkcs11 key"
  284. ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \
  285. > /dev/null 2>&1
  286. r=$?
  287. if [ $r -ne 0 ]; then
  288. fail "ssh-add -d failed with ECDSA key: exit code $r"
  289. fi
  290. trace " remove already-removed pkcs11 key should fail"
  291. ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \
  292. > /dev/null 2>&1
  293. r=$?
  294. if [ $r -eq 0 ]; then
  295. fail "FAIL: ssh-add -d passed with non-existing key (should fail)"
  296. fi
  297. trace " pkcs11 connect via agent (the RSA key should be still usable)"
  298. ${SSH} -F $OBJ/ssh_proxy somehost exit 5
  299. r=$?
  300. if [ $r -ne 5 ]; then
  301. fail "ssh connect failed with RSA key (after removing ECDSA): exit code $r"
  302. fi
  303. trace "kill agent"
  304. ${SSHAGENT} -k > /dev/null
  305. fi