Home | History | Annotate | Line # | Download | only in certs
      1 #! /bin/bash
      2 #
      3 # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
      4 # Copyright (c) 2016 Viktor Dukhovni <openssl-users (at] dukhovni.org>.
      5 # All rights reserved.
      6 #
      7 # Licensed under the OpenSSL license (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 OPTIND=1
    118     local purpose=
    119 
    120     while getopts p: o
    121     do
    122         case $o in
    123         p) purpose="$OPTARG";;
    124         *) echo "Usage: $0 genca [-p EKU] cn keyname certname cakeyname cacertname" >&2
    125            return 1;;
    126         esac
    127     done
    128 
    129     shift $((OPTIND - 1))
    130     local cn=$1; shift
    131     local key=$1; shift
    132     local cert=$1; shift
    133     local cakey=$1; shift
    134     local cacert=$1; shift
    135     local skid="subjectKeyIdentifier = hash"
    136     local akid="authorityKeyIdentifier = keyid"
    137 
    138     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = critical,CA:true")
    139     if [ -n "$purpose" ]; then
    140         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$purpose")
    141     fi
    142     if [ -n "$NC" ]; then
    143         exts=$(printf "%s\nnameConstraints = %s\n" "$exts" "$NC")
    144     fi
    145     csr=$(req "$key" "CN = $cn") || return 1
    146     echo "$csr" |
    147         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
    148 	    -set_serial 2 -days "${DAYS}" "$@"
    149 }
    150 
    151 gen_nonbc_ca() {
    152     local cn=$1; shift
    153     local key=$1; shift
    154     local cert=$1; shift
    155     local cakey=$1; shift
    156     local cacert=$1; shift
    157     local skid="subjectKeyIdentifier = hash"
    158     local akid="authorityKeyIdentifier = keyid"
    159 
    160     exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid")
    161     exts=$(printf "%s\nkeyUsage = %s\n" "$exts" "keyCertSign, cRLSign")
    162     for eku in "$@"
    163     do
    164         exts=$(printf "%s\nextendedKeyUsage = %s\n" "$exts" "$eku")
    165     done
    166     csr=$(req "$key" "CN = $cn") || return 1
    167     echo "$csr" |
    168         cert "$cert" "$exts" -CA "${cacert}.pem" -CAkey "${cakey}.pem" \
    169 	    -set_serial 2 -days "${DAYS}"
    170 }
    171 
    172 # Usage: $0 genpc keyname certname eekeyname eecertname pcext1 pcext2 ...
    173 #
    174 # Note: takes csr on stdin, so must be used with $0 req like this:
    175 #
    176 # $0 req keyname dn | $0 genpc keyname certname eekeyname eecertname pcext ...
    177 genpc() {
    178     local key=$1; shift
    179     local cert=$1; shift
    180     local cakey=$1; shift
    181     local ca=$1; shift
    182 
    183     exts=$(printf "%s\n%s\n%s\n%s\n" \
    184 	    "subjectKeyIdentifier = hash" \
    185 	    "authorityKeyIdentifier = keyid, issuer:always" \
    186 	    "basicConstraints = CA:false" \
    187 	    "proxyCertInfo = critical, @pcexts";
    188            echo "[pcexts]";
    189            for x in "$@"; do echo $x; done)
    190     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    191 	 -set_serial 2 -days "${DAYS}"
    192 }
    193 
    194 # Usage: $0 geneealt keyname certname eekeyname eecertname alt1 alt2 ...
    195 #
    196 # Note: takes csr on stdin, so must be used with $0 req like this:
    197 #
    198 # $0 req keyname dn | $0 geneealt keyname certname eekeyname eecertname alt ...
    199 geneealt() {
    200     local key=$1; shift
    201     local cert=$1; shift
    202     local cakey=$1; shift
    203     local ca=$1; shift
    204 
    205     exts=$(printf "%s\n%s\n%s\n%s\n" \
    206 	    "subjectKeyIdentifier = hash" \
    207 	    "authorityKeyIdentifier = keyid" \
    208 	    "basicConstraints = CA:false" \
    209 	    "subjectAltName = @alts";
    210            echo "[alts]";
    211            for x in "$@"; do echo $x; done)
    212     cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    213 	 -set_serial 2 -days "${DAYS}"
    214 }
    215 
    216 genee() {
    217     local OPTIND=1
    218     local purpose=serverAuth
    219 
    220     while getopts p: o
    221     do
    222         case $o in
    223         p) purpose="$OPTARG";;
    224         *) echo "Usage: $0 genee [-p EKU] cn keyname certname cakeyname cacertname" >&2
    225            return 1;;
    226         esac
    227     done
    228 
    229     shift $((OPTIND - 1))
    230     local cn=$1; shift
    231     local key=$1; shift
    232     local cert=$1; shift
    233     local cakey=$1; shift
    234     local ca=$1; shift
    235 
    236     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    237 	    "subjectKeyIdentifier = hash" \
    238 	    "authorityKeyIdentifier = keyid, issuer" \
    239 	    "basicConstraints = CA:false" \
    240 	    "extendedKeyUsage = $purpose" \
    241 	    "subjectAltName = @alts" "DNS=${cn}")
    242     csr=$(req "$key" "CN = $cn") || return 1
    243     echo "$csr" |
    244 	cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    245 	    -set_serial 2 -days "${DAYS}" "$@"
    246 }
    247 
    248 geneenocsr() {
    249     local OPTIND=1
    250     local purpose=serverAuth
    251 
    252     while getopts p: o
    253     do
    254         case $o in
    255         p) purpose="$OPTARG";;
    256         *) echo "Usage: $0 genee [-p EKU] cn certname cakeyname cacertname" >&2
    257            return 1;;
    258         esac
    259     done
    260 
    261     shift $((OPTIND - 1))
    262     local cn=$1; shift
    263     local cert=$1; shift
    264     local cakey=$1; shift
    265     local ca=$1; shift
    266 
    267     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    268 	    "subjectKeyIdentifier = hash" \
    269 	    "authorityKeyIdentifier = keyid, issuer" \
    270 	    "basicConstraints = CA:false" \
    271 	    "extendedKeyUsage = $purpose" \
    272 	    "subjectAltName = @alts" "DNS=${cn}")
    273 	cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \
    274 	    -set_serial 2 -days "${DAYS}" "$@"
    275 }
    276 
    277 genss() {
    278     local cn=$1; shift
    279     local key=$1; shift
    280     local cert=$1; shift
    281 
    282     exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \
    283 	    "subjectKeyIdentifier   = hash" \
    284 	    "authorityKeyIdentifier = keyid, issuer" \
    285 	    "basicConstraints = CA:false" \
    286 	    "extendedKeyUsage = serverAuth" \
    287 	    "subjectAltName = @alts" "DNS=${cn}")
    288     csr=$(req "$key" "CN = $cn") || return 1
    289     echo "$csr" |
    290         cert "$cert" "$exts" -signkey "${key}.pem" \
    291             -set_serial 1 -days "${DAYS}" "$@"
    292 }
    293 
    294 gennocn() {
    295     local key=$1; shift
    296     local cert=$1; shift
    297 
    298     csr=$(req_nocn "$key") || return 1
    299     echo "$csr" |
    300 	cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@"
    301 }
    302 
    303 "$@"
    304