#!/bin/bash -e
# Copyright (C) 2022 Simo Sorce <simo@redhat.com>
# SPDX-License-Identifier: Apache-2.0

source "${TESTSSRCDIR}/helpers.sh"

DEMOCA="${TMPPDIR}/demoCA"

title PARA "Set up demoCA"
mkdir -p "${DEMOCA}/newcerts" "${DEMOCA}/private"
if [ ! -e "${DEMOCA}/serial" ]; then
    echo "01" > "${DEMOCA}/serial"
fi
touch "${DEMOCA}/index.txt"

title PARA "Generating CA cert if needed"
if [ ! -e "${DEMOCA}/cacert.pem" ]; then
    ossl 'req -batch -noenc -x509 -new -key ${PRIURI} -out ${DEMOCA}/cacert.pem'
fi

title PARA "Generating a new CSR with key in file"
ossl '
req -batch -noenc -newkey rsa:2048
    -subj "/CN=testing-csr-signing/O=PKCS11 Provider/C=US"
    -keyout ${DEMOCA}/cert.key -out ${DEMOCA}/cert.csr'

title PARA "Signing the new certificate"
ossl '
ca -batch -in ${DEMOCA}/cert.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'

title PARA "Generating a new CSR with existing RSA key in token"
ossl '
req -batch -noenc -new -key ${PRIURI}
    -subj "/CN=testing-rsa-signing/O=PKCS11 Provider/C=US"
    -out ${DEMOCA}/cert-rsa.csr'

title PARA "Signing the new RSA key certificate"
ossl '
ca -batch -in ${DEMOCA}/cert-rsa.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'

title PARA "Generating a new CSR with existing EC key in token"
ossl '
req -batch -noenc -new -key ${ECPRIURI}
    -subj "/CN=testing-ec-signing/O=PKCS11 Provider/C=US"
    -out ${DEMOCA}/cert-ec.csr'

title PARA "Signing the new EC key certificate"
ossl '
ca -batch -in ${DEMOCA}/cert-ec.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'


if [[ -n $EDPRIURI ]]; then
    title PARA "Generating a new CSR with existing ED key in token"
    ossl '
    req -batch -noenc -new -key ${EDPRIURI}
        -subj "/CN=testing-ed-signing/O=PKCS11 Provider/C=US"
        -out ${DEMOCA}/cert-ed.csr'

    title PARA "Signing the new ED key certificate"
    ossl '
    ca -batch -in ${DEMOCA}/cert-ed.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'
fi

if [[ -n $ED2PRIURI ]]; then
    title PARA "Generating a new CSR with existing ED448 key in token"
    ossl '
    req -batch -noenc -new -key ${ED2PRIURI}
        -subj "/CN=testing-ed2-signing/O=PKCS11 Provider/C=US"
        -out ${DEMOCA}/cert-ed2.csr'

    title PARA "Signing the new ED448 key certificate"
    ossl '
    ca -batch -in ${DEMOCA}/cert-ed2.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'
fi

if [[ -n $RSAPSSPRIURI ]]; then
    title PARA "Generating a new CSR with existing RSA-PSS key in token"
    ossl '
    req -batch -noenc -new -key ${RSAPSSPRIURI} -sigopt rsa_padding_mode:pss
        -subj "/CN=testing-rsapss-signing/O=PKCS11 Provider/C=US"
        -sigopt rsa_padding_mode:pss
        -out ${DEMOCA}/cert-rsa-pss.csr'

    title PARA "Signing the new RSA-PSS key certificate"
    ossl '
    ca -batch -in ${DEMOCA}/cert-rsa-pss.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'

    ossl 'x509 -text -in ${DEMOCA}/cert.pem' "$helper_emit"
    output="$helper_output"
    FAIL=1
    echo "$output" | grep "No PSS parameter restrictions" > /dev/null 2>&1 && FAIL=0
    if [ $FAIL -ne 0 ]; then
        echo "Generated certificate has some RSA-PSS restrictions while it should not"
        echo "$output";
        exit 1
    fi
fi

if [[ -n $RSAPSS2PRIURI ]]; then
    title PARA "Generating a new CSR with existing SHA256 restricted RSA-PSS key in token"
    ossl '
    req -batch -noenc -new -key ${RSAPSS2PRIURI} -sigopt rsa_padding_mode:pss
        -subj "/CN=testing-rsapss-sha2-signing/O=PKCS11 Provider/C=US"
        -out ${DEMOCA}/cert-rsa-pss2.csr
        -sigopt rsa_padding_mode:pss
        -sigopt digest:sha256'

    title PARA "Signing the new SHA256 restricted RSA-PSS key certificate"
    ossl '
    ca -batch -in ${DEMOCA}/cert-rsa-pss2.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'

    ossl 'x509 -text -in ${DEMOCA}/cert.pem' "$helper_emit"
    output="$helper_output"
    # TODO we should get restrictions visible here when implemented
    #FAIL=0
    #echo "$output" | grep "No PSS parameter restrictions" > /dev/null 2>&1 && FAIL=1
    #if [ $FAIL -ne 0 ]; then
    #    echo "Generated certificate does not have any RSA-PSS restrictions while it should"
    #    echo "$output";
    #    exit 1
    #fi
fi

if [[ -n $RSAPSS2PRIURI ]]; then
    title PARA "Generating a new CSR with existing RSA-PSS key in token"
    ossl '
    req -batch -noenc -new -key ${RSAPSS2PRIURI} -sigopt rsa_padding_mode:pss
        -subj "/CN=testing-rsapss-signing/O=PKCS11 Provider/C=US"
        -out ${DEMOCA}/cert-rsa-pss2.csr
        -sigopt rsa_padding_mode:pss
        -sigopt digest:sha256
        -sigopt rsa_pss_saltlen:-2'

    title PARA "Signing the new RSA-PSS key certificate"
    ossl '
    ca -batch -in ${DEMOCA}/cert-rsa-pss.csr -keyfile ${PRIURI} -out ${DEMOCA}/cert.pem'
fi

title PARA "Set up OCSP"
ossl '
req -batch -noenc -new -subj "/CN=OCSP/O=PKCS11 Provider/C=US"
    -key ${PRIURI} -out ${DEMOCA}/ocspSigning.csr'
ossl '
ca -batch -keyfile ${PRIURI} -cert ${DEMOCA}/cacert.pem
   -in ${DEMOCA}/ocspSigning.csr -out ${DEMOCA}/ocspSigning.pem'


#The next test is not working on Debian for some reason, so skip the rest for now
if [ -e /etc/debian_version ]; then
    exit 0
fi

title PARA "Run OCSP"
PORT=12345
trap kill_children EXIT
#Unclear why but w/o -rmd sha1 this fails
#call this without wrapper otherwise we have issues killing it later ...
# shellcheck disable=SC2153 # the PRIURI is defined in setup-soft{hsm,okn}
$CHECKER openssl ocsp -index "${DEMOCA}/index.txt" -rsigner \
    "${DEMOCA}/ocspSigning.pem" -rkey "${PRIURI}" -CA "${DEMOCA}/cacert.pem" \
    -rmd sha256 -port "${PORT}" -text &
sleep 0.5
# with valgrind, it might take a bit longer
if [ -n "$VALGRIND" ]; then
    sleep 5
fi
ossl '
ocsp -CAfile ${DEMOCA}/cacert.pem -issuer ${DEMOCA}/cacert.pem
     -cert ${DEMOCA}/cert.pem -resp_text -noverify
     -url http://127.0.0.1:${PORT}' $helper_emit
output="$helper_output"
FAIL=0
echo "$output" | grep ": good" > /dev/null 2>&1 || FAIL=1
if [ $FAIL -eq 1 ]; then
    echo "The OCSP response failed"
    echo
    echo "Original command output:"
    echo "$output"
    echo
    exit 1
fi

title PARA "Kill any remaining children and wait for them"
kill_children

exit 0
