Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
apt update --fix-missing
apt install -y --no-install-recommends cmake ccache lcov \
libp11-kit-dev \
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip xxd
pip3 install reuse --break-system-packages
- name: Configure and build
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt update --fix-missing \
&& apt install -y --no-install-recommends cmake ccache lcov \
libp11-kit-dev \
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip \
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip xxd \
&& apt clean \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install reuse --break-system-packages
Expand Down
68 changes: 68 additions & 0 deletions tests/cmds/sign-cmd-pkeyutl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,76 @@ KEY="${P2C_CERT/.pem/.key}"
# Get the directory where the key is located
KEY_DIR=$(dirname "$KEY")

# PKCS#11 sends signature input for RSA in ASN.1 encoding
if (openssl asn1parse -inform DER -in "$P2C_DATA" 2> /dev/null) | grep -q 'SEQUENCE'; then
echo "$P2C_DATA ist ASN.1-coded extract raw data from DigestInfo"

openssl asn1parse -inform DER -in "$P2C_DATA"

hash_hex=$(openssl asn1parse -inform DER -in "$P2C_DATA" | awk '/OCTET STRING/ {sub(/^.*\[HEX DUMP\]:/, ""); print $0; exit}')
if [ ! -n "$hash_hex" ]; then
echo "Extraction failed"
openssl asn1parse -inform DER -in "$P2C_DATA"
exit 1
fi

echo "$hash_hex" | xxd -r -p > "${P2C_DATA}.raw"

if [ ! -s "${P2C_DATA}.raw" ]; then
echo "Extraction failed"
openssl asn1parse -inform DER -in "$P2C_DATA"
exit 1
fi

export P2C_DATA="${P2C_DATA}.raw"
fi

ls -l "$P2C_DATA"

# sign hashed data
openssl pkeyutl -sign -inkey "$KEY" -in "$P2C_DATA" -out "$P2C_SIG"

# Verify plain the signature
openssl pkeyutl -verify -certin -inkey $P2C_CERT -in $P2C_DATA -sigfile $P2C_SIG

# The signer returns the signature in ASN.1 format for ECDSA/EDDSA, and in DER format for RSA.
# The PKCS#11 expects the signature in DER format for RSA and in raw R|S for ECDSA/EDDSA.
if [ "$P2C_MECHANISM" == "CKM_ECDSA" ]; then
echo "Converting ECDSA signature from asn.1 to DER format"

# Determine curve from certificate if available
curve_bytes=32 # Default for P-256

if [ -f "${P2C_CERT}" ]; then
curve_info=$(openssl x509 -in "${P2C_CERT}" -text -noout | sed -n '/Public Key Algorithm/,/Signature Algorithm/p' | grep -E "(ASN1 OID|NIST CURVE|brainpool|secp|prime)")

if echo "$curve_info" | grep -q "brainpoolP512r1\|secp521r1"; then
curve_bytes=66 # P-521
echo "Detected P-521 curve"
elif echo "$curve_info" | grep -q "brainpoolP384r1\|secp384r1"; then
curve_bytes=48 # P-384
echo "Detected P-384 curve"
elif echo "$curve_info" | grep -q "brainpoolP256r1\|secp256r1\|prime256v1"; then
curve_bytes=32 # P-256
echo "Detected P-256 curve"
else
echo "Unknown curve, using default P-256"
fi

echo "Detected curve requiring $curve_bytes bytes per component"
fi
hex_chars=$((curve_bytes * 2))

# openssl asn1parse -inform DER -in $P2C_SIG

r=$(openssl asn1parse -inform DER -in $P2C_SIG | awk '/INTEGER/ {sub(/^.*:/,"",$0); print $0}' | head -1)
s=$(openssl asn1parse -inform DER -in $P2C_SIG | awk '/INTEGER/ {sub(/^.*:/,"",$0); print $0}' | tail -1)

# Use detected curve length for padding
printf "%0*s" "$hex_chars" "$r" | tr ' ' 0 | xxd -r -p > r.bin
printf "%0*s" "$hex_chars" "$s" | tr ' ' 0 | xxd -r -p > s.bin

cat r.bin s.bin > $P2C_SIG

rm r.bin s.bin
fi
27 changes: 27 additions & 0 deletions tests/test_ssh-keygen_export_ec_public_key.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
#
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: (C) 2025 Siemens
#
# Authors:
# Eugen Kremer <[email protected]>
#
#

set -e

source "$(dirname "${BASH_SOURCE[0]}")/common.sh"

PUBLIC_KEY_FILE="$TEST_WORK_DIR/$SCRIPT_NAME-my_ec_0"

export P2C_SLOT_CERT_0="$TEST_KEY_DIR/ec.pem"

ssh-keygen -D "$PKCS11_MODULE" > $PUBLIC_KEY_FILE.openssh.pub

# convert ssh public key to PEM format
ssh-keygen -e -m PKCS8 -f $PUBLIC_KEY_FILE.openssh.pub > $PUBLIC_KEY_FILE.pub

# extract public key from PEM file
openssl x509 -in "$P2C_SLOT_CERT_0" -pubkey -noout > $PUBLIC_KEY_FILE.original.pem

diff $PUBLIC_KEY_FILE.original.pem $PUBLIC_KEY_FILE.pub
36 changes: 36 additions & 0 deletions tests/test_ssh-keygen_sign_ec_sshcert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
#
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: (C) 2025 Siemens
#
# Authors:
# Eugen Kremer <[email protected]>
#
#

set -euo pipefail

source "$(dirname "$0")/common.sh"

cd "$TEST_WORK_DIR"

KEY_NAME="test_ssh_key"

# 1. generate SSH-Key to be signed
ssh-keygen -t rsa -b 2048 -N "" -f "$KEY_NAME" > /dev/null

export P2C_SLOT_CERT_0="$TEST_KEY_DIR/ec.pem" # this is our CA certificate
export P2C_CMD="$SCRIPT_DIR/cmds/sign-cmd-pkeyutl.sh"
export P2C_DATA="$TEST_WORK_DIR/data.bin"
export P2C_SIG="$TEST_WORK_DIR/sig.bin"

# 2. Export the public key of the signer certificate (CA) in OpenSSH format
ssh-keygen -D "$PKCS11_MODULE" > "$TEST_KEY_DIR/ec.openssh.pub"

# sign the public ssh key with private key of the CA
# ssh-keygen uses $TEST_KEY_DIR/ec.openssh.pub to find the matching private key in the PKCS#11 module
ssh-keygen -s "$TEST_KEY_DIR/ec.openssh.pub" -D "$PKCS11_MODULE" -I test_user -n testuser -V +1h -z 1 "$KEY_NAME.pub"

# print the signed certificate
echo "Signed SSH certificate:"
ssh-keygen -L -f "$KEY_NAME-cert.pub"