Home | History | Annotate | Line # | Download | only in certs
mkcert.sh revision 1.1.1.4
      1      1.1  christos #! /bin/bash
      2      1.1  christos #
      3  1.1.1.4  christos # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
      4      1.1  christos # Copyright (c) 2016 Viktor Dukhovni <openssl-users (at] dukhovni.org>.
      5      1.1  christos # All rights reserved.
      6      1.1  christos #
      7  1.1.1.2  christos # Licensed under the OpenSSL license (the "License").  You may not use
      8  1.1.1.2  christos # this file except in compliance with the License.  You can obtain a copy
      9  1.1.1.2  christos # in the file LICENSE in the source distribution or at
     10  1.1.1.2  christos # https://www.openssl.org/source/license.html
     11  1.1.1.2  christos 
     12  1.1.1.2  christos # This file is dual-licensed and is also available under other terms.
     13  1.1.1.2  christos # Please contact the author.
     14      1.1  christos 
     15      1.1  christos # 100 years should be enough for now
     16      1.1  christos if [ -z "$DAYS" ]; then
     17      1.1  christos     DAYS=36525
     18      1.1  christos fi
     19      1.1  christos 
     20      1.1  christos if [ -z "$OPENSSL_SIGALG" ]; then
     21      1.1  christos     OPENSSL_SIGALG=sha256
     22      1.1  christos fi
     23      1.1  christos 
     24      1.1  christos if [ -z "$REQMASK" ]; then
     25      1.1  christos     REQMASK=utf8only
     26      1.1  christos fi
     27      1.1  christos 
     28      1.1  christos stderr_onerror() {
     29      1.1  christos     (
     30      1.1  christos         err=$("$@" >&3 2>&1) || {
     31      1.1  christos             printf "%s\n" "$err" >&2
     32      1.1  christos             exit 1
     33      1.1  christos         }
     34      1.1  christos     ) 3>&1
     35      1.1  christos }
     36      1.1  christos 
     37      1.1  christos key() {
     38      1.1  christos     local key=$1; shift
     39      1.1  christos 
     40      1.1  christos     local alg=rsa
     41      1.1  christos     if [ -n "$OPENSSL_KEYALG" ]; then
     42      1.1  christos         alg=$OPENSSL_KEYALG
     43      1.1  christos     fi
     44      1.1  christos 
     45      1.1  christos     local bits=2048
     46      1.1  christos     if [ -n "$OPENSSL_KEYBITS" ]; then
     47      1.1  christos         bits=$OPENSSL_KEYBITS
     48      1.1  christos     fi
     49      1.1  christos 
     50      1.1  christos     if [ ! -f "${key}.pem" ]; then
     51      1.1  christos         args=(-algorithm "$alg")
     52      1.1  christos         case $alg in
     53      1.1  christos         rsa) args=("${args[@]}" -pkeyopt rsa_keygen_bits:$bits );;
     54      1.1  christos         ec)  args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
     55      1.1  christos                args=("${args[@]}" -pkeyopt ec_param_enc:named_curve);;
     56  1.1.1.2  christos         dsa)  args=(-paramfile "$bits");;
     57  1.1.1.2  christos         ed25519)  ;;
     58  1.1.1.2  christos         ed448)  ;;
     59      1.1  christos         *) printf "Unsupported key algorithm: %s\n" "$alg" >&2; return 1;;
     60      1.1  christos         esac
     61      1.1  christos         stderr_onerror \
     62      1.1  christos             openssl genpkey "${args[@]}" -out "${key}.pem"
     63      1.1  christos     fi
     64      1.1  christos }
     65      1.1  christos 
     66      1.1  christos # Usage: $0 req keyname dn1 dn2 ...
     67      1.1  christos req() {
     68      1.1  christos     local key=$1; shift
     69      1.1  christos 
     70      1.1  christos     key "$key"
     71      1.1  christos     local errs
     72      1.1  christos 
     73      1.1  christos     stderr_onerror \
     74      1.1  christos         openssl req -new -"${OPENSSL_SIGALG}" -key "${key}.pem" \
     75      1.1  christos             -config <(printf "string_mask=%s\n[req]\n%s\n%s\n[dn]\n" \
     76      1.1  christos               "$REQMASK" "prompt = no" "distinguished_name = dn"
     77      1.1  christos                       for dn in "$@"; do echo "$dn"; done)
     78      1.1  christos }
     79      1.1  christos 
     80      1.1  christos req_nocn() {
     81      1.1  christos     local key=$1; shift
     82      1.1  christos 
     83      1.1  christos     key "$key"
     84      1.1  christos     stderr_onerror \
     85      1.1  christos         openssl req -new -"${OPENSSL_SIGALG}" -subj / -key "${key}.pem" \
     86      1.1  christos             -config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
     87      1.1  christos 		      "distinguished_name = dn")
     88      1.1  christos }
     89      1.1  christos 
     90      1.1  christos cert() {
     91      1.1  christos     local cert=$1; shift
     92      1.1  christos     local exts=$1; shift
     93      1.1  christos 
     94      1.1  christos     stderr_onerror \
     95      1.1  christos         openssl x509 -req -"${OPENSSL_SIGALG}" -out "${cert}.pem" \
     96      1.1  christos             -extfile <(printf "%s\n" "$exts") "$@"
     97      1.1  christos }
     98      1.1  christos 
     99      1.1  christos genroot() {
    100      1.1  christos     local cn=$1; shift
    101      1.1  christos     local key=$1; shift
    102      1.1  christos     local cert=$1; shift
    103      1.1  christos     local skid="subjectKeyIdentifier = hash"
    104      1.1  christos     local akid="authorityKeyIdentifier = keyid"
    105      1.1  christos 
    106      1.1  christos     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
    107      1.1  christos     for eku in "$@"
    108      1.1  christos     do
    109      1.1  christos         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
    110      1.1  christos     done
    111      1.1  christos     csr=$(req "$key" "CN = $cn") || return 1
    112      1.1  christos     echo "$csr" |
    113      1.1  christos        cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days "${DAYS}"
    114      1.1  christos }
    115      1.1  christos 
    116      1.1  christos genca() {
    117  1.1.1.4  christos     local OPTIND=1
    118  1.1.1.4  christos     local purpose=
    119  1.1.1.4  christos 
    120  1.1.1.4  christos     while getopts p: o
    121  1.1.1.4  christos     do
    122  1.1.1.4  christos         case $o in
    123  1.1.1.4  christos         p) purpose="$OPTARG";;
    124  1.1.1.4  christos         *) echo "Usage: $0 genca [-p EKU] cn keyname certname cakeyname cacertname" >&2
    125  1.1.1.4  christos            return 1;;
    126  1.1.1.4  christos         esac
    127  1.1.1.4  christos     done
    128  1.1.1.4  christos 
    129  1.1.1.4  christos     shift $((OPTIND - 1))
    130      1.1  christos     local cn=$1; shift
    131      1.1  christos     local key=$1; shift
    132      1.1  christos     local cert=$1; shift
    133      1.1  christos     local cakey=$1; shift
    134      1.1  christos     local cacert=$1; shift
    135      1.1  christos     local skid="subjectKeyIdentifier = hash"
    136      1.1  christos     local akid="authorityKeyIdentifier = keyid"
    137      1.1  christos 
    138      1.1  christos     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
    139  1.1.1.4  christos     if [ -n "$purpose" ]; then
    140  1.1.1.4  christos         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$purpose")
    141  1.1.1.4  christos     fi
    142      1.1  christos     if [ -n "$NC" ]; then
    143      1.1  christos         exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
    144      1.1  christos     fi
    145      1.1  christos     csr=$(req "$key" "CN = $cn") || return 1
    146      1.1  christos     echo "$csr" |
    147      1.1  christos         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
    148  1.1.1.4  christos 	    -set_serial 2 -days "${DAYS}" "$@"
    149      1.1  christos }
    150      1.1  christos 
    151      1.1  christos gen_nonbc_ca() {
    152      1.1  christos     local cn=$1; shift
    153      1.1  christos     local key=$1; shift
    154      1.1  christos     local cert=$1; shift
    155      1.1  christos     local cakey=$1; shift
    156      1.1  christos     local cacert=$1; shift
    157      1.1  christos     local skid="subjectKeyIdentifier = hash"
    158      1.1  christos     local akid="authorityKeyIdentifier = keyid"
    159      1.1  christos 
    160      1.1  christos     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
    161      1.1  christos     exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
    162      1.1  christos     for eku in "$@"
    163      1.1  christos     do
    164      1.1  christos         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
    165      1.1  christos     done
    166      1.1  christos     csr=$(req "$key" "CN = $cn") || return 1
    167      1.1  christos     echo "$csr" |
    168      1.1  christos         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
    169      1.1  christos 	    -set_serial 2 -days "${DAYS}"
    170      1.1  christos }
    171      1.1  christos 
    172      1.1  christos # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
    173      1.1  christos #
    174      1.1  christos # Note: takes csr on stdin, so must be used with $0 req like this:
    175      1.1  christos #
    176      1.1  christos # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
    177      1.1  christos genpc() {
    178      1.1  christos     local key=$1; shift
    179      1.1  christos     local cert=$1; shift
    180      1.1  christos     local cakey=$1; shift
    181      1.1  christos     local ca=$1; shift
    182      1.1  christos 
    183      1.1  christos     exts=$(printf "%s\n%s\n%s\n%s\n" \
    184      1.1  christos 	    "subjectKeyIdentifier = hash" \
    185      1.1  christos 	    "authorityKeyIdentifier = keyid, issuer:always" \
    186      1.1  christos 	    "basicConstraints = CA:false" \
    187      1.1  christos 	    "proxyCertInfo = critical, @pcexts";
    188      1.1  christos            echo "[pcexts]";
    189      1.1  christos            for x in "$@"; do echo $x; done)
    190      1.1  christos     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    191      1.1  christos 	 -set_serial 2 -days "${DAYS}"
    192      1.1  christos }
    193      1.1  christos 
    194  1.1.1.2  christos # Usage: $0 geneealt keyname certname eekeyname eecertname alt1 alt2 ...
    195      1.1  christos #
    196      1.1  christos # Note: takes csr on stdin, so must be used with $0 req like this:
    197      1.1  christos #
    198  1.1.1.2  christos # $0 req keyname dn | $0 geneealt keyname certname eekeyname eecertname alt ...
    199      1.1  christos geneealt() {
    200      1.1  christos     local key=$1; shift
    201      1.1  christos     local cert=$1; shift
    202      1.1  christos     local cakey=$1; shift
    203      1.1  christos     local ca=$1; shift
    204      1.1  christos 
    205      1.1  christos     exts=$(printf "%s\n%s\n%s\n%s\n" \
    206      1.1  christos 	    "subjectKeyIdentifier = hash" \
    207      1.1  christos 	    "authorityKeyIdentifier = keyid" \
    208      1.1  christos 	    "basicConstraints = CA:false" \
    209      1.1  christos 	    "subjectAltName = @alts";
    210      1.1  christos            echo "[alts]";
    211      1.1  christos            for x in "$@"; do echo $x; done)
    212      1.1  christos     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    213      1.1  christos 	 -set_serial 2 -days "${DAYS}"
    214      1.1  christos }
    215      1.1  christos 
    216      1.1  christos genee() {
    217      1.1  christos     local OPTIND=1
    218      1.1  christos     local purpose=serverAuth
    219      1.1  christos 
    220      1.1  christos     while getopts p: o
    221      1.1  christos     do
    222      1.1  christos         case $o in
    223      1.1  christos         p) purpose="$OPTARG";;
    224      1.1  christos         *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
    225      1.1  christos            return 1;;
    226      1.1  christos         esac
    227      1.1  christos     done
    228      1.1  christos 
    229      1.1  christos     shift $((OPTIND - 1))
    230      1.1  christos     local cn=$1; shift
    231      1.1  christos     local key=$1; shift
    232      1.1  christos     local cert=$1; shift
    233      1.1  christos     local cakey=$1; shift
    234      1.1  christos     local ca=$1; shift
    235      1.1  christos 
    236      1.1  christos     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    237      1.1  christos 	    "subjectKeyIdentifier = hash" \
    238      1.1  christos 	    "authorityKeyIdentifier = keyid, issuer" \
    239      1.1  christos 	    "basicConstraints = CA:false" \
    240      1.1  christos 	    "extendedKeyUsage = $purpose" \
    241      1.1  christos 	    "subjectAltName = @alts" "DNS=${cn}")
    242      1.1  christos     csr=$(req "$key" "CN = $cn") || return 1
    243      1.1  christos     echo "$csr" |
    244      1.1  christos 	cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    245      1.1  christos 	    -set_serial 2 -days "${DAYS}" "$@"
    246      1.1  christos }
    247      1.1  christos 
    248  1.1.1.3  christos geneenocsr() {
    249  1.1.1.3  christos     local OPTIND=1
    250  1.1.1.3  christos     local purpose=serverAuth
    251  1.1.1.3  christos 
    252  1.1.1.3  christos     while getopts p: o
    253  1.1.1.3  christos     do
    254  1.1.1.3  christos         case $o in
    255  1.1.1.3  christos         p) purpose="$OPTARG";;
    256  1.1.1.3  christos         *) echo "Usage: $0 genee [-p EKU] cn certname cakeyname cacertname" >&2
    257  1.1.1.3  christos            return 1;;
    258  1.1.1.3  christos         esac
    259  1.1.1.3  christos     done
    260  1.1.1.3  christos 
    261  1.1.1.3  christos     shift $((OPTIND - 1))
    262  1.1.1.3  christos     local cn=$1; shift
    263  1.1.1.3  christos     local cert=$1; shift
    264  1.1.1.3  christos     local cakey=$1; shift
    265  1.1.1.3  christos     local ca=$1; shift
    266  1.1.1.3  christos 
    267  1.1.1.3  christos     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    268  1.1.1.3  christos 	    "subjectKeyIdentifier = hash" \
    269  1.1.1.3  christos 	    "authorityKeyIdentifier = keyid, issuer" \
    270  1.1.1.3  christos 	    "basicConstraints = CA:false" \
    271  1.1.1.3  christos 	    "extendedKeyUsage = $purpose" \
    272  1.1.1.3  christos 	    "subjectAltName = @alts" "DNS=${cn}")
    273  1.1.1.3  christos 	cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    274  1.1.1.3  christos 	    -set_serial 2 -days "${DAYS}" "$@"
    275  1.1.1.3  christos }
    276  1.1.1.3  christos 
    277      1.1  christos genss() {
    278      1.1  christos     local cn=$1; shift
    279      1.1  christos     local key=$1; shift
    280      1.1  christos     local cert=$1; shift
    281      1.1  christos 
    282      1.1  christos     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    283      1.1  christos 	    "subjectKeyIdentifier   = hash" \
    284      1.1  christos 	    "authorityKeyIdentifier = keyid, issuer" \
    285      1.1  christos 	    "basicConstraints = CA:false" \
    286      1.1  christos 	    "extendedKeyUsage = serverAuth" \
    287      1.1  christos 	    "subjectAltName = @alts" "DNS=${cn}")
    288      1.1  christos     csr=$(req "$key" "CN = $cn") || return 1
    289      1.1  christos     echo "$csr" |
    290      1.1  christos         cert "$cert" "$exts" -signkey "${key}.pem" \
    291      1.1  christos             -set_serial 1 -days "${DAYS}" "$@"
    292      1.1  christos }
    293      1.1  christos 
    294      1.1  christos gennocn() {
    295      1.1  christos     local key=$1; shift
    296      1.1  christos     local cert=$1; shift
    297      1.1  christos 
    298      1.1  christos     csr=$(req_nocn "$key") || return 1
    299      1.1  christos     echo "$csr" |
    300      1.1  christos 	cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
    301      1.1  christos }
    302      1.1  christos 
    303      1.1  christos "$@"
    304