SignPath

Documentation  ❯  Crypto Providers   ❯   Cryptoki/PKCS#11

General instructions

The SignPath Cryptoki library is used to enable code signing using tools that support the Cryptoki/PKCS #11 standard.

Cryptoki and PKCS #11

Cryptoki is the Cryptographic Token Interface defined by the PKCS #11 standard. It is used by cryotographic software to access encryption and signing keys that are not stored on disks.

Cryptoki/PKCS #11 is primarily used in the Open Source ecosystem, e.g. Linux tools and their ports to other platforms including Windows. Some tools support it indirectly through their own provider ecosystem, e.g. Java via SunPKCS11 and GPG via gnupg-pkcs11-scd.

This section provides general information about using the SignPath Cryptoki library with code signing tools. Subsequent sections provide instructions for specific tools.

Supported Linux distributions

Distribution Version Comment
Debian 11 “bullseye”  
Debian 12 “bookworm”  
Ubuntu 20.04 Except osslsigncode
Ubuntu 22.04  
Ubuntu 24.04  
RedHat 8 (latest minor)  
RedHat 9 (latest minor)  

OpenSSL 3.0.0 - 3.0.8 incompatibility

Distributions with an OpenSSL version between 3.0.0 and 3.0.8 (including) don’t support the the OpenSSL and osslsigncode scenarios. The reason is an OpenSSL bug which has been fixed in OpenSSL 3.0.9. The issue results in “http_exception occurred (error code= generic:168296454): Error in SSL handshake” errors.

You need to replace the system’s OpenSSL version with >= 3.0.9 or use an isolated OpenSSL installation.

Installation

Windows

The Cryptoki library is installed to %ProgramFiles%\SignPath\CryptoProviders\SignPath.Cryptoki.dll by the MSI installer.

Alternatively, you can copy-deploy Windows\SignPath.Cryptoki.dll from the Crypto Providers ZIP archive to your target system.

Linux

Copy-deploy the Cryptoki library Linux/libSignPath.Cryptoki/$OpenSslVersion/libSignPath.Cryptoki.so from the Crypto Providers ZIP archive to your target system.

Check the output of openssl version on your target system to select the correct OpenSSL version.

Parameters

Signing tools with Cryptoki support usually provide PIN and key ID parameters. These are passed to the respective Cryptoki provider. For SignPath, provide the following values:

Tool parameter Value (using SignPath provider) Description
PIN $OrganizationId:$ApiToken or CONFIG SignPath Organization and Submitter API token, separated by a colon. Specify CONFIG to use the values definded in the configuration file or environment variables
key ID $ProjectSlug/$SigningPolicySlug SignPath Project and Signing Policy slugs, separated by a forward slash

Name and synopsis for these parameters depend on the tool. For tools that support Cryptoki only indirectly, parameters may also be passed indirectly or using a specific syntax for an existing tool parameter (see below).

Keys are not specified directly

The Cryptoki API expects you to identify a key, but SignPath requires you to specify a Project and a Signing Policy. SignPath will select the key or certificate of the specified Signing Policy.

Error handling

The following table shows the PKCS #11 Cryptoki function return values for the different error situations when calling the SignPath REST API.

Situation PKCS #11 error code
Transient errors like HTTP timeouts or 503 CKR_FUNCTION_FAILED
Non-transient service errors (e.g. 500 Internal Server Error) CKR_DEVICE_ERROR
User errors detected by service (4xx returned) CKR_ARGUMENTS_BAD
Other unspecified errors (fall back) CKR_GENERAL_ERROR

Integration with signing tools

For Cryptoki-based signing, tool setup can be complex. Unlike the KSP/CSP provider architecture of Windows, Cryptoki is not a system API. As a consequence, support for Cryptoki libraries varies significantly between tools:

  • A tool might directly support Cryptoki (and will provide a parameter or configuration option to specify the Cryptoki library and key identifier)
  • A tool might support different engines. If it doesn’t come with a Cryptoki engine, you need to get it from another source and install it. In this case you need to
    • specify the engine in the tool’s configuration or parameter list,
    • and specify the SignPath Cryptoki library in the engine’s configuration
  • A tool might internally call another tool such as OpenSSL or GPG to create the signature

If your signing tool does not provide guidance for using Cryptoki libraries, you probably need a solid understanding of the specific tool chain to configure it. For better results, please also refer to signing flow.

OpenSSL

OpenSSL is a toolkit that provides a range of cryptographic operations, including signing.

Important

Only latest OpenSSL 1.1 and 3.x versions are supported. For Linux, see also the notes in supported Linux distributions.

Setup

OpenSSL cannot directly communicate with a Cryptoki library. Instead, the OpenSC pkcs11 OpenSSL engine can be used as adapter between OpenSSL and the SignPath Cryptoki library.

Windows: Download libp11-...-windows.zip from OpenSC libp11 Releases and copy-deploy pkcs11.dll (x64 version).

Linux: Install the OpenSC pkcs11 engine via your package manager (e.g. apt-get install libengine-pkcs11-openssl in Ubuntu).

Sample: openssl-signpath.cnf

config_diagnostics = 1
openssl_conf = openssl_init

[openssl_init]
engines = engines_section

[engines_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11
dynamic_path = /path/to/libpkcs11.so
MODULE_PATH = /path/to/libSignPath.Cryptoki.so
default_algorithms = ALL
init = 0
PIN = CONFIG

Default installation paths of libp11

Note that Linux distributions have different default installation paths for libpkcs11.so:

Distribution Default path
Debian/Ubuntu w/ OpenSSL 1.1 /usr/lib/x86_64-linux-gnu/engines-1.1/libpkcs11.so
Debian/Ubuntu w/ OpenSSL 3.x /usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so
RedHat w/ OpenSSL 1.1 /usr/lib64/engines-1.1/libpkcs11.so
RedHat w/ OpenSSL 3.x /usr/lib64/engines-3/libpkcs11.so

For Windows use .dll paths respectively (note the double backslashes):

dynamic_path = C:\\path\\to\\pkcs11.dll
MODULE_PATH = C:\\path\\to\\SignPath.Cryptoki.dll

Also set the following environment variable:

Environment variable Value Description
OPENSSL_CONF Path to openssl-signpath.cnf file This variable tells OpenSSL to load the custom configuration file

Invocation

OpenSSL provides a variety of commands that can be used for signing. In this section, a few of them are outlined.

Tip

For Linux, configuration, signing invocation and verification examples are provided in the Linux container samples within Scenarios/OpenSSL/OpenSSL.ps1. Sample invocation:

run_scenario.sh ... -Scenario OpenSSL -ProjectSlug "hash-signing" -SigningPolicySlug "test-signing"

Generally, all commands require the following parameters to work with the SignPath Cryptoki library:

Parameter Value Description
-keyform engine Use the specified engine to access the key.
-engine pkcs11 Use the libp11 engine specified in the openssl-signpath.cnf file.
-inkey pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private A PKCS #11 URI including Project and Signing Policy slug, see also Cryptoki parameters.
openssl dgst

The dgst command calculates digests of files, but can also be used to create and verify signatures.

Sample: sign artifact.bin and write the signature to artifact.sig.

openssl dgst -engine pkcs11 -keyform engine -sign "pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private" -sha256 -out "artifact.sig" "artifact.bin"

Supported digests

The following digests are supported: sha256, sha384, sha512

openssl pkeyutl

The pkeyutl command performs low-level cryptographic operations, such as signing.

Note: provide binary hash digest

The command does hash the input data but will use the data directly as an input for the signature algorithm. To create the hash of a file, you can use the following snippet:

$ArtifactHash = Get-FileHash "artifact.bin" -Algorithm "SHA256" # SHA1, SHA256, SHA384 and SHA512 are supported
$ArtifactHashBytes = [byte[]] -split ($ArtifactHash.Hash -replace '..', '0x$& ')
[IO.File]::WriteAllBytes("artifact.hash.bin", $ArtifactHashBytes)

Sample: sign the hash code in artifact.hash.bin using PKCS1 padding, write the signature to artifact.sig

openssl pkeyutl -engine pkcs11 -keyform engine -inkey "pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private" -sign -in "artifact.hash.bin" -out "artifact.sig" -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pkcs1

Sample: sign the hash code in artifact.hash.bin using PSS padding, write the signature to artifact.sig

openssl pkeyutl -engine pkcs11 -keyform engine -inkey "pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private" -sign -in "artifact.hash.bin" -out "artifact.sig" -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:-1 -pkeyopt rsa_mgf1_md:sha256

openssl cms

The cms command can be used to create embedded S/MIME or detached PEM/DER signatures. It uses the Cryptographic Message Syntax format (CMS, formerly known as PKCS#7).

openssl cms requires the X.509 certificate corresponding to the SignPath Project and Signing Policy to be downloaded from SignPath and converted to PEM format. You can convert the certificate using OpenSSL via the following example.

openssl x509 -inform DER -in "certificate.cer" -outform PEM -out "certificate.pem"

Sample: sign the file artifact.bin using certificate.pem, write the detached signature to artifact.sig in PEM format

openssl cms -engine pkcs11 -signer "certificate.pem" -inkey "pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private" -keyform engine -sign -binary -in "artifact.bin" -noattr -out "artifact.sig" -outform PEM

osslsigncode

osslsigncode is a tool that allows applying Windows Authenticode signatures on Linux systems using OpenSSL. Accordingly, it also requires an OpenSC pkcs11 OpenSSL engine installation. See the OpenSSL section for details.

Important

Only osslsigncode 2.x or higher is supported. Also see the notes in supported Linux distributions regarding the supported OpenSSL versions.

Setup

osslsigncode requires the X.509 certificate corresponding to the SignPath Project and Signing Policy to be downloaded from SignPath and converted to PEM format. You can convert the certificate using OpenSSL via the following example.

openssl x509 -inform DER -in "certificate.cer" -outform PEM -out "certificate.pem"

Invocation

osslsigncode sign `
   -pkcs11module $LibSignPathCryptokiPath `
   -key "pkcs11:id=$ProjectSlug/$SigningPolicySlug;type=private;pin-value=CONFIG" `
   -certs "certificate.pem" `
   -in "sample.exe" -out "sample.signed.exe"
Parameter Value Description
--pkcs11module /path/to/libSignPath.Cryptoki.so Path to the SignPath Cryptoki library
--key pkcs11:id=... A PKCS #11 URI as shown in the example above including Project and Signing Policy slugs and the “pin” value (see also Cryptoki parameters)
--certs certificate.pem Certificate of the used signing policy in PEM format

Tip

This invocation is also provided in the Linux container samples within Scenarios/osslsigncode/osslsigncode.ps1. Sample invocation:

run_scenario.sh ... -Scenario osslsigncode -ProjectSlug "hash-signing" -SigningPolicySlug "test-signing"

OpenSC pkcs11-tool (Linux)

The OpenSC pkcs11-tool utility can be used to troubleshoot PKCS #11 modules (e.g. listing all available objects or supported algorithms) but also can be used to read certificates/public keys and to perform signing operations.

Setup

pkcs11-tool before version 0.23

Set Cryptoki.DoNotFailOnReadWriteSessions to true in the SignPath Crypto Provider configuration.

Background: pkcs11-tool used to open the Cryptoki session in a read/write mode (see GitHub issue #2182) and therefore fails with PKCS11 function C_OpenSession failed: rv = CKR_TOKEN_WRITE_PROTECTED. This flag enables compatibility with these earlier versions.

Invocation

Tip

The following invocation examples are also provided in the Linux container samples within Scenarios/Pkcs11Tool/Pkcs11Tool.ps1. Sample invocation:

run_scenario.sh ... -Scenario Pkcs11Tool -ProjectSlug "hash-signing" -SigningPolicySlug "test-signing"
Common parameters
pkcs11-tool --module $LibSignPathCryptokiPath --pin CONFIG ...
Parameter Value Description
--module /path/to/libSignPath.Cryptoki.so Path to the SignPath Cryptoki library
--pin CONFIG or $OrganizationId:$ApiToken See PIN parameter
Listing of the available PKCS #11 objects

The following command lists available objects, which corresponds to the list of signing policies for which the authenticated user has Submitter permissions.

pkcs11-tool --module $LibSignPathCryptokiPath --pin CONFIG --list-objects
Signing operation

The following sample call shows an RSA signing operation using PSS padding and SHA-256.

pkcs11-tool --module $LibSignPathCryptokiPath --pin CONFIG `
   --sign --mechanism "RSA-PKCS-PSS" --hash-algorithm "SHA256" --label "$ProjectSlug/$SigningPolicySlug" `
   --input-file "artifact.hash.bin" --output-file "artifact.sig"
Parameter Value Description
--mechanism e.g. RSA-PKCS-PSS Use the --list-mechanisms argument to list all available mechanisms
--hash-algorithm e.g. SHA256 Only necessary for RSA-PKCS-PSS mechanism
--label $ProjectSlug/$SigningPolicySlug Project and Signing Policy slugs, separated by a forward slash
--input-file /path/to/hash.bin File containing a hash in binary form

Java jarsigner

The jarsigner command signs and verifies Java archives (e.g. JAR, WAR, EAR). It is included with the Java Development Kit (JDK).

Setup

  1. Configure the SunPKCS11 Provider
  2. Register the SignPath Cryptoki library for the SunPKCS11 Provider

Sample pkcs11.config

name=SignPath.Cryptoki
library=<path>\SignPath.Cryptoki.dll
slot=1

Invocation

Tip

For Linux, configuration and invocation examples are provided in the Linux container samples within Scenarios/Jar/JarSigner.ps1. Sample invocation:

run_scenario.sh ... -Scenario JarSigner -ProjectSlug "hash-signing" -SigningPolicySlug "test-signing"

Synopsis for jarsigner when using the SignPath Cryptoki library:

jarsigner <parameters> <jar-files> <keystore-alias>
Parameter Value Description
-storetype PKCS11 Use a PKCS11 store for the signing operation
-providerClass sun.security.pkcs11.SunPKCS11 Use the SunPKCS11 provider for the signing operation
-keystore NONE Key is not loaded from a file
-providerArg Path to pkcs11.config The SunPKCS11 provider expects a path to the config file
-sigalg SHA256withRSA, SHA384withRSA, SHA512withRSA, SHA256withECDSA, SHA384withECDSA, or SHA512withECDSA Digest and signature algorithm
-storepass CONFIG or $OrganizationId:$ApiToken See “PIN” parameter
keystore-alias $ProjectSlug/$SigningPolicySlug Project and Signing Policy slug, separated by a forward slash

Sample: sign myapp.jar

jarsigner -keystore NONE -storetype PKCS11 -providerClass "sun.security.pkcs11.SunPKCS11" -providerArg pkcs11.config -sigalg "SHA256withRSA" -storepass "CONFIG" myapp.jar "$ProjectSlug/$SigningPolicySlug" 

Warning: Produce correct timestamps

When using jarsigner (or any other signing tool) directly, you are responsible for correct time stamping. See Timestamps

Sign up for news and special offers