# Copyright (c) 2023-2025 Roumen Petrov, Sofia, Bulgaria
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# DESCRIPTION: PKCS#11 token setup for X.509 tests.
#


# load X.509 certificate to pkcs#11 token:
load_cert=:
#load_cert=false


# ===
#env. vars:
#  TEST_SSH_PKCS11 - pkcs#11 module
#  userpin
p11_module_write() {
  OPENSC_DEBUG=1 \
  $PKCS11_TOOL --module $TEST_SSH_PKCS11 --verbose \
    --login --pin $userpin \
    ${1+"$@"} \
  >> $SSH_MODULE_LOG 2>&1
}


# ===
#args:
#  $1 - userpin
#  $2 - key_file
#  $3 - key_id
#  $4 - key_label
p11_write_object() {
  userpin=$1
  key_file=$2
  key_id=$3
  key_label=$4

  echo "write ${extd}$key_label${norm} ..." >&2

  echo "= prepare $key_id ..." >> $SSH_MODULE_LOG
  $OPENSSL x509 -in $key_file -outform DER -out pkcs11_tool-$key_id-cert.der || return $?

  key_type=privkey
  echo "== write $key_id-$key_type" >> $SSH_MODULE_LOG
  $OPENSSL pkey -in $key_file -outform DER -out pkcs11_tool-$key_id-$key_type.der || return $?
  p11_module_write \
    --write-object pkcs11_tool-$key_id-$key_type.der --type $key_type \
    --id $key_id --label "$key_label" \
    --attr-from pkcs11_tool-$key_id-cert.der \
  || return $?
  rm -f pkcs11_tool-$key_id-$key_type.der

  key_type=pubkey
  echo "== write $key_id-$key_type" >> $SSH_MODULE_LOG
  $OPENSSL pkey -in $key_file -outform DER -pubout -out pkcs11_tool-$key_id-$key_type.der || return $?
  p11_module_write \
    --write-object pkcs11_tool-$key_id-$key_type.der --type $key_type \
    --id $key_id --label "$key_label" \
  || return $?
  rm -f pkcs11_tool-$key_id-$key_type.der

if $load_cert ; then
  key_type=cert
  echo "== write $key_id-$key_type" >> $SSH_MODULE_LOG
  p11_module_write \
    --write-object pkcs11_tool-$key_id-$key_type.der --type $key_type \
    --id $key_id --label "$key_label" \
  || return $?
fi

  rm -f pkcs11_tool-$key_id-cert.der
}


# ===
p11_setup_token() {
  p11_token_conf

  # stop on first rsa digest
  for type in $SSH_SIGN_TYPES; do
    case $type in
    *rsa*);;
    *) continue;;
    esac
    break;
  done

  # setup token
  echo "create ${extd}test0${norm} token ..." >&2
  echo "=== create token" >> $SSH_MODULE_LOG
  $SOFTHSM2_TOOL --init-token --label test0 --slot free \
    --so-pin $TEST_SSH_SOPIN --pin $TEST_SSH_PIN \
    >> $SSH_MODULE_LOG 2>&1 \
  || return $?

  # load keys and X.509 certificates
  for SSH_CLIENTKEY in $TEST_SSH_CLIENTKEYS; do
    case $SSH_CLIENTKEY in
    *rsa*)         key_id='0001'; key_label=p11-rsa;;
    *eccnistp256*) key_id='0002'; key_label=p11-ec256;;
    *eccnistp384*) key_id='0003'; key_label=p11-ec384;;
    *eccnistp521*) key_id='0004'; key_label=p11-ec521;;
    *ed25519*)     key_id='0005'; key_label=p11-ed;;
    *) continue;;
    esac
    p11_write_object $TEST_SSH_PIN $SSH_CLIENTKEY-$type $key_id $key_label \
    || return $?
  done
  echo "=== write end" >> $SSH_MODULE_LOG
}
