cloudflare / cfssl

CFSSL: Cloudflare's PKI and TLS toolkit
https://cfssl.org/
BSD 2-Clause "Simplified" License
8.56k stars 1.09k forks source link

pkcs11 docs #247

Closed carlhoerberg closed 8 years ago

carlhoerberg commented 9 years ago

How do you use a pkcs#11 module with cfssl?

oliof commented 9 years ago

Her is a write-up for running CFSSL against softHSM (not better than using file based secrets security wise, but it exercises the pkcs11 code) in ten wonky steps. This is a proof-of-concept, do not use in production!

WARNING HERE BE DRAGONS

You follow this outline at your own risk! If your HSM catches fire, it's on you. This write-up describes what worked once for me. It's not official. Horrible hacks abound. Not tested, only ran once on ubuntu 14.04.

# 1. Install pre-requisites
aptitude install libldtl-dev  # to build github.com/miekg/pkcs11
aptitude install gnutls-bin   # for p11tool
aptitide install opensc       # for pkcs11-tool
aptitude install softhsm libsofthsm
# 2. Build CFSSL with pkcs11 support
go get -u -a -tags pkcs11 github.com/cloudflare/cfssl/cmd/...
# 3. If you haven't yet, create key and cert for CA
# (see notes on how this part of the instructions are conceptually broken) 
# (requires csrjson as config for cert).
cfssl genkey -initca csrjson | cfssljson -bare ca 
# 4. Convert ca-key to DER format
openssl rsa -in ca-key.pem -outform DER -out ca-key.der
# 5. Set shortcut for pkcs#11 implementation of softhsm
export HSMLIB=/usr/lib/softhsm/libsofthsm.so
# 6. Initialize a new token (asks you to set an SO pin)
pkcs11-tool --module ${HSMLIB} --init-token --label cfssl_token 
# 7. Set user pin (assume 1234 for the example, but see below)
pkcs11-tool --module ${HSMLIB} --init-pin --label cfssl_token --login
# 8. Import private key into soft token.
# Ugly, but trying to import with pkcs11-tool breaks badly.
HSM_TOKEN_URI=$(\
    p11tool --provider ${HSMLIB} --list-tokens --no-detailed-url |\
    awk '/URL:.*SoftHSM/{print $2}')
p11tool --provider ${HSMLIB} --login --write ${HSM_TOKEN_URI} \
    --load-privkey ca-key.der --inder --label 'cfssl_privkey'
# 9. Remove on-disk key. 
# If your HSM breaks after this, you need to create a new signing cert.
rm -f ca-key.pem ca-key.der
# 10. Run CFSSL with pkcs11 flags
$GOPATH/bin/cfssl -loglevel 0 serve \
    -config=/etc/cfssl/config.json -ca=/etc/cfssl/ca.pem \
    -pkcs11-module=${HSMLIB} -pkcs11-label="cfssl_privkey" \
    -pkcs11-token="SoftHSM" -pkcs11-pin=1234  # https://youtu.be/a6iW-8xPw3k?t=33

Some commentary

-pkcs11-module is as expected, the .so library implementing the pkcs11 interface to your HSM -pkcs11-label is the label of the imported key as set in step 8 above -pkcs11-token is the name of the HSM Model / Manufacturer (crypto/pkcs11key actually looks up a SlotDescription which is neither a token nor unique if you have multiple slots in one HSM; I only figured this one out with some strategic debug statements). -pkcs11-pin is the pin as a command line arg (sic). Everyone on your machine will be able to see this, so running CFSSL in this configuration is not secure. That said, there is helpers/pkcs11uri which mentions that pins can only come from a file pin-source. I expect future changes here.

Conceptual brokenness in the write-up above: Keys should be generated on the HSM

It bears repeating that the above write-up is how I did it, not how it should be done. In a production environment you want to create the key on the HSM (i.e., using pkcs11-tool --keypairgen --keytype rsa:1024 --token-label cfssl_token --label cfssl_privkey --login) and then sign with that. cfssl genkey doesn't support pkcs11, but it should. I filed issue https://github.com/cloudflare/cfssl/issues/254 as a feature request.

jsha commented 9 years ago

It's also worth noting that certificate signing in go 1.4.2 (the latest stable) with an HSM won't work because the x509 library expects a crypto.PrivateKey, while a PKCS11 token can only provide crypto.Signer. The latest master branch of Go accepts crypto.Signer in the x509 library. With the release of go 1.5 in ~August, this should just work out of the box. https://github.com/golang/go/commit/fe40cdd756763982db6815ee87318f418218fcf5

jcjones commented 8 years ago

I've produced a script to help with this: https://github.com/jcjones/cfssl-pkcs11-ca

kisom commented 8 years ago

@jcjones Thanks for this; I'll include a link in the documentation.

0xhaven commented 8 years ago

This will be handled in a separate repo.

zosocanuck commented 8 years ago

Hi,

I recently attempted to follow these directions however the latest build doesn't seem to support pkcs#11. Any latest updates on how the PKCS#11 integration?

I work for Thales (we manufacturer the nShield/nCipher HSMs) and trying to perform interop testing.

Regards, Ivan

jsha commented 8 years ago

The PKCS#11 code has been moved into a separate package, https://github.com/letsencrypt/pkcs11key.

jabbrwcky commented 7 years ago

Hi,

I tried to find documentation how to use cfssl with a HSM, but found the few bits of documentation rather unhelpful.

What steps are needed to integrate the pcks#11 functionality in the letsencrypt repository with cfssl (via multirootca possibly)?

Could this be configured or have the respesctive tools in cfssl to be patched to support pcks#11?

Regards, Jens

silveraid commented 7 years ago

@jsha , am I understand this well, the latest stable cfssl release does not have HSM support?

jsha commented 7 years ago

@silveraid I believe that the cfssl binary does not have HSM support, but if you are compiling your own binaries using the cfssl libraries, you can provide HSM support using the pkcs11key module. See also https://github.com/cloudflare/cfssl/issues/563.