# 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: setup PKCS#11 test environment.
#

TEST_SSH_PIN=${TEST_SSH_PIN-1234}
TEST_SSH_SOPIN=${TEST_SSH_SOPIN-12345678}

CWD=${CWD-$OBJ}


# find a PKCS#11 module
p11_find_module() {
  if test -z "$TEST_SSH_PKCS11" ; then
    for D in \
      /usr/lib64/pkcs11 \
      /usr/lib64/softhsm \
      /usr/lib/x86_64-linux-gnu/softhsm \
      /usr/local/lib/softhsm \
      /opt/local/lib/softhsm \
      /usr/lib/softhsm \
      /usr/lib \
    ; do
      test -d "$D" || continue

      if test -f "$D"/libsofthsm2.so ; then
        TEST_SSH_PKCS11="$D"/libsofthsm2.so
        break
      fi
    done
    test -n "$TEST_SSH_PKCS11"
  else
    test -f "$TEST_SSH_PKCS11"
  fi
}


# find a SoftHSM2 utility
p11_find_SOFTHSM2_TOOL() {
  if test -z "$SOFTHSM2_TOOL" ; then
    for D in \
      /usr/bin \
      /usr/local/bin \
      /opt/local/bin \
    ; do
      test -d "$D" || continue

      if test -x "$D/softhsm2-util" ; then
        SOFTHSM2_TOOL="$D/softhsm2-util"
        break
      fi
    done
    test -n "$SOFTHSM2_TOOL"
  else
    test -x "$SOFTHSM2_TOOL"
  fi
}


# find a SoftHSM2 utility
p11_find_PKCS11_TOOL() {
  if test -z "$PKCS11_TOOL" ; then
    for D in \
      /usr/bin \
      /usr/local/bin \
      /opt/local/bin \
    ; do
      test -d "$D" || continue

      if test -x "$D/pkcs11-tool" ; then
        PKCS11_TOOL="$D/pkcs11-tool"
        break
      fi
    done
    test -n "$PKCS11_TOOL"
  else
    test -x "$PKCS11_TOOL"
  fi
}


# prepare PKCS#11 askpass helper utility
P11_ASKPASS=$CWD/ssh_askpass-pkcs11
cre_ssh_p11_askpass() {
if test -x "$P11_ASKPASS" ; then :
else
  cat > $P11_ASKPASS <<EOF
#! $TEST_SHELL
echo $TEST_SSH_PIN
EOF
  chmod 0700 $P11_ASKPASS
fi
}


# force load with token PIN.
p11_ssh_add() {
  cre_ssh_p11_askpass

  SSHADD=${SSHADD-$TEST_SSH_SSHADD}
  env SSH_ASKPASS="$P11_ASKPASS" SSH_ASKPASS_REQUIRE=force \
  $SSHADD ${1+"$@"}
}


# prepares a softhsm2 token configuration
p11_token_conf() {
	EXTRA_AGENT_ARGS="$EXTRA_AGENT_ARGS -P$TEST_SSH_PKCS11"

	# setup environment for softhsm2 token
	SSH_SOFTHSM_DIR=$CWD/softhsm
	export SSH_SOFTHSM_DIR
	rm -rf $SSH_SOFTHSM_DIR

	TOKEN=$SSH_SOFTHSM_DIR/tokens
	$abs_top_srcdir/install-sh -d $TOKEN

	SOFTHSM2_CONF=$SSH_SOFTHSM_DIR/softhsm2.conf
	export SOFTHSM2_CONF
	cat > $SOFTHSM2_CONF << EOF
# PKIX-SSH test - SoftHSM v2 configuration file
directories.tokendir = $TOKEN
objectstore.backend = file

slots.removable = false
slots.mechanisms = ALL

# ERROR, WARNING, INFO, DEBUG
log.level = ERROR
#log.level = DEBUG
EOF
}


# find a PKCS#11 engine
p11_find_engine() {
  if test -z "$TEST_SSH_PKCS11_ENGINE" ; then

    # use command and try to extract path
    enginedir=`$OPENSSL version -e 2>/dev/null`
    if test -n "$enginedir" ; then
      enginedir=`set -- $enginedir; test "x$1" = "xENGINESDIR:" && echo $2`
    fi

    # failback to defaults
    if test -n "$enginedir" ; then
      case $openssl_version in
      *"OpenSSL 3."*)  enginedir=engines-3;;   #why command fail?
      *"OpenSSL 1.1"*) enginedir=engines-1.1;; #why command fail?
      *"OpenSSL 1."*)  enginedir=engines;;
      esac
    fi

    test -n "$enginedir" &&
    for D in \
      /usr/lib64/$enginedir \
      /usr/lib/$enginedir \
    ; do
      test -d "$D" || continue

      if test -f "$D"/pkcs11.so ; then
        TEST_SSH_PKCS11_ENGINE="$D"/pkcs11.so
        break
      fi
      if test -f "$D"/libpkcs11.so ; then
        TEST_SSH_PKCS11_ENGINE="$D"/libpkcs11.so
        break
      fi
    done
    test -n "$TEST_SSH_PKCS11_ENGINE"
  else
    test -f "$TEST_SSH_PKCS11_ENGINE"
  fi
}


# find a PKCS#11 provider
p11_find_provider() {
  if test -z "$TEST_SSH_PKCS11_PROVIDER" ; then

    # use command and try to extract path
    moduledir=`$OPENSSL version -m 2>/dev/null`
    if test -n "$moduledir" ; then
      moduledir=`set -- $moduledir; test "x$1" = "xMODULESDIR:" && echo $2`
    fi

    test -n "$moduledir" &&
    for D in \
      /usr/lib64/$moduledir \
      /usr/lib/$moduledir \
    ; do
      test -d "$D" || continue

      if test -f "$D"/pkcs11.so ; then
        TEST_SSH_PKCS11_PROVIDER="$D"/pkcs11.so
        break
      fi
      if test -f "$D"/libpkcs11.so ; then
        TEST_SSH_PKCS11_PROVIDER="$D"/libpkcs11.so
        break
      fi
    done
    test -n "$TEST_SSH_PKCS11_PROVIDER"
  else
    test -f "$TEST_SSH_PKCS11_PROVIDER"
  fi
}
