#! /usr/bin/env bash # Bash needed for PIPESTATUS array extract() { case "$4" in 0) openssl x509 -in "$1" -outform DER;; 1) openssl x509 -in "$1" -noout -pubkey | openssl pkey -pubin -outform DER;; esac } digest() { case "$5" in 0) cat;; 1) openssl dgst -sha256 -binary;; 2) openssl dgst -sha512 -binary;; esac } encode() { local cert=$1; shift local hostport=$1; shift local u=$1; shift local s=$1; shift local m=$1; shift local host=$hostport local port=25 OIFS="$IFS"; IFS=":"; set -- $hostport; IFS="$OIFS" if [ $# -eq 2 ]; then host=$1; port=$2; fi printf "_%d._tcp.%s. IN TLSA %d %d %d %s\n" \ "$port" "$host" "$u" "$s" "$m" \ "$(hexdump -ve '/1 "%02X"')" } error() { echo "$1" 1>&2; exit 1; } usage() { error "Usage: $0 cert.pem host[:port] usage selector mtype"; } if [ $# -ne 5 ]; then usage; fi case "$(echo $3 | tr '[A-Z]' '[a-z]')" in 0|pkix-[ct]a) usage=0;; 1|pkix-ee) usage=1;; 2|dane-[ct]a) usage=2;; 3|dane-ee) usage=3;; *) error "Invalid certificate usage: $3";; esac case "$(echo $4 | tr '[A-Z]' '[a-z]')" in 0|cert) selector=0;; 1|spki|pkey) selector=1;; *) error "Invalid selector: $4";; esac case "$(echo $5 | tr '[A-Z]' '[a-z]')" in 0|full) mtype=0;; 1|sha2-256|sha256|sha-256) mtype=1;; 2|sha2-512|sha512|sha-512) mtype=2;; *) error "Invalid matching type: $5";; esac set -- "$1" "$2" "$usage" "$selector" "$mtype" rr=$( extract "$@" | digest "$@" | encode "$@" exit $(( ${PIPESTATUS[0]} | ${PIPESTATUS[1]} | ${PIPESTATUS[2]} )) ) status=$? if [ $status -ne 0 ]; then exit $status fi echo "$rr"