#!/bin/bash
###########################################################################
#user Variables 
#Must changes these variables
###########################################################################


###########################################################################
#Program Variables                                                        #
#Dont change these variables unless you know what you are doing)          #
###########################################################################

# Which OpenSSL config file are we using for this
export OPENSSL_CONF=$PWD/openssl.cnf

# Changed because this device is already previously initialized.
export FACTORY_DEFAULT_SOPIN="1636511164917894"

#OEM Default SOPIN
#export FACTORY_DEFAULT_SOPIN="3537363231383830"

###########################################################################
#Function definitions                                                     #
###########################################################################

function exit_error()
{
  echo 
  echo " FATAL ERROR: $1"
  echo " Script aborted."
  echo
  echo "-------------------------------------------------------------------------------"

  exit 1
}

###########################################################################
# Preflight work, exit on any errors                                       #
###########################################################################

# Banner and instructions for the user.
/usr/bin/clear
echo "==============================================================================="
echo " Intermediate CA Generator"
echo
echo "FAILURE TO FOLLOW SECURITY PROCEDURES CAN AND WILL RESULT IN CONSEQUENCES UP TO"
echo "AND INCLUDING LEGAL ACTION.  YOU ARE WARNED."
echo
echo "     Right now, you should be sitting inside the SCIF, reading this on the computer formerly contained in the safe.  Before we begin, ensure that the only devices plugged into this machine are:"
echo
echo "  * The *RED* PNY 8GB USB thumbdrive, with a GREEN 'PKI' tag."
echo "  * The *ORANGE* USB Thumbdrive that was in the safe with the former."
echo
echo "     This process involves swapping between two different NitroKey HSM devices.  Please ensure that you use the correct User PIN with the correct Nitrokey when prompted by the software, otherwise this process will fail."

echo
echo "You may hit CTRL-C now to cancel execution of this script."
echo
read -p "==============================================================================="

#Check for prerequiste packages
echo "Preflight:  Checking installed packages"
echo "-------------------------------------------------------------------------------"
echo

PKG_LIST="libccid pcscd pcsc-tools opensc libengine-pkcs11-openssl openssl"

for pkg in $PKG_LIST; do
  echo -n "Checking for package $pkg: "; 
  if [ $(dpkg -l | grep $pkg -c) -lt 1 ]; then
    echo "missing!"
    exit_error "Required package '$pkg' is not installed."
  else 
    echo "found.";
  fi
done
echo

echo "-------------------------------------------------------------------------------"
echo "Preflight:  Checking configuration file"
echo "-------------------------------------------------------------------------------"
echo

# Load in the SECRET variables
. ./online-SECRETS.inc

#Check the SOPIN
if [ $SECRET_SOPIN = "0000000000000000" ] ; then
  exit_error "SOPIN is still default.  Check offline-SECRETS.inc."
fi

export SECRET_SOPIN_LENGTH=$(echo $SECRET_SOPIN|wc -c)

if [ $SECRET_SOPIN_LENGTH -lt 17 ]; then
  exit_error "HSM SOPIN is too short.  Check offline-SECRETS.inc."
fi

#Check the USERPIN
if [ "$SECRET_USER_PIN" = "0000000000000000" ] ; then
  exit_error "USER PIN is still default.  Check offline-SECRETS.inc."
fi

export SECRET_USERPIN_LENGTH=$(echo $SECRET_USER_PIN|wc -c)

if [ $SECRET_USERPIN_LENGTH -lt 7 ]; then
  exit_error "USER PIN is too short.  Check offline-SECRETS.inc."
fi

echo "Length and content check complete."
echo

#Create directories to hold the bits
echo "-------------------------------------------------------------------------------"
echo "Preflight:  Creating certificate directory structure"
echo "-------------------------------------------------------------------------------"
echo

mkdir -vp ca/intermediate/{certs,crl,csr,newcerts}
mkdir -vp ca/{client,server}/{certs,csr,pfx,private}
touch ca/intermediate/database
echo 1000 | tee ca/intermediate/{serial,crlnumber}
chmod -v 700 ca/{client,server}/private
echo

echo "-------------------------------------------------------------------------------"
echo "Preflight:  Verifying absence of HSM"
echo "-------------------------------------------------------------------------------"
echo

# Detect HSMs and prompt until gone.
DETECTLOOP=1;
while [ $DETECTLOOP = 1 ]; do
  if [ $(pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -L 2>&1 | grep -c Slot) -gt 0 ]; then
    read -p "WARNING: There is a hardware security module plugged into this machine.  Please remove it now, and press ENTER."
    echo 
  else
    DETECTLOOP=0
  fi
done

echo "No existing HSM present."
echo
echo "-------------------------------------------------------------------------------"

echo "==============================================================================="
echo "Intermediate CA Generation"
echo "==============================================================================="
echo

############################################################################
#offline Root HSM Stuff
############################################################################

read -p "Insert the INTERMEDIATE Nitrokey HSM (tagged as 'I') and press ENTER."
echo

# Trust, but verify
if [ $(pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -L 2>&1 | grep -c Slot) -lt 1 ]; then
  exit_error "No Hardware HSM found."
fi

echo "Device found:"
echo
#List the nitrokey
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -L
echo 

#Setup the HSM for use
echo "-------------------------------------------------------------------------------"
echo "Setting up the HSM for first use."
echo "-------------------------------------------------------------------------------"
echo 

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --login --login-type so --so-pin $FACTORY_DEFAULT_SOPIN --change-pin --new-pin $SECRET_SOPIN
sc-hsm-tool --initialize --so-pin $SECRET_SOPIN --pin $SECRET_USER_PIN


echo "-------------------------------------------------------------------------------"
echo "Creating intermediate key"
echo "-------------------------------------------------------------------------------"
echo

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --login --keypairgen --key-type EC:prime256v1 --label intermediate
if [ "$?" -ne 0 ]; then exit_error "Key creation failed"; fi

echo
echo "-------------------------------------------------------------------------------"
echo "Creating intermediate certificate CSR"
echo "-------------------------------------------------------------------------------"
echo
openssl req -engine pkcs11 -keyform engine -new -key label_intermediate -out ca/intermediate/csr/intermediate.csr.pem -days 10240 -subj '/C=US/ST=Texas/O=TurnNetSystems/OU=Certificate Services/CN=TSYS Intermediate CA'
if [ "$?" -ne 0 ]; then exit_error "Create CSR failed"; fi

echo
echo "-------------------------------------------------------------------------------"
echo "Signing intermediate certificate"
echo "-------------------------------------------------------------------------------"
echo

echo "Please REMOVE the INTERMEDIATE Nitrokey (marked 'I')"
echo "and INSERT the ROOT Nitrokey (marked 'R')"
read -p " and press ENTER to continue."

openssl ca -engine pkcs11 -keyform engine -name ca_root -extensions ext_intermediate -notext -in ca/intermediate/csr/intermediate.csr.pem -out ca/intermediate/certs/intermediate.cert.pem
if [ "$?" -ne 0 ]; then exit_error "Certificate signing failed."; fi

echo
echo "-------------------------------------------------------------------------------"
echo "Verifying intermediate certificate"
echo "-------------------------------------------------------------------------------"
echo

openssl x509 -noout -text -in ca/intermediate/certs/intermediate.cert.pem 
if [ "$?" -ne 0 ]; then exit_error "Verification failed."; fi
openssl verify -CAfile ca/root/certs/root.cert.pem ca/intermediate/certs/intermediate.cert.pem 
if [ "$?" -ne 0 ]; then exit_error "Verification failed."; fi

echo
echo "-------------------------------------------------------------------------------"
echo "Store Root and Intermediate Certificates on HSM"
echo "-------------------------------------------------------------------------------"
echo

echo "Please REMOVE the ROOT Nitrokey (marked 'R')"
echo "and INSERT the INTERMEDIATE Nitrokey (marked 'I')"
read -p " and press ENTER to continue."

openssl x509 -in ca/intermediate/certs/intermediate.cert.pem -out ca/intermediate/certs/intermediate.cert.der -outform der
if [ "$?" -ne 0 ]; then exit_error "Certificate conversion failed"; fi

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --login --write-object ca/root/certs/root.cert.der --type cert --label root
if [ "$?" -ne 0 ]; then exit_error "Failed to store root certificate"; fi

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --login --write-object ca/intermediate/certs/intermediate.cert.der --type cert --label intermediate
if [ "$?" -ne 0 ]; then exit_error "Failed to store intermediate certificate"; fi

echo
echo "-------------------------------------------------------------------------------"
echo "Creating chain certificate"
echo "-------------------------------------------------------------------------------"
echo

cat ca/intermediate/certs/intermediate.cert.pem ca/root/certs/root.cert.pem > ca/intermediate/certs/chain.cert.pem
chmod 444 ca/intermediate/certs/chain.cert.pem


echo
echo "-------------------------------------------------------------------------------"
echo "Visual verification"
echo "-------------------------------------------------------------------------------"
echo
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -L -O

echo
echo "Done."
echo
echo "-------------------------------------------------------------------------------"
