PKI - PKCS11

The first time I heard about PKCS#11, I had to perform a cryptographic operation on firmware that required secrets stored in an HSM. At that time, I was completely lost while my supervisor tried to explain what needed to be done. The truth is, I had no idea what PKCS#11 was, let alone how to use it.

This article is, in a way, my personal “revenge” on PKCS#11. More importantly, I want to share some practical guidelines to help beginners who are starting to work with PKCS#11, whatever their use case may be.

TL;DR The PKCS#11 Standard

First, know that the PKCS#11 standard is also referred to as Cryptoki. The two terms are interchangeable.

If someone asks you what PKCS#11 is, here’s an answer that works in most cases:

PKCS#11 (Public-Key Cryptography Standard #11) is a platform-independent API standard for managing cryptographic devices such as smartcards, HSMs (Hardware Security Modules), SSMs (Software Security Modules), and other secure elements. It defines a set of functions that applications can use to interact with these devices. For example, PKCS#11 allows you to access, create, delete, or modify keys and certificates stored in an HSM.

For non-technical audiences, you can think of PKCS#11 as a universal translator that lets software securely communicate with devices that protect sensitive secrets, such as smartcards or hardware security boxes (HSMs).

Historically, PKCS#11 was developed and maintained by RSA Labs from 1995 to 2009. It is now maintained by the OASIS PKCS#11 Technical Committee. The different versions of the standard are available on the PKCS#11 documentation site:

  • V2.20: Widely used and supported by multiple token vendors.

  • V2.30: Draft version.

  • V2.40: The first version published under OASIS.

Where to Start ?

My first advice would be to take some time to read the standard’s introduction, which you can find at https://www.cryptsoft.com/pkcs11doc/v220/ (version 2.20). Once you’ve done that, you’ll have a clearer idea of what PKCS#11 is used for, as well as the process that shaped the standard.

Practicing

Next, I recommend you start practicing. To do that, you’ll need a cryptographic device to interact with. This can be a physical HSM or a virtual HSM (SSM). In the standard, both are referred to as tokens.

Whatever you choose, you’ll also need a client to communicate with your token:

  • If you buy a physical HSM (which can be very expensive), the vendor will provide a proprietary client with all the required tools to interact with it. You won’t need to develop anything yourself, just use the provided CLI or GUI tools. For example, the manual for the Thales SafeNet PTK 5.9 client can be found here.

  • The vendor will also provide a library (.dll or .so) that allows you to integrate HSM interactions into your own applications. This is useful if you’re building software that needs direct access to cryptographic functions. Some vendors also provide libraries for virtual HSMs (SSMs) that you can use for development and testing.

  • If you don’t have the budget for a hardware HSM, you can use open-source software alternatives such as SoftHSM or OpenSC, which provide both a client and a library.

Going Beyond Vendor Tools

Vendor clients are useful but limited. If you need to perform a very specific task, the client tools may not support it. That’s when the PKCS#11 library becomes essential: you can integrate it directly into your own application.

To do this, you’ll need to pick a programming language that has PKCS#11 support or a provider. A provider is a wrapper that allows your application to load and use the PKCS#11 library. Personally, I use Java, which offers a PKCS#11 provider out of the box.

Practicing PKCS#11 through programming is harder, but far more rewarding. Vendor tools hide most of the complexity, but when you work with the library directly, you’ll discover the finer details of the standard. I strongly recommend this approach if you really want to understand PKCS#11.

What to Do Next?

For practice, start with simple unit tasks on your token, such as:

  • Generating or deleting a keys, certificates, or random numbers

  • Encrypting or decrypting data

  • Storing sensitive information like keys in your token

At first, you can reuse existing examples and try to understand what each line of code does. I’ve published some sample code on my github at kmanu225/pkcs11.

Then, go deeper into the standard itself:

  • Learn PKCS#11 syntax and symbols (for example: all functions start with C_, all data types with CK_). This will save you a lot of time when writing code and using autocompletion.

  • Study the PKCS#11 process flow, which will help you avoid errors like dangling pointers.

  • Understand the fundamental concepts of PKCS#11: objects, slots, users, sessions, mechanisms, etc.

Never Really the End

Learning PKCS#11 is an ongoing process. The standard is full of details and specificities, and you’ll always discover new aspects as you explore different use cases. But the deeper you go, the more powerful and flexible it becomes.

Last updated