1#! /bin/bash 2 3set -e 4 5DOMAIN=example.com 6HOST=mail.${DOMAIN} 7TEST=./tls_dane 8 9key() { 10 local key=$1; shift 11 12 if [ ! -f "${key}.pem" ]; then 13 openssl genpkey 2>/dev/null \ 14 -paramfile <(openssl ecparam -name prime256v1) \ 15 -out "${key}.pem" 16 fi 17} 18 19req() { 20 local key=$1; shift 21 local cn=$1; shift 22 23 key "$key" 24 openssl req -new -sha256 -key "${key}.pem" 2>/dev/null \ 25 -config <(printf "[req]\n%s\n%s\n[dn]\nCN=%s\n" \ 26 "prompt = no" "distinguished_name = dn" "${cn}") 27} 28 29req_nocn() { 30 local key=$1; shift 31 32 key "$key" 33 openssl req -new -sha256 -subj / -key "${key}.pem" 2>/dev/null \ 34 -config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \ 35 "distinguished_name = dn") 36} 37 38cert() { 39 local cert=$1; shift 40 local exts=$1; shift 41 42 openssl x509 -req -sha256 -out "${cert}.pem" 2>/dev/null \ 43 -extfile <(printf "%s\n" "$exts") "$@" 44} 45 46genroot() { 47 local cn=$1; shift 48 local key=$1; shift 49 local cert=$1; shift 50 local skid=$1; shift 51 local akid=$1; shift 52 53 exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true") 54 req "$key" "$cn" | 55 cert "$cert" "$exts" -signkey "${key}.pem" -set_serial 1 -days 30 56} 57 58genca() { 59 local cn=$1; shift 60 local key=$1; shift 61 local cert=$1; shift 62 local skid=$1; shift 63 local akid=$1; shift 64 local ca=$1; shift 65 local cakey=$1; shift 66 67 exts=$(printf "%s\n%s\n%s\n" "$skid" "$akid" "basicConstraints = CA:true") 68 req "$key" "$cn" | 69 cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ 70 -set_serial 2 -days 30 "$@" 71} 72 73genee() { 74 local cn=$1; shift 75 local key=$1; shift 76 local cert=$1; shift 77 local ca=$1; shift 78 local cakey=$1; shift 79 80 exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \ 81 "subjectKeyIdentifier = hash" \ 82 "authorityKeyIdentifier = keyid, issuer" \ 83 "basicConstraints = CA:false" \ 84 "extendedKeyUsage = serverAuth" \ 85 "subjectAltName = @alts" "DNS=${cn}") 86 req "$key" "$cn" | 87 cert "$cert" "$exts" -CA "${ca}.pem" -CAkey "${cakey}.pem" \ 88 -set_serial 2 -days 30 "$@" 89} 90 91genss() { 92 local cn=$1; shift 93 local key=$1; shift 94 local cert=$1; shift 95 96 exts=$(printf "%s\n%s\n%s\n%s\n%s\n[alts]\n%s\n" \ 97 "subjectKeyIdentifier = hash" \ 98 "authorityKeyIdentifier = keyid, issuer" \ 99 "basicConstraints = CA:true" \ 100 "extendedKeyUsage = serverAuth" \ 101 "subjectAltName = @alts" "DNS=${cn}") 102 req "$key" "$cn" | 103 cert "$cert" "$exts" -set_serial 1 -days 30 -signkey "${key}.pem" "$@" 104} 105 106gennocn() { 107 local key=$1; shift 108 local cert=$1; shift 109 110 req_nocn "$key" | 111 cert "$cert" "" -signkey "${key}.pem" -set_serial 1 -days -1 "$@" 112} 113 114runtest() { 115 local desc=$1; shift 116 local usage=$1; shift 117 local selector=$1; shift 118 local mtype=$1; shift 119 local tlsa=$1; shift 120 local ca=$1; shift 121 local chain=$1; shift 122 local digest 123 124 case $mtype in 125 0) digest="";; 126 1) digest=sha256;; 127 2) digest=sha512;; 128 *) echo "bad mtype: $mtype"; exit 1;; 129 esac 130 131 printf "%d %d %d %-24s %s: " "$usage" "$selector" "$mtype" "$tlsa" "$desc" 132 133 if [ -n "$ca" ]; then ca="$ca.pem"; fi 134 "$TEST" "$usage" "$selector" "$digest" "$tlsa.pem" "$ca" "$chain.pem" \ 135 "$@" > /dev/null 136} 137 138checkpass() { runtest "$@" && { echo pass; } || { echo fail; exit 1; }; } 139checkfail() { runtest "$@" && { echo fail; exit 1; } || { echo pass; }; } 140 141#--------- 142 143genss "$HOST" sskey sscert 144gennocn akey acert 145 146# Tests that might depend on akid/skid chaining 147# 148for rakid in "" \ 149 "authorityKeyIdentifier = keyid,issuer" \ 150 "authorityKeyIdentifier = issuer" \ 151 "authorityKeyIdentifier = keyid" 152do 153for cakid in "" \ 154 "authorityKeyIdentifier = keyid,issuer" \ 155 "authorityKeyIdentifier = issuer" \ 156 "authorityKeyIdentifier = keyid" 157do 158for rskid in "" "subjectKeyIdentifier = hash" 159do 160for caskid in "" "subjectKeyIdentifier = hash" 161do 162 163genroot "Root CA" rootkey rootcert "$rskid" "$rakid" 164genca "CA 1" cakey1 cacert1 "$caskid" "$cakid" rootcert rootkey 165genca "CA 2" cakey2 cacert2 "$caskid" "$cakid" cacert1 cakey1 166genee "$HOST" eekey eecert cacert2 cakey2 167cat eecert.pem cacert2.pem cacert1.pem rootcert.pem > chain.pem 168cat eecert.pem cacert2.pem cacert1.pem > chain1.pem 169 170for s in 0 1 171do 172 checkpass "OOB root TA" 2 "$s" 0 rootcert "" chain1 "$HOST" 173 checkpass "OOB TA" 2 "$s" 0 cacert2 "" eecert "$HOST" 174 checkpass "in-chain root TA" 2 "$s" 1 rootcert "" chain "$HOST" 175 176 for m in 0 1 2 177 do 178 checkpass "valid TA" 2 "$s" "$m" rootcert "" chain "$HOST" 179 for ca in "cacert1" "cacert2"; do 180 checkpass "valid TA" 2 "$s" "$m" "$ca" "" chain "$HOST" 181 checkpass "valid TA" 2 "$s" "$m" "$ca" "" chain1 "$HOST" 182 checkpass "valid TA+CA" 2 "$s" "$m" "$ca" rootcert chain1 "$HOST" 183 checkpass "sub-domain" 2 "$s" "$m" "$ca" "" chain1 whatever ".$DOMAIN" 184 checkfail "wrong name" 2 "$s" "$m" "$ca" "" chain1 "whatever" 185 done 186 done 187done 188 189done 190done 191done 192done 193 194# These tests don't depend in the akid/skid chaining: 195# 196for s in 0 1 197do 198 checkfail "missing TA" 2 "$s" 1 rootcert "" chain1 "$HOST" 199 for m in 0 1 2 200 do 201 checkpass "depth 0 TA" 2 "$s" "$m" sscert "" sscert "$HOST" 202 checkfail "non-TA" 2 "$s" "$m" eecert rootcert chain "$HOST" 203 checkfail "depth 0 TA namecheck" 2 "$s" "$m" sscert sscert sscert whatever 204 205 checkpass "valid EE" 3 "$s" "$m" eecert "" chain whatever 206 checkpass "key-only EE" 3 "$s" "$m" acert "" acert whatever 207 checkfail "wrong EE" 3 "$s" "$m" cacert2 "" chain whatever 208 done 209done 210 211rm -f *.pem 212