From b09e1807ba0a8d5c1bfc90f8af456842decb39bb Mon Sep 17 00:00:00 2001 From: Tim Kimber Date: Wed, 12 Feb 2020 14:22:30 +0000 Subject: [PATCH] Fix #424 - Sporadic "error in EC signing couldn't get R from ..." --- getssl | 29 ++++++++++----- test/5-secp384-http01.bats | 41 ++++++++++++++++++++++ test/test-config/getssl-http01-secp384.cfg | 32 +++++++++++++++++ test/test-config/getssl-http01-secp521.cfg | 32 +++++++++++++++++ 4 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 test/5-secp384-http01.bats create mode 100644 test/test-config/getssl-http01-secp384.cfg create mode 100644 test/test-config/getssl-http01-secp521.cfg diff --git a/getssl b/getssl index 0d593d7..5af09e1 100755 --- a/getssl +++ b/getssl @@ -1801,20 +1801,27 @@ sign_string() { # sign a string with a given key and algorithm and return urlbas elif openssl ec -in "${skey}" -noout 2>/dev/null ; then # Elliptic curve key. signed=$(printf '%s' "${str}" | openssl dgst -"$signalg" -sign "$key" -hex | awk '{print $2}') debug "EC signature $signed" - if [[ "${signed:4:4}" == "0220" ]]; then #sha256 + if [[ "${signed:4:4}" == "021f" ]]; then #sha256 which needs padding + R=$(echo -n 00;echo "$signed" | cut -c 9-70) + part2=$(echo "$signed" | cut -c 71-) + elif [[ "${signed:4:4}" == "0220" ]]; then #sha256 R=$(echo "$signed" | cut -c 9-72) part2=$(echo "$signed" | cut -c 73-) - elif [[ "${signed:4:4}" == "0221" ]]; then #sha256 + elif [[ "${signed:4:4}" == "0221" ]]; then #sha256 which needs trimming R=$(echo "$signed" | cut -c 11-74) part2=$(echo "$signed" | cut -c 75-) + elif [[ "${signed:4:4}" == "022f" ]]; then #sha384 which needs padding + info "Padding sha384" + R=$(echo -n 00;echo "$signed" | cut -c 9-102) + part2=$(echo "$signed" | cut -c 103-) elif [[ "${signed:4:4}" == "0230" ]]; then #sha384 R=$(echo "$signed" | cut -c 9-104) part2=$(echo "$signed" | cut -c 105-) - elif [[ "${signed:4:4}" == "0231" ]]; then #sha384 + elif [[ "${signed:4:4}" == "0231" ]]; then #sha384 which needs trimming R=$(echo "$signed" | cut -c 11-106) part2=$(echo "$signed" | cut -c 107-) - elif [[ "${signed:6:4}" == "0241" ]]; then #sha512 - R=$(echo "$signed" | cut -c 11-140) + elif [[ "${signed:6:4}" == "0241" ]]; then #sha512 which needs padding + R=$(echo -n 00;echo "$signed" | cut -c 11-140) part2=$(echo "$signed" | cut -c 141-) elif [[ "${signed:6:4}" == "0242" ]]; then #sha512 R=$(echo "$signed" | cut -c 11-142) @@ -1824,18 +1831,22 @@ sign_string() { # sign a string with a given key and algorithm and return urlbas fi debug "R $R" - if [[ "${part2:0:4}" == "0220" ]]; then #sha256 + if [[ "${part2:0:4}" == "021f" ]]; then #sha256 with padding + S=$(echo -n 00;echo "$part2" | cut -c 5-) + elif [[ "${part2:0:4}" == "0220" ]]; then #sha256 S=$(echo "$part2" | cut -c 5-68) elif [[ "${part2:0:4}" == "0221" ]]; then #sha256 S=$(echo "$part2" | cut -c 7-70) + elif [[ "${part2:0:4}" == "022f" ]]; then #sha384 with padding + S=$(echo -n 00;echo "$part2" | cut -c 5-) elif [[ "${part2:0:4}" == "0230" ]]; then #sha384 S=$(echo "$part2" | cut -c 5-100) elif [[ "${part2:0:4}" == "0231" ]]; then #sha384 S=$(echo "$part2" | cut -c 7-102) - elif [[ "${part2:0:4}" == "0241" ]]; then #sha512 - S=$(echo "$part2" | cut -c 5-136) + elif [[ "${part2:0:4}" == "0241" ]]; then #sha512 with padding + S=$(echo -n 00;echo "$part2" | cut -c 5-) elif [[ "${part2:0:4}" == "0242" ]]; then #sha512 - S=$(echo "$part2" | cut -c 5-136) + S=$(echo "$part2" | cut -c 5-) else error_exit "error in EC signing couldn't get S from $signed" fi diff --git a/test/5-secp384-http01.bats b/test/5-secp384-http01.bats new file mode 100644 index 0000000..9010d58 --- /dev/null +++ b/test/5-secp384-http01.bats @@ -0,0 +1,41 @@ +#! /usr/bin/env bats + +load '/bats-support/load.bash' +load '/bats-assert/load.bash' +load '/getssl/test/test_helper.bash' + + +# This is run for every test +setup() { + export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt +} + + +@test "Create new secp384r1 certificate using HTTP-01 verification" { + CONFIG_FILE="getssl-http01-secp384.cfg" + setup_environment + init_getssl + create_certificate + assert_success +} + + +@test "Force renewal of secp384r1 certificate using HTTP-01" { + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success +} + + +@test "Create new secp521r1 certificate using HTTP-01 verification" { + CONFIG_FILE="getssl-http01-secp521.cfg" + setup_environment + init_getssl + create_certificate + assert_success +} + + +@test "Force renewal of secp521r1 certificate using HTTP-01" { + run ${CODE_DIR}/getssl -f $GETSSL_HOST + assert_success +} diff --git a/test/test-config/getssl-http01-secp384.cfg b/test/test-config/getssl-http01-secp384.cfg new file mode 100644 index 0000000..4fa3e82 --- /dev/null +++ b/test/test-config/getssl-http01-secp384.cfg @@ -0,0 +1,32 @@ +# Uncomment and modify any variables you need +# see https://github.com/srvrco/getssl/wiki/Config-variables for details +# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs +# +CA="https://pebble:14000/dir" + +ACCOUNT_KEY_TYPE="secp384r1" +PRIVATE_KEY_ALG="secp384r1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') + +#Set USE_SINGLE_ACL="true" to use a single ACL for all checks +USE_SINGLE_ACL="false" + +# Location for all your certs, these can either be on the server (full path name) +# or using ssh /sftp as for the ACL +DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert +DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert + +# The command needed to reload apache / nginx or whatever you use +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true" diff --git a/test/test-config/getssl-http01-secp521.cfg b/test/test-config/getssl-http01-secp521.cfg new file mode 100644 index 0000000..6068fbf --- /dev/null +++ b/test/test-config/getssl-http01-secp521.cfg @@ -0,0 +1,32 @@ +# Uncomment and modify any variables you need +# see https://github.com/srvrco/getssl/wiki/Config-variables for details +# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs +# +CA="https://pebble:14000/dir" + +ACCOUNT_KEY_TYPE="secp521r1" +PRIVATE_KEY_ALG="secp521r1" + +# Additional domains - this could be multiple domains / subdomains in a comma separated list +SANS="" + +# Acme Challenge Location. +ACL=('/var/www/html/.well-known/acme-challenge') + +#Set USE_SINGLE_ACL="true" to use a single ACL for all checks +USE_SINGLE_ACL="false" + +# Location for all your certs, these can either be on the server (full path name) +# or using ssh /sftp as for the ACL +DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt" +DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key" +CA_CERT_LOCATION="/etc/nginx/pki/chain.crt" +DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert +DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert + +# The command needed to reload apache / nginx or whatever you use +RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx" + +# Define the server type and confirm correct certificate is installed +SERVER_TYPE="https" +CHECK_REMOTE="true"