INSTALL.md: Restore $ as command prompt indicator
[oweals/openssl.git] / test / certs / mkcert.sh
1 #! /bin/bash
2 #
3 # Copyright 2016-2020 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 skid="subjectKeyIdentifier = hash"
104     local akid="authorityKeyIdentifier = keyid"
105
106     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
107     for eku in "$@"
108     do
109         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
110     done
111     csr=$(req "$key" "CN = $cn") || return 1
112     echo "$csr" |
113        cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days "${DAYS}"
114 }
115
116 genca() {
117     local cn=$1; shift
118     local key=$1; shift
119     local cert=$1; shift
120     local cakey=$1; shift
121     local cacert=$1; shift
122     local skid="subjectKeyIdentifier = hash"
123     local akid="authorityKeyIdentifier = keyid"
124
125     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
126     for eku in "$@"
127     do
128         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
129     done
130     if [ -n "$NC" ]; then
131         exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
132     fi
133     csr=$(req "$key" "CN = $cn") || return 1
134     echo "$csr" |
135         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
136             -set_serial 2 -days "${DAYS}"
137 }
138
139 gen_nonbc_ca() {
140     local cn=$1; shift
141     local key=$1; shift
142     local cert=$1; shift
143     local cakey=$1; shift
144     local cacert=$1; shift
145     local skid="subjectKeyIdentifier = hash"
146     local akid="authorityKeyIdentifier = keyid"
147
148     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
149     exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
150     for eku in "$@"
151     do
152         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
153     done
154     csr=$(req "$key" "CN = $cn") || return 1
155     echo "$csr" |
156         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
157             -set_serial 2 -days "${DAYS}"
158 }
159
160 # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
161 #
162 # Note: takes csr on stdin, so must be used with $0 req like this:
163 #
164 # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
165 genpc() {
166     local key=$1; shift
167     local cert=$1; shift
168     local cakey=$1; shift
169     local ca=$1; shift
170
171     exts=$(printf "%s\n%s\n%s\n%s\n" \
172             "subjectKeyIdentifier = hash" \
173             "authorityKeyIdentifier = keyid, issuer:always" \
174             "basicConstraints = CA:false" \
175             "proxyCertInfo = critical, @pcexts";
176            echo "[pcexts]";
177            for x in "$@"; do echo $x; done)
178     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
179          -set_serial 2 -days "${DAYS}"
180 }
181
182 # Usage: $0 geneealt keyname certname eekeyname eecertname alt1 alt2 ...
183 #
184 # Note: takes csr on stdin, so must be used with $0 req like this:
185 #
186 # $0 req keyname dn | $0 geneealt keyname certname eekeyname eecertname alt ...
187 geneealt() {
188     local key=$1; shift
189     local cert=$1; shift
190     local cakey=$1; shift
191     local ca=$1; shift
192
193     exts=$(printf "%s\n%s\n%s\n%s\n" \
194             "subjectKeyIdentifier = hash" \
195             "authorityKeyIdentifier = keyid" \
196             "basicConstraints = CA:false" \
197             "subjectAltName = @alts";
198            echo "[alts]";
199            for x in "$@"; do echo $x; done)
200     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
201          -set_serial 2 -days "${DAYS}"
202 }
203
204 genee() {
205     local OPTIND=1
206     local purpose=serverAuth
207
208     while getopts p: o
209     do
210         case $o in
211         p) purpose="$OPTARG";;
212         *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
213            return 1;;
214         esac
215     done
216
217     shift $((OPTIND - 1))
218     local cn=$1; shift
219     local key=$1; shift
220     local cert=$1; shift
221     local cakey=$1; shift
222     local ca=$1; shift
223
224     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
225             "subjectKeyIdentifier = hash" \
226             "authorityKeyIdentifier = keyid, issuer" \
227             "basicConstraints = CA:false" \
228             "extendedKeyUsage = $purpose" \
229             "subjectAltName = @alts" "DNS=${cn}")
230     csr=$(req "$key" "CN = $cn") || return 1
231     echo "$csr" |
232         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
233             -set_serial 2 -days "${DAYS}" "$@"
234 }
235
236 geneenocsr() {
237     local OPTIND=1
238     local purpose=serverAuth
239
240     while getopts p: o
241     do
242         case $o in
243         p) purpose="$OPTARG";;
244         *) echo "Usage: $0 genee [-p EKU] cn certname cakeyname cacertname" >&2
245            return 1;;
246         esac
247     done
248
249     shift $((OPTIND - 1))
250     local cn=$1; shift
251     local cert=$1; shift
252     local cakey=$1; shift
253     local ca=$1; shift
254
255     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
256             "subjectKeyIdentifier = hash" \
257             "authorityKeyIdentifier = keyid, issuer" \
258             "basicConstraints = CA:false" \
259             "extendedKeyUsage = $purpose" \
260             "subjectAltName = @alts" "DNS=${cn}")
261         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
262             -set_serial 2 -days "${DAYS}" "$@"
263 }
264
265 genss() {
266     local cn=$1; shift
267     local key=$1; shift
268     local cert=$1; shift
269
270     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
271             "subjectKeyIdentifier   = hash" \
272             "authorityKeyIdentifier = keyid, issuer" \
273             "basicConstraints = CA:false" \
274             "extendedKeyUsage = serverAuth" \
275             "subjectAltName = @alts" "DNS=${cn}")
276     csr=$(req "$key" "CN = $cn") || return 1
277     echo "$csr" |
278         cert "$cert" "$exts" -signkey "${key}.pem" \
279             -set_serial 1 -days "${DAYS}" "$@"
280 }
281
282 gennocn() {
283     local key=$1; shift
284     local cert=$1; shift
285
286     csr=$(req_nocn "$key") || return 1
287     echo "$csr" |
288         cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
289 }
290
291 genct() {
292     local OPTIND=1
293     local purpose=serverAuth
294
295     while getopts p: o
296     do
297         case $o in
298         p) purpose="$OPTARG";;
299         *) echo "Usage: $0 genct [-p EKU] cn keyname certname cakeyname cacertname ctlogkey" >&2
300            return 1;;
301         esac
302     done
303
304     shift $((OPTIND - 1))
305     local cn=$1; shift
306     local key=$1; shift
307     local cert=$1; shift
308     local cakey=$1; shift
309     local ca=$1; shift
310     local logkey=$1; shift
311
312     exts=$(printf "%s\n%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
313             "subjectKeyIdentifier = hash" \
314             "authorityKeyIdentifier = keyid, issuer" \
315             "basicConstraints = CA:false" \
316             "extendedKeyUsage = $purpose" \
317             "1.3.6.1.4.1.11129.2.4.3 = critical,ASN1:NULL"\
318             "subjectAltName = @alts" "DNS=${cn}")
319     csr=$(req "$key" "CN = $cn") || return 1
320     echo "$csr" |
321         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
322             -set_serial 2 -days "${DAYS}" "$@"
323     cat ${cert}.pem ${ca}.pem > ${cert}-chain.pem
324     go run github.com/google/certificate-transparency-go/ctutil/sctgen \
325        --log_private_key ${logkey}.pem \
326        --timestamp="2020-01-01T00:00:00Z" \
327        --cert_chain ${cert}-chain.pem \
328        --tls_out ${cert}.tlssct
329     rm ${cert}-chain.pem
330     filesize=$(wc -c <${cert}.tlssct)
331     exts=$(printf "%s\n%s\n%s\n%s\n%s%04X%04X%s\n%s\n[alts]\n%s\n" \
332             "subjectKeyIdentifier = hash" \
333             "authorityKeyIdentifier = keyid, issuer" \
334             "basicConstraints = CA:false" \
335             "extendedKeyUsage = $purpose" \
336             "1.3.6.1.4.1.11129.2.4.2 = ASN1:FORMAT:HEX,OCT:" $((filesize+2)) $filesize `xxd -p ${cert}.tlssct | tr -d '\n'` \
337             "subjectAltName = @alts" "DNS=${cn}")
338     echo "$csr" |
339         cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
340             -set_serial 2 -days "${DAYS}" "$@"
341 }
342
343 "$@"