#! /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"
