Export PKCS: Expand usage for incomplete PKI

The current export functions only allow use on a complete PKI, with CA.

This change allows the following:
* Server - Export P12/P7 without client key
* Client - Export P12/P7 without CA, P8/P1 without PKI

Due to the relative obscurity of the command options 'noca' and 'nokey',
exporting P12/P7 with incorrect options can be adjusted on-the-fly with
confirmation from the user.

Correct behaviour of export-p1 with OpenSSL v3 by using -legacy option.
Otherwise, OpenSSL v3 outputs a PKCS#8 format file.

Minor improvements to comments.

Signed-off-by: Richard T Bonhomme <tincantech@protonmail.com>
This commit is contained in:
Richard T Bonhomme 2023-07-25 15:11:26 +01:00
parent cc089ab008
commit aaa44558b2
No known key found for this signature in database
GPG Key ID: 2D767DB92FB6C246

View File

@ -64,7 +64,7 @@ A list of commands is shown below:
# vars file details # vars file details
case "$found_vars" in case "$found_vars" in
0) vars_status="Missing or undefined." ;; 0) vars_status="Missing or undefined" ;;
1) vars_status="$vars" ;; 1) vars_status="$vars" ;;
*) vars_status="WARNING: Multiple conflicting vars files!" *) vars_status="WARNING: Multiple conflicting vars files!"
esac esac
@ -81,7 +81,7 @@ A list of commands is shown below:
CA_subject=" CA subject: ${CA_subject#subject=}" CA_subject=" CA subject: ${CA_subject#subject=}"
CA_status="${CA_status}${NL}${CA_subject}" CA_status="${CA_status}${NL}${CA_subject}"
else else
CA_status=" CA status: CA has not been built." CA_status=" CA status: CA has not been built"
fi fi
# Print details # Print details
@ -1131,6 +1131,7 @@ verify_ssl_lib() {
# Run once only # Run once only
[ "$verify_ssl_lib_ok" ] && return [ "$verify_ssl_lib_ok" ] && return
verify_ssl_lib_ok=1 verify_ssl_lib_ok=1
unset -v openssl_v3
# redirect std-err, ignore missing ssl/openssl.cnf # redirect std-err, ignore missing ssl/openssl.cnf
val="$( val="$(
@ -1169,8 +1170,13 @@ $error_msg"
2) no_password='-nodes' ;; 2) no_password='-nodes' ;;
3) 3)
case "$ssl_lib" in case "$ssl_lib" in
openssl) no_password='-noenc' ;; openssl)
libressl) no_password='-nodes' ;; openssl_v3=1
no_password='-noenc'
;;
libressl)
no_password='-nodes'
;;
*) die "Unexpected SSL library: $ssl_lib" *) die "Unexpected SSL library: $ssl_lib"
esac esac
;; ;;
@ -3715,7 +3721,7 @@ export_pkcs() {
shift shift
[ "$1" ] || user_error "\ [ "$1" ] || user_error "\
Unable to export p12: incorrect command syntax. Unable to export '$pkcs_type': incorrect command syntax.
Run easyrsa without commands for usage and command help." Run easyrsa without commands for usage and command help."
short_name="$1" short_name="$1"
@ -3729,36 +3735,121 @@ Run easyrsa without commands for usage and command help."
cipher=-aes256 cipher=-aes256
want_ca=1 want_ca=1
want_key=1 want_key=1
unset -v pkcs_friendly_name unset -v nokeys friendly_name
while [ "$1" ]; do while [ "$1" ]; do
case "$1" in case "$1" in
noca) want_ca="" ;; noca)
nokey) want_key="" ;; want_ca=""
;;
nokey)
want_key=""
# Undocumented OpenSSL feature: option
# -nokeys will ignore missing -inkey file
# No doubt, the reason for the extra -inkey
nokeys=-nokeys
;;
nopass) nopass)
[ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1
;; ;;
usefn) pkcs_friendly_name="$short_name" ;; usefn)
friendly_name="$short_name"
;;
*) warn "Ignoring unknown command option: '$1'" *) warn "Ignoring unknown command option: '$1'"
esac esac
shift shift
done done
pkcs_certfile_path= # Required options - PKCS, rhymes with mess
if [ "$want_ca" ]; then case "$pkcs_type" in
verify_file x509 "$crt_ca" || user_error "\ p12|p7)
Unable to include CA cert in the $pkcs_type output. : # ok
Missing CA file expected at: ;;
* $crt_ca p8|p1)
want_key=1
;;
*) die "Unknown PKCS type: $pkcs_type"
esac
Try 'noca' option.)" # Check for CA, if required
pkcs_certfile_path="$crt_ca" if [ "$want_ca" ]; then
case "$pkcs_type" in
p12|p7)
# verify_ca_init() here, otherwise not required
if verify_ca_init test; then
: # ok
else
warn "\
Missing CA file expected at:
* $crt_ca"
confirm "\
Continue without CA certificate (EG: option 'noca') ? " yes "
Your PKI does not include a CA certificate.
You can export your user certificate to a $pkcs_type file
but it will not include the CA."
# --batch mode does not allow
# on-the-fly command changes
if [ "$EASYRSA_BATCH" ]; then
die "export-$pkcs_type: Missing CA"
fi
want_ca=""
fi
;;
p8|p1)
: # Not required
;;
*) die "Unknown PKCS type: $pkcs_type"
esac
fi fi
# input files must exist # Check for key, if required
verify_file x509 "$crt_in" || user_error "\ if [ "$want_key" ]; then
Unable to export $pkcs_type for short name '$short_name'. if [ -e "$key_in" ]; then
Missing cert expected at: : #ok
* $crt_in" else
case "$pkcs_type" in
p12)
warn "\
Missing key expected at:
* $key_in"
confirm "\
Continue without Private key (EG: option 'nokey') ? " yes "
Your PKI does not include a Private key for '$short_name'.
You can export your user certificate to a '$pkcs_type' file
but it will not include the Private key."
# --batch mode does not allow
# on-the-fly command changes
if [ "$EASYRSA_BATCH" ]; then
die "export-$pkcs_type: Missing key"
fi
nokeys=-nokeys
;;
p8|p1)
user_error "Private key required."
;;
p7)
: # Not required
;;
*) die "Unknown PKCS type: $pkcs_type"
esac
fi
fi
# Check for certificate, if required
if [ -e "$crt_in" ]; then
: # ok
else
case "$pkcs_type" in
p12|p7)
user_error "Certificate required."
;;
p8|p1)
: # Not required
;;
*) die "Unknown PKCS type: $pkcs_type"
esac
fi
# For 'nopass' PKCS requires an explicit empty password # For 'nopass' PKCS requires an explicit empty password
if [ "$EASYRSA_NO_PASS" ]; then if [ "$EASYRSA_NO_PASS" ]; then
@ -3767,27 +3858,18 @@ Missing cert expected at:
unset -v cipher # pkcs#1 only unset -v cipher # pkcs#1 only
fi fi
# Complete export
case "$pkcs_type" in case "$pkcs_type" in
p12) p12)
pkcs_out="$EASYRSA_PKI/private/$short_name.p12" pkcs_out="$EASYRSA_PKI/private/$short_name.p12"
if [ "$want_key" ]; then
[ -e "$key_in" ] || user_error "\
Unable to export p12 for short name '$short_name'.
Missing key expected at:
* $key_in
if you want a p12 without the private key, use 'nokey' option."
else
nokeys=1
fi
# export the p12: # export the p12:
easyrsa_openssl pkcs12 -in "$crt_in" -inkey "$key_in" \ easyrsa_openssl pkcs12 -export \
-export -out "$pkcs_out" \ -inkey "$key_in" -in "$crt_in" \
${nokeys:+ -nokeys} \ -out "$pkcs_out" \
${pkcs_certfile_path:+ -certfile "$pkcs_certfile_path"} \ ${nokeys} \
${pkcs_friendly_name:+ -name "$pkcs_friendly_name"} \ ${want_ca:+ -certfile "$crt_ca"} \
${friendly_name:+ -name "$friendly_name"} \
${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \ ${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \
${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \ ${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \
|| die "Failed to export PKCS#12" || die "Failed to export PKCS#12"
@ -3796,28 +3878,43 @@ if you want a p12 without the private key, use 'nokey' option."
pkcs_out="$EASYRSA_PKI/issued/$short_name.p7b" pkcs_out="$EASYRSA_PKI/issued/$short_name.p7b"
# export the p7: # export the p7:
easyrsa_openssl crl2pkcs7 -nocrl -certfile "$crt_in" \ easyrsa_openssl crl2pkcs7 -nocrl \
-certfile "$crt_in" \
-out "$pkcs_out" \ -out "$pkcs_out" \
${pkcs_certfile_path:+ -certfile "$pkcs_certfile_path"} \ ${want_ca:+ -certfile "$crt_ca"} \
|| die "Failed to export PKCS#7" || die "Failed to export PKCS#7"
;; ;;
p8) p8)
pkcs_out="$EASYRSA_PKI/private/$short_name.p8" pkcs_out="$EASYRSA_PKI/private/$short_name.p8"
# export the p8: # export the p8:
easyrsa_openssl pkcs8 -in "$key_in" -topk8 \ easyrsa_openssl pkcs8 -topk8 \
-in "$key_in" \
-out "$pkcs_out" \ -out "$pkcs_out" \
${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \ ${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \
${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \ ${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \
|| die "Failed to export PKCS#8" || die "Failed to export PKCS#8"
;; ;;
p1) p1)
pkcs_out="$EASYRSA_PKI/private/$short_name.p1" pkcs_out="$EASYRSA_PKI/private/$short_name.p1"
# OpenSSLv3 requires -legacy for PKCS#1
# Otherwise, OpenSSLv3 outputs PKCS#8
[ "$verify_ssl_lib_ok" ] || \
die "export_pkcs.p1: verify_ssl_lib_ok FAIL"
if [ "$openssl_v3" ]; then
legacy=-legacy
else
unset -v legacy
fi
# export the p1: # export the p1:
easyrsa_openssl rsa -in "$key_in" \ easyrsa_openssl rsa \
-in "$key_in" \
-out "$pkcs_out" \ -out "$pkcs_out" \
${cipher:+ "$cipher"} \ ${legacy} \
${cipher} \
${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \ ${EASYRSA_PASSIN:+ -passin "$EASYRSA_PASSIN"} \
${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \ ${EASYRSA_PASSOUT:+ -passout "$EASYRSA_PASSOUT"} \
|| die "Failed to export PKCS#1" || die "Failed to export PKCS#1"
@ -6994,7 +7091,7 @@ case "$cmd" in
require_pki=1 require_pki=1
case "$cmd" in case "$cmd" in
gen-req|gen-dh|build-ca|show-req| \ gen-req|gen-dh|build-ca|show-req| \
make-safe-ssl) make-safe-ssl|export-p*)
unset -v require_ca unset -v require_ca
;; ;;
*) *)
@ -7009,6 +7106,7 @@ vars_setup
mutual_exclusions mutual_exclusions
# Hand off to the function responsible # Hand off to the function responsible
# ONLY verify_working_env() for valid commands
case "$cmd" in case "$cmd" in
init-pki|clean-all) init-pki|clean-all)
verify_working_env verify_working_env