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