From f0fb974f22a110d9d919514823d9dc73249f7f6a Mon Sep 17 00:00:00 2001 From: "Akhilesh Kr. Yadav" Date: Sat, 8 Feb 2025 18:09:44 +0530 Subject: [PATCH] feat: adds 3-level certificate chain generation script Signed-off-by: Akhilesh Kr. Yadav Addressing comments on #165 Signed-off-by: Akhilesh Kr. Yadav Addressing comments on #165 Signed-off-by: Akhilesh Kr. Yadav Addressing comments on #165 Signed-off-by: Akhilesh Kr. Yadav Addressing comments on #165 Signed-off-by: Akhilesh Kr. Yadav Addressing comments on #165 Signed-off-by: Akhilesh Kr. Yadav --- Makefile | 6 ++ misc/endEntity.der | Bin 0 -> 384 bytes misc/endEntity.key | 5 + misc/intermediateCA.der | Bin 0 -> 369 bytes misc/rootCA.der | Bin 0 -> 386 bytes scripts/gen-certs.sh | 202 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+) create mode 100644 misc/endEntity.der create mode 100644 misc/endEntity.key create mode 100644 misc/intermediateCA.der create mode 100644 misc/rootCA.der create mode 100644 scripts/gen-certs.sh diff --git a/Makefile b/Makefile index 28ec37d..4e52f6f 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,11 @@ presubmit: .PHONY: licenses licenses: ; @./scripts/licenses.sh +.PHONY: test-certs +test-certs: + @echo "Regenerating certificate chain..." + @$(SHELL) scripts/gen-certs.sh create + .PHONY: help help: @echo "Available targets:" @@ -58,3 +63,4 @@ help: @echo " * presubmit: check you are ready to push your local branch to remote" @echo " * help: print this menu" @echo " * licenses: check licenses of dependent packages" + @echo " * test-certs: regenerate the certificate chain" diff --git a/misc/endEntity.der b/misc/endEntity.der new file mode 100644 index 0000000000000000000000000000000000000000..0d1c6ce6c6e16ca42ffdc5b0da10fbc843b9c55f GIT binary patch literal 384 zcmXqLVyrP}VpLkd%*4pVB*I^MvQ=5`*!{Oh?q8DUnjEFoxz@*ki;Y98&EuRc3p0~} zn4yS)5F2wS3o{S5V{&e)f_r9FZho`YIG>rst&=8AKWgv$2D1Vq%0^$;`;k?8Lyrd0z4KwhIbjo@`gP zE@j;->~#70@{D*tQTCr<@g-YoCNwd!-8pzue~XZsA5ZP8q#x;OL2CWl+DcVHOe_I~ z?6!-Y3>*w(f!53Nv52vVto^%@ZEbkB%+xyX{*2AZclU=bl`)V9Nh`BR7>G599DM!G zx;rU;)x}p)e?N)^UkXZ3Fh&jrW)B7fS0)8vl{e<5b_eI>O`IF`pVQ<2J^k7lSB;M} yW(A}O&yLNV!KBFW>s@oh_pa#yS?agXOuM0(m;Af?%BnU~L>dUQv4hQKVuV`4%*f8{#K6KT`ERfI_SUEMTnEkv{0LS*>MYcM zkXKKo^OMb{2`=9@vUD91K5cS-hh~3WQAAwW&vX63@gDAu`{{$(;9wvN zv{IIjMT|w{;OlqR-AVDQF20KT`%x_TQc!w=v4K2DTA4+{K&(NeeXoxCx7NLuUwi+` z9g|$}?y~-tzsMeEc4shfVN$60?~|ujuf<xOL`b~?24FU~hfzFiWV-aH!Y2T}({;hSd z<=5W7a>pbWyt}Nw<*$J}NLrai!a%G6y8?cY0%1nR|17Kq%s>h`9GE>B4BVI$8QyXU za%M8Tc)i$JNb6hOGM~p*Z?ZU<^vYlTnUsI(SKD!*lI}R)j&8f(D<-|)C;0G9f6(6R Tv*#qZ&oGsY_Xx^xJs%7Juu6k0 literal 0 HcmV?d00001 diff --git a/scripts/gen-certs.sh b/scripts/gen-certs.sh new file mode 100644 index 0000000..5b0d6c4 --- /dev/null +++ b/scripts/gen-certs.sh @@ -0,0 +1,202 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +set -eu +set -o pipefail + +ROOT_CERT_NAME=rootCA +INTERMEDIATE_CERT_NAME=intermediateCA +END_ENTITY_CERT_NAME=endEntity + +THIS_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +MISC_DIR="$THIS_DIR/../misc" + +mkdir -p "$MISC_DIR" + +trap '[[ $_should_clean_certs_artifacts == true ]] && clean_certs_artifacts' EXIT + +function create_root_cert() { + _check_openssl + + if [[ -f "${MISC_DIR}/${ROOT_CERT_NAME}.der" ]]; then + echo "Root certificate already exists. Skipping creation." + return + fi + + openssl ecparam -name prime256v1 -genkey -noout -out ${MISC_DIR}/${ROOT_CERT_NAME}.key + openssl req -x509 -new -nodes -key ${MISC_DIR}/${ROOT_CERT_NAME}.key \ + -sha256 -days 3650 \ + -subj "/CN=Acme Inc." \ + -out ${MISC_DIR}/${ROOT_CERT_NAME}.crt + openssl x509 -in ${MISC_DIR}/${ROOT_CERT_NAME}.crt -outform der \ + -out ${MISC_DIR}/${ROOT_CERT_NAME}.der + rm -f ${MISC_DIR}/${ROOT_CERT_NAME}.crt + + echo "Created ${MISC_DIR}/${ROOT_CERT_NAME}.der and ${MISC_DIR}/${ROOT_CERT_NAME}.key" +} + +function create_intermediate_cert() { + _check_openssl + _check_root_cert + + if [[ -f "${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.der" ]]; then + echo "Intermediate certificate already exists. Skipping creation." + return + fi + + openssl ecparam -name prime256v1 -genkey -noout -out ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.key + openssl req -new -key ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.key \ + -out ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.csr \ + -subj "/CN=Acme Gizmos" + openssl x509 -req -in ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.csr \ + -CA ${MISC_DIR}/${ROOT_CERT_NAME}.der \ + -CAkey ${MISC_DIR}/${ROOT_CERT_NAME}.key \ + -CAcreateserial \ + -out ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.crt \ + -days 3650 -sha256 + openssl x509 -in ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.crt \ + -outform der -out ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.der + rm -f ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.crt + + echo "Created ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.der and ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.key" +} + +function create_end_entity_cert() { + _check_openssl + _check_root_cert + + if ([[ -f "${MISC_DIR}/${END_ENTITY_CERT_NAME}.der" ]] && [[ -f "${MISC_DIR}/${END_ENTITY_CERT_NAME}.key" ]]); then + echo "End-entity certificate and key already exist. Skipping creation." + return + fi + + openssl ecparam -name prime256v1 -genkey -noout -out ${MISC_DIR}/${END_ENTITY_CERT_NAME}.key + openssl req -new -key ${MISC_DIR}/${END_ENTITY_CERT_NAME}.key \ + -out ${MISC_DIR}/${END_ENTITY_CERT_NAME}.csr \ + -subj "/CN=Acme Gizmo CoRIM signer" + openssl x509 -req -in ${MISC_DIR}/${END_ENTITY_CERT_NAME}.csr \ + -CA ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.der \ + -CAkey ${MISC_DIR}/${INTERMEDIATE_CERT_NAME}.key \ + -CAcreateserial \ + -out ${MISC_DIR}/${END_ENTITY_CERT_NAME}.crt \ + -days 1825 -sha256 \ + -CAform der + openssl x509 -in ${MISC_DIR}/${END_ENTITY_CERT_NAME}.crt \ + -outform der -out ${MISC_DIR}/${END_ENTITY_CERT_NAME}.der + rm -f ${MISC_DIR}/${END_ENTITY_CERT_NAME}.crt + + echo "Created ${MISC_DIR}/${END_ENTITY_CERT_NAME}.der and ${MISC_DIR}/${END_ENTITY_CERT_NAME}.key" +} + +function clean_certs_artifacts() { + pushd "$MISC_DIR" > /dev/null || exit 1 + echo "rm -f -- *.csr *.srl" + rm -f -- *.csr *.srl + popd > /dev/null || exit 1 +} + +function clean_cert() { + pushd "$MISC_DIR" > /dev/null || exit 1 + local cert="$1" + echo "rm -f \"${cert}.der\" \"${cert}.key\"" + rm -f "${cert}.der" "${cert}.key" + popd > /dev/null || exit 1 +} + +function clean_all() { + clean_certs_artifacts + clean_cert "$ROOT_CERT_NAME" + clean_cert "$INTERMEDIATE_CERT_NAME" + clean_cert "$END_ENTITY_CERT_NAME" +} + +function help() { + set +e + read -r -d '' usage <<-EOF + Usage: gen-certs [-h] [-C] [COMMAND] + + This script is used to (re-)generate certificates used for a veraison + deployment. The certificates are signed by a CA certificate called + ${ROOT_CERT_NAME}.crt. If this does not exist, a self-signed one will + be (re-)generated. + + Commands: + + create + Create the root, intermediate, and end-entity certificates. + + clean_certs_artifacts + Clean output artifacts for the certificates. + + clean_all + Clean both intermediate and output artifacts for everything (including + the root CA cert). + + help + Print this message and exit (same as -h option). + + Options: + + -h Print this message and exit. + -C Do not clean up intermediate artifacts (e.g., CSRs). + + Note: Regenerating the certificate chain is an exceptional action and should + only be done when necessary (e.g., when certificates expire). + +EOF + + echo "$usage" + set -e +} + +function _check_openssl() { + if [[ "$(which openssl 2>/dev/null)" == "" ]]; then + echo -e "ERROR: openssl executable must be installed to use this command." + exit 1 + fi +} + +function _check_root_cert() { + if [[ ! -f "${MISC_DIR}/${ROOT_CERT_NAME}.der" ]]; then + create_root_cert + fi +} + +_should_clean_certs_artifacts=true + +OPTIND=1 + +while getopts "hC" opt; do + case "$opt" in + h) help; exit 0;; + C) _should_clean_certs_artifacts=false;; + *) break;; + esac +done + +shift $((OPTIND-1)) +[ "${1:-}" = "--" ] && shift + +command=$1 +case $command in + help) + help + exit 0 + ;; + clean) + clean_certs_artifacts + ;; + clean_all) + clean_all + ;; + create) + create_root_cert + create_intermediate_cert + create_end_entity_cert + if [[ $_should_clean_certs_artifacts == true ]]; then + clean_certs_artifacts + fi + ;; + *) + echo -e "ERROR: unexpected command: \"$command\" (use -h for help)" + ;; +esac \ No newline at end of file