#!/bin/bash

function store_provisioning_cert_on_provisioner {
    # make sure the provisioning storage dir exists and create it if it does not.
    if ! "$OP_MKDIR" -p "$CERT_STORE_DIR"; then
        echo "Could not create the provisioning storage directory: $CERT_STORE_DIR . Check permissions."
        exit 1
    fi
    # check that the provisioning gen directory contains the recently generated provisioning cert
    if ! test -f "$CERT_GEN_DIR/$OP_NAME.crt"; then
        echo "Generated provisioning certificate, $OP_NAME.crt, cannot be found at $CERT_GEN_DIR . Make sure it is generated successfully and is accessible."
        exit 1
    fi
    # check that the private key exists (extension depends on whether a tpm is used or not)
    if [ "$OP_TPM" = "false" ]; then
        # check that the provisioning gen directory contains the 'unsealed' private key (indicated by .key extension)
        if ! test -f "$CERT_GEN_DIR/$OP_NAME.key"; then
            echo "Generated provisioning unsealed key, $OP_NAME.key, cannot be found at $CERT_GEN_DIR . Make sure it is generated successfully and is accessible."
            exit 1
        fi
        # clear the current provisioning storage dir
        if ! "$OP_RM" -f "$CERT_STORE_DIR/$CERT_STORE_EXTENSIONS"; then
            echo "Could not clear existing contents of the provisioning storage directory: $CERT_STORE_DIR . Check permissions."
            exit 1
        fi
        # copy the unsealed private key and provisioning cert into the provisioning storage dir
        if ! "$OP_CP" "$CERT_GEN_DIR/$OP_NAME.key" "$CERT_STORE_DIR"; then
            echo "Could not copy the unsealed private key $CERT_GEN_DIR/$OP_NAME.key to $CERT_STORE_DIR. Check file accessiblity."
            exit 1
        fi
        if ! "$OP_CP" "$CERT_GEN_DIR/$OP_NAME.crt" "$CERT_STORE_DIR"; then
            echo "Could not copy the generated provisioning certificate $CERT_GEN_DIR/$OP_NAME.crt to $CERT_STORE_DIR. Check file accessiblity."
            exit 1
        fi
    else
        if [ "$OP_TPM" = "true" ]; then
            # check that the provisioning cert gen directory contains the recently generated 'sealed' private key and provisioning cert
            if ! test -f "$CERT_GEN_DIR/$OP_NAME.bin"; then
                echo "Generated provisioning sealed key, $OP_NAME.bin, cannot be found at $CERT_GEN_DIR . Make sure it is generated successfully and is accessible."
                exit 1
            fi
            # clear the corresponding indices for storing provisioning cert and private key from the tpm
            if ! "$TPM2_NV_UNDEFINE" "$OP_TPM2_PROVISIONING_CERT_INDEX 2>/dev/null"; then
                echo "Could not clear TPM NVRAM index $OP_TPM2_PROVISIONING_CERT_INDEX allocated for storing the provisioning certificate. Check accessibility of TPM tools, TPM module, and correctness of PCR policies."
                echo "Ignore If the TPM device has not been provisioned with a provisioning cert before."
                #exit 1
            fi
            if ! "$TPM2_NV_UNDEFINE" "$OP_TPM2_PROVISIONING_SEALEDKEY_INDEX 2>/dev/null"; then
                echo "Could not clear TPM NVRAM index $OP_TPM2_PROVISIONING_SEALEDKEY_INDEX allocated for storing sealed provisioning key. Check accessibility of TPM tools, TPM module, and correctness of PCR policies."
                echo "Ignore If the TPM device has not been provisioned with a provisioning cert before. Otherwise, you must reprovision again as no provisioning cert exists on the TPM now (previous provisioning cert, if any, has been removed)."
                #exit 1
            fi

            # clear the current provisioning storage dir
            if ! "$OP_RM" -f "$CERT_STORE_DIR/$CERT_STORE_EXTENSIONS"; then
                echo "Could not clear existing contents of the provisioning storage directory: $CERT_STORE_DIR . Check permissions."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi

            ##### store provisioning cert on corresponding indeces in the tpm #####
            # convert the generated provisioning cert, which is in PEM format to the more efficient DER format for storage on tpm
            if ! "$OP_OPENSSL" x509 -inform PEM -outform DER -in "$CERT_GEN_DIR/$OP_NAME.crt" -out "$CERT_GEN_DIR/$OP_NAME.der"; then
                echo "Could not convert the generated PEM provisioning certificate into a DER certificate. Ensure the generated cert is formatted correctly."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            # find size of the provisioning cert
            if ! OP_PROVISIONING_CERT_SIZE="$("$OP_CAT" "$CERT_GEN_DIR/$OP_NAME.der" | "$OP_WC" -c )"; then
                echo "Could not calculate size of the provisioning cert. Ensure the provisioning cert has been generated successfully and $OP_CAT and $OP_WC are runnable."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            # define tpm nvram index where the provisioning cert would be written
            if ! "$TPM2_NV_DEFINE" "$OP_TPM2_PROVISIONING_CERT_INDEX" -C o -s "$OP_PROVISIONING_CERT_SIZE"; then
                echo "Could not allocate TPM NVRAM index $OP_TPM2_PROVISIONING_CERT_INDEX for the provisioning certificate of size $OP_PROVISIONING_CERT_SIZE. Ensure the size is within acceptable range, tpm tools are accessible, and PCR policies are correctly set."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            # write provisioning cert onto the corresponding tpm nvram index
            if ! "$TPM2_NV_WRITE" "$OP_TPM2_PROVISIONING_CERT_INDEX" -i "$CERT_GEN_DIR/$OP_NAME.der" -C o ; then
                echo "Could not write the generated provisioning certificate (in DER) onto the TPM NVRAM. Check the cert is available, TPM tools are accessible, and PCR policies are set correctly."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            ##### storing sealed provisioning key on corresponding index in the tpm
            # find size of the provisioning key
            if ! OP_PROVISIONING_KEY_SIZE="$("$OP_CAT" "$CERT_GEN_DIR/$OP_NAME.bin" | "$OP_WC" -c )"; then
                echo "Could not calculate size of the provisioning key. Ensure the provisioning key has been generated successfully and $OP_CAT and $OP_WC are runnable."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            # define tpm nvram index where the provisioning key would be written
            if ! "$TPM2_NV_DEFINE" "$OP_TPM2_PROVISIONING_SEALEDKEY_INDEX" -C o -s "$OP_PROVISIONING_KEY_SIZE"; then
                echo "Could not allocate TPM NVRAM index $OP_TPM2_PROVISIONING_SEALEDKEY_INDEX for the provisioning key of size $OP_PROVISIONING_KEY_SIZE. Ensure the size is within acceptable range, tpm tools are accessible, and PCR policies are correctly set."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi
            # write provisioning key onto the corresponding tpm nvram index
            if ! "$TPM2_NV_WRITE" "$OP_TPM2_PROVISIONING_SEALEDKEY_INDEX" -i "$CERT_GEN_DIR/$OP_NAME.bin" -C o; then
                echo "Could not write the generated provisioning key onto the TPM NVRAM. Check the key file is available, TPM tools are accessible, and PCR policies are set correctly."
                echo "You must reprovision again as no provisioning cert and key exists on the TPM now (previous provisioning cert and key, if any, have been removed)."
                exit 1
            fi

            # copy the sealed private key, PEM & DER provisioning certs into the storage provisioning cert dir. This is done for testing purposes here. Operator machines should overwrite this directory by extracting and copying cert and sealed key from the tpm upon startup (separate script needed).
            if ! "$OP_CP" "$CERT_GEN_DIR/$OP_NAME.bin" "$CERT_STORE_DIR"; then
                echo "Could not copy the sealed private key $CERT_GEN_DIR/$OP_NAME.bin to $CERT_STORE_DIR. Check file accessiblity."
                exit 1
            fi
            if ! "$OP_CP" "$CERT_GEN_DIR/$OP_NAME.der" "$CERT_STORE_DIR"; then
                echo "Could not copy the generated provisioning certificate $CERT_GEN_DIR/$OP_NAME.der to $CERT_STORE_DIR. Check file accessiblity."
                exit 1
            fi
            if ! "$OP_CP" "$CERT_GEN_DIR/$OP_NAME.crt" "$CERT_STORE_DIR"; then
                echo "Could not copy the generated provisioning certificate $CERT_GEN_DIR/$OP_NAME.crt to $CERT_STORE_DIR. Check file accessiblity."
                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."
            exit 1
        fi
    fi
}
