#!/bin/bash

function gen_provisioning_csr {
    SEALED_KEY_FILENAME="$OP_NAME.bin"
    UNSEALED_KEY_FILENAME="$OP_NAME.key"
    CSR_SUBJECT="/C=$OP_CSR_COUNTRY/ST=$OP_CSR_STATE/L=$OP_CSR_LOCALITY/O=$OP_CSR_ORG/OU=$OP_CSR_ORG_UNIT/CN=$OP_NAME"
    SANITIZED_CSR_CONTENT=

    # ensure provisioning cert generation directory exists. If not, create it.
    if ! "$OP_MKDIR" -p "$CERT_GEN_DIR"; then
        echo "Could not create the provisioning cert generation directory: $CERT_GEN_DIR . Check permissions."
        exit 1
    fi
    # clear the contents of the provisioning cert generation directory, to ensure we do not re-use any csr/key created previously
    if ! "$OP_RM" -f "$CERT_GEN_DIR/$CERT_GEN_EXTENSIONS"; then
        echo "Could not clear existing contents of the provisioning cert generation directory: $CERT_GEN_DIR . Check permissions."
        exit 1
    fi
    # generate key pair and csr (particular command depends on existence of tpm)
    if [ "$OP_TPM" = "true" ]; then
        # generating keypair, private key is sealed using the tpm
        if ! OPENSSL_ENGINES="$TPM2TSS_ENGINE" TPM2TSSENGINE_TCTI="$OP_TPM2TSSENGINE_TCTI" "$TPM2TSS_GENKEY" -a "$OP_PROVISIONING_KEY_ALG" -s "$OP_PROVISIONING_KEY_SIZE" "$CERT_GEN_DIR/$SEALED_KEY_FILENAME"; then
            echo "Could not generate key pair using TPM. Ensure TPM software stack are installed correctly."
            exit 1
        fi
        # generating csr
        if ! "$OP_OPENSSL" req -engine tpm2tss -keyform ENGINE -new -key "$CERT_GEN_DIR"/"$SEALED_KEY_FILENAME" -out "$CERT_GEN_DIR"/"$OP_NAME".csr  -subj "$CSR_SUBJECT"; then
            echo "Could not generate CSR using TPM. Ensure TPM software stack are installed correctly."
            exit 1
        fi
    else
        if [ "$OP_TPM" = "false" ]; then
        # generating csr without a tpm. Private key will be unsealed. Primary use is for machines that do not (yet) have the TPM chip.
        # generating unsealed private key
            if ! "$OP_OPENSSL" genpkey -algorithm "$OP_PROVISIONING_KEY_ALG" -out "$CERT_GEN_DIR"/"$UNSEALED_KEY_FILENAME" -pkeyopt "$OP_PROVISIONING_KEY_NOTPM_OPTIONS"; then
                echo "Could not generate key (no TPM). Ensure OpenSSL is installed correctly."
                exit 1
            fi
            # generating csr
            if ! "$OP_OPENSSL" req -new -key "$CERT_GEN_DIR"/"$UNSEALED_KEY_FILENAME" -out "$CERT_GEN_DIR"/"$OP_NAME".csr -subj "$CSR_SUBJECT"; then
                echo "Could not generate CSR (no TPM). Ensure OpenSSL is installed correctly."
                exit 1
            fi
            else
                echo "Invalid value for option '-p' or '--with-op-tpm'. Legitimate values are: 'true' or 'false'; case-sensitive and without single-quotes."
            fi
    fi
    # prepare contents of a json file with cert req parameters expected by Vault
    # reading csr and santizing its content (convert csr newlines created by openssl to '\n')
    if ! SANITIZED_CSR_CONTENT=$("$OP_CAT" "$CERT_GEN_DIR/$OP_NAME".csr | "$OP_JQ" --raw-input --slurp --compact-output '.'); then
        echo "Could not read and sanitize the local CSR file. Make sure 'jq' and 'cat' are installed and used correctly on target and CSR file is accessible."
        exit 1
    fi

    # adding json file parameters. Vault doesn't seem to return the correct "DER", so we'll use PEM here. We convert it to DER later as it's more compressed, and allows for efficient storage in the tpm chip.
    # Note: Sanitized CSR content is already surrounded with double qutoes, so we don't include them here
    if ! echo "{" \"csr\": "$SANITIZED_CSR_CONTENT" "," \"format\": \"pem\" "}" > "$CERT_GEN_DIR"/"$OP_NAME".json ; then
        echo "Could not generate JSON file."
        exit 1
    fi
}
