SuisseID as Code Signing HSM
Views: 2787
If you buy a new code signing certificate from SwissSign, you must generate a CSR using a hardware HSM which stores your private key inaccessibly. Unfortunately, this is a new requirement and pure soft certificates (all secrets in a file) are no more allowed.
Fortunately, the SuisseID is such a valid HSM. It can easily be used in your Ubuntu Linux MinGW cross build environment to sign your executables.
Sign CSR With SuisseID Private Key
You need the engine file, in current Ubuntu, this is /usr/lib/ssl/engines/libpkcs11.so
from package libengine-pkcs11-openssl
, the PKCS#11 library, which is /usr/lib/libcvP11.so
provided by SwissSign in package suisseid-pkcs11
. You also need pkcs11-tool
from package opensc
and openssl
from package openssl
. For code signing, you need osslsigncode
from package osslsigncode
. Your SuisseID must be initialized using SuisseID Assistant name swisssign-init from package swisssign-init.
If you haven’t run the SuisseID installer, you can also add the SwissSign repository manually:
sudo apt-add-repository http://update.swisssign.com/repo sudo apt update
Install the dependencies:
sudo apt install libengine-pkcs11-openssl suisseid-pkcs11 \ opensc openssl osslsigncode swisssign-init
If you haven’t initialized your SuisseID, do it now. You should have received a TIN / PUK Sheet from SwissSign with the transport PIN (TIN). Run swisssign-init
and follow the instructions. Set a PIN, that you will need below.
Compile osslsigncode
Unfortunately, as of July 2018, the version of osslsigncode delivered in Ubuntu 16.04 is of the latest version 1.7.1, but still does not support the options -pkcs11engine
and -pkcs11module
. So I had to compile my own version of osslsigncode
:
apt install libcurl4-openssl-dev git clone https://github.com/Dimrok/osslsigncode cd osslsigncode ./autogen.sh ./configure make
Find Key ID
Get a list of all objects in your SuisseID:
pkcs11-tool --module /usr/lib/libcvP11.so -O
This shows all objects found on your SuisseID smart card (which is your HSM), e.g.:
marc@merkur:~$ pkcs11-tool --module /usr/lib/libcvP11.so -O LOGIN CALLBACK in libCVP11LCB: CK_RV CB_Initialize(CK_CONTEXT_PTR, CK_C_INITIALIZE_ARGS_PTR, CK_ULONG_PTR) Using slot 0 with a present token (0x1) Public Key Object; RSA 2048 bits label: SwissSign_nonRep ID: 8b17b91399f4bd9ab62bc6c6ff21c9de4b353133 Usage: verify Public Key Object; RSA 2048 bits label: SwissSign_digSig ID: 00903c80c138a20f4b92625a25550a6503273537 Usage: encrypt, verify, wrap Public Key Object; RSA 2048 bits label: SwissSign_dataEnc ID: 247882b46782e951da176b1170b0031dcf24d932 Usage: encrypt, verify, wrap Certificate Object, type = X.509 cert label: SwissSign Platinum CA - G2 ID: 7cc3c3b0688964ea3fc31e14687036b91cd566d6 Certificate Object, type = X.509 cert label: SwissSign SuisseID Platinum CA 2010 - G2 ID: 40788b2001d803248c5815af9e53d5688d4c4cef Certificate Object, type = X.509 cert label: Tester test (Authentication) ID: 00903c80c138a20f4b92625a25550a6503273537 Certificate Object, type = X.509 cert label: SwissSign Qualified Platinum CA 2010 - G2 ID: 799ab530ff54cfeddc3f8246a0ad8f3371f885bd Certificate Object, type = X.509 cert label: Tester test (Qualified Signature) ID: 8b17b91399f4bd9ab62bc6c6ff21c9de4b353133 Certificate Object, type = X.509 cert label: SwissSign CH Person Platinum CA 2017 - G22 (STAG) ID: d0ca90120c47fb3765f8e86c0a4ea9cc2585eb80 Certificate Object, type = X.509 cert label: SwissSign CH Qualified Platinum CA 2017 - G22 (STAG) ID: 0ab4be9d404c9fce373579f22da20e8fe27ce407 LOGIN CALLBACK in libCVP11LCB: CK_RV CB_Finalize(CK_VOID_PTR)
You need the ID of the key with label SwissSign_digSig
, here 00903c80c138a20f4b92625a25550a6503273537
.
OpenSSL Configuration
You need am openssl configurate file engine.conf
:
openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = /usr/lib/ssl/engines/libpkcs11.so MODULE_PATH = /usr/lib/libcvP11.so init = 0 [req] distinguished_name = req_dn string_mask = utf8only utf8 = yes [req_dn] commonName = Common Name (eg, your name)
Generate CSR
Now you have all puzzle pieces to generate the HSM-signed CSR required for getting your SwissSign code signing certificate. Do not forget to plug in your USB SuisseID:
openssl req -nodes -new -sha256 -config engine.conf -engine pkcs11 -keyform engine \ -key slot_1-id_00903c80c138a20f4b92625a25550a6503273537 \ -out request.csr
It asks for your PIN and a common name. The comon name will be overwritten in the SwissSign request form anyway. As you see, in option -key
you specify a slot number (1, if you have one reader, just try different numbers), and the key ID that you got in the instructions above.
After running the command, a file request.csr is generated, that contains some lines between -----BEGIN CERTIFICATE REQUEST-----
and -----END CERTIFICATE REQUEST-----
.
Just copy the content of file request.csr
into the CSR field on SuisseSign’s web page, fillout the forms, download the request form, fill it out, sign it and send it to the fullfilment.
Sign Code With SuisseID
After some days, you get a mail containing download link for your certificate from SwissSign. Download it in cer
format as certificate.pem
.
Something to Sign
You need a windows exe or a dll to test. Simply use my windows cross compilation docker image to generate a windows openssl version in /tmp/test
:
docker run -it --rm -u $(id -u) \ -v /tmp/test:/workdir \ mwaeckerlin/mingw \ /build-openssl.sh -d
Now you have an exe that you can sign in the next step:
marc@merkur:~$ ls -l /tmp/test/usr/exeinsgesamt 10876 -rwxr-xr-x 1 marc root 5110 Jul 11 11:34 c_rehash drwxr-xr-x 1 marc marc 340 Jul 11 11:34 engines -rw-r--r-- 1 marc root 3700930 Jul 11 11:34 libcrypto.a -r-xr-xr-x 1 marc root 2348736 Jul 11 11:34 libcrypto.dll.a -rwxr-xr-x 1 marc root 2760552 Jul 11 11:34 libeay32.dll -rw-r--r-- 1 marc root 596088 Jul 11 11:34 libssl.a -r-xr-xr-x 1 marc root 208402 Jul 11 11:34 libssl.dll.a -rwxr-xr-x 1 marc root 904182 Jul 11 11:34 openssl.exe drwxr-xr-x 1 marc marc 62 Jul 11 09:28 pkgconfig -rwxr-xr-x 1 marc root 599307 Jul 11 11:34 ssleay32.dll
Sign a Windows Executable
Use osslsigncode(self-compiled, as explained above) to sign /tmp/test/usr/exe/openssl.exe
:
~/git/osslsigncode/osslsigncode sign \ -pkcs11engine /usr/lib/engines/engine_pkcs11.so \ -pkcs11module /usr/lib/libcvP11.so \ -key 00903c80c138a20f4b92625a25550a6503273537 \ -pass your-suisse-id-pin \ -certs certificate.pem \ -ts http://tsa.swisssign.net \ -h sha2 \ -in /tmp/test/usr/exe/openssl.exe \ -out /tmp/test/usr/exe/openssl-signed.exeIf you don't specify the password (which is the SuisseID PIN) on command line, you will be asked on the console.