mirror of https://github.com/wolfSSL/wolfBoot.git
268 lines
9.6 KiB
Bash
Executable File
268 lines
9.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Certificate Chain Generation Script (ECC P256 or RSA)
|
|
# Creates a certificate chain with root, intermediate, and leaf
|
|
# Outputs DER format files plus C arrays for embedding
|
|
# Optional: Use existing leaf private key with --leaf <file> argument
|
|
|
|
set -e # Exit on any error
|
|
|
|
# Default output directory and algorithm
|
|
OUTPUT_DIR="test-dummy-ca"
|
|
ALGO="ecc256" # Default to ECC P-256 keys
|
|
|
|
# Helper functions for key operations
|
|
generate_private_key() {
|
|
local output_file=$1
|
|
|
|
if [[ "$ALGO" == "ecc256" ]]; then
|
|
openssl ecparam -genkey -name prime256v1 -noout -out "$output_file"
|
|
elif [[ "$ALGO" == "rsa2048" ]]; then
|
|
openssl genrsa -out "$output_file" 2048
|
|
elif [[ "$ALGO" == "rsa4096" ]]; then
|
|
openssl genrsa -out "$output_file" 4096
|
|
fi
|
|
}
|
|
|
|
convert_key_to_der() {
|
|
local input_file=$1
|
|
local output_file=$2
|
|
|
|
if [[ "$ALGO" == "ecc256" ]]; then
|
|
openssl ec -in "$input_file" -outform DER -out "$output_file"
|
|
elif [[ "$ALGO" == "rsa2048" || "$ALGO" == "rsa4096" ]]; then
|
|
openssl rsa -in "$input_file" -outform DER -out "$output_file"
|
|
fi
|
|
}
|
|
|
|
extract_public_key() {
|
|
local cert_file=$1
|
|
local pubkey_pem=$2
|
|
local pubkey_der=$3
|
|
|
|
# Extract public key from certificate (same for both algos)
|
|
openssl x509 -in "$cert_file" -pubkey -noout > "$pubkey_pem"
|
|
|
|
# Convert public key to DER format
|
|
if [[ "$ALGO" == "ecc256" ]]; then
|
|
openssl ec -pubin -in "$pubkey_pem" -outform DER -out "$pubkey_der"
|
|
elif [[ "$ALGO" == "rsa2048" || "$ALGO" == "rsa4096" ]]; then
|
|
openssl rsa -pubin -in "$pubkey_pem" -outform DER -out "$pubkey_der"
|
|
fi
|
|
}
|
|
|
|
validate_key_format() {
|
|
local key_file=$1
|
|
|
|
if [[ "$ALGO" == "ecc256" ]]; then
|
|
openssl ec -in "$key_file" -noout
|
|
elif [[ "$ALGO" == "rsa2048" || "$ALGO" == "rsa4096" ]]; then
|
|
openssl rsa -in "$key_file" -noout
|
|
fi
|
|
}
|
|
|
|
# Parse command line arguments
|
|
LEAF_KEY_FILE=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--leaf)
|
|
LEAF_KEY_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--outdir)
|
|
OUTPUT_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--algo)
|
|
ALGO="$2"
|
|
if [[ "$ALGO" != "ecc256" && "$ALGO" != "rsa2048" && "$ALGO" != "rsa4096" ]]; then
|
|
echo "Invalid algorithm: $ALGO. Use 'ecc256', 'rsa2048', or 'rsa4096'"
|
|
exit 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
echo "Usage: $0 [--leaf <private_key_file>] [--outdir <output_directory>] [--algo <ecc256|rsa2048|rsa4096>]"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Configuration
|
|
ROOT_SUBJECT="/C=US/ST=California/L=San Francisco/O=MyOrganization/OU=Root CA/CN=My Root CA"
|
|
INTERMEDIATE_SUBJECT="/C=US/ST=California/L=San Francisco/O=MyOrganization/OU=Intermediate CA/CN=My Intermediate CA"
|
|
LEAF_SUBJECT="/C=US/ST=California/L=San Francisco/O=MyOrganization/OU=Services/CN=service.example.com"
|
|
|
|
# Create directory structure
|
|
echo "Creating directory structure..."
|
|
mkdir -p ${OUTPUT_DIR}/temp
|
|
|
|
##################
|
|
# GENERATE CHAIN
|
|
##################
|
|
echo "Generating Certificate Chain using $ALGO..."
|
|
|
|
# Step 1: Generate Root key and certificate
|
|
echo "Generating Root CA..."
|
|
generate_private_key "${OUTPUT_DIR}/temp/root.key.pem"
|
|
|
|
# Create PEM format root certificate (temporary)
|
|
openssl req -new -x509 -days 3650 -sha256 \
|
|
-key ${OUTPUT_DIR}/temp/root.key.pem \
|
|
-out ${OUTPUT_DIR}/temp/root.crt.pem \
|
|
-subj "$ROOT_SUBJECT" \
|
|
-addext "basicConstraints=critical,CA:TRUE" \
|
|
-addext "keyUsage=critical,keyCertSign,cRLSign,digitalSignature"
|
|
|
|
# Convert root key and certificate to DER format
|
|
convert_key_to_der "${OUTPUT_DIR}/temp/root.key.pem" "${OUTPUT_DIR}/root-prvkey.der"
|
|
openssl x509 -in ${OUTPUT_DIR}/temp/root.crt.pem -outform DER -out ${OUTPUT_DIR}/root-cert.der
|
|
|
|
# Step 2: Generate Intermediate key and CSR
|
|
echo "Generating Intermediate CA..."
|
|
generate_private_key "${OUTPUT_DIR}/temp/intermediate.key.pem"
|
|
|
|
openssl req -new -sha256 \
|
|
-key ${OUTPUT_DIR}/temp/intermediate.key.pem \
|
|
-out ${OUTPUT_DIR}/temp/intermediate.csr \
|
|
-subj "$INTERMEDIATE_SUBJECT"
|
|
|
|
# Step 3: Sign Intermediate certificate with Root
|
|
openssl x509 -req -days 1825 -sha256 \
|
|
-in ${OUTPUT_DIR}/temp/intermediate.csr \
|
|
-out ${OUTPUT_DIR}/temp/intermediate.crt.pem \
|
|
-CA ${OUTPUT_DIR}/temp/root.crt.pem \
|
|
-CAkey ${OUTPUT_DIR}/temp/root.key.pem \
|
|
-CAcreateserial \
|
|
-extfile <(printf "basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign,digitalSignature")
|
|
|
|
# Convert intermediate key and certificate to DER format
|
|
convert_key_to_der "${OUTPUT_DIR}/temp/intermediate.key.pem" "${OUTPUT_DIR}/intermediate-prvkey.der"
|
|
openssl x509 -in ${OUTPUT_DIR}/temp/intermediate.crt.pem -outform DER -out ${OUTPUT_DIR}/intermediate-cert.der
|
|
|
|
# Step 4: Handle Leaf key (generate or use existing)
|
|
echo "Handling Leaf Certificate..."
|
|
if [ -z "$LEAF_KEY_FILE" ]; then
|
|
echo "Generating new leaf private key..."
|
|
generate_private_key "${OUTPUT_DIR}/temp/leaf.key.pem"
|
|
else
|
|
echo "Using provided leaf private key: $LEAF_KEY_FILE"
|
|
cp "$LEAF_KEY_FILE" ${OUTPUT_DIR}/temp/leaf.key.pem
|
|
# Ensure the key file is in the right format
|
|
validate_key_format "${OUTPUT_DIR}/temp/leaf.key.pem"
|
|
fi
|
|
|
|
# Create CSR for leaf certificate
|
|
openssl req -new -sha256 \
|
|
-key ${OUTPUT_DIR}/temp/leaf.key.pem \
|
|
-out ${OUTPUT_DIR}/temp/leaf.csr \
|
|
-subj "$LEAF_SUBJECT"
|
|
|
|
# Step 5: Sign Leaf certificate with Intermediate
|
|
openssl x509 -req -days 365 -sha256 \
|
|
-in ${OUTPUT_DIR}/temp/leaf.csr \
|
|
-out ${OUTPUT_DIR}/temp/leaf.crt.pem \
|
|
-CA ${OUTPUT_DIR}/temp/intermediate.crt.pem \
|
|
-CAkey ${OUTPUT_DIR}/temp/intermediate.key.pem \
|
|
-CAcreateserial \
|
|
-extfile <(printf "basicConstraints=CA:FALSE\nkeyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth")
|
|
|
|
# Convert leaf key and certificate to DER format
|
|
convert_key_to_der "${OUTPUT_DIR}/temp/leaf.key.pem" "${OUTPUT_DIR}/leaf-prvkey.der"
|
|
openssl x509 -in ${OUTPUT_DIR}/temp/leaf.crt.pem -outform DER -out ${OUTPUT_DIR}/leaf-cert.der
|
|
|
|
# Extract the public key from leaf certificate in DER format
|
|
echo "Extracting public key from leaf certificate..."
|
|
extract_public_key "${OUTPUT_DIR}/temp/leaf.crt.pem" "${OUTPUT_DIR}/temp/leaf_pubkey.pem" "${OUTPUT_DIR}/leaf-pubkey.der"
|
|
|
|
# Create raw DER format certificate chain
|
|
cat ${OUTPUT_DIR}/intermediate-cert.der ${OUTPUT_DIR}/leaf-cert.der > ${OUTPUT_DIR}/raw-chain.der
|
|
|
|
##################################
|
|
# GENERATE C ARRAYS FOR EMBEDDING
|
|
##################################
|
|
echo "Generating C arrays for embedding in programs..."
|
|
|
|
# Create a header file for certificates
|
|
HEADER_FILE="${OUTPUT_DIR}/gen_certificates.h"
|
|
|
|
# Initialize the header file with header guards and includes
|
|
cat > "${HEADER_FILE}" << 'EOT'
|
|
/*
|
|
* Certificate arrays for embedded SSL/TLS applications
|
|
* Generated by OpenSSL certificate chain script
|
|
*/
|
|
|
|
#ifndef GEN_CERTIFICATES_H
|
|
#define GEN_CERTIFICATES_H
|
|
|
|
#include <stddef.h>
|
|
|
|
EOT
|
|
|
|
# Function to append a certificate array to the header file
|
|
append_cert_array() {
|
|
local infile=$1
|
|
local arrayname=$2
|
|
local description=$3
|
|
|
|
echo "/* ${description} */" >> "${HEADER_FILE}"
|
|
echo "const unsigned char ${arrayname}[] = {" >> "${HEADER_FILE}"
|
|
|
|
# Use xxd instead of hexdump for more reliable output
|
|
xxd -i < "${infile}" | grep -v "unsigned char" | grep -v "unsigned int" | \
|
|
sed 's/ 0x/0x/g' >> "${HEADER_FILE}"
|
|
|
|
echo "};" >> "${HEADER_FILE}"
|
|
echo "const size_t ${arrayname}_len = sizeof(${arrayname});" >> "${HEADER_FILE}"
|
|
echo "" >> "${HEADER_FILE}"
|
|
}
|
|
|
|
### Add certificates to the header file
|
|
echo "/* Certificates */" >> "${HEADER_FILE}"
|
|
append_cert_array "${OUTPUT_DIR}/root-cert.der" "ROOT_CERT" "Root CA Certificate (DER format)"
|
|
append_cert_array "${OUTPUT_DIR}/intermediate-cert.der" "INTERMEDIATE_CERT" "Intermediate CA Certificate (DER format)"
|
|
append_cert_array "${OUTPUT_DIR}/leaf-cert.der" "LEAF_CERT" "Leaf/Server Certificate (DER format)"
|
|
append_cert_array "${OUTPUT_DIR}/raw-chain.der" "RAW_CERT_CHAIN" "Raw Certificate Chain (Intermediate+Leaf) (DER format)"
|
|
# Add leaf certificate public key
|
|
append_cert_array "${OUTPUT_DIR}/leaf-pubkey.der" "LEAF_PUBKEY" "Leaf Certificate Public Key (DER format)"
|
|
|
|
# Close the header guard
|
|
echo "#endif /* GEN_CERTIFICATES_H */" >> "${HEADER_FILE}"
|
|
|
|
echo "Generated C header file with certificate arrays: ${HEADER_FILE}"
|
|
|
|
# Display verification information
|
|
echo ""
|
|
echo "=== Certificate Chain Generation Complete ==="
|
|
echo ""
|
|
|
|
# Verify Chain
|
|
echo "=== Verifying Certificate Chain ==="
|
|
echo "Verifying intermediate certificate against root:"
|
|
openssl verify -CAfile ${OUTPUT_DIR}/temp/root.crt.pem ${OUTPUT_DIR}/temp/intermediate.crt.pem
|
|
|
|
echo ""
|
|
echo "Verifying leaf certificate against intermediate and root:"
|
|
openssl verify -CAfile ${OUTPUT_DIR}/temp/root.crt.pem -untrusted ${OUTPUT_DIR}/temp/intermediate.crt.pem ${OUTPUT_DIR}/temp/leaf.crt.pem
|
|
|
|
# Display generated files summary
|
|
echo ""
|
|
echo "=== Generated Files Summary ==="
|
|
echo ""
|
|
echo "DER Format (Algorithm: $ALGO):"
|
|
echo " Root CA certificate: ${OUTPUT_DIR}/root-cert.der"
|
|
echo " Root CA key: ${OUTPUT_DIR}/root-prvkey.der"
|
|
echo " Intermediate certificate: ${OUTPUT_DIR}/intermediate-cert.der"
|
|
echo " Intermediate key: ${OUTPUT_DIR}/intermediate-prvkey.der"
|
|
echo " Leaf certificate: ${OUTPUT_DIR}/leaf-cert.der"
|
|
echo " Leaf key: ${OUTPUT_DIR}/leaf-prvkey.der"
|
|
echo " Raw chain: ${OUTPUT_DIR}/raw-chain.der"
|
|
echo " Leaf public key: ${OUTPUT_DIR}/leaf-pubkey.der"
|
|
echo ""
|
|
echo "C Header file:"
|
|
echo " Certificate arrays: ${OUTPUT_DIR}/gen_certificates.h"
|
|
|
|
# Clean up temporary files
|
|
rm -rf ${OUTPUT_DIR}/temp ${OUTPUT_DIR}/root.srl ${OUTPUT_DIR}/intermediate.srl
|