check_sig_alg_match(): weaken sig nid comparison to allow RSA{,PSS} key verify RSA-PSS
[openssl.git] / test / certs / mkcert.sh
1 #! /bin/bash
2 #
3 # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
4 # Copyright (c) 2016 Viktor Dukhovni <openssl-users@dukhovni.org>.
5 # All rights reserved.
6 #
7 # Licensed under the Apache License 2.0 (the "License").  You may not use
8 # this file except in compliance with the License.  You can obtain a copy
9 # in the file LICENSE in the source distribution or at
10 # https://www.openssl.org/source/license.html
11
12 # This file is dual-licensed and is also available under other terms.
13 # Please contact the author.
14
15 # 100 years should be enough for now
16 if [ -z "$DAYS" ]; then
17     DAYS=36525
18 fi
19
20 if [ -z "$OPENSSL_SIGALG" ]; then
21     OPENSSL_SIGALG=sha256
22 fi
23
24 if [ -z "$REQMASK" ]; then
25     REQMASK=utf8only
26 fi
27
28 stderr_onerror() {
29     (
30         err=$("$@" >&3 2>&1) || {
31             printf "%s\n" "$err" >&2
32             exit 1
33         }
34     ) 3>&1
35 }
36
37 key() {
38     local key=$1; shift
39
40     local alg=rsa
41     if [ -n "$OPENSSL_KEYALG" ]; then
42         alg=$OPENSSL_KEYALG
43     fi
44
45     local bits=2048
46     if [ -n "$OPENSSL_KEYBITS" ]; then
47         bits=$OPENSSL_KEYBITS
48     fi
49
50     if [ ! -f "${key}.pem" ]; then
51         args=(-algorithm "$alg")
52         case $alg in
53         rsa) args=("${args[@]}" -pkeyopt rsa_keygen_bits:$bits );;
54         ec)  args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
55                args=("${args[@]}" -pkeyopt ec_param_enc:named_curve);;
56         dsa)  args=(-paramfile "$bits");;
57         ed25519)  ;;
58         ed448)  ;;
59         *) printf "Unsupported key algorithm: %s\n" "$alg" >&2; return 1;;
60         esac
61         stderr_onerror \
62             openssl genpkey "${args[@]}" -out "${key}.pem"
63     fi
64 }
65
66 # Usage: $0 req keyname dn1 dn2 ...
67 req() {
68     local key=$1; shift
69
70     key "$key"
71     local errs
72
73     stderr_onerror \
74         openssl req -new -"${OPENSSL_SIGALG}" -key "${key}.pem" \
75             -config <(printf "string_mask=%s\n[req]\n%s\n%s\n[dn]\n" \
76               "$REQMASK" "prompt = no" "distinguished_name = dn"
77                       for dn in "$@"; do echo "$dn"; done)
78 }
79
80 req_nocn() {
81     local key=$1; shift
82
83     key "$key"
84     stderr_onerror \
85         openssl req -new -"${OPENSSL_SIGALG}" -subj / -key "${key}.pem" \
86             -config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
87                       "distinguished_name = dn")
88 }
89
90 cert() {
91     local cert=$1; shift
92     local exts=$1; shift
93
94     stderr_onerror \
95         openssl x509 -req -"${OPENSSL_SIGALG}" -out "${cert}.pem" \
96             -extfile <(printf "%s\n" "$exts") "$@"
97 }
98
99 genroot() {
100     local cn=$1; shift
101     local key=$1; shift
102     local cert=$1; shift
103     local bcon="basicConstraints = critical,CA:true"
104     local ku="keyUsage = keyCertSign,cRLSign"
105     local skid="subjectKeyIdentifier = hash"
106     local akid="authorityKeyIdentifier = keyid"
107
108     exts=$(printf "%s\n%s\n%s\n" "$bcon" "$ku" "$skid" "$akid")
109     for eku in "$@"
110     do
111         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
112     done
113     csr=$(req "$key" "CN = $cn") || return 1
114     echo "$csr" |
115        cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days "${DAYS}"
116 }
117
118 genca() {
119     local OPTIND=1
120     local purpose=
121
122     while getopts p: o
123     do
124         case $o in
125         p) purpose="$OPTARG";;
126         *) echo "Usage: $0 genca [-p EKU] cn keyname certname cakeyname cacertname" >&2
127            return 1;;
128         esac
129     done
130
131     shift $((OPTIND - 1))
132     local cn=$1; shift
133     local key=$1; shift
134     local cert=$1; shift
135     local cakey=$1; shift
136     local cacert=$1; shift
137     local bcon="basicConstraints = critical,CA:true"
138     local ku="keyUsage = keyCertSign,cRLSign"
139     local skid="subjectKeyIdentifier = hash"
140     local akid="authorityKeyIdentifier = keyid"
141
142     exts=$(printf "%s\n%s\n%s\n" "$bcon" "$ku" "$skid" "$akid")
143     if [ -n "$purpose" ]; then
144         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$purpose")
145     fi
146     if [ -n "$NC" ]; then
147         exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
148     fi
149     csr=$(req "$key" "CN = $cn") || return 1
150     echo "$csr" |
151         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
152             -set_serial 2 -days "${DAYS}" "$@"
153 }
154
155 gen_nonbc_ca() {
156     local cn=$1; shift
157     local key=$1; shift
158     local cert=$1; shift
159     local cakey=$1; shift
160     local cacert=$1; shift
161     local skid="subjectKeyIdentifier = hash"
162     local akid="authorityKeyIdentifier = keyid"
163
164     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
165     exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
166     for eku in "$@"
167     do
168         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
169     done
170     csr=$(req "$key" "CN = $cn") || return 1
171     echo "$csr" |
172         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
173             -set_serial 2 -days "${DAYS}"
174 }
175
176 # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
177 #
178 # Note: takes csr on stdin, so must be used with $0 req like this:
179 #
180 # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
181 genpc() {
182     local key=$1; shift
183     local cert=$1; shift
184     local cakey=$1; shift
185     local ca=$1; shift
186
187     exts=$(printf "%s\n%s\n%s\n%s\n" \
188             "subjectKeyIdentifier = hash" \
189             "authorityKeyIdentifier = keyid, issuer:always" \
190             "basicConstraints = CA:false" \
191             "proxyCertInfo = critical, @pcexts";
192            echo "[pcexts]";
193            for x in "$@"; do echo $x; done)
194     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
195          -set_serial 2 -days "${DAYS}"
196 }
197
198 # Usage: $0 geneealt keyname certname eekeyname eecertname alt1 alt2 ...
199 #
200 # Note: takes csr on stdin, so must be used with $0 req like this:
201 #
202 # $0 req keyname dn | $0 geneealt keyname certname eekeyname eecertname alt ...
203 geneealt() {
204     local key=$1; shift
205     local cert=$1; shift
206     local cakey=$1; shift
207     local ca=$1; shift
208
209     exts=$(printf "%s\n%s\n%s\n%s\n" \
210             "subjectKeyIdentifier = hash" \
211             "authorityKeyIdentifier = keyid" \
212             "basicConstraints = CA:false" \
213             "subjectAltName = @alts";
214            echo "[alts]";
215            for x in "$@"; do echo $x; done)
216     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
217          -set_serial 2 -days "${DAYS}"
218 }
219
220 genee() {
221     local OPTIND=1
222     local purpose=serverAuth
223
224     while getopts p: o
225     do
226         case $o in
227         p) purpose="$OPTARG";;
228         *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
229            return 1;;
230         esac
231     done
232
233     shift $((OPTIND - 1))
234     local cn=$1; shift
235     local key=$1; shift
236     local cert=$1; shift
237     local cakey=$1; shift
238     local ca=$1; shift
239
240     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
241             "subjectKeyIdentifier = hash" \
242             "authorityKeyIdentifier = keyid, issuer" \
243             "basicConstraints = CA:false" \
244             "extendedKeyUsage = $purpose" \
245             "subjectAltName = @alts" "DNS=${cn}")
246     csr=$(req "$key" "CN = $cn") || return 1
247     echo "$csr" |
248         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
249             -set_serial 2 -days "${DAYS}" "$@"
250 }
251
252 geneeextra() {
253     local OPTIND=1
254     local purpose=serverAuth
255
256     while getopts p: o
257     do
258         case $o in
259         p) purpose="$OPTARG";;
260         *) echo "Usage: $0 geneeextra [-p EKU] cn keyname certname cakeyname cacertname extraext" >&2
261            return 1;;
262         esac
263     done
264
265     shift $((OPTIND - 1))
266     local cn=$1; shift
267     local key=$1; shift
268     local cert=$1; shift
269     local cakey=$1; shift
270     local ca=$1; shift
271     local extraext=$1; shift
272
273     exts=$(printf "%s\n%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
274             "subjectKeyIdentifier = hash" \
275             "authorityKeyIdentifier = keyid, issuer" \
276             "basicConstraints = CA:false" \
277             "extendedKeyUsage = $purpose" \
278             "subjectAltName = @alts"\
279             "$extraext" "DNS=${cn}")
280     csr=$(req "$key" "CN = $cn") || return 1
281     echo "$csr" |
282         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
283             -set_serial 2 -days "${DAYS}" "$@"
284 }
285
286 geneenocsr() {
287     local OPTIND=1
288     local purpose=serverAuth
289
290     while getopts p: o
291     do
292         case $o in
293         p) purpose="$OPTARG";;
294         *) echo "Usage: $0 geneenocsr [-p EKU] cn certname cakeyname cacertname" >&2
295            return 1;;
296         esac
297     done
298
299     shift $((OPTIND - 1))
300     local cn=$1; shift
301     local cert=$1; shift
302     local cakey=$1; shift
303     local ca=$1; shift
304
305     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
306             "subjectKeyIdentifier = hash" \
307             "authorityKeyIdentifier = keyid, issuer" \
308             "basicConstraints = CA:false" \
309             "extendedKeyUsage = $purpose" \
310             "subjectAltName = @alts" "DNS=${cn}")
311         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
312             -set_serial 2 -days "${DAYS}" "$@"
313 }
314
315 genss() {
316     local cn=$1; shift
317     local key=$1; shift
318     local cert=$1; shift
319
320     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
321             "subjectKeyIdentifier   = hash" \
322             "authorityKeyIdentifier = keyid, issuer" \
323             "basicConstraints = CA:false" \
324             "extendedKeyUsage = serverAuth" \
325             "subjectAltName = @alts" "DNS=${cn}")
326     csr=$(req "$key" "CN = $cn") || return 1
327     echo "$csr" |
328         cert "$cert" "$exts" -signkey "${key}.pem" \
329             -set_serial 1 -days "${DAYS}" "$@"
330 }
331
332 gennocn() {
333     local key=$1; shift
334     local cert=$1; shift
335
336     csr=$(req_nocn "$key") || return 1
337     echo "$csr" |
338         cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
339 }
340
341 genct() {
342     local OPTIND=1
343     local purpose=serverAuth
344
345     while getopts p: o
346     do
347         case $o in
348         p) purpose="$OPTARG";;
349         *) echo "Usage: $0 genct [-p EKU] cn keyname certname cakeyname cacertname ctlogkey" >&2
350            return 1;;
351         esac
352     done
353
354     shift $((OPTIND - 1))
355     local cn=$1; shift
356     local key=$1; shift
357     local cert=$1; shift
358     local cakey=$1; shift
359     local ca=$1; shift
360     local logkey=$1; shift
361
362     exts=$(printf "%s\n%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
363             "subjectKeyIdentifier = hash" \
364             "authorityKeyIdentifier = keyid, issuer" \
365             "basicConstraints = CA:false" \
366             "extendedKeyUsage = $purpose" \
367             "1.3.6.1.4.1.11129.2.4.3 = critical,ASN1:NULL"\
368             "subjectAltName = @alts" "DNS=${cn}")
369     csr=$(req "$key" "CN = $cn") || return 1
370     echo "$csr" |
371         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
372             -set_serial 2 -days "${DAYS}" "$@"
373     cat ${cert}.pem ${ca}.pem > ${cert}-chain.pem
374     go run github.com/google/certificate-transparency-go/ctutil/sctgen \
375        --log_private_key ${logkey}.pem \
376        --timestamp="2020-01-01T00:00:00Z" \
377        --cert_chain ${cert}-chain.pem \
378        --tls_out ${cert}.tlssct
379     rm ${cert}-chain.pem
380     filesize=$(wc -c <${cert}.tlssct)
381     exts=$(printf "%s\n%s\n%s\n%s\n%s%04X%04X%s\n%s\n[alts]\n%s\n" \
382             "subjectKeyIdentifier = hash" \
383             "authorityKeyIdentifier = keyid, issuer" \
384             "basicConstraints = CA:false" \
385             "extendedKeyUsage = $purpose" \
386             "1.3.6.1.4.1.11129.2.4.2 = ASN1:FORMAT:HEX,OCT:" $((filesize+2)) $filesize `xxd -p ${cert}.tlssct | tr -d '\n'` \
387             "subjectAltName = @alts" "DNS=${cn}")
388     echo "$csr" |
389         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
390             -set_serial 2 -days "${DAYS}" "$@"
391 }
392
393 "$@"