ryankurte / pki

Scripts to bootstrap internal Certificate Authorities (CAs) using Yubikeys
MIT License
76 stars 11 forks source link

Windows certificate generation #9

Open ryankurte opened 4 years ago

ryankurte commented 4 years ago

Client certificate generation using windows is required for production-line deployment.

OpenSC provide a minidriver and pkcs#11 module for windows, providers can be listed using certutil -csplist

Request information specified using INF files:

[NewRequest] 
; At least one value must be set in this section 
Subject = "CN=test-client-cert,E=pki@test.com,OU=TestOrg_UNIT,0=TestOrg,S=TestCity,c=CN"

HashAlgorithm = Sha512
KeyAlgorithm = RSA
KeyLength = 2048
KeyUsage = "CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_KEY_AGREEMENT_KEY_USAGE"
RequestType=PKCS10

Create a CSR using certreq -new client.inf client.req

Signing via certutil -sign .\client.req client.crt locates the correct certificate, but, fails with:

CertUtil: -sign command FAILED: 0x80090014 (-2146893804 NTE_BAD_PROV_TYPE)
CertUtil: Invalid provider type specified.

And I don't know how to get the private key in this instance either...

Possibly should try using openssl with opensc-pkcs#11 :-/

ryankurte commented 4 years ago

OpenSSL installed via chocolatey loads configuration from C:\Program Files\OpenSSL-Win64\openssl.cfg.

Config (from here where someone appears to have got pkcs11 and windows working):

openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11

dynamic_path = "C:\\Windows\\SysWOW64\\pkcs11.dll"
MODULE_PATH = "C:\\Program Files\\OpenSC Project\\OpenSC\\pkcs11\\opensc-pkcs11.dll"

init = 0

However C:\\Windows\\SysWOW64\\pkcs11.dll does not exist, nor is there a pkcs11.dll in C:\Program Files\OpenSSL\lib\engines-1_1\pkcs11.dll as expected by openssl.

Running 'C:\Program Files\OpenSSL-Win64\bin\openssl.exe' x509 -engine pkcs11 results in:

invalid engine "pkcs11"
16692:error:25078067:DSO support routines:win32_load:could not load the shared library:crypto\dso\dso_win32.c:108:filename(C:\Program Files\OpenSSL\lib\engines-1_1\pkcs11.dll)
16692:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto\dso\dso_lib.c:162:
16692:error:260B6084:engine routines:dynamic_load:dso not found:crypto\engine\eng_dyn.c:414:
16692:error:2606A074:engine routines:ENGINE_by_id:no such engine:crypto\engine\eng_list.c:334:id=pkcs11
16692:error:25078067:DSO support routines:win32_load:could not load the shared library:crypto\dso\dso_win32.c:108:filename(pkcs11.dll)
16692:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto\dso\dso_lib.c:162:
16692:error:260B6084:engine routines:dynamic_load:dso not found:crypto\engine\eng_dyn.c:414:

Maybe the chocolatey version of openssl isn't built with pkcs11 support? could try compiling myself or another build.

ryankurte commented 4 years ago

~Openssl binaries from https://slproweb.com/products/Win32OpenSSL.html do not seem to have paths replaced sensibly (looking for .so rather than .dll files etc.), try another build i guess?~

edit: actually due to invoking the wrong openssl instance (in WSL)...

ryankurte commented 4 years ago

Building libp11

In the x64 (!!) developer terminal:

git clone https://github.com/OpenSC/libp11
cd libp11
nmake -f Makefile.mak OPENSSL_DIR="c:\Program Files\OpenSSL-Win64" BUILD_FOR=WIN64

Win64 / VS2019 outputs libp11.zip, ~openssl configuration: openssl.zip~

Using chocolatey: choco install openssl opensc

Openssl configuration:

openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
pkcs11 = pkcs11_section

[pkcs11_section]
engine_id = pkcs11

dynamic_path = "C:\\Program Files\\OpenSSL-Win64\\pkcs11.dll"
MODULE_PATH = "C:\Program Files\OpenSC Project\OpenSC\pkcs11\onepin-opensc-pkcs11.dll"

init = 0

Updating C:\Program Files\OpenSSL-Win64\openssl.cfg with dynamic_path = "C:\\Users\\Ryan\\projects\\libp11\\src\\pkcs11.dll" gets pkcs11 to load at least!

ryankurte commented 4 years ago

omg it works! Using openssl for everything for consistency / since we have it loaded anyway.

C:\Users\Ryan\projects\ca [master ≡ +4 ~0 -0 !]> .\scripts\new-client.cmd electronpowered ep-int-01 test-client

C:\Users\Ryan\projects\ca>set ROOT_NAME=electronpowered
C:\Users\Ryan\projects\ca>set INT_NAME=ep-int-01
C:\Users\Ryan\projects\ca>set CLIENT_NAME=test-client
C:\Users\Ryan\projects\ca>set OPENSSL_BIN="C:\Program Files\OpenSSL-Win64\bin\openssl.exe"
C:\Users\Ryan\projects\ca>set KEY_LEN=2048
C:\Users\Ryan\projects\ca>set EXPIRY_DAYS=9999

"Using existing key: electronpowered/test-client.key"
"Generating CSR: electronpowered/test-client.csr"
engine "pkcs11" set.
Signature ok
subject=C = NZ, ST = Auckland, O = ElectronPowered Ltd, OU = Research and Development, CN = test-client, emailAddress = pki@electronpowered.org
Getting CA Private Key
Enter PKCS#11 token PIN for Yubico PIV Authentication:
Enter PKCS#11 key PIN for SIGN key:
C:\Users\Ryan\projects\ca [master ≡ +4 ~1 -0 !]> ls