Skip to content

Commit d994026

Browse files
vdukhovnihs-viktor
andauthored
Refined compat matrix for certs_r5 (#189)
There are multiple artefacts/tests for each OID, so need an additional CSV column to show the tested artefact. The new "consistent" entry means that at least two public keys were found between any certificate and provided private keys and all matched. Simplest are the SLH-DSA cases, with just one "priv" key format, and one self-signed "cert". key_algorithm_oid,type,test_result 2.16.840.1.101.3.4.3.20,priv,Y 2.16.840.1.101.3.4.3.20,cert,Y 2.16.840.1.101.3.4.3.20,consistent,Y ... Then for ML-DSA we have three key formats and a self-signed cert: 2.16.840.1.101.3.4.3.17,seed,Y 2.16.840.1.101.3.4.3.17,expandedkey,Y 2.16.840.1.101.3.4.3.17,both,Y 2.16.840.1.101.3.4.3.17,cert,Y 2.16.840.1.101.3.4.3.17,consistent,Y ... Then for ML-KEM we have three key formats and an EE cert signed by the corresponding ML-DSA TA. Each private key is tested against the encapsulation ciphertext and expected shared secret, if provided. 2.16.840.1.101.3.4.4.1,seed,Y 2.16.840.1.101.3.4.4.1,expandedkey,Y 2.16.840.1.101.3.4.4.1,both,Y 2.16.840.1.101.3.4.4.1,cert,Y 2.16.840.1.101.3.4.4.1,consistent,Y ... -- Viktor. Co-authored-by: Viktor Dukhovni <ietf-dane@dukhovni.org>
1 parent e8637f3 commit d994026

File tree

2 files changed

+161
-199
lines changed

2 files changed

+161
-199
lines changed

providers/ossl35/check_certs.sh

+94-180
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,90 @@
11
#! /usr/bin/env bash
22

3-
die() { printf "$@" >&2; exit 1; }
3+
warn() { printf "$@" >&2; }
4+
die() { warn "$@"; exit 1; }
45
if [[ $# != 1 ]]; then die 'Usage: %s <zipfile>\n' "$0"; fi
6+
xxd -p </dev/null || die 'Missing xxd command\n'
7+
8+
case $(openssl version -v) in
9+
"OpenSSL 3.5".*) : ;;
10+
*) die 'Unsupported OpenSSL version\n';;
11+
esac
12+
13+
set -o pipefail
14+
shopt -s nullglob
515

616
tmp=$(mktemp -t -d)
717
trap 'e=$?; rm -rf ${tmp}; exit $e' EXIT HUP INT TERM
818
unzip -qq -j -d "$tmp" "$1" || die 'Error unzipping %s\n' "$1"
919

1020
ptext="${tmp}/plaintext"
1121
printf "Attack at dawn\n" > "$ptext"
12-
sigfile="${tmp}/sig.dat"
22+
23+
check_keys() {
24+
local oid=$1
25+
local -a pubs
26+
if [[ $# -lt 2 ]]; then warn 'Usage: check_keys <oid> <form> ...\n'; return 1; fi
27+
shift
28+
29+
for form in "$@"
30+
do
31+
case $form in
32+
priv|ee|ta) set -- "$tmp"/*-"${oid}_${form}.der";;
33+
ss|ciphertext) set -- "$tmp"/*-"${oid}_${form}.bin";;
34+
pubs) set -- pubs;;
35+
*) set -- "$tmp"/*-"${oid}_${form}_priv.der";;
36+
esac
37+
if [[ $# -eq 0 ]]; then continue; fi
38+
if [[ $# -ne 1 ]]; then
39+
warn 'Too many inputs match %s for %s\n' \
40+
"$form" "${oid}"
41+
continue
42+
fi
43+
obj=$1
44+
pubout="$tmp/${oid}_${form}_pub.der"
45+
/bin/rm -f "$pubout"
46+
case $form in
47+
ss) ss_file=$obj;;
48+
ciphertext) ct_file=$obj;;
49+
pubs)
50+
if [[ "${#pubs[@]}" -gt 1 ]]; then
51+
uniq=$(for dgst in "${pubs[@]}"; do printf "%s\n" "$dgst"; done | sort -u | wc -l) &&
52+
[[ $uniq -eq 1 ]] &&
53+
printf "%s,%s,%s\n" "${oid}" "consistent" "Y" ||
54+
printf "%s,%s,%s\n" "${oid}" "consistent" "N"
55+
fi;;
56+
ta) openssl x509 -in "$obj" -pubkey -noout |
57+
openssl pkey -pubin -pubout -outform DER -out "$pubout" &&
58+
openssl verify -verify_depth 0 -trusted "$obj" "$obj" >/dev/null &&
59+
ta_file="$obj" &&
60+
dgst=$(openssl dgst -sha256 -binary < "$pubout" | xxd -p -c32) &&
61+
pubs=("${pubs[@]}" "$dgst") &&
62+
printf "%s,%s,%s\n" "${oid}" "cert" "Y" ||
63+
printf "%s,%s,%s\n" "${oid}" "cert" "N";;
64+
ee) openssl x509 -in "$obj" -pubkey -noout |
65+
openssl pkey -pubin -pubout -outform DER -out "$pubout" &&
66+
openssl verify -verify_depth 0 -trusted "$ta_file" "$obj" >/dev/null &&
67+
dgst=$(openssl dgst -sha256 -binary < "$pubout" | xxd -p -c32) &&
68+
pubs=("${pubs[@]}" "$dgst") &&
69+
printf "%s,%s,%s\n" "${oid}" "cert" "Y" ||
70+
printf "%s,%s,%s\n" "${oid}" "cert" "N";;
71+
*) openssl pkey -in "$obj" -pubout -outform DER -out "$pubout" &&
72+
if [[ -n "$sigfile" ]]; then
73+
openssl pkeyutl -sign -rawin -inkey "$obj" -in "$ptext" -out "$sigfile" &&
74+
openssl pkeyutl -verify -rawin -in "$ptext" -pubin -inkey "$pubout" \
75+
-sigfile "$sigfile" >/dev/null
76+
elif [[ -n "$ct_file" && -n "$ss_file" ]]; then
77+
cmp -s "$ss_file" <(
78+
openssl pkeyutl -decap -inkey "$obj" -in "$ct_file" -secret /dev/stdout)
79+
fi &&
80+
dgst=$(openssl dgst -sha256 -binary < "$pubout" | xxd -p -c32) &&
81+
pubs=("${pubs[@]}" "$dgst") &&
82+
printf "%s,%s,%s\n" "${oid}" "$form" "Y" ||
83+
printf "%s,%s,%s\n" "${oid}" "$form" "N"
84+
;;
85+
esac
86+
done
87+
}
1388

1489
mldsa_oids=(2.16.840.1.101.3.4.3.{17,18,19})
1590
mlkem_oids=(2.16.840.1.101.3.4.4.{1,2,3})
@@ -19,185 +94,24 @@ slh3s_oids=(2.16.840.1.101.3.4.3.{26,28,30})
1994
slh3f_oids=(2.16.840.1.101.3.4.3.{27,29,31})
2095
while [[ ${#mldsa_oids[@]} -gt 0 ]]
2196
do
22-
#
23-
# ML-DSA
24-
#
25-
(
26-
set -e
27-
set -o pipefail
28-
shopt -s nullglob
29-
pubs=()
30-
set -- "$tmp"/*-"${mldsa_oids[0]}"_*.der
31-
if [[ $# -eq 0 ]]; then exit 2; fi
32-
for form in seed expandedkey both ta
33-
do
34-
pubout="$tmp/${mldsa_oids[0]}_${form}_pub.der"
35-
/bin/rm -f "$pubout"
36-
count=0
37-
for obj in "$tmp"/*-"${mldsa_oids[0]}_${form}"*.der
38-
do
39-
if [[ $count > 0 ]]; then
40-
die 'Too many inputs match %s for %s\n'
41-
"$form" "${mldsa_oids[0]}"
42-
fi
43-
case $form in
44-
ta) openssl x509 -in "$obj" -pubkey -noout |
45-
openssl pkey -pubin -pubout -outform DER -out "$pubout"
46-
openssl verify -verify_depth 0 -trusted "$obj" "$obj" >/dev/null
47-
;;
48-
*) openssl pkey -in "$obj" -pubout -outform DER -out "$pubout"
49-
openssl pkeyutl -sign -rawin -inkey "$obj" -in "$ptext" -out "$sigfile"
50-
openssl pkeyutl -verify -rawin -in "$ptext" -pubin -inkey "$pubout" \
51-
-sigfile "$sigfile" >/dev/null ||
52-
die 'Signature verification failed for %s %s\n' \
53-
"$form" "${mldsa_oids[0]}"
54-
;;
55-
esac
56-
dgst=$(openssl dgst -sha256 -binary < "$pubout" | xxd -p -c32)
57-
pubs=("${pubs[@]}" "$dgst")
58-
count=$((count + 1))
59-
done
60-
if [[ $count -ne 1 ]]; then
61-
die 'Missing key form %s for %s\n' \
62-
"$form" "${mldsa_oids[0]}"
63-
fi
64-
done
65-
uniq=$(for dgst in "${pubs[@]}"; do printf "%s\n" "$dgst"; done | sort -u | wc -l)
66-
if [[ $uniq -ne 1 ]]; then
67-
die 'Multiple distinct pubkeys for %s\n' \
68-
"${mldsa_oids[0]}"
69-
fi
70-
)
71-
case $? in
72-
0) printf "%s,%s\n" "${mldsa_oids[0]}" "Y";;
73-
1) printf "%s,%s\n" "${mldsa_oids[0]}" "N";;
74-
*) : ignored ;;
75-
esac
97+
ta_file=
98+
ss_file=
99+
ct_file=
100+
sigfile="${tmp}/sig.dat"
76101

77-
#
78-
# SLH-DSA
79-
#
80-
for oid in \
81-
"${slh2f_oids[0]}" "${slh2s_oids[0]}" \
82-
"${slh3f_oids[0]}" "${slh3s_oids[0]}"
83-
do
84-
(
85-
set -e
86-
set -o pipefail
87-
shopt -s nullglob
88-
count=0
89-
for obj in "$tmp"/*-"${oid}_ta.der"
90-
do
91-
if [[ $count > 0 ]]; then
92-
die 'Too many inputs for %s\n' "${oid}"
93-
fi
94-
openssl verify -verify_depth 0 -trusted "$obj" "$obj" >/dev/null
95-
count=$((count + 1))
96-
done
97-
if [[ $count -eq 0 ]]; then exit 2; fi
98-
)
99-
case $? in
100-
0) printf "%s,%s\n" "${oid}" "Y";;
101-
1) printf "%s,%s\n" "${oid}" "N";;
102-
*) : ignored ;;
103-
esac
104-
done
102+
for oid in "${slh2f_oids[0]}" "${slh2s_oids[0]}" \
103+
"${slh3f_oids[0]}" "${slh3s_oids[0]}"
104+
do check_keys "$oid" priv ta pubs; done
105105

106-
#
107-
# ML-KEM
108-
#
109-
(
110-
set -e
111-
set -o pipefail
112-
shopt -s nullglob
113-
set -- "$tmp"/*-"${mlkem_oids[0]}"_*.der
114-
if [[ $# -eq 0 ]]; then exit 2; fi
115-
count=0; for ta in "$tmp"/*-"${mldsa_oids[0]}_ta.der"
116-
do
117-
if [[ $count > 0 ]]; then
118-
die 'Too many TA files for %s\n' \
119-
"${mldsa_oids[0]}"
120-
fi
121-
count=$((count + 1))
122-
done
123-
count=0; for ct in "$tmp"/*-"${mlkem_oids[0]}_ciphertext.bin"
124-
do
125-
if [[ $count > 0 ]]; then
126-
die 'Too many ciphertext files for %s\n' \
127-
"${mlkem_oids[0]}"
128-
fi
129-
count=$((count + 1))
130-
done
131-
if [[ $count -ne 1 ]]; then
132-
die 'No ciphertext file for %s\n' \
133-
"${mlkem_oids[0]}"
134-
fi
135-
count=0; for ss in "$tmp"/*-"${mlkem_oids[0]}_ss.bin"
136-
do
137-
if [[ $count > 0 ]]; then
138-
die 'Too many shared secret files for %s\n' \
139-
"${mlkem_oids[0]}"
140-
fi
141-
count=$((count + 1))
142-
done
143-
if [[ $count -ne 1 ]]; then
144-
die 'No shared secret file for %s\n' \
145-
"${mlkem_oids[0]}"
146-
fi
147-
pubs=()
148-
for form in seed expandedkey both ee
149-
do
150-
pubout="$tmp/${mlkem_oids[0]}_${form}_pub.der"
151-
/bin/rm -f "$pubout"
152-
count=0; for obj in "$tmp"/*-"${mlkem_oids[0]}_${form}"*.der
153-
do
154-
if [[ $count > 0 ]]; then
155-
die 'Too many inputs match %s for %s\n' \
156-
"$form" "${mlkem_oids[0]}"
157-
fi
158-
case $form in
159-
ee) openssl x509 -in "$obj" -pubkey -noout |
160-
openssl pkey -pubin -pubout -outform DER -out "$pubout"
161-
openssl verify -verify_depth 0 -trusted "$ta" "$obj" >/dev/null
162-
;;
163-
*) openssl pkey -in "$obj" -pubout -outform DER -out "$pubout"
164-
cmp -s "$ss" <(
165-
openssl pkeyutl -decap -inkey "$obj" -in "$ct" -secret /dev/stdout) ||
166-
die 'Shared secret mismatch for %s of %s\n' \
167-
"$form" "${mlkem_names[0]}"
168-
;;
169-
esac
170-
dgst=$(openssl dgst -sha256 -binary < "$pubout" | xxd -p -c32)
171-
pubs=("${pubs[@]}" "$dgst")
172-
count=$((count + 1))
173-
done
174-
if [[ $count -ne 1 ]]; then
175-
die 'Missing key form %s for %s\n' \
176-
"$form" "${mlkem_oids[0]}"
177-
fi
178-
done
179-
uniq=$(for dgst in "${pubs[@]}"; do printf "%s\n" "$dgst"; done | sort -u | wc -l)
180-
if [[ $uniq -ne 1 ]]; then
181-
die 'Multiple distinct pubkeys for %s\n' \
182-
"${mlkem_oids[0]}"
183-
fi
184-
)
185-
case $? in
186-
0) printf "%s,%s\n" "${mldsa_oids[0]}" "Y";;
187-
1) printf "%s,%s\n" "${mldsa_oids[0]}" "N";;
188-
*) : ignored ;;
189-
esac
106+
# Must run just before ML-KEM to set correct ta_file
107+
check_keys "${mldsa_oids[0]}" seed expandedkey both ta pubs
108+
sigfile=
109+
check_keys "${mlkem_oids[0]}" ss ciphertext seed expandedkey both ee pubs
190110

191-
unset "mldsa_oids[0]"
192-
unset "mlkem_oids[0]"
193-
unset "slh2f_oids[0]"
194-
unset "slh2s_oids[0]"
195-
unset "slh3f_oids[0]"
196-
unset "slh3s_oids[0]"
197-
mldsa_oids=( "${mldsa_oids[@]}")
198-
mlkem_oids=( "${mlkem_oids[@]}")
199-
slh2f_oids=( "${slh2f_oids[@]}")
200-
slh2s_oids=( "${slh2s_oids[@]}")
201-
slh3f_oids=( "${slh3f_oids[@]}")
202-
slh3s_oids=( "${slh3s_oids[@]}")
111+
unset "mldsa_oids[0]"; mldsa_oids=("${mldsa_oids[@]}")
112+
unset "mlkem_oids[0]"; mlkem_oids=("${mlkem_oids[@]}")
113+
unset "slh2f_oids[0]"; slh2f_oids=("${slh2f_oids[@]}")
114+
unset "slh2s_oids[0]"; slh2s_oids=("${slh2s_oids[@]}")
115+
unset "slh3f_oids[0]"; slh3f_oids=("${slh3f_oids[@]}")
116+
unset "slh3s_oids[0]"; slh3s_oids=("${slh3s_oids[@]}")
203117
done
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,67 @@
1-
key_algorithm_oid,test_result
2-
2.16.840.1.101.3.4.3.17,Y
3-
2.16.840.1.101.3.4.3.21,Y
4-
2.16.840.1.101.3.4.3.20,Y
5-
2.16.840.1.101.3.4.3.27,Y
6-
2.16.840.1.101.3.4.3.26,Y
7-
2.16.840.1.101.3.4.4.1,Y
8-
2.16.840.1.101.3.4.3.18,Y
9-
2.16.840.1.101.3.4.3.23,Y
10-
2.16.840.1.101.3.4.3.22,Y
11-
2.16.840.1.101.3.4.3.29,Y
12-
2.16.840.1.101.3.4.3.28,Y
13-
2.16.840.1.101.3.4.4.2,Y
14-
2.16.840.1.101.3.4.3.19,Y
15-
2.16.840.1.101.3.4.3.25,Y
16-
2.16.840.1.101.3.4.3.24,Y
17-
2.16.840.1.101.3.4.3.31,Y
18-
2.16.840.1.101.3.4.3.30,Y
19-
2.16.840.1.101.3.4.4.3,Y
1+
key_algorithm_oid,type,test_result
2+
2.16.840.1.101.3.4.3.21,priv,Y
3+
2.16.840.1.101.3.4.3.21,cert,Y
4+
2.16.840.1.101.3.4.3.21,consistent,Y
5+
2.16.840.1.101.3.4.3.20,priv,Y
6+
2.16.840.1.101.3.4.3.20,cert,Y
7+
2.16.840.1.101.3.4.3.20,consistent,Y
8+
2.16.840.1.101.3.4.3.27,priv,Y
9+
2.16.840.1.101.3.4.3.27,cert,Y
10+
2.16.840.1.101.3.4.3.27,consistent,Y
11+
2.16.840.1.101.3.4.3.26,priv,Y
12+
2.16.840.1.101.3.4.3.26,cert,Y
13+
2.16.840.1.101.3.4.3.26,consistent,Y
14+
2.16.840.1.101.3.4.3.17,seed,Y
15+
2.16.840.1.101.3.4.3.17,expandedkey,Y
16+
2.16.840.1.101.3.4.3.17,both,Y
17+
2.16.840.1.101.3.4.3.17,cert,Y
18+
2.16.840.1.101.3.4.3.17,consistent,Y
19+
2.16.840.1.101.3.4.4.1,seed,Y
20+
2.16.840.1.101.3.4.4.1,expandedkey,Y
21+
2.16.840.1.101.3.4.4.1,both,Y
22+
2.16.840.1.101.3.4.4.1,cert,Y
23+
2.16.840.1.101.3.4.4.1,consistent,Y
24+
2.16.840.1.101.3.4.3.23,priv,Y
25+
2.16.840.1.101.3.4.3.23,cert,Y
26+
2.16.840.1.101.3.4.3.23,consistent,Y
27+
2.16.840.1.101.3.4.3.22,priv,Y
28+
2.16.840.1.101.3.4.3.22,cert,Y
29+
2.16.840.1.101.3.4.3.22,consistent,Y
30+
2.16.840.1.101.3.4.3.29,priv,Y
31+
2.16.840.1.101.3.4.3.29,cert,Y
32+
2.16.840.1.101.3.4.3.29,consistent,Y
33+
2.16.840.1.101.3.4.3.28,priv,Y
34+
2.16.840.1.101.3.4.3.28,cert,Y
35+
2.16.840.1.101.3.4.3.28,consistent,Y
36+
2.16.840.1.101.3.4.3.18,seed,Y
37+
2.16.840.1.101.3.4.3.18,expandedkey,Y
38+
2.16.840.1.101.3.4.3.18,both,Y
39+
2.16.840.1.101.3.4.3.18,cert,Y
40+
2.16.840.1.101.3.4.3.18,consistent,Y
41+
2.16.840.1.101.3.4.4.2,seed,Y
42+
2.16.840.1.101.3.4.4.2,expandedkey,Y
43+
2.16.840.1.101.3.4.4.2,both,Y
44+
2.16.840.1.101.3.4.4.2,cert,Y
45+
2.16.840.1.101.3.4.4.2,consistent,Y
46+
2.16.840.1.101.3.4.3.25,priv,Y
47+
2.16.840.1.101.3.4.3.25,cert,Y
48+
2.16.840.1.101.3.4.3.25,consistent,Y
49+
2.16.840.1.101.3.4.3.24,priv,Y
50+
2.16.840.1.101.3.4.3.24,cert,Y
51+
2.16.840.1.101.3.4.3.24,consistent,Y
52+
2.16.840.1.101.3.4.3.31,priv,Y
53+
2.16.840.1.101.3.4.3.31,cert,Y
54+
2.16.840.1.101.3.4.3.31,consistent,Y
55+
2.16.840.1.101.3.4.3.30,priv,Y
56+
2.16.840.1.101.3.4.3.30,cert,Y
57+
2.16.840.1.101.3.4.3.30,consistent,Y
58+
2.16.840.1.101.3.4.3.19,seed,Y
59+
2.16.840.1.101.3.4.3.19,expandedkey,Y
60+
2.16.840.1.101.3.4.3.19,both,Y
61+
2.16.840.1.101.3.4.3.19,cert,Y
62+
2.16.840.1.101.3.4.3.19,consistent,Y
63+
2.16.840.1.101.3.4.4.3,seed,Y
64+
2.16.840.1.101.3.4.4.3,expandedkey,Y
65+
2.16.840.1.101.3.4.4.3,both,Y
66+
2.16.840.1.101.3.4.4.3,cert,Y
67+
2.16.840.1.101.3.4.4.3,consistent,Y

0 commit comments

Comments
 (0)