pkitool 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #!/bin/sh
  2. # OpenVPN -- An application to securely tunnel IP networks
  3. # over a single TCP/UDP port, with support for SSL/TLS-based
  4. # session authentication and key exchange,
  5. # packet encryption, packet authentication, and
  6. # packet compression.
  7. #
  8. # Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
  9. #
  10. # This program is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License version 2
  12. # as published by the Free Software Foundation.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program (see the file COPYING included with this
  21. # distribution); if not, write to the Free Software Foundation, Inc.,
  22. # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. # pkitool is a front-end for the openssl tool.
  24. # Calling scripts can set the certificate organizational
  25. # unit with the KEY_OU environmental variable.
  26. # Calling scripts can also set the KEY_NAME environmental
  27. # variable to set the "name" X509 subject field.
  28. PROGNAME=pkitool
  29. VERSION=2.0
  30. DEBUG=0
  31. die()
  32. {
  33. local m="$1"
  34. echo "$m" >&2
  35. exit 1
  36. }
  37. need_vars()
  38. {
  39. cat <<EOM
  40. Please edit the vars script to reflect your configuration,
  41. then source it with "source ./vars".
  42. Next, to start with a fresh PKI configuration and to delete any
  43. previous certificates and keys, run "./clean-all".
  44. Finally, you can run this tool ($PROGNAME) to build certificates/keys.
  45. EOM
  46. }
  47. usage()
  48. {
  49. cat <<EOM
  50. $PROGNAME $VERSION
  51. Usage: $PROGNAME [options...] [common-name]
  52. Options:
  53. --batch : batch mode (default)
  54. --keysize : Set keysize
  55. size : size (default=1024)
  56. --interact : interactive mode
  57. --server : build server cert
  58. --initca : build root CA
  59. --inter : build intermediate CA
  60. --pass : encrypt private key with password
  61. --csr : only generate a CSR, do not sign
  62. --sign : sign an existing CSR
  63. --pkcs12 : generate a combined PKCS#12 file
  64. --pkcs11 : generate certificate on PKCS#11 token
  65. lib : PKCS#11 library
  66. slot : PKCS#11 slot
  67. id : PKCS#11 object id (hex string)
  68. label : PKCS#11 object label
  69. Standalone options:
  70. --pkcs11-slots : list PKCS#11 slots
  71. lib : PKCS#11 library
  72. --pkcs11-objects : list PKCS#11 token objects
  73. lib : PKCS#11 library
  74. slot : PKCS#11 slot
  75. --pkcs11-init : initialize PKCS#11 token DANGEROUS!!!
  76. lib : PKCS#11 library
  77. slot : PKCS#11 slot
  78. label : PKCS#11 token label
  79. Notes:
  80. EOM
  81. need_vars
  82. cat <<EOM
  83. In order to use PKCS#11 interface you must have opensc-0.10.0 or higher.
  84. Generated files and corresponding OpenVPN directives:
  85. (Files will be placed in the \$KEY_DIR directory, defined in ./vars)
  86. ca.crt -> root certificate (--ca)
  87. ca.key -> root key, keep secure (not directly used by OpenVPN)
  88. .crt files -> client/server certificates (--cert)
  89. .key files -> private keys, keep secure (--key)
  90. .csr files -> certificate signing request (not directly used by OpenVPN)
  91. dh1024.pem or dh2048.pem -> Diffie Hellman parameters (--dh)
  92. Examples:
  93. $PROGNAME --initca -> Build root certificate
  94. $PROGNAME --initca --pass -> Build root certificate with password-protected key
  95. $PROGNAME --server server1 -> Build "server1" certificate/key
  96. $PROGNAME client1 -> Build "client1" certificate/key
  97. $PROGNAME --pass client2 -> Build password-protected "client2" certificate/key
  98. $PROGNAME --pkcs12 client3 -> Build "client3" certificate/key in PKCS#12 format
  99. $PROGNAME --csr client4 -> Build "client4" CSR to be signed by another CA
  100. $PROGNAME --sign client4 -> Sign "client4" CSR
  101. $PROGNAME --inter interca -> Build an intermediate key-signing certificate/key
  102. Also see ./inherit-inter script.
  103. $PROGNAME --pkcs11 /usr/lib/pkcs11/lib1 0 010203 "client5 id" client5
  104. -> Build "client5" certificate/key in PKCS#11 token
  105. Typical usage for initial PKI setup. Build myserver, client1, and client2 cert/keys.
  106. Protect client2 key with a password. Build DH parms. Generated files in ./keys :
  107. [edit vars with your site-specific info]
  108. source ./vars
  109. ./clean-all
  110. ./build-dh -> takes a long time, consider backgrounding
  111. ./$PROGNAME --initca
  112. ./$PROGNAME --server myserver
  113. ./$PROGNAME client1
  114. ./$PROGNAME --pass client2
  115. Typical usage for adding client cert to existing PKI:
  116. source ./vars
  117. ./$PROGNAME client-new
  118. EOM
  119. }
  120. # Set tool defaults
  121. [ -n "$OPENSSL" ] || export OPENSSL="openssl"
  122. [ -n "$PKCS11TOOL" ] || export PKCS11TOOL="pkcs11-tool"
  123. [ -n "$GREP" ] || export GREP="grep"
  124. # Set defaults
  125. DO_REQ="1"
  126. REQ_EXT=""
  127. DO_CA="1"
  128. CA_EXT=""
  129. DO_P12="0"
  130. DO_P11="0"
  131. DO_ROOT="0"
  132. NODES_REQ="-nodes"
  133. NODES_P12=""
  134. BATCH="-batch"
  135. CA="ca"
  136. # must be set or errors of openssl.cnf
  137. PKCS11_MODULE_PATH="dummy"
  138. PKCS11_PIN="dummy"
  139. # Process options
  140. while [ $# -gt 0 ]; do
  141. case "$1" in
  142. --keysize ) KEY_SIZE=$2
  143. shift;;
  144. --server ) REQ_EXT="$REQ_EXT -extensions server"
  145. CA_EXT="$CA_EXT -extensions server" ;;
  146. --batch ) BATCH="-batch" ;;
  147. --interact ) BATCH="" ;;
  148. --inter ) CA_EXT="$CA_EXT -extensions v3_ca" ;;
  149. --initca ) DO_ROOT="1" ;;
  150. --pass ) NODES_REQ="" ;;
  151. --csr ) DO_CA="0" ;;
  152. --sign ) DO_REQ="0" ;;
  153. --pkcs12 ) DO_P12="1" ;;
  154. --pkcs11 ) DO_P11="1"
  155. PKCS11_MODULE_PATH="$2"
  156. PKCS11_SLOT="$3"
  157. PKCS11_ID="$4"
  158. PKCS11_LABEL="$5"
  159. shift 4;;
  160. # standalone
  161. --pkcs11-init)
  162. PKCS11_MODULE_PATH="$2"
  163. PKCS11_SLOT="$3"
  164. PKCS11_LABEL="$4"
  165. if [ -z "$PKCS11_LABEL" ]; then
  166. die "Please specify library name, slot and label"
  167. fi
  168. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --init-token --slot "$PKCS11_SLOT" \
  169. --label "$PKCS11_LABEL" &&
  170. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --init-pin --slot "$PKCS11_SLOT"
  171. exit $?;;
  172. --pkcs11-slots)
  173. PKCS11_MODULE_PATH="$2"
  174. if [ -z "$PKCS11_MODULE_PATH" ]; then
  175. die "Please specify library name"
  176. fi
  177. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --list-slots
  178. exit 0;;
  179. --pkcs11-objects)
  180. PKCS11_MODULE_PATH="$2"
  181. PKCS11_SLOT="$3"
  182. if [ -z "$PKCS11_SLOT" ]; then
  183. die "Please specify library name and slot"
  184. fi
  185. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --list-objects --login --slot "$PKCS11_SLOT"
  186. exit 0;;
  187. --help|--usage)
  188. usage
  189. exit ;;
  190. --version)
  191. echo "$PROGNAME $VERSION"
  192. exit ;;
  193. # errors
  194. --* ) die "$PROGNAME: unknown option: $1" ;;
  195. * ) break ;;
  196. esac
  197. shift
  198. done
  199. if ! [ -z "$BATCH" ]; then
  200. if $OPENSSL version | grep 0.9.6 > /dev/null; then
  201. die "Batch mode is unsupported in openssl<0.9.7"
  202. fi
  203. fi
  204. if [ $DO_P12 -eq 1 -a $DO_P11 -eq 1 ]; then
  205. die "PKCS#11 and PKCS#12 cannot be specified together"
  206. fi
  207. if [ $DO_P11 -eq 1 ]; then
  208. if ! grep "^pkcs11.*=" "$KEY_CONFIG" > /dev/null; then
  209. die "Please edit $KEY_CONFIG and setup PKCS#11 engine"
  210. fi
  211. fi
  212. # If we are generating pkcs12, only encrypt the final step
  213. if [ $DO_P12 -eq 1 ]; then
  214. NODES_P12="$NODES_REQ"
  215. NODES_REQ="-nodes"
  216. fi
  217. if [ $DO_P11 -eq 1 ]; then
  218. if [ -z "$PKCS11_LABEL" ]; then
  219. die "PKCS#11 arguments incomplete"
  220. fi
  221. fi
  222. # If undefined, set default key expiration intervals
  223. if [ -z "$KEY_EXPIRE" ]; then
  224. KEY_EXPIRE=3650
  225. fi
  226. if [ -z "$CA_EXPIRE" ]; then
  227. CA_EXPIRE=3650
  228. fi
  229. # Set organizational unit to empty string if undefined
  230. if [ -z "$KEY_OU" ]; then
  231. KEY_OU=""
  232. fi
  233. # Set X509 Name string to empty string if undefined
  234. if [ -z "$KEY_NAME" ]; then
  235. KEY_NAME=""
  236. fi
  237. # Set KEY_CN, FN
  238. if [ $DO_ROOT -eq 1 ]; then
  239. if [ -z "$KEY_CN" ]; then
  240. if [ "$1" ]; then
  241. KEY_CN="$1"
  242. KEY_ALTNAMES="DNS:${KEY_CN}"
  243. elif [ "$KEY_ORG" ]; then
  244. KEY_CN="$KEY_ORG CA"
  245. KEY_ALTNAMES="$KEY_CN"
  246. fi
  247. fi
  248. if [ $BATCH ] && [ "$KEY_CN" ]; then
  249. echo "Using CA Common Name:" "$KEY_CN"
  250. KEY_ALTNAMES="$KEY_CN"
  251. fi
  252. FN="$KEY_CN"
  253. elif [ $BATCH ] && [ "$KEY_CN" ]; then
  254. echo "Using Common Name:" "$KEY_CN"
  255. KEY_ALTNAMES="$KEY_CN"
  256. FN="$KEY_CN"
  257. if [ "$1" ]; then
  258. FN="$1"
  259. fi
  260. else
  261. KEY_CN="$1"
  262. KEY_ALTNAMES="DNS:$1"
  263. shift
  264. while [ "x$1" != "x" ]
  265. do
  266. KEY_ALTNAMES="${KEY_ALTNAMES},DNS:$1"
  267. shift
  268. done
  269. FN="$KEY_CN"
  270. fi
  271. export CA_EXPIRE KEY_EXPIRE KEY_OU KEY_NAME KEY_CN PKCS11_MODULE_PATH PKCS11_PIN KEY_ALTNAMES
  272. # Show parameters (debugging)
  273. if [ $DEBUG -eq 1 ]; then
  274. echo DO_REQ $DO_REQ
  275. echo REQ_EXT $REQ_EXT
  276. echo DO_CA $DO_CA
  277. echo CA_EXT $CA_EXT
  278. echo NODES_REQ $NODES_REQ
  279. echo NODES_P12 $NODES_P12
  280. echo DO_P12 $DO_P12
  281. echo KEY_CN $KEY_CN
  282. echo KEY_ALTNAMES $KEY_ALTNAMES
  283. echo BATCH $BATCH
  284. echo DO_ROOT $DO_ROOT
  285. echo KEY_EXPIRE $KEY_EXPIRE
  286. echo CA_EXPIRE $CA_EXPIRE
  287. echo KEY_OU $KEY_OU
  288. echo KEY_NAME $KEY_NAME
  289. echo DO_P11 $DO_P11
  290. echo PKCS11_MODULE_PATH $PKCS11_MODULE_PATH
  291. echo PKCS11_SLOT $PKCS11_SLOT
  292. echo PKCS11_ID $PKCS11_ID
  293. echo PKCS11_LABEL $PKCS11_LABEL
  294. fi
  295. # Make sure ./vars was sourced beforehand
  296. if [ -d "$KEY_DIR" ] && [ "$KEY_CONFIG" ]; then
  297. cd "$KEY_DIR"
  298. # Make sure $KEY_CONFIG points to the correct version
  299. # of openssl.cnf
  300. if $GREP -i 'easy-rsa version 2\.[0-9]' "$KEY_CONFIG" >/dev/null; then
  301. :
  302. else
  303. echo "$PROGNAME: KEY_CONFIG (set by the ./vars script) is pointing to the wrong"
  304. echo "version of openssl.cnf: $KEY_CONFIG"
  305. echo "The correct version should have a comment that says: easy-rsa version 2.x";
  306. exit 1;
  307. fi
  308. # Build root CA
  309. if [ $DO_ROOT -eq 1 ]; then
  310. $OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE \
  311. -x509 -keyout "$CA.key" -out "$CA.crt" -config "$KEY_CONFIG" && \
  312. chmod 0600 "$CA.key"
  313. else
  314. # Make sure CA key/cert is available
  315. if [ $DO_CA -eq 1 ] || [ $DO_P12 -eq 1 ]; then
  316. if [ ! -r "$CA.crt" ] || [ ! -r "$CA.key" ]; then
  317. echo "$PROGNAME: Need a readable $CA.crt and $CA.key in $KEY_DIR"
  318. echo "Try $PROGNAME --initca to build a root certificate/key."
  319. exit 1
  320. fi
  321. fi
  322. # Generate key for PKCS#11 token
  323. PKCS11_ARGS=
  324. if [ $DO_P11 -eq 1 ]; then
  325. stty -echo
  326. echo -n "User PIN: "
  327. read -r PKCS11_PIN
  328. stty echo
  329. export PKCS11_PIN
  330. echo "Generating key pair on PKCS#11 token..."
  331. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --keypairgen \
  332. --login --pin "$PKCS11_PIN" \
  333. --key-type rsa:1024 \
  334. --slot "$PKCS11_SLOT" --id "$PKCS11_ID" --label "$PKCS11_LABEL" || exit 1
  335. PKCS11_ARGS="-engine pkcs11 -keyform engine -key $PKCS11_SLOT:$PKCS11_ID"
  336. fi
  337. # Build cert/key
  338. ( [ $DO_REQ -eq 0 ] || $OPENSSL req $BATCH $NODES_REQ -new -newkey rsa:$KEY_SIZE \
  339. -keyout "$FN.key" -out "$FN.csr" $REQ_EXT -config "$KEY_CONFIG" $PKCS11_ARGS ) && \
  340. ( [ $DO_CA -eq 0 ] || $OPENSSL ca $BATCH -days $KEY_EXPIRE -out "$FN.crt" \
  341. -in "$FN.csr" $CA_EXT -config "$KEY_CONFIG" ) && \
  342. ( [ $DO_P12 -eq 0 ] || $OPENSSL pkcs12 -export -inkey "$FN.key" \
  343. -in "$FN.crt" -certfile "$CA.crt" -out "$FN.p12" $NODES_P12 ) && \
  344. ( [ $DO_CA -eq 0 -o $DO_P11 -eq 1 ] || chmod 0600 "$FN.key" ) && \
  345. ( [ $DO_P12 -eq 0 ] || chmod 0600 "$FN.p12" )
  346. # Load certificate into PKCS#11 token
  347. if [ $DO_P11 -eq 1 ]; then
  348. $OPENSSL x509 -in "$FN.crt" -inform PEM -out "$FN.crt.der" -outform DER && \
  349. $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --write-object "$FN.crt.der" --type cert \
  350. --login --pin "$PKCS11_PIN" \
  351. --slot "$PKCS11_SLOT" --id "$PKCS11_ID" --label "$PKCS11_LABEL"
  352. [ -e "$FN.crt.der" ]; rm "$FN.crt.der"
  353. fi
  354. fi
  355. # Need definitions
  356. else
  357. need_vars
  358. fi