Skip to content

Commit d86afdb

Browse files
committed
test: add ssh-keygen export and sign tests for EC
Signed-off-by: Eugen Kremer <[email protected]>
1 parent e370ee1 commit d86afdb

File tree

6 files changed

+133
-2
lines changed

6 files changed

+133
-2
lines changed

.github/workflows/build-and-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
apt update --fix-missing
3030
apt install -y --no-install-recommends cmake ccache lcov \
3131
libp11-kit-dev \
32-
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip
32+
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip xxd
3333
pip3 install reuse --break-system-packages
3434
3535
- name: Configure and build

docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
1010
RUN apt update --fix-missing \
1111
&& apt install -y --no-install-recommends cmake ccache lcov \
1212
libp11-kit-dev \
13-
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip \
13+
bsdextrautils opensc libengine-pkcs11-openssl dumpasn1 gnutls-bin squashfs-tools rauc python3-pip xxd \
1414
&& apt clean \
1515
&& rm -rf /var/lib/apt/lists/* \
1616
&& pip3 install reuse --break-system-packages

tests/cmds/sign-cmd-pkeyutl.sh

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,76 @@ KEY="${P2C_CERT/.pem/.key}"
1919
# Get the directory where the key is located
2020
KEY_DIR=$(dirname "$KEY")
2121

22+
# PKCS#11 sends signature input for RSA in ASN.1 encoding
23+
if (openssl asn1parse -inform DER -in "$P2C_DATA" 2> /dev/null) | grep -q 'SEQUENCE'; then
24+
echo "$P2C_DATA ist ASN.1-coded extract raw data from DigestInfo"
25+
26+
openssl asn1parse -inform DER -in "$P2C_DATA"
27+
28+
hash_hex=$(openssl asn1parse -inform DER -in "$P2C_DATA" | awk '/OCTET STRING/ {sub(/^.*\[HEX DUMP\]:/, ""); print $0; exit}')
29+
if [ ! -n "$hash_hex" ]; then
30+
echo "Extraction failed"
31+
openssl asn1parse -inform DER -in "$P2C_DATA"
32+
exit 1
33+
fi
34+
35+
echo "$hash_hex" | xxd -r -p > "${P2C_DATA}.raw"
36+
37+
if [ ! -s "${P2C_DATA}.raw" ]; then
38+
echo "Extraction failed"
39+
openssl asn1parse -inform DER -in "$P2C_DATA"
40+
exit 1
41+
fi
42+
43+
export P2C_DATA="${P2C_DATA}.raw"
44+
fi
45+
46+
ls -l "$P2C_DATA"
47+
2248
# sign hashed data
2349
openssl pkeyutl -sign -inkey "$KEY" -in "$P2C_DATA" -out "$P2C_SIG"
2450

2551
# Verify plain the signature
2652
openssl pkeyutl -verify -certin -inkey $P2C_CERT -in $P2C_DATA -sigfile $P2C_SIG
53+
54+
# The signer returns the signature in ASN.1 format for ECDSA/EDDSA, and in DER format for RSA.
55+
# The PKCS#11 expects the signature in DER format for RSA and in raw R|S for ECDSA/EDDSA.
56+
if [ "$P2C_MECHANISM" == "CKM_ECDSA" ]; then
57+
echo "Converting ECDSA signature from asn.1 to DER format"
58+
59+
# Determine curve from certificate if available
60+
curve_bytes=32 # Default for P-256
61+
62+
if [ -f "${P2C_CERT}" ]; then
63+
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)")
64+
65+
if echo "$curve_info" | grep -q "brainpoolP512r1\|secp521r1"; then
66+
curve_bytes=66 # P-521
67+
echo "Detected P-521 curve"
68+
elif echo "$curve_info" | grep -q "brainpoolP384r1\|secp384r1"; then
69+
curve_bytes=48 # P-384
70+
echo "Detected P-384 curve"
71+
elif echo "$curve_info" | grep -q "brainpoolP256r1\|secp256r1\|prime256v1"; then
72+
curve_bytes=32 # P-256
73+
echo "Detected P-256 curve"
74+
else
75+
echo "Unknown curve, using default P-256"
76+
fi
77+
78+
echo "Detected curve requiring $curve_bytes bytes per component"
79+
fi
80+
hex_chars=$((curve_bytes * 2))
81+
82+
# openssl asn1parse -inform DER -in $P2C_SIG
83+
84+
r=$(openssl asn1parse -inform DER -in $P2C_SIG | awk '/INTEGER/ {sub(/^.*:/,"",$0); print $0}' | head -1)
85+
s=$(openssl asn1parse -inform DER -in $P2C_SIG | awk '/INTEGER/ {sub(/^.*:/,"",$0); print $0}' | tail -1)
86+
87+
# Use detected curve length for padding
88+
printf "%0*s" "$hex_chars" "$r" | tr ' ' 0 | xxd -r -p > r.bin
89+
printf "%0*s" "$hex_chars" "$s" | tr ' ' 0 | xxd -r -p > s.bin
90+
91+
cat r.bin s.bin > $P2C_SIG
92+
93+
rm r.bin s.bin
94+
fi
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/bash
2+
#
3+
# SPDX-License-Identifier: MIT
4+
# SPDX-FileCopyrightText: (C) 2025 Siemens
5+
#
6+
# Authors:
7+
# Eugen Kremer <[email protected]>
8+
#
9+
#
10+
11+
set -e
12+
13+
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
14+
15+
PUBLIC_KEY_FILE="$TEST_WORK_DIR/$SCRIPT_NAME-my_ec_0"
16+
17+
export P2C_SLOT_CERT_0="$TEST_KEY_DIR/ec.pem"
18+
19+
ssh-keygen -D "$PKCS11_MODULE" > $PUBLIC_KEY_FILE.openssh.pub
20+
21+
# convert ssh public key to PEM format
22+
ssh-keygen -e -m PKCS8 -f $PUBLIC_KEY_FILE.openssh.pub > $PUBLIC_KEY_FILE.pub
23+
24+
# extract public key from PEM file
25+
openssl x509 -in "$P2C_SLOT_CERT_0" -pubkey -noout > $PUBLIC_KEY_FILE.original.pem
26+
27+
diff $PUBLIC_KEY_FILE.original.pem $PUBLIC_KEY_FILE.pub
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
#
3+
# SPDX-License-Identifier: MIT
4+
# SPDX-FileCopyrightText: (C) 2025 Siemens
5+
#
6+
# Authors:
7+
# Eugen Kremer <[email protected]>
8+
#
9+
#
10+
11+
set -euo pipefail
12+
13+
source "$(dirname "$0")/common.sh"
14+
15+
cd "$TEST_WORK_DIR"
16+
17+
KEY_NAME="test_ssh_key"
18+
19+
# 1. generate SSH-Key to be signed
20+
ssh-keygen -t rsa -b 2048 -N "" -f "$KEY_NAME" > /dev/null
21+
22+
export P2C_SLOT_CERT_0="$TEST_KEY_DIR/ec.pem" # this is our CA certificate
23+
export P2C_CMD="$SCRIPT_DIR/cmds/sign-cmd-pkeyutl.sh"
24+
export P2C_DATA="$TEST_WORK_DIR/data.bin"
25+
export P2C_SIG="$TEST_WORK_DIR/sig.bin"
26+
27+
# 2. Export the public key of the signer certificate (CA) in OpenSSH format
28+
ssh-keygen -D "$PKCS11_MODULE" > "$TEST_KEY_DIR/ec.openssh.pub"
29+
30+
# sign the public ssh key with private key of the CA
31+
# ssh-keygen uses $TEST_KEY_DIR/ec.openssh.pub to find the matching private key in the PKCS#11 module
32+
ssh-keygen -s "$TEST_KEY_DIR/ec.openssh.pub" -D "$PKCS11_MODULE" -I test_user -n testuser -V +1h -z 1 "$KEY_NAME.pub"
33+
34+
# print the signed certificate
35+
echo "Signed SSH certificate:"
36+
ssh-keygen -L -f "$KEY_NAME-cert.pub"
File renamed without changes.

0 commit comments

Comments
 (0)