From e982959aaf7014dca60176821894f5beab9280b7 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 12:03:39 -0400 Subject: [PATCH 01/12] Initial Yubikey support --- create-client | 75 +++++++++++++++++++++++----- create-root-ca | 94 ++++++++++++++++++++++++----------- create-server | 79 +++++++++++++++++++++++++----- create-signing-ca | 121 ++++++++++++++++++++++++++++++++++------------ defaults.conf | 2 + functions | 47 ++++++++++++++++++ revoke-cert | 10 ++++ show-status | 2 +- sign-csr | 38 +++++++++++---- 9 files changed, 376 insertions(+), 92 deletions(-) diff --git a/create-client b/create-client index 3f03cba..1ec7c58 100755 --- a/create-client +++ b/create-client @@ -6,6 +6,7 @@ # Derek Moore # Christian Göttsche +# Tom Bereknyei set -eu set -o pipefail @@ -59,14 +60,23 @@ fi echo +if [ -n "$CA_ENABLE_ENGINE" ]; then + echo -e "$NOTE Your CA key is on PKCS11 device, enter PIN." +fi echo -e -n "$INPUT Enter passphase for signing CA key: " read -r -s PASS echo export CA_PASS="${PASS}" -openssl rsa -check \ - -in ca/private/ca.key \ - -passin env:CA_PASS \ - -noout + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=SIGN%20key' +openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout \ + -passin env:CA_PASS trap 'rm -Rf "certs/clients/$SAFE_NAME"' 0 mkdir "certs/clients/$SAFE_NAME" @@ -78,30 +88,73 @@ ask_client_cert_questions export SAN="email:$CA_CERT_MAIL" template "${BIN_DIR}/templates/client.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" +echo -e -n "$INPUT Create csr on pkcs11 device? (key must be in \"PIV AUTH key\" or 9a): [yN]" +read -r SURE +if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + ENABLE_ENGINE= +else + ENABLE_ENGINE=1 + init_slot 9a +fi + echo -e "$NOTE Creating the client key and csr" # Create the client key and csr -openssl req -new -nodes \ - -batch \ +openssl_engine_cmd=' + -engine pkcs11 + -keyform engine + -key pkcs11:object=PIV%20AUTH%20key' +openssl req -new -batch \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ -config "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" \ - -keyout "certs/clients/$SAFE_NAME/$SAFE_NAME.key" \ - -out "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" -openssl rsa -noout -check -in "certs/clients/$SAFE_NAME/$SAFE_NAME.key" -chmod 0400 "certs/clients/$SAFE_NAME/$SAFE_NAME.key" + -out "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ + $( [ -z $ENABLE_ENGINE ] && echo " + -nodes + -keyout certs/clients/$SAFE_NAME/$SAFE_NAME.key") + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=PIV%20AUTH%20key' +openssl rsa \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/clients/$SAFE_NAME/$SAFE_NAME.key") \ + -noout + +if [ -z "$ENABLE_ENGINE" ]; then + chmod 0400 "certs/clients/$SAFE_NAME/$SAFE_NAME.key" +fi echo -e "$NOTE Creating the client certificate" # Create the client certificate +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" openssl ca -batch -notext \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ -extensions client_ext \ -passin env:CA_PASS +if [[ -n "$ENABLE_ENGINE" ]]; then + replace_crt 9a certs/clients/"$SAFE_NAME"/"$SAFE_NAME".crt +fi + echo -e "$NOTE Verifying certificate/key pair" -key_mod=$(openssl rsa -noout -modulus -in "certs/clients/$SAFE_NAME/$SAFE_NAME.key") +openssl_engine_cmd="\ + -engine pkcs11 \ + -inform engine \ + -in pkcs11:object=PIV%20AUTH%20key" +key_mod=$(openssl rsa \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} -noout -modulus \ + $( [ -z $ENABLE_ENGINE ] && echo "-in certs/clients/$SAFE_NAME/$SAFE_NAME.key") +) + cert_mod=$(openssl x509 -noout -modulus -in "certs/clients/$SAFE_NAME/$SAFE_NAME.crt") if [ ! "$key_mod" = "$cert_mod" ];then diff --git a/create-root-ca b/create-root-ca index 20eb451..e8ba6dc 100755 --- a/create-root-ca +++ b/create-root-ca @@ -61,20 +61,33 @@ if [ -n "${CERT_CN}" ]; then CA_CERT_CN="${CERT_CN}" fi -echo -echo -e -n "$INPUT Enter passphase for encrypting root CA key: " -read -r -s PASS1 -echo -if [[ ${#PASS1} -lt 4 ]]; then - echo -e "$ERR Passphrase is too short, please use at least 4 characters!" - exit 1 -fi -echo -e -n "$INPUT Verifying - Enter passphase for encrypting root CA key: " -read -r -s PASS2 -echo -if [[ "${PASS1}" != "${PASS2}" ]]; then - echo -e "$ERR Passphrases did not match, exiting." - exit 1 +if [[ -n $CA_ENABLE_ENGINE ]]; then + init_engine 9c + # Slot 9c requires PIN entry on every operation. + # No need to ask for the PIN for re-use. + echo -e -n "$INPUT Enter PIN for signing root CA key: " + read -r -s PASS1 + echo + if [[ ${#PASS1} -lt 4 ]]; then + echo -e "$ERR Passphrase is too short, please use at least 4 characters!" + exit 1 + fi +else + echo + echo -e -n "$INPUT Enter passphase for encrypting root CA key: " + read -r -s PASS1 + echo + if [[ ${#PASS1} -lt 4 ]]; then + echo -e "$ERR Passphrase is too short, please use at least 4 characters!" + exit 1 + fi + echo -e -n "$INPUT Verifying - Enter passphase for encrypting root CA key: " + read -r -s PASS2 + echo + if [[ "${PASS1}" != "${PASS2}" ]]; then + echo -e "$ERR Passphrases did not match, exiting." + exit 1 + fi fi export CA_PASS="${PASS1}" @@ -88,38 +101,65 @@ pushd "${CA_DIR}" > /dev/null # Generate the root CA openssl config template "${BIN_DIR}/templates/root.tpl" "ca/ca.conf" -echo -e "$NOTE Creating the root CA key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" +# Create the signing CA key +if [[ -z $CA_ENABLE_ENGINE ]]; then + echo -e "$NOTE Creating the root CA key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" -openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" -chmod 0400 ca/private/ca.key + openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" + chmod 0400 ca/private/ca.key +else + echo -e "$NOTE Root CA key should already exist via pkcs11 engine." +fi echo -e "$NOTE Creating the root CA csr" +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -key pkcs11:object=SIGN%20key" + openssl req -new -batch \ - -config ca/ca.conf \ - -key ca/private/ca.key \ - -out ca/ca.csr \ - -passin env:CA_PASS + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-key ca/private/ca.key") \ + -config ca/ca.conf \ + -out ca/ca.csr \ + -passin env:CA_PASS +echo echo -e "$NOTE Creating the root CA certificate" -openssl ca -selfsign -batch -notext \ - -config ca/ca.conf \ - -in ca/ca.csr \ - -out ca/ca.crt \ - -extensions root_ca_ext \ - -passin env:CA_PASS +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" + +openssl ca \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + -selfsign -batch -notext \ + -config ca/ca.conf \ + -in ca/ca.csr \ + -out ca/ca.crt \ + -extensions root_ca_ext \ + -passin env:CA_PASS ln -s ca.crt ca/chain.pem ln -s ca.crt ca/root.crt +echo +if [[ -n "$CA_ENABLE_ENGINE" ]]; then + replace_crt 9c ca/ca.crt +fi + +echo echo -e "$NOTE Creating the root CA CRL" openssl ca -gencrl -batch \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -out ca/ca.crl \ -passin env:CA_PASS +echo if [ $SYMLINK -eq 1 ]; then echo -e "$NOTE Symlinking toolchain (dev mode)" CP_CMD='ln -s' diff --git a/create-server b/create-server index 0cc8235..d3c2530 100755 --- a/create-server +++ b/create-server @@ -74,14 +74,23 @@ fi echo +if [ -n "$CA_ENABLE_ENGINE" ]; then + echo -e "$NOTE Your CA key is on PKCS11 device, enter PIN." +fi echo -e -n "$INPUT Enter passphase for signing CA key: " read -r -s PASS echo export CA_PASS="${PASS}" -openssl rsa -check \ - -in ca/private/ca.key \ - -passin env:CA_PASS \ - -noout + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=SIGN%20key' +openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout \ + -passin env:CA_PASS trap 'rm -Rf "certs/server/$SAFE_NAME"' 0 mkdir "certs/server/$SAFE_NAME" @@ -92,28 +101,74 @@ export SAN="${ALT_NAME}" ask_server_cert_questions template "${BIN_DIR}/templates/server.tpl" "certs/server/$SAFE_NAME/$SAFE_NAME.conf" +echo -e "$NOTE Usually a server key will not be on a pkcs11 device." +echo -e -n "$INPUT Create csr on pkcs11 device? (key must be in \"PIV AUTH key\" or 9a): [yN]" +read -r SURE +if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + ENABLE_ENGINE= +else + ENABLE_ENGINE=1 + init_slot 9a +fi + echo -e "$NOTE Creating the server key and csr" -openssl req -new -nodes \ - -batch \ +# Create the sever key and csr +openssl_engine_cmd=' + -engine pkcs11 + -keyform engine + -key pkcs11:object=PIV%20AUTH%20key' +openssl req -new -batch \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ -config "certs/server/$SAFE_NAME/$SAFE_NAME.conf" \ - -keyout "certs/server/$SAFE_NAME/$SAFE_NAME.key" \ - -out "certs/server/$SAFE_NAME/$SAFE_NAME.csr" -openssl rsa -noout -check -in "certs/server/$SAFE_NAME/$SAFE_NAME.key" -chmod 0400 "certs/server/$SAFE_NAME/$SAFE_NAME.key" + -out "certs/server/$SAFE_NAME/$SAFE_NAME.csr" \ + $( [ -z $ENABLE_ENGINE ] && echo " + -nodes + -keyout certs/server/$SAFE_NAME/$SAFE_NAME.key") + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=PIV%20AUTH%20key' +openssl rsa \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/server/$SAFE_NAME/$SAFE_NAME.key") \ + -noout + +if [ -z "$ENABLE_ENGINE" ]; then + chmod 0400 "certs/server/$SAFE_NAME/$SAFE_NAME.key" +fi echo -e "$NOTE Creating the server certificate" +# Create the server certificate +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" openssl ca -batch -notext \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -in "certs/server/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/server/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions server_ext \ + -extensions client_ext \ -passin env:CA_PASS +if [[ -n "$ENABLE_ENGINE" ]]; then + replace_crt 9a certs/server/"$SAFE_NAME"/"$SAFE_NAME".crt +fi + echo -e "$NOTE Verifying certificate/key pair" -key_mod=$(openssl rsa -noout -modulus -in "certs/server/$SAFE_NAME/$SAFE_NAME.key") +openssl_engine_cmd="\ + -engine pkcs11 \ + -inform engine \ + -in pkcs11:object=PIV%20AUTH%20key" +key_mod=$(openssl rsa \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} -noout -modulus \ + $( [ -z $ENABLE_ENGINE ] && echo "-in certs/server/$SAFE_NAME/$SAFE_NAME.key") +) + cert_mod=$(openssl x509 -noout -modulus -in "certs/server/$SAFE_NAME/$SAFE_NAME.crt") if [ ! "$key_mod" = "$cert_mod" ];then diff --git a/create-signing-ca b/create-signing-ca index dd87546..ae45bf6 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -66,11 +66,17 @@ echo -e -n "$INPUT Enter passphase for root CA key: " read -r -s PARENT_PASS echo export CA_PARENT_PASS="${PARENT_PASS}" -openssl rsa -check \ - -in ca/private/ca.key \ - -passin env:CA_PARENT_PASS \ - -noout - +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=SIGN%20key' +openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout \ + -passin env:CA_PARENT_PASS + +CA_PARENT_ENABLE_ENGINE=$CA_ENABLE_ENGINE generate_conf "${CA_DIR}/bin/defaults.conf" source "${CA_DIR}/bin/defaults.conf" @@ -82,20 +88,34 @@ if [ -n "${CERT_CN}" ]; then CA_CERT_CN="${CERT_CN}" fi -echo -echo -e -n "$INPUT Enter passphase for encrypting signing sub-CA key: " -read -r -s PASS1 -echo -if [[ ${#PASS1} -lt 4 ]]; then - echo -e "$ERR Passphrase is too short, please use at least 4 characters!" - exit 1 -fi -echo -e -n "$INPUT Verifying - Enter passphase for encrypting signing sub-CA key: " -read -r -s PASS2 -echo -if [ "${PASS1}" != "${PASS2}" ]; then - echo -e "$ERR Passphrases did not match, exiting." - exit 1 +if [[ -n $CA_ENABLE_ENGINE ]]; then + if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then + echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. Do not have your root CA inserted." + fi + init_engine 9c + echo -e -n "$INPUT Enter PIN for signing sub-CA key: " + read -r -s PASS1 + echo + if [[ ${#PASS1} -lt 4 ]]; then + echo -e "$ERR Passphrase is too short, please use at least 4 characters!" + exit 1 + fi +else + echo + echo -e -n "$INPUT Enter passphase for encrypting signing sub-CA key: " + read -r -s PASS1 + echo + if [[ ${#PASS1} -lt 4 ]]; then + echo -e "$ERR Passphrase is too short, please use at least 4 characters!" + exit 1 + fi + echo -e -n "$INPUT Verifying - Enter passphase for encrypting signing sub-CA key: " + read -r -s PASS2 + echo + if [ "${PASS1}" != "${PASS2}" ]; then + echo -e "$ERR Passphrases did not match, exiting." + exit 1 + fi fi export CA_PASS"=${PASS1}" @@ -109,31 +129,70 @@ template "${BIN_DIR}/templates/signing.tpl" "ca/ca.conf" echo -e "$NOTE Creating the signing sub-CA key" # Create the signing CA key -openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_SIGNCA}" -chmod 0400 ca/private/ca.key +if [[ -z $CA_ENABLE_ENGINE ]]; then + echo -e "$NOTE Creating the signing sub-CA key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" + + openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" + chmod 0400 ca/private/ca.key +else + echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." +fi echo -e "$NOTE Creating the signing sub-CA csr" +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -key pkcs11:object=SIGN%20key" openssl req -new -batch \ - -config ca/ca.conf \ - -key ca/private/ca.key \ - -out ca/ca.csr \ - -passin env:CA_PASS + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-key ca/private/ca.key") \ + -config ca/ca.conf \ + -out ca/ca.csr \ + -passin env:CA_PASS echo -e "$NOTE Creating the signing sub-CA certificate" pushd "${PARENT}" > /dev/null -openssl ca -batch -notext \ - -config ca/ca.conf \ - -in "${CA_DIR}/ca/ca.csr" \ - -out "${CA_DIR}/ca/ca.crt" \ - -extensions signing_ca_ext \ - -passin env:CA_PARENT_PASS +if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then + echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. You are signing the sub-CA with the root CA device. Do not have your sub-CA device inserted." + echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " + read -r SURE + if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + echo -e "$ERR Exiting." + exit 1 + fi +fi +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" + +openssl ca \ + ${CA_PARENT_ENABLE_ENGINE:+$openssl_engine_cmd} \ + -batch -notext \ + -config ca/ca.conf \ + -in "${CA_DIR}/ca/ca.csr" \ + -out "${CA_DIR}/ca/ca.crt" \ + -extensions signing_ca_ext \ + -passin env:CA_PARENT_PASS + +if [[ -n "$CA_ENABLE_ENGINE" ]]; then + echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. You are uploading the sub-CA cert. Insert the sub-CA deivce." + echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " + read -r SURE + if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + echo -e "$ERR Exiting." + exit 1 + fi + replace_crt 9c "${CA_DIR}/ca/ca.crt" +fi popd > /dev/null echo -e "$NOTE Creating the signing sub-CA CRL" openssl ca -gencrl -batch \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -out ca/ca.crl \ -passin env:CA_PASS diff --git a/defaults.conf b/defaults.conf index 13c4da3..d903f2f 100644 --- a/defaults.conf +++ b/defaults.conf @@ -11,3 +11,5 @@ CA_KEY_ALG="aes256" CA_KEY_LENGTH_ROOTCA=4096 CA_KEY_LENGTH_SIGNCA=4096 CA_KEY_LENGTH_ENDCRT=3072 + +CA_ENABLE_ENGINE= diff --git a/functions b/functions index eea64c1..23617dc 100644 --- a/functions +++ b/functions @@ -124,6 +124,14 @@ init_ca_home() { generate_conf() { DEST="$1" + echo -e -n "$INPUT Enable PKCS11 Engine for this CA? [y/N]: " + read -r ENABLE_ENGINE + if [ "${ENABLE_ENGINE}" == "y" ] || [ "${ENABLE_ENGINE}" == "Y" ]; then + CA_ENABLE_ENGINE="${ENABLE_ENGINE}" + else + CA_ENABLE_ENGINE= + fi + echo -e -n "$INPUT Short label for new CA [${CA_NAME}]: " read -r NAME if [ -n "${NAME}" ]; then @@ -184,6 +192,7 @@ CA_CERT_ST="${CA_CERT_ST}" CA_CERT_L="${CA_CERT_L}" CA_CERT_O="${CA_CERT_O}" CA_CERT_OU="${CA_CERT_OU}" +CA_ENABLE_ENGINE="${CA_ENABLE_ENGINE}" CA_KEY_ALG="${CA_KEY_ALG}" CA_KEY_LENGTH_ROOTCA="${CA_KEY_LENGTH_ROOTCA}" @@ -276,3 +285,41 @@ ask_client_cert_questions() { exit 1 fi } + +## +## PKCS11 support functions, currently hard coded to support yubikeys using ykman +## +function init_slot(){ + local SLOT=$1 + echo -e -n "$INPUT Do you wish to create a new key in slot $SLOT? [y/N]: " + read -r SURE + if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then + ykman piv generate-key "$SLOT" yubi.pub + # This cert is to make PKCS11 happy. + # Should replace this with the proper cert later in the process. + ykman piv generate-certificate "$SLOT" yubi.pub -s 'bootstrap' + rm yubi.pub + fi +} +function replace_crt(){ + local SLOT=$1 + local CERT=$2 + echo -e -n "$INPUT Do you wish to upload this cert to $SLOT? [y/N]: " + read -r SURE + if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then + ykman piv import-certificate "$SLOT" "$2" + fi +} +function init_engine(){ + local SLOT=$1 + echo -e "$NOTE THIS WILL RESET YOUR YUBIKEY USING YKMAN" + echo -e -n "$INPUT Do you wish to reset your device? [y/N]: " + read -r SURE + if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then + ykman piv reset + fi + init_slot "$SLOT" +} +#function openssl_engine() { + #[ -z $ENABLE_ENGINE ] || echo "engine dynamic -pre \"SO_PATH:${cfg_file_engine_pkcs11}\" -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre \"MODULE_PATH:${cfg_file_opensc_pkcs11}\" ${ENGINE_VERBOSE:+"-pre VERBOSE"}" +#} diff --git a/revoke-cert b/revoke-cert index 0e11ae5..68d47da 100755 --- a/revoke-cert +++ b/revoke-cert @@ -112,7 +112,12 @@ export SAN="" echo -e "$NOTE Revoke the certificate" +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" openssl ca \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -revoke "${CERT_PATH}" \ -crl_reason "${REASON}" \ @@ -120,7 +125,12 @@ openssl ca \ echo -e "$NOTE Regenerate the CRL" +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" openssl ca -gencrl \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -out ca/ca.crl \ -passin env:CA_PASS diff --git a/show-status b/show-status index 31d7e2b..41e4972 100755 --- a/show-status +++ b/show-status @@ -97,7 +97,7 @@ if [ ! -f ca/db/crt.srl ]; then exit 2 fi -if [ ! -f ca/private/ca.key ]; then +if [ ! -f ca/private/ca.key ] && [ -z "${CA_ENABLE_ENGINE}" ]; then echo -e "$ERR No 'ca/private/ca.key' file!'"; exit 2 fi diff --git a/sign-csr b/sign-csr index 1d15f87..d79f8d8 100755 --- a/sign-csr +++ b/sign-csr @@ -6,7 +6,7 @@ # Derek Moore # Christian Göttsche -# tomberek +# Tom Bereknyei set -eu set -o pipefail @@ -22,10 +22,13 @@ usage() { echo "Signs a client certificate located at CSR_PATH" echo echo "Options:" - echo " -c CSR_PATH Path to client certificate request" + echo " -c CSR_PATH Path to client certificate request" echo - echo " -F NAME force to use custom SAFE_NAME" - echo " useful for name clahses, use with caution" + echo " -m CSR_CERT_MAIL Email address to use in client certificate request" + echo " Useful when using ykman which doesn't use email" + echo + echo " -F NAME Force to use custom SAFE_NAME" + echo " Useful for name clahses, use with caution" echo } @@ -37,10 +40,11 @@ fi CSR_PATH= CSR_NAME= -while getopts c:F:h FLAG; do +while getopts c:F:m:h FLAG; do case $FLAG in c) CSR_PATH=${OPTARG} ;; F) CSR_NAME=${OPTARG} ;; + m) CSR_CERT_MAIL=${OPTARG} ;; h) echo -e -n "$SUCC " && usage && exit 0 ;; *) echo -e -n "$ERR " && usage && exit 2 ;; esac @@ -56,7 +60,7 @@ openssl req -text -noout -verify -in "$CSR_PATH" export CSR_SUBJ=$(openssl req -utf8 -in "$CSR_PATH" -noout -subject -nameopt multiline) export CSR_CERT_CN=$(echo "$CSR_SUBJ" | grep -P '^\s+commonName' | cut -d '=' -f 2- | sed -e 's/^[[:space:]]*//') -export CSR_CERT_MAIL=$(echo "$CSR_SUBJ" | grep -P '^\s+emailAddress' | cut -d '=' -f 2- | sed -e 's/^[[:space:]]*//') +export CSR_CERT_MAIL=${CSR_CERT_MAIL:-$(echo "$CSR_SUBJ" | grep -P '^\s+emailAddress' | cut -d '=' -f 2- | sed -e 's/^[[:space:]]*//')} if [ -z "$CSR_CERT_CN" ]; then echo -e "$ERR No name supplied in request, exiting." exit 1 @@ -82,14 +86,23 @@ echo -e "$NOTE Signing CSR for '$CSR_CERT_CN' with email address '$CSR_CERT_MAIL pushd "${BIN_DIR}/.." > /dev/null echo +if [ -n "$CA_ENABLE_ENGINE" ]; then + echo -e "$NOTE Your CA key is on PKCS11 device, enter PIN." +fi echo -e -n "$INPUT Enter passphase for signing CA key (verify the above informations!):" read -r -s PASS echo export CA_PASS="$PASS" -openssl rsa -check \ - -in ca/private/ca.key \ - -passin env:CA_PASS \ - -noout + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=SIGN%20key' +openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout \ + -passin env:CA_PASS echo -e "$NOTE Creating client directory certs/clients/$SAFE_NAME" mkdir -p "certs/clients/$SAFE_NAME" @@ -105,7 +118,12 @@ template "$BIN_DIR/templates/client.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.co echo -e "$NOTE Creating the client certificate (overwriting C,ST,L,O,OU DN fields)." # Create the client certificate overwriting CSR values +openssl_engine_cmd="\ + -engine pkcs11 \ + -keyform engine \ + -keyfile pkcs11:object=SIGN%20key" openssl ca -batch -notext \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ From 0af2058f0e055f9add2198af26fec0c53921ccf4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 15:38:04 -0400 Subject: [PATCH 02/12] Add create-csr function and SSH pub creation --- README.md | 12 ++ create-client | 8 +- create-csr | 159 ++++++++++++++++++++++++++ create-root-ca | 6 +- create-server | 8 +- create-signing-ca | 6 +- functions | 11 +- sign-csr | 2 +- templates/{client.tpl => clients.tpl} | 0 9 files changed, 200 insertions(+), 12 deletions(-) create mode 100755 create-csr rename templates/{client.tpl => clients.tpl} (100%) diff --git a/README.md b/README.md index 45fd293..1b123d1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ A suite of bash scripts for automating very basic OpenSSL Certificate Authority * Creating Server certificates * Creating Client certificates * Revoking certificates and maintaining CRLs +* Creating CSRs +* Managing SSH keys ## Usage @@ -27,6 +29,7 @@ A suite of bash scripts for automating very basic OpenSSL Certificate Authority | revoke-cert | Revoke a (client\|server) certificate | | show-status | Show the infos about the current CA (signed certificates...) | | sign-csr | Sign an imported client certificate | +| create-csr | Create a client certificate | #### Important files: @@ -49,6 +52,8 @@ create-root-ca -d $ROOT_CA_DIR ``` $ROOT_CA_DIR/ca/ca.crt +$ROOT_CA_DIR/ca/ca.pub +$ROOT_CA_DIR/ca/ca.ssh.pub $ROOT_CA_DIR/ca/private/ca.key $ROOT_CA_DIR/ca/ca.crl ``` @@ -65,6 +70,8 @@ $ROOT_CA_DIR/bin/create-signing-ca -d $SIGNING_CA_DIR ``` $SIGNING_CA_DIR/ca/ca.crt +$SIGNING_CA_DIR/ca/ca.pub +$SIGNING_CA_DIR/ca/ca.ssh.pub $SIGNING_CA_DIR/ca/private/ca.key $SIGNING_CA_DIR/ca/ca.crl $SIGNING_CA_DIR/ca/root.crt @@ -86,6 +93,8 @@ All addresses **must** be supplied via the *-a* flag. ``` $CA_DIR/certs/server/FQDN-Description/FQDN-Description.crt $CA_DIR/certs/server/FQDN-Description/FQDN-Description.key +$CA_DIR/certs/server/FQDN-Description/FQDN-Description.pub +$CA_DIR/certs/server/FQDN-Description/FQDN-Description.ssh.pub $CA_DIR/certs/server/FQDN-Description/FQDN-Description.csr ``` @@ -102,6 +111,8 @@ $CA_DIR/bin/create-client -c user@domain.com ``` $CA_DIR/certs/clients/user-domain-com/user-domain-com.crt $CA_DIR/certs/clients/user-domain-com/user-domain-com.key +$CA_DIR/certs/clients/user-domain-com/user-domain-com.pub +$CA_DIR/certs/clients/user-domain-com/user-domain-com.ssh.pub $CA_DIR/certs/clients/user-domain-com/user-domain-com.csr ``` @@ -130,6 +141,7 @@ These scripts are very simple, and make some hard-coded assumptions about behavi * Client and Server certificates have 3072-bit RSA keys (configurable in *defaults.conf*) * Client and Server keys are not encrypted * There is no wrapper *yet* for renewing certificates +* PKCS11 support is in beta ## License diff --git a/create-client b/create-client index 1ec7c58..8957bca 100755 --- a/create-client +++ b/create-client @@ -86,7 +86,7 @@ export CA_USERNAME="${CLIENT_NAME}" export CA_CERT_MAIL="" ask_client_cert_questions export SAN="email:$CA_CERT_MAIL" -template "${BIN_DIR}/templates/client.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" +template "${BIN_DIR}/templates/clients.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" echo -e -n "$INPUT Create csr on pkcs11 device? (key must be in \"PIV AUTH key\" or 9a): [yN]" read -r SURE @@ -94,7 +94,7 @@ if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then ENABLE_ENGINE= else ENABLE_ENGINE=1 - init_slot 9a + init_slot 9a "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" fi echo -e "$NOTE Creating the client key and csr" @@ -123,7 +123,11 @@ openssl rsa \ if [ -z "$ENABLE_ENGINE" ]; then chmod 0400 "certs/clients/$SAFE_NAME/$SAFE_NAME.key" + openssl rsa -in "certs/clients/$SAFE_NAME/$SAFE_NAME.key" \ + -pubout -out "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" fi +ssk-keygen -f "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/clients/$SAFE_NAME/$SAFE_NAME.ssh.pub" echo -e "$NOTE Creating the client certificate" diff --git a/create-csr b/create-csr new file mode 100755 index 0000000..173c3ad --- /dev/null +++ b/create-csr @@ -0,0 +1,159 @@ +#!/bin/bash + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Derek Moore +# Christian Göttsche +# Tom Bereknyei + +set -eu +set -o pipefail + +umask 0077 + +BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "${BIN_DIR}/functions" +source "${BIN_DIR}/defaults.conf" + +usage() { + echo "Usage: $0 -c CSR_PATH [-F NAME] [-s] [-m CSR_CERT_MAIL]" + echo "Create a client certificate request located at CSR_PATH" + echo + echo "Options:" + echo " -c CSR_NAME Name of certificate request" + echo + echo " -s Request is a server [default is client]" + echo + echo " -k KEY_PATH Path to key to use [default is to create one]" + echo + echo " -m CSR_CERT_MAIL Email address to use in client certificate request" + echo " Useful when using ykman which doesn't use email" + echo + echo " -F NAME Force to use custom SAFE_NAME" + echo " Useful for name clahses, use with caution" + echo +} + +if [ ! -f ca/ca.crt ]; then + echo -e "$ERR Must be run inside a CA directory!" + exit 2 +fi + +CSR_PATH= +CSR_NAME= +CSR_TYPE="clients" +CSR_KEY= +CSR_CERT_MAIL= + +while getopts c:sk:F:m:h FLAG; do + case $FLAG in + c) CSR_PATH=${OPTARG} ;; + F) CSR_NAME=${OPTARG} ;; + m) CSR_CERT_MAIL=${OPTARG} ;; + s) CSR_TYPE="server" ;; + k) CSR_KEY=${OPTARG} ;; + h) echo -e -n "$SUCC " && usage && exit 0 ;; + *) echo -e -n "$ERR " && usage && exit 2 ;; + esac +done + +if [ $OPTIND -le $# ]; then + echo -e -n "$ERR " && usage && exit 2 +elif [ "$CSR_PATH" = "" ]; then + echo -e -n "$ERR " && usage && exit 1 +fi + +if [ -n "$CSR_NAME" ]; then + SAFE_NAME=$(echo "$CSR_NAME" | sed 's/\*/star/g' | sed 's/[^A-Za-z0-9-]/-/g') +else + SAFE_NAME=$(echo "$CSR_PATH" | sed 's/\*/star/g' | sed 's/[^A-Za-z0-9-]/-/g') +fi + +echo -e "$NOTE Creating new "$CSR_TYPE" certificate request for '$SAFE_NAME'" + +if [ -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" ]; then + echo -e "$ERR Certificate already exist for ($SCR_TYPE/$SAFE_NAME), exiting." + exit 1 +fi + +pushd "${BIN_DIR}/.." > /dev/null + +mkdir -p "certs/$CSR_TYPE/$SAFE_NAME" + +# Generate the client cert openssl config +export CA_USERNAME="${SAFE_NAME}" +export CA_CERT_MAIL="${CSR_CERT_MAIL}" +if [[ "$CSR_TYPE" = "server" ]]; then + ask_server_cert_questions +else + ask_client_cert_questions +fi +export SAN="email:$CA_CERT_MAIL" +template "${BIN_DIR}/templates/$CSR_TYPE.tpl" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.conf" + +echo -e "$NOTE Key is ${CSR_KEY:-" being created"}" + +ENABLE_ENGINE= +if [[ -z "$CSR_KEY" ]]; then + echo -e -n "$INPUT Use PKCS11 Engine for this csr (key must be in \"PIV AUTH key\" or 9a)? [y/N]: " + read -r ENABLE_ENGINE + if [ "${ENABLE_ENGINE}" == "y" ] || [ "${ENABLE_ENGINE}" == "Y" ]; then + ENABLE_ENGINE=1 + init_slot 9a "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" + else + ENABLE_ENGINE= + fi +else + cp "$CSR_KEY" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" + chmod 0400 "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" + openssl rsa -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" \ + -pubout -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" +fi + +echo -e "$NOTE Creating csr" + +# Create the csr +openssl_engine_cmd=' + -engine pkcs11 + -keyform engine + -key pkcs11:object=PIV%20AUTH%20key' +openssl req -new -batch \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ + -config "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.conf" \ + -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" \ + $( [ -z $ENABLE_ENGINE ] && echo " + -nodes + ${CSR_KEY:+"-key $CSR_KEY"} + $( [ -z $CSR_KEY ] && echo "-keyout certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key") + ") + +openssl_engine_cmd=' + -engine pkcs11 + -inform engine + -in pkcs11:object=PIV%20AUTH%20key' +openssl rsa \ + ${ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key") \ + -noout + +echo values $ENABLE_ENGINE $CSR_KEY +if [ -z "$ENABLE_ENGINE" ] && [ -z "$CSR_KEY" ]; then + echo entered + pwd + chmod 0400 "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" + openssl rsa -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" \ + -pubout -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" +fi + +ssh-keygen -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.ssh.pub" + +echo -e "$NOTE Verifying csr" + +openssl req -text -noout -verify -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" + +popd > /dev/null + +echo -e "$SUCC CSR for '$SAFE_NAME' created." diff --git a/create-root-ca b/create-root-ca index e8ba6dc..6f34ea1 100755 --- a/create-root-ca +++ b/create-root-ca @@ -62,7 +62,8 @@ if [ -n "${CERT_CN}" ]; then fi if [[ -n $CA_ENABLE_ENGINE ]]; then - init_engine 9c + init_engine + init_slot 9c "${CA_DIR}/ca/ca.pub" # Slot 9c requires PIN entry on every operation. # No need to ask for the PIN for re-use. echo -e -n "$INPUT Enter PIN for signing root CA key: " @@ -107,9 +108,12 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key + openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub else echo -e "$NOTE Root CA key should already exist via pkcs11 engine." fi +ssk-keygen -f ca/ca.pub -i -mPKCS8 \ + | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub echo -e "$NOTE Creating the root CA csr" diff --git a/create-server b/create-server index d3c2530..5725683 100755 --- a/create-server +++ b/create-server @@ -108,7 +108,7 @@ if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then ENABLE_ENGINE= else ENABLE_ENGINE=1 - init_slot 9a + init_slot 9a "certs/server/$SAFE_NAME/$SAFE_NAME.pub" fi echo -e "$NOTE Creating the server key and csr" @@ -137,7 +137,13 @@ openssl rsa \ if [ -z "$ENABLE_ENGINE" ]; then chmod 0400 "certs/server/$SAFE_NAME/$SAFE_NAME.key" + openssl rsa -in "certs/server/$SAFE_NAME/$SAFE_NAME.key" \ + -pubout -out "certs/server/$SAFE_NAME/$SAFE_NAME.pub" fi +ssk-keygen -f "certs/server/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/server/$SAFE_NAME/$SAFE_NAME.ssh.pub" + + echo -e "$NOTE Creating the server certificate" diff --git a/create-signing-ca b/create-signing-ca index ae45bf6..0006b01 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -92,7 +92,8 @@ if [[ -n $CA_ENABLE_ENGINE ]]; then if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. Do not have your root CA inserted." fi - init_engine 9c + init_engine + init_slot 9c "${CA_DIR}/ca/ca.pub" echo -e -n "$INPUT Enter PIN for signing sub-CA key: " read -r -s PASS1 echo @@ -134,9 +135,12 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key + openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub else echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." fi +ssk-keygen -f ca/ca.pub -i -mPKCS8 \ + | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub echo -e "$NOTE Creating the signing sub-CA csr" diff --git a/functions b/functions index 23617dc..8610fb1 100644 --- a/functions +++ b/functions @@ -19,7 +19,7 @@ gen-html " export TEMPLATES_ROOT=" -client.tpl +clients.tpl server.tpl signing.tpl root_index.tpl @@ -37,7 +37,7 @@ gen-html " export TEMPLATES_SIGN=" -client.tpl +clients.tpl server.tpl sign_index.tpl " @@ -291,14 +291,14 @@ ask_client_cert_questions() { ## function init_slot(){ local SLOT=$1 + local PUB=$2 echo -e -n "$INPUT Do you wish to create a new key in slot $SLOT? [y/N]: " read -r SURE if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then - ykman piv generate-key "$SLOT" yubi.pub + ykman piv generate-key "$SLOT" "$PUB" # This cert is to make PKCS11 happy. # Should replace this with the proper cert later in the process. - ykman piv generate-certificate "$SLOT" yubi.pub -s 'bootstrap' - rm yubi.pub + ykman piv generate-certificate "$SLOT" "$PUB" -s 'bootstrap' fi } function replace_crt(){ @@ -318,7 +318,6 @@ function init_engine(){ if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then ykman piv reset fi - init_slot "$SLOT" } #function openssl_engine() { #[ -z $ENABLE_ENGINE ] || echo "engine dynamic -pre \"SO_PATH:${cfg_file_engine_pkcs11}\" -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre \"MODULE_PATH:${cfg_file_opensc_pkcs11}\" ${ENGINE_VERBOSE:+"-pre VERBOSE"}" diff --git a/sign-csr b/sign-csr index d79f8d8..54c34cf 100755 --- a/sign-csr +++ b/sign-csr @@ -113,7 +113,7 @@ export CA_USERNAME="$CSR_CERT_CN" export CA_CERT_MAIL="$CSR_CERT_MAIL" cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" -template "$BIN_DIR/templates/client.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" +template "$BIN_DIR/templates/clients.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" echo -e "$NOTE Creating the client certificate (overwriting C,ST,L,O,OU DN fields)." diff --git a/templates/client.tpl b/templates/clients.tpl similarity index 100% rename from templates/client.tpl rename to templates/clients.tpl From 5457c7a5c581907ae4275b7b738afa25416bd40c Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 15:54:11 -0400 Subject: [PATCH 03/12] Allow signing of created CSR's and server CSR's --- create-client | 2 +- create-server | 2 +- sign-csr | 24 ++++++++++++++---------- templates/root.tpl | 2 +- templates/signing.tpl | 2 +- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/create-client b/create-client index 8957bca..211edfa 100755 --- a/create-client +++ b/create-client @@ -141,7 +141,7 @@ openssl ca -batch -notext \ -config ca/ca.conf \ -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -extensions clients_ext \ -passin env:CA_PASS if [[ -n "$ENABLE_ENGINE" ]]; then diff --git a/create-server b/create-server index 5725683..6d65880 100755 --- a/create-server +++ b/create-server @@ -157,7 +157,7 @@ openssl ca -batch -notext \ -config ca/ca.conf \ -in "certs/server/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/server/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -extensions server_ext \ -passin env:CA_PASS if [[ -n "$ENABLE_ENGINE" ]]; then diff --git a/sign-csr b/sign-csr index 54c34cf..5bacae1 100755 --- a/sign-csr +++ b/sign-csr @@ -24,6 +24,8 @@ usage() { echo "Options:" echo " -c CSR_PATH Path to client certificate request" echo + echo " -s Request is a server [default is client]" + echo echo " -m CSR_CERT_MAIL Email address to use in client certificate request" echo " Useful when using ykman which doesn't use email" echo @@ -39,10 +41,12 @@ fi CSR_PATH= CSR_NAME= +CSR_TYPE="clients" while getopts c:F:m:h FLAG; do case $FLAG in c) CSR_PATH=${OPTARG} ;; + s) CSR_TYPE="server" ;; F) CSR_NAME=${OPTARG} ;; m) CSR_CERT_MAIL=${OPTARG} ;; h) echo -e -n "$SUCC " && usage && exit 0 ;; @@ -76,7 +80,7 @@ else SAFE_NAME=$(echo "$CSR_CERT_CN" | sed 's/\*/star/g' | sed 's/[^A-Za-z0-9-]/-/g') fi -if [ -f "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" ]; then +if [ -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" ]; then echo -e "$ERR Certificate already exist for '$CSR_CERT_CN' ($SAFE_NAME), exiting." exit 1 fi @@ -104,18 +108,18 @@ openssl rsa \ -noout \ -passin env:CA_PASS -echo -e "$NOTE Creating client directory certs/clients/$SAFE_NAME" -mkdir -p "certs/clients/$SAFE_NAME" +echo -e "$NOTE Creating $CSR_TYPE directory certs/$CSR_TYPE/$SAFE_NAME" +mkdir -p "certs/$CSR_TYPE/$SAFE_NAME" # Generate the client cert openssl config export SAN="email:$CSR_CERT_MAIL" export CA_USERNAME="$CSR_CERT_CN" export CA_CERT_MAIL="$CSR_CERT_MAIL" -cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" -template "$BIN_DIR/templates/clients.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" +cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" +template "$BIN_DIR/templates/$CSR_TYPE.tpl" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.conf" -echo -e "$NOTE Creating the client certificate (overwriting C,ST,L,O,OU DN fields)." +echo -e "$NOTE Creating the certificate (overwriting C,ST,L,O,OU DN fields)." # Create the client certificate overwriting CSR values openssl_engine_cmd="\ @@ -125,15 +129,15 @@ openssl_engine_cmd="\ openssl ca -batch -notext \ ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ - -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ - -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" \ + -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" \ + -extensions ${CSR_TYPE}_ext \ -subj "/C=${CA_CERT_C}/ST=${CA_CERT_ST}/L=${CA_CERT_L}/O=${CA_CERT_O}/OU=${CA_CERT_OU}/CN=${CA_USERNAME}/emailAddress=${CSR_CERT_MAIL}" \ -passin env:CA_PASS echo -e "$NOTE Verifying trusted chain" -openssl verify -CAfile ca/chain.pem "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" +openssl verify -CAfile ca/chain.pem "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" popd > /dev/null diff --git a/templates/root.tpl b/templates/root.tpl index 228e186..cf869c2 100644 --- a/templates/root.tpl +++ b/templates/root.tpl @@ -107,7 +107,7 @@ authorityInfoAccess = @issuer_info crlDistributionPoints = @crl_info subjectAltName = $ENV::SAN -[ client_ext ] +[ clients_ext ] keyUsage = critical,digitalSignature basicConstraints = critical,CA:false extendedKeyUsage = critical,clientAuth diff --git a/templates/signing.tpl b/templates/signing.tpl index 500175b..947a534 100644 --- a/templates/signing.tpl +++ b/templates/signing.tpl @@ -91,7 +91,7 @@ authorityInfoAccess = @issuer_info crlDistributionPoints = @crl_info subjectAltName = $ENV::SAN -[ client_ext ] +[ clients_ext ] keyUsage = critical,digitalSignature basicConstraints = critical,CA:false extendedKeyUsage = critical,clientAuth From 7ffbc1085d967ecd218001e8e21abca7c832aad7 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 15:54:11 -0400 Subject: [PATCH 04/12] Allow signing of created CSR's and server CSR's --- create-client | 2 +- create-csr | 2 +- create-server | 2 +- sign-csr | 24 ++++++++++++++---------- templates/root.tpl | 2 +- templates/signing.tpl | 2 +- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/create-client b/create-client index 8957bca..211edfa 100755 --- a/create-client +++ b/create-client @@ -141,7 +141,7 @@ openssl ca -batch -notext \ -config ca/ca.conf \ -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -extensions clients_ext \ -passin env:CA_PASS if [[ -n "$ENABLE_ENGINE" ]]; then diff --git a/create-csr b/create-csr index 173c3ad..e72dc9f 100755 --- a/create-csr +++ b/create-csr @@ -74,7 +74,7 @@ fi echo -e "$NOTE Creating new "$CSR_TYPE" certificate request for '$SAFE_NAME'" if [ -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" ]; then - echo -e "$ERR Certificate already exist for ($SCR_TYPE/$SAFE_NAME), exiting." + echo -e "$ERR Certificate already exist for ($CSR_TYPE/$SAFE_NAME), exiting." exit 1 fi diff --git a/create-server b/create-server index 5725683..6d65880 100755 --- a/create-server +++ b/create-server @@ -157,7 +157,7 @@ openssl ca -batch -notext \ -config ca/ca.conf \ -in "certs/server/$SAFE_NAME/$SAFE_NAME.csr" \ -out "certs/server/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -extensions server_ext \ -passin env:CA_PASS if [[ -n "$ENABLE_ENGINE" ]]; then diff --git a/sign-csr b/sign-csr index 54c34cf..5bacae1 100755 --- a/sign-csr +++ b/sign-csr @@ -24,6 +24,8 @@ usage() { echo "Options:" echo " -c CSR_PATH Path to client certificate request" echo + echo " -s Request is a server [default is client]" + echo echo " -m CSR_CERT_MAIL Email address to use in client certificate request" echo " Useful when using ykman which doesn't use email" echo @@ -39,10 +41,12 @@ fi CSR_PATH= CSR_NAME= +CSR_TYPE="clients" while getopts c:F:m:h FLAG; do case $FLAG in c) CSR_PATH=${OPTARG} ;; + s) CSR_TYPE="server" ;; F) CSR_NAME=${OPTARG} ;; m) CSR_CERT_MAIL=${OPTARG} ;; h) echo -e -n "$SUCC " && usage && exit 0 ;; @@ -76,7 +80,7 @@ else SAFE_NAME=$(echo "$CSR_CERT_CN" | sed 's/\*/star/g' | sed 's/[^A-Za-z0-9-]/-/g') fi -if [ -f "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" ]; then +if [ -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" ]; then echo -e "$ERR Certificate already exist for '$CSR_CERT_CN' ($SAFE_NAME), exiting." exit 1 fi @@ -104,18 +108,18 @@ openssl rsa \ -noout \ -passin env:CA_PASS -echo -e "$NOTE Creating client directory certs/clients/$SAFE_NAME" -mkdir -p "certs/clients/$SAFE_NAME" +echo -e "$NOTE Creating $CSR_TYPE directory certs/$CSR_TYPE/$SAFE_NAME" +mkdir -p "certs/$CSR_TYPE/$SAFE_NAME" # Generate the client cert openssl config export SAN="email:$CSR_CERT_MAIL" export CA_USERNAME="$CSR_CERT_CN" export CA_CERT_MAIL="$CSR_CERT_MAIL" -cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" -template "$BIN_DIR/templates/clients.tpl" "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" +cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" +template "$BIN_DIR/templates/$CSR_TYPE.tpl" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.conf" -echo -e "$NOTE Creating the client certificate (overwriting C,ST,L,O,OU DN fields)." +echo -e "$NOTE Creating the certificate (overwriting C,ST,L,O,OU DN fields)." # Create the client certificate overwriting CSR values openssl_engine_cmd="\ @@ -125,15 +129,15 @@ openssl_engine_cmd="\ openssl ca -batch -notext \ ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ -config ca/ca.conf \ - -in "certs/clients/$SAFE_NAME/$SAFE_NAME.csr" \ - -out "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" \ - -extensions client_ext \ + -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" \ + -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" \ + -extensions ${CSR_TYPE}_ext \ -subj "/C=${CA_CERT_C}/ST=${CA_CERT_ST}/L=${CA_CERT_L}/O=${CA_CERT_O}/OU=${CA_CERT_OU}/CN=${CA_USERNAME}/emailAddress=${CSR_CERT_MAIL}" \ -passin env:CA_PASS echo -e "$NOTE Verifying trusted chain" -openssl verify -CAfile ca/chain.pem "certs/clients/$SAFE_NAME/$SAFE_NAME.crt" +openssl verify -CAfile ca/chain.pem "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.crt" popd > /dev/null diff --git a/templates/root.tpl b/templates/root.tpl index 228e186..cf869c2 100644 --- a/templates/root.tpl +++ b/templates/root.tpl @@ -107,7 +107,7 @@ authorityInfoAccess = @issuer_info crlDistributionPoints = @crl_info subjectAltName = $ENV::SAN -[ client_ext ] +[ clients_ext ] keyUsage = critical,digitalSignature basicConstraints = critical,CA:false extendedKeyUsage = critical,clientAuth diff --git a/templates/signing.tpl b/templates/signing.tpl index 500175b..947a534 100644 --- a/templates/signing.tpl +++ b/templates/signing.tpl @@ -91,7 +91,7 @@ authorityInfoAccess = @issuer_info crlDistributionPoints = @crl_info subjectAltName = $ENV::SAN -[ client_ext ] +[ clients_ext ] keyUsage = critical,digitalSignature basicConstraints = critical,CA:false extendedKeyUsage = critical,clientAuth From 6aa15c0c52368b267322542e49969a6aecddcb6c Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 16:13:29 -0400 Subject: [PATCH 05/12] Fix ssk-keygen typo --- create-client | 2 +- create-root-ca | 2 +- create-server | 2 +- create-signing-ca | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/create-client b/create-client index 211edfa..d919308 100755 --- a/create-client +++ b/create-client @@ -126,7 +126,7 @@ if [ -z "$ENABLE_ENGINE" ]; then openssl rsa -in "certs/clients/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" fi -ssk-keygen -f "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ +ssh-keygen -f "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/clients/$SAFE_NAME/$SAFE_NAME.ssh.pub" echo -e "$NOTE Creating the client certificate" diff --git a/create-root-ca b/create-root-ca index 6f34ea1..29d75cb 100755 --- a/create-root-ca +++ b/create-root-ca @@ -112,7 +112,7 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then else echo -e "$NOTE Root CA key should already exist via pkcs11 engine." fi -ssk-keygen -f ca/ca.pub -i -mPKCS8 \ +ssh-keygen -f ca/ca.pub -i -mPKCS8 \ | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub echo -e "$NOTE Creating the root CA csr" diff --git a/create-server b/create-server index 6d65880..fdb4724 100755 --- a/create-server +++ b/create-server @@ -140,7 +140,7 @@ if [ -z "$ENABLE_ENGINE" ]; then openssl rsa -in "certs/server/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/server/$SAFE_NAME/$SAFE_NAME.pub" fi -ssk-keygen -f "certs/server/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ +ssh-keygen -f "certs/server/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/server/$SAFE_NAME/$SAFE_NAME.ssh.pub" diff --git a/create-signing-ca b/create-signing-ca index 0006b01..ed6e324 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -139,7 +139,7 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then else echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." fi -ssk-keygen -f ca/ca.pub -i -mPKCS8 \ +ssh-keygen -f ca/ca.pub -i -mPKCS8 \ | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub echo -e "$NOTE Creating the signing sub-CA csr" From d852cc528b8ef699619c34a8ae94187ecfdd8231 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 16:29:40 -0400 Subject: [PATCH 06/12] Fix tests for PKCS11 prompts --- .travis.yml | 7 +++++++ create-client | 2 +- create-server | 4 +--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9faa036..9039c4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_install: script: - | bash --posix ./create-root-ca -l -d travis-ca < "certs/server/$SAFE_NAME/$SAFE_NAME.ssh.pub" - - echo -e "$NOTE Creating the server certificate" From 706d374bc0870964ed8fd3bfb94165f9a3ec25d7 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 16:36:01 -0400 Subject: [PATCH 07/12] One more password entry for travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9039c4e..d410352 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ script: Bogus Inc. Certificate Authority rootCA_password rootCA_password + rootCA_password EOF - cd travis-ca/ - | From cad5c074138d697ec208d5ac1837638173266fab Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 16:53:42 -0400 Subject: [PATCH 08/12] passin CA_PASS --- .travis.yml | 2 -- create-root-ca | 2 +- create-signing-ca | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d410352..64c5045 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,6 @@ script: Bogus Inc. Certificate Authority rootCA_password rootCA_password - rootCA_password EOF - cd travis-ca/ - | @@ -60,7 +59,6 @@ script: Bogus Inc. Certificate travis-signing signCA_password signCA_password - signCA_password EOF - bash --posix ./bin/show-status - bash --posix ./bin/gen-html diff --git a/create-root-ca b/create-root-ca index 29d75cb..d857d26 100755 --- a/create-root-ca +++ b/create-root-ca @@ -108,7 +108,7 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key - openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub + openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else echo -e "$NOTE Root CA key should already exist via pkcs11 engine." fi diff --git a/create-signing-ca b/create-signing-ca index ed6e324..ced79a3 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -135,7 +135,7 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key - openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub + openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." fi From 0fe1bcd2fd0c56445c5ce80c59afaa65be773dc4 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Mon, 8 Oct 2018 17:09:21 -0400 Subject: [PATCH 09/12] init_slot is distinct from init_engine --- functions | 1 - 1 file changed, 1 deletion(-) diff --git a/functions b/functions index 8610fb1..120f35a 100644 --- a/functions +++ b/functions @@ -311,7 +311,6 @@ function replace_crt(){ fi } function init_engine(){ - local SLOT=$1 echo -e "$NOTE THIS WILL RESET YOUR YUBIKEY USING YKMAN" echo -e -n "$INPUT Do you wish to reset your device? [y/N]: " read -r SURE From 9f4fa652253c510645b607db6ee4d79a4142bd41 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Tue, 9 Oct 2018 05:00:14 -0400 Subject: [PATCH 10/12] Refine ssh support, sign, revoke, move all to ./ssh folder --- create-client | 13 ++++- create-csr | 9 ++- create-root-ca | 10 +++- create-server | 10 +++- create-signing-ca | 5 +- functions | 6 +- revoke-cert | 24 ++++++++ sign-csr | 8 ++- sign-ssh | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 212 insertions(+), 13 deletions(-) create mode 100755 sign-ssh diff --git a/create-client b/create-client index 60e6641..9739c1f 100755 --- a/create-client +++ b/create-client @@ -79,7 +79,7 @@ openssl rsa \ -passin env:CA_PASS trap 'rm -Rf "certs/clients/$SAFE_NAME"' 0 -mkdir "certs/clients/$SAFE_NAME" +mkdir -p "certs/clients/$SAFE_NAME/ssh" # Generate the client cert openssl config export CA_USERNAME="${CLIENT_NAME}" @@ -123,11 +123,20 @@ openssl rsa \ if [ -z "$ENABLE_ENGINE" ]; then chmod 0400 "certs/clients/$SAFE_NAME/$SAFE_NAME.key" + ln -s ../"$SAFE_NAME".key "certs/clients/$SAFE_NAME/ssh/$SAFE_NAME.ssh" openssl rsa -in "certs/clients/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" fi + +echo -e "$NOTE Creating client SSH ($SAFE_NAME.ssh.pub)" +echo -e "$NOTE Example sshd_config: TrustedUserCAKeys ca.ssh.pub" +echo -e "$NOTE Example sshd_config: AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u" +echo -e "$NOTE Example known_hosts: @cert-authority *.example.com " + ssh-keygen -f "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ - | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/clients/$SAFE_NAME/$SAFE_NAME.ssh.pub" + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/clients/$SAFE_NAME/ssh/$SAFE_NAME.ssh.pub" +ssh-keygen -lvf "certs/clients/$SAFE_NAME/ssh/$SAFE_NAME.ssh.pub" + echo -e "$NOTE Creating the client certificate" diff --git a/create-csr b/create-csr index e72dc9f..d0be885 100755 --- a/create-csr +++ b/create-csr @@ -80,7 +80,7 @@ fi pushd "${BIN_DIR}/.." > /dev/null -mkdir -p "certs/$CSR_TYPE/$SAFE_NAME" +mkdir -p "certs/$CSR_TYPE/$SAFE_NAME/ssh" # Generate the client cert openssl config export CA_USERNAME="${SAFE_NAME}" @@ -108,6 +108,7 @@ if [[ -z "$CSR_KEY" ]]; then else cp "$CSR_KEY" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" chmod 0400 "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" + ln -s ../"$SAFE_NAME".key "certs/$CSR_TYPE/$SAFE_NAME/ssh/$SAFE_NAME.ssh" openssl rsa -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" fi @@ -138,17 +139,15 @@ openssl rsa \ $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key") \ -noout -echo values $ENABLE_ENGINE $CSR_KEY if [ -z "$ENABLE_ENGINE" ] && [ -z "$CSR_KEY" ]; then - echo entered - pwd chmod 0400 "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" + ln -s "$SAFE_NAME".key "certs/$CSR_TYPE/$SAFE_NAME/ssh/$SAFE_NAME.ssh" openssl rsa -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" fi ssh-keygen -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ - | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.ssh.pub" + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/$CSR_TYPE/$SAFE_NAME/ssh/$SAFE_NAME.ssh.pub" echo -e "$NOTE Verifying csr" diff --git a/create-root-ca b/create-root-ca index d857d26..9085486 100755 --- a/create-root-ca +++ b/create-root-ca @@ -101,6 +101,8 @@ pushd "${CA_DIR}" > /dev/null # Generate the root CA openssl config template "${BIN_DIR}/templates/root.tpl" "ca/ca.conf" +mkdir -p ca/ssh +echo $( od -vAn -N2 -tu2 < /dev/urandom )00 > ca/ssh/serial # Create the signing CA key if [[ -z $CA_ENABLE_ENGINE ]]; then @@ -108,12 +110,18 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key + ln -s ../private/ca.key ca/ssh/ca.ssh openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else echo -e "$NOTE Root CA key should already exist via pkcs11 engine." fi + +echo -e "$NOTE Creating root SSH (ca.ssh.pub)" +echo -e "$NOTE Example in sshd_config: TrustedUserCAKeys ca.ssh.pub" + ssh-keygen -f ca/ca.pub -i -mPKCS8 \ - | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub + | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ssh/ca.ssh.pub +ssh-keygen -lvf ca/ssh/ca.ssh.pub echo -e "$NOTE Creating the root CA csr" diff --git a/create-server b/create-server index 05764b4..4be2329 100755 --- a/create-server +++ b/create-server @@ -93,7 +93,7 @@ openssl rsa \ -passin env:CA_PASS trap 'rm -Rf "certs/server/$SAFE_NAME"' 0 -mkdir "certs/server/$SAFE_NAME" +mkdir -p "certs/server/$SAFE_NAME/ssh" # Generate the server openssl config export CA_HOSTNAME="${SERVER_NAME}" @@ -135,13 +135,19 @@ openssl rsa \ $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/server/$SAFE_NAME/$SAFE_NAME.key") \ -noout +echo -e "$NOTE Example known_hosts: @cert-authority *.example.com ca.ssh-cert.pub" +echo -e "$NOTE Example sshd_config: HostCertificate $SAFE_NAME.ssh-cert.pub" +echo -e "$NOTE Example sshd_config: TrustedUserCAKeys ca.ssh.pub" +echo -e "$NOTE Example sshd_config: RevokedKeys revoked-keys" + if [ -z "$ENABLE_ENGINE" ]; then chmod 0400 "certs/server/$SAFE_NAME/$SAFE_NAME.key" + ln -s ../"$SAFE_NAME".key "certs/server/$SAFE_NAME/ssh/$SAFE_NAME.ssh" openssl rsa -in "certs/server/$SAFE_NAME/$SAFE_NAME.key" \ -pubout -out "certs/server/$SAFE_NAME/$SAFE_NAME.pub" fi ssh-keygen -f "certs/server/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ - | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/server/$SAFE_NAME/$SAFE_NAME.ssh.pub" + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/server/$SAFE_NAME/ssh/$SAFE_NAME.ssh.pub" echo -e "$NOTE Creating the server certificate" diff --git a/create-signing-ca b/create-signing-ca index ced79a3..d54ba1f 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -126,6 +126,8 @@ pushd "${CA_DIR}" > /dev/null # Generate the signing CA openssl config template "${BIN_DIR}/templates/signing.tpl" "ca/ca.conf" +mkdir -p ca/ssh +echo $( od -vAn -N2 -tu2 < /dev/urandom )00 > ca/ssh/serial echo -e "$NOTE Creating the signing sub-CA key" @@ -135,12 +137,13 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" chmod 0400 ca/private/ca.key + ln -s ../private/ca.key "ca/ssh/ca.ssh" openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." fi ssh-keygen -f ca/ca.pub -i -mPKCS8 \ - | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ca.ssh.pub + | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ssh/ca.ssh.pub echo -e "$NOTE Creating the signing sub-CA csr" diff --git a/functions b/functions index 120f35a..eac79fc 100644 --- a/functions +++ b/functions @@ -6,12 +6,14 @@ # Derek Moore # Christian Göttsche +export TZ= # Binaries copied during install export BINARIES_ROOT=" create-signing-ca create-server create-client sign-csr +sign-ssh revoke-cert functions show-status @@ -30,6 +32,7 @@ export BINARIES_SIGN=" create-server create-client sign-csr +sign-ssh revoke-cert functions show-status @@ -192,12 +195,13 @@ CA_CERT_ST="${CA_CERT_ST}" CA_CERT_L="${CA_CERT_L}" CA_CERT_O="${CA_CERT_O}" CA_CERT_OU="${CA_CERT_OU}" -CA_ENABLE_ENGINE="${CA_ENABLE_ENGINE}" CA_KEY_ALG="${CA_KEY_ALG}" CA_KEY_LENGTH_ROOTCA="${CA_KEY_LENGTH_ROOTCA}" CA_KEY_LENGTH_SIGNCA="${CA_KEY_LENGTH_SIGNCA}" CA_KEY_LENGTH_ENDCRT="${CA_KEY_LENGTH_ENDCRT}" + +CA_ENABLE_ENGINE="${CA_ENABLE_ENGINE}" EOF } diff --git a/revoke-cert b/revoke-cert index 68d47da..a22667d 100755 --- a/revoke-cert +++ b/revoke-cert @@ -55,6 +55,30 @@ if [ ! -f "${CERT_PATH}" ]; then exit 1 fi +if ssh-keygen -lvf "$CERT_PATH" ; then + if ssh-keygen -Lf "$CERT_PATH" ; then + echo -e "$NOTE Detected SSH certificate; revoke by serial." + SSH_REVOKE="serial: $(ssh-keygen -Lf "$CERT_PATH" | grep Serial | awk '{print $2;}')" + else + echo -e "$NOTE Detected SSH [public] key; revoke by sha1." + SSH_REVOKE="sha1: $(cat "$CERT_PATH")" + fi + pushd "${BIN_DIR}/.." > /dev/null + echo -e "$SUCC You are about to revoke this certificate." + echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " + read -r SURE + if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + echo -e "$ERR Exiting." + exit 1 + fi + ssh-keygen -k $( [ -f ca/ssh/revoke ] && echo "-u" ) -s ca/ssh/ca.ssh.pub -f ca/ssh/revoke <(echo $SSH_REVOKE) + ! ssh-keygen -Q -f ca/ssh/revoke "$CERT_PATH" + popd > /dev/null + echo -e "$NOTE Remember to update sshd_config with: RevokedKeys ca/ssh/revoke" + echo -e "$SUCC Server certificate '${CERT_PATH}' revoked." + exit 0 +fi + echo -e "$NOTE Verifying trusted chain" openssl verify -CAfile ca/chain.pem "$CERT_PATH" diff --git a/sign-csr b/sign-csr index 5bacae1..4106b90 100755 --- a/sign-csr +++ b/sign-csr @@ -43,7 +43,7 @@ CSR_PATH= CSR_NAME= CSR_TYPE="clients" -while getopts c:F:m:h FLAG; do +while getopts c:sF:m:h FLAG; do case $FLAG in c) CSR_PATH=${OPTARG} ;; s) CSR_TYPE="server" ;; @@ -119,6 +119,12 @@ export CA_CERT_MAIL="$CSR_CERT_MAIL" cp --suffix ".old" -b -f -u "$CSR_PATH" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" template "$BIN_DIR/templates/$CSR_TYPE.tpl" "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.conf" +openssl req -in "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.csr" -pubkey \ + -out "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" + +ssh-keygen -f "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.pub" -i -mPKCS8 \ + | awk "{printf \$0;print \" ${SAFE_NAME}\"}" > "certs/$CSR_TYPE/$SAFE_NAME/$SAFE_NAME.ssh.pub" + echo -e "$NOTE Creating the certificate (overwriting C,ST,L,O,OU DN fields)." # Create the client certificate overwriting CSR values diff --git a/sign-ssh b/sign-ssh new file mode 100755 index 0000000..93f60de --- /dev/null +++ b/sign-ssh @@ -0,0 +1,140 @@ +#!/bin/bash + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Derek Moore +# Christian Göttsche +# Tom Bereknyei + +set -eu +set -o pipefail + +umask 0077 + +BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "${BIN_DIR}/functions" +source "${BIN_DIR}/defaults.conf" + +usage() { + echo "Usage: $0 -f SSH_PATH [-h] [-n PRINCIPALS] [-I CERT_ID] [-z SERIAL] [-V VALIDITY]" + echo " Signs a ssh certificate located at SSH_PATH" + echo " Will use the crt info located at SSH_PATH as defaults" + echo + echo "Options:" + echo " -f SSH_PATH Path to ssh public key" + echo + echo " -h Sign a host key for a server" + echo + echo " -n PRINCIPALS SSH Principals - WARNING, default allows all logins" + echo + echo " -I CERT_ID Certificate ID" + echo + echo " -z SERIAL Serial Number" + echo + echo " -V VALIDITY Validity interval" + echo + echo " -Z KEYGEN_OPTS Other options to pass to ssh-keygen" + echo +} + +if [ ! -f ca/ca.crt ]; then + echo -e "$ERR Must be run inside a CA directory!" + exit 2 +fi + +SSH_PATH= +SSH_TYPE= +SSH_ID= +# ssh-keygen default is to allow no principals to login as any user +# this script keeps this default +SSH_PRINCIPALS= +SSH_SERIAL=0 +SSH_VALIDITY= +SSH_OPTIONS= + +while getopts f:hI:n:z:V:Z:v FLAG; do + case $FLAG in + f) SSH_PATH=${OPTARG} ;; + h) SSH_TYPE="-h" ;; + I) SSH_ID=${OPTARG} ;; + n) SSH_PRINCIPALS="-n ${OPTARG}" ;; + z) SSH_SERIAL="${OPTARG}" ;; + V) SSH_VALIDITY="-V ${OPTARG}" ;; + Z) SSH_OPTIONS="${OPTARG}" ;; + # h taken by ssh-keygen, attempting to keep same options + v) echo -e -n "$SUCC " && usage && exit 0 ;; + *) echo -e -n "$ERR " && usage && exit 2 ;; + esac +done + +if [ $OPTIND -le $# ]; then + echo -e -n "$ERR " && usage && exit 2 +elif [ -z "$SSH_PATH" ]; then + echo -e "$ERR No path supplied, exiting." + usage && exit 1 +fi + +ssh-keygen -lvf "$SSH_PATH" + +SSH_PATH_SHORT=$(basename "$SSH_PATH" .pub) +SSH_PATH_SHORTER=$(basename "$SSH_PATH_SHORT" .ssh) +SAFE_NAME=$(echo "$SSH_PATH_SHORTER" | sed 's/\*/star/g' | sed 's/[^A-Za-z0-9-]/-/g') + +SSH_DIR="$(realpath `dirname $SSH_PATH`)" +SSH_BASE="$(basename $SSH_DIR)" +SSH_DIR1="$(dirname $SSH_DIR)" +SSH_BASE1="$(basename $SSH_DIR1)" +SSH_DIR2="$(dirname $SSH_DIR1)" +SSH_BASE2="$(basename $SSH_DIR2)" + +if [ -f "$SSH_DIR/$SAFE_NAME-cert.pub" ]; then + echo -e "$ERR SSH Certificate already exist for $SAFE_NAME, exiting." + exit 1 +fi +if [[ ( "$SSH_BASE1" == "ca" || "$SSH_BASE2" == "server" ) && "$SSH_TYPE" != "-h" ]]; then + echo -e -n "$ERR SSH User Certificate being created for a host, please confim." + read -r -s SURE +elif [[ "$SSH_BASE2" == "clients" && "$SSH_TYPE" == "-h" ]]; then + echo -e -n "$ERR SSH Host Certificate being created for a client, please confim." + read -r -s SURE +fi + +CRT_PATH="${SSH_DIR1}/${SAFE_NAME}.crt" +if [ -f "$CRT_PATH" ]; then + CRT_SUBJ=$(openssl x509 -in "$CRT_PATH" -noout -subject -nameopt multiline) + SSH_ID=${SSH_ID:-$(echo "$CRT_SUBJ" | grep -P '^\s+commonName' | cut -d '=' -f 2- | sed -e 's/^[[:space:]]*//')} + SSH_VALID_START=$(openssl x509 -in "$CRT_PATH" -noout -startdate | cut -d'=' -f2 | date -u -f - +%Y%m%d%H%M%S ) + SSH_VALID_END=$(openssl x509 -in "$CRT_PATH" -noout -enddate | cut -d'=' -f2 | date -u -f - +%Y%m%d%H%M%S ) + SSH_VALIDITY=${SSH_VALIDITY:-"-V ${SSH_VALID_START}:${SSH_VALID_END}"} +fi +SSH_ID=${SSH_ID:-$SAFE_NAME} +if [ -f ca/ssh/serial ]; then + SSH_SERIAL=$(cat ca/ssh/serial) + echo $((SSH_SERIAL+1)) > ca/ssh/serial +fi +SSH_SERIAL="-z $((SSH_SERIAL+1))" + +echo -e "$NOTE Signing SSH cert for $SAFE_NAME using ID: $SSH_ID" + +pushd "${BIN_DIR}/.." > /dev/null + +echo +if [ -n "$CA_ENABLE_ENGINE" ]; then + echo -e "$NOTE Your CA key is on PKCS11 device" + ssh_engine_cmd="-D opensc-pkcs11.so" + ca_path="ca/ca.ssh.pub" +else + ssh_engine_cmd= + ca_path="ca/private/ca.key" +fi + +# Create the ssh certificate +ssh-keygen $ssh_engine_cmd $SSH_TYPE -s $ca_path -I "$SSH_ID" $SSH_PRINCIPALS $SSH_SERIAL $SSH_VALIDITY $SSH_PATH $SSH_OPTIONS + +ssh-keygen -Lf "$SSH_DIR/${SAFE_NAME}.ssh-cert.pub" + +popd > /dev/null + +echo -e "$SUCC SSH certificate for $SAFE_NAME at $SSH_DIR/${SAFE_NAME}.ssh-cert.pub created." From 49e52da7ee334f044bc628500ae580c396d90412 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Tue, 9 Oct 2018 23:07:54 -0400 Subject: [PATCH 11/12] Additional protections from overwriting. Cleaner ssh management --- create-root-ca | 5 ++++ create-signing-ca | 62 ++++++++++++++++++++++++++++++++++++----------- functions | 1 + sign-ssh | 2 +- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/create-root-ca b/create-root-ca index 9085486..241a918 100755 --- a/create-root-ca +++ b/create-root-ca @@ -113,6 +113,11 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then ln -s ../private/ca.key ca/ssh/ca.ssh openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else + openssl_engine_cmd="\ + -engine pkcs11 \ + -inform engine \ + -in pkcs11:object=SIGN%20key" + openssl rsa $openssl_engine_cmd -pubout -out ca/ca.pub -passin env:CA_PASS echo -e "$NOTE Root CA key should already exist via pkcs11 engine." fi diff --git a/create-signing-ca b/create-signing-ca index d54ba1f..772c17f 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -62,6 +62,9 @@ init_ca_home "${CA_DIR}" trap 'rm -Rf "${CA_DIR}"' 0 # early verification of root ca password +if [ -n "$CA_ENABLE_ENGINE" ]; then + echo -e "$NOTE Your CA key is on PKCS11 device, enter PIN." +fi echo -e -n "$INPUT Enter passphase for root CA key: " read -r -s PARENT_PASS echo @@ -70,11 +73,11 @@ openssl_engine_cmd=' -engine pkcs11 -inform engine -in pkcs11:object=SIGN%20key' -openssl rsa \ +CA_PARENT_MODULUS=$(openssl rsa \ ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ - -noout \ - -passin env:CA_PARENT_PASS + -noout -modulus \ + -passin env:CA_PARENT_PASS) CA_PARENT_ENABLE_ENGINE=$CA_ENABLE_ENGINE @@ -89,9 +92,24 @@ if [ -n "${CERT_CN}" ]; then fi if [[ -n $CA_ENABLE_ENGINE ]]; then - if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then - echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. Do not have your root CA inserted." - fi + LOOP=1 + while [[ -n $CA_PARENT_ENABLE_ENGINE ]] && [[ -n $LOOP ]]; do + echo -e "$ERR WARNING: please make sure you have the proper pkcs11 device inserted. Do not have your root CA inserted." + echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " + read -r SURE + if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + echo -e "$ERR Exiting." + exit 1 + fi + CA_MODULUS=$(openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout -modulus \ + -passin env:CA_PARENT_PASS) + if [[ $CA_PARENT_MODULUS != $CA_MODULUS ]] ; then + LOOP= + fi + done init_engine init_slot 9c "${CA_DIR}/ca/ca.pub" echo -e -n "$INPUT Enter PIN for signing sub-CA key: " @@ -140,6 +158,11 @@ if [[ -z $CA_ENABLE_ENGINE ]]; then ln -s ../private/ca.key "ca/ssh/ca.ssh" openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS else + openssl_engine_cmd="\ + -engine pkcs11 \ + -inform engine \ + -in pkcs11:object=SIGN%20key" + openssl rsa $openssl_engine_cmd -pubout -out ca/ca.pub -passin env:CA_PASS echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." fi ssh-keygen -f ca/ca.pub -i -mPKCS8 \ @@ -162,7 +185,7 @@ echo -e "$NOTE Creating the signing sub-CA certificate" pushd "${PARENT}" > /dev/null if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then - echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. You are signing the sub-CA with the root CA device. Do not have your sub-CA device inserted." + echo -e "$ERR WARNING: please make sure you have the proper pkcs11 device inserted. You are signing the sub-CA with the root CA device. Do not have your sub-CA device inserted." echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " read -r SURE if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then @@ -185,13 +208,24 @@ openssl ca \ -passin env:CA_PARENT_PASS if [[ -n "$CA_ENABLE_ENGINE" ]]; then - echo -e "$NOTE WARNING: please make sure you have the proper pkcs11 device inserted. You are uploading the sub-CA cert. Insert the sub-CA deivce." - echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " - read -r SURE - if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then - echo -e "$ERR Exiting." - exit 1 - fi + LOOP=1 + while [[ -n $CA_PARENT_ENABLE_ENGINE ]] && [[ -n $LOOP ]]; do + echo -e "$ERR WARNING: please make sure you have the proper pkcs11 device inserted. Do not have your root CA inserted." + echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " + read -r SURE + if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then + echo -e "$ERR Exiting." + exit 1 + fi + CA_MODULUS=$(openssl rsa \ + ${CA_ENABLE_ENGINE:+$openssl_engine_cmd} \ + $( [ -z $CA_ENABLE_ENGINE ] && echo "-check -in ca/private/ca.key") \ + -noout -modulus \ + -passin env:CA_PARENT_PASS) + if [[ $CA_PARENT_MODULUS != $CA_MODULUS ]] ; then + LOOP= + fi + done replace_crt 9c "${CA_DIR}/ca/ca.crt" fi popd > /dev/null diff --git a/functions b/functions index eac79fc..c519b5e 100644 --- a/functions +++ b/functions @@ -316,6 +316,7 @@ function replace_crt(){ } function init_engine(){ echo -e "$NOTE THIS WILL RESET YOUR YUBIKEY USING YKMAN" + echo -e "$NOTE Run 'ykman piv reset' on your own to set PIN/PUK/management keys properly." echo -e -n "$INPUT Do you wish to reset your device? [y/N]: " read -r SURE if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then diff --git a/sign-ssh b/sign-ssh index 93f60de..6ad5b2b 100755 --- a/sign-ssh +++ b/sign-ssh @@ -124,7 +124,7 @@ echo if [ -n "$CA_ENABLE_ENGINE" ]; then echo -e "$NOTE Your CA key is on PKCS11 device" ssh_engine_cmd="-D opensc-pkcs11.so" - ca_path="ca/ca.ssh.pub" + ca_path="ca/ssh/ca.ssh.pub" else ssh_engine_cmd= ca_path="ca/private/ca.key" From fe7d3a48f929ee15594de268c5d2983bf416fc80 Mon Sep 17 00:00:00 2001 From: Tom Bereknyei Date: Sat, 13 Oct 2018 14:56:40 -0400 Subject: [PATCH 12/12] start refactor to for DRY --- create-client | 15 +++++++++++---- create-root-ca | 23 +++++------------------ create-signing-ca | 25 ++++++++++--------------- functions | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/create-client b/create-client index 9739c1f..c5d6a65 100755 --- a/create-client +++ b/create-client @@ -93,8 +93,12 @@ read -r SURE if [ "${SURE}" != "y" ] && [ "${SURE}" != "Y" ]; then ENABLE_ENGINE= else + echo -e -n "$INPUT Enter PIN for PIV key: " + read -r -s PASS + echo + export PIV_PASS="${PASS}" ENABLE_ENGINE=1 - init_slot 9a "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" + CA_PASS=$PIV_PASS init_slot 9a "certs/clients/$SAFE_NAME/$SAFE_NAME.pub" "pkcs11:object=PIV%20AUTH%20key" fi echo -e "$NOTE Creating the client key and csr" @@ -103,7 +107,8 @@ echo -e "$NOTE Creating the client key and csr" openssl_engine_cmd=' -engine pkcs11 -keyform engine - -key pkcs11:object=PIV%20AUTH%20key' + -key pkcs11:object=PIV%20AUTH%20key + -passin env:PIV_PASS' openssl req -new -batch \ ${ENABLE_ENGINE:+$openssl_engine_cmd} \ -config "certs/clients/$SAFE_NAME/$SAFE_NAME.conf" \ @@ -115,7 +120,8 @@ openssl req -new -batch \ openssl_engine_cmd=' -engine pkcs11 -inform engine - -in pkcs11:object=PIV%20AUTH%20key' + -in pkcs11:object=PIV%20AUTH%20key + -passin env:PIV_PASS' openssl rsa \ ${ENABLE_ENGINE:+$openssl_engine_cmd} \ $( [ -z $ENABLE_ENGINE ] && echo "-check -in certs/clients/$SAFE_NAME/$SAFE_NAME.key") \ @@ -162,7 +168,8 @@ echo -e "$NOTE Verifying certificate/key pair" openssl_engine_cmd="\ -engine pkcs11 \ -inform engine \ - -in pkcs11:object=PIV%20AUTH%20key" + -in pkcs11:object=PIV%20AUTH%20key \ + -passin env:PIV_PASS" key_mod=$(openssl rsa \ ${ENABLE_ENGINE:+$openssl_engine_cmd} -noout -modulus \ $( [ -z $ENABLE_ENGINE ] && echo "-in certs/clients/$SAFE_NAME/$SAFE_NAME.key") diff --git a/create-root-ca b/create-root-ca index 241a918..bb1b86c 100755 --- a/create-root-ca +++ b/create-root-ca @@ -101,32 +101,19 @@ pushd "${CA_DIR}" > /dev/null # Generate the root CA openssl config template "${BIN_DIR}/templates/root.tpl" "ca/ca.conf" +# Generate the root CA openssh config mkdir -p ca/ssh echo $( od -vAn -N2 -tu2 < /dev/urandom )00 > ca/ssh/serial # Create the signing CA key if [[ -z $CA_ENABLE_ENGINE ]]; then - echo -e "$NOTE Creating the root CA key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" - - openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" - chmod 0400 ca/private/ca.key + generate_key ca/private/ca.key ln -s ../private/ca.key ca/ssh/ca.ssh - openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS + generate_pubkey ca/private/ca.key ca/ca.pub else - openssl_engine_cmd="\ - -engine pkcs11 \ - -inform engine \ - -in pkcs11:object=SIGN%20key" - openssl rsa $openssl_engine_cmd -pubout -out ca/ca.pub -passin env:CA_PASS - echo -e "$NOTE Root CA key should already exist via pkcs11 engine." + generate_pubkey_pkcs11 pkcs11:object=SIGN%20key ca/ca.pub fi - -echo -e "$NOTE Creating root SSH (ca.ssh.pub)" -echo -e "$NOTE Example in sshd_config: TrustedUserCAKeys ca.ssh.pub" - -ssh-keygen -f ca/ca.pub -i -mPKCS8 \ - | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ssh/ca.ssh.pub -ssh-keygen -lvf ca/ssh/ca.ssh.pub +generate_pubkey_ssh ca/ca.pub ca/ssh/ca.ssh.pub ${CA_DIR} echo -e "$NOTE Creating the root CA csr" diff --git a/create-signing-ca b/create-signing-ca index 772c17f..218c6ea 100755 --- a/create-signing-ca +++ b/create-signing-ca @@ -143,7 +143,10 @@ export SAN="" pushd "${CA_DIR}" > /dev/null # Generate the signing CA openssl config +echo enter template template "${BIN_DIR}/templates/signing.tpl" "ca/ca.conf" +echo exit template +# Generate the signing CA openssh config mkdir -p ca/ssh echo $( od -vAn -N2 -tu2 < /dev/urandom )00 > ca/ssh/serial @@ -151,22 +154,13 @@ echo -e "$NOTE Creating the signing sub-CA key" # Create the signing CA key if [[ -z $CA_ENABLE_ENGINE ]]; then - echo -e "$NOTE Creating the signing sub-CA key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" - - openssl genrsa -out ca/private/ca.key -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" - chmod 0400 ca/private/ca.key - ln -s ../private/ca.key "ca/ssh/ca.ssh" - openssl rsa -in ca/private/ca.key -pubout -out ca/ca.pub -passin env:CA_PASS + generate_key ca/private/ca.key + ln -s ../private/ca.key ca/ssh/ca.ssh + generate_pubkey ca/private/ca.key ca/ca.pub else - openssl_engine_cmd="\ - -engine pkcs11 \ - -inform engine \ - -in pkcs11:object=SIGN%20key" - openssl rsa $openssl_engine_cmd -pubout -out ca/ca.pub -passin env:CA_PASS - echo -e "$NOTE Signing sub-CA key should already exist via pkcs11 engine." + generate_pubkey_pkcs11 pkcs11:object=SIGN%20key ca/ca.pub fi -ssh-keygen -f ca/ca.pub -i -mPKCS8 \ - | awk "{printf \$0;print \" ${CA_DIR}\"}" > ca/ssh/ca.ssh.pub +generate_pubkey_ssh ca/ca.pub ca/ssh/ca.ssh.pub ${CA_DIR} echo -e "$NOTE Creating the signing sub-CA csr" @@ -184,7 +178,8 @@ openssl req -new -batch \ echo -e "$NOTE Creating the signing sub-CA certificate" pushd "${PARENT}" > /dev/null -if [[ -n $CA_PARENT_ENABLE_ENGINE ]]; then + +if [[ -n $CA_PARENT_ENABLE_ENGINE ]] && [[ -n $CA_ENABLE_ENGINE ]] ; then echo -e "$ERR WARNING: please make sure you have the proper pkcs11 device inserted. You are signing the sub-CA with the root CA device. Do not have your sub-CA device inserted." echo -e -n "$INPUT Are you SURE you wish to continue? [y/N]: " read -r SURE diff --git a/functions b/functions index c519b5e..599cb15 100644 --- a/functions +++ b/functions @@ -290,12 +290,43 @@ ask_client_cert_questions() { fi } +function generate_key(){ + local KEYPATH=$1 + echo -e "$NOTE Creating the key (${CA_KEY_ALG} with ${CA_KEY_LENGTH_ROOTCA} bits)" + openssl genrsa -out $KEYPATH -"${CA_KEY_ALG}" -passout env:CA_PASS "${CA_KEY_LENGTH_ROOTCA}" + chmod 0400 $KEYPATH +} +function generate_pubkey(){ + local KEYPATH=$1 + local PUBPATH=$2 + openssl rsa -in $KEYPATH -pubout -out $PUBPATH -passin env:CA_PASS +} +function generate_pubkey_pkcs11(){ + local KEYPATH=$1 + local PUBPATH=$2 + echo -e "$NOTE CA key should already exist via pkcs11 engine." + openssl rsa -engine pkcs11 -inform engine \ + -in $KEYPATH -pubout -out $PUBPATH -passin env:CA_PASS +} + +function generate_pubkey_ssh(){ + local PUBPATH=$1 + local SSHPUBPATH=$2 + local NAME=$3 + echo -e "$NOTE Creating SSH pub ($SSHPUBPATH)" + echo -e "$NOTE Example in sshd_config: TrustedUserCAKeys ca.ssh.pub" + + ssh-keygen -f $PUBPATH -i -mPKCS8 \ + | awk "{printf \$0;print \" $3\"}" > $SSHPUBPATH + ssh-keygen -lvf $SSHPUBPATH +} ## ## PKCS11 support functions, currently hard coded to support yubikeys using ykman ## function init_slot(){ local SLOT=$1 local PUB=$2 + local SLOTPKCS=$3 echo -e -n "$INPUT Do you wish to create a new key in slot $SLOT? [y/N]: " read -r SURE if [ "${SURE}" == "y" ] || [ "${SURE}" == "Y" ]; then @@ -303,6 +334,8 @@ function init_slot(){ # This cert is to make PKCS11 happy. # Should replace this with the proper cert later in the process. ykman piv generate-certificate "$SLOT" "$PUB" -s 'bootstrap' + else + generate_pubkey_pkcs11 "$SLOTPKCS" "$PUB" fi } function replace_crt(){