Add PKCS #11 API README and generate ECC key sample

pull/120/head
Sean Parkinson 2019-02-06 08:23:37 +10:00
parent 0e65ab1c3c
commit cfba1af8af
5 changed files with 306 additions and 0 deletions

1
.gitignore vendored
View File

@ -139,6 +139,7 @@ rsa/verify
pkcs11/pkcs11_test pkcs11/pkcs11_test
pkcs11/pkcs11_rsa pkcs11/pkcs11_rsa
pkcs11/pkcs11_ecc pkcs11/pkcs11_ecc
pkcs11/pkcs11_genecc
pkcs11/pkcs11_aesgcm pkcs11/pkcs11_aesgcm
pkcs11/softhsm2.conf pkcs11/softhsm2.conf
pkcs11/softhsm2 pkcs11/softhsm2

164
pkcs11/PKCS11.md 100644
View File

@ -0,0 +1,164 @@
## Using PKCS #11 with wolfSSL
# Initializing PKCS #11 library
In order to use a PKCS #11 device it is necessary to load the device specific
PKCS #11 shared (or dynamic) library.
The wolfSSL API wc_Pkcs11_Initialize() takes the path to the library and
initializes a Pkcs11Dev instance for accessing tokens.
/**
* Load library, get function list and initialize PKCS#11.
*
* @param dev [in] Device object.
* @param library [in] Library name including path.
* @param heap [in] Heap hint.
* @return BAD_FUNC_ARG when dev or library are NULL pointers.
* BAD_PATH_ERROR when dynamic library cannot be opened.
* WC_INIT_E when the initialization PKCS#11 fails.
* WC_HW_E when unable to get PKCS#11 function list.
* 0 on success.
*/
int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap);
# Finalizing PKCS #11 library
When the device is not longer required then Pkcs11Dev instance can be finalized.
This unloads the shared library.
/**
* Close the Pkcs#11 library.
*
* @param dev [in] Device object.
*/
void wc_Pkcs11_Finalize(Pkcs11Dev* dev);
# Initializing a token
PKCS #11 defines tokens to be in slots. wolfSSL assumes that the token is in a
slot and abstracts slots away.
To initialize a token instance using the API wc_Pkcs11Token_Init().
The slot number of the token need not be supplied if the token name is unique.
Pass -1 for the slotId to find token by name on any slot.
The userPin must be supplied to login into a session.
/**
* Set up a token for use.
*
* @param token [in] Token object.
* @param dev [in] PKCS#11 device object.
* @param slotId [in] Slot number of the token.<br>
* Passing -1 uses the first available slot.
* @param tokenName [in] Name of token to initialize.
* @param userPin [in] PIN to use to login as user.
* @param userPinSz [in] Number of bytes in PIN.
* @return BAD_FUNC_ARG when token, dev and/or tokenName is NULL.
* WC_INIT_E when initializing token fails.
* WC_HW_E when another PKCS#11 library call fails.
* -1 when no slot available.
* 0 on success.
*/
int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId,
const char* tokenName, const unsigned char* userPin, int userPinSz);
# Finalize token
Finalizing a token will close all session on the token and zeroize any User PIN.
/**
* Finalize token.
* Closes all sessions on token.
*
* @param token [in] Token object.
*/
void wc_Pkcs11Token_Final(Pkcs11Token* token);
# Open Session
A session needs to be opened on a token in order for operations to be performed.
If keys need to persist across operations in a session or you need to manage
sessions in the application then opening a session using the API
wc_Pkcs11Token_Open().
A session can be opened for reading and writing by setting the flag to 1.
/**
* Open a session on the token to be used for all operations.
*
* @param token [in] Token object.
* @param readWrite [in] Boolean indicating to open session for Read/Write.
* @return BAD_FUNC_ARG when token is NULL.
* WC_HW_E when opening the session fails.
* 0 on success.
*/
int wc_Pkcs11Token_Open(Pkcs11Token* token, int readWrite);
# Close Session
If you opened a session in your application then you should close it too.
Use the API wc_Pkcs11Token_Close() to close the session. wolfSSL will create
a session to perform any new cryptographic operations.
Any keys in the session will be lost.
/**
* Close the token's session.
* All object, like keys, will be destoyed.
*
* @param token [in] Token object.
*/
void wc_Pkcs11Token_Close(Pkcs11Token* token);
# Registering a PKCS #11 device
Cryptographic operations will be performed on a PKCS #11 device when initialized
with a device identifier associated with a token.
An application chooses a number that will be the device identifier and
associates the PKCS #11 callback and Pkcs11Token pointer using the API
wc_CryptoDev_RegisterDevice().
e.g.:
int ret;
int devId = 1;
Pkcs11Token token;
ret = wc_CryptoDev_RegisterDevice(devId, wc_Pkcs11_CryptoDevCb, &token);
if (ret != 0)
fprintf(stderr, "Failed to register token");
# Initializing ECDSA Cryptographic Operation
To initialize ECC signing or verification operration to use the PKCS #11 token,
use the API wc_ecc_init_ex().
e.g:
int ret;
ecc_key key;
int devId = 1;
ret = wc_ecc_init_ex(&key, NULL, devId);
# Using a Private Key
To use an EC private key, load as normal.
(Keys can be generated on the device and the private key will not come off.)
Perform the cryptographic operation as normal and the private key will be loaded
onto the token in the session if required.
# Performing other PKCS #11 operations
The function list is available as the field func in Pkcs11Dev, Pkcs11Token and
Pkcs11Session.
The Slot Id is availabe in Pkcs11Token and Pkcs11Session as slotId.
The session handle is available in Pkcs11Token and Pkcs11Session aa handle.

View File

@ -9,6 +9,9 @@ echo
echo "# ECC example" echo "# ECC example"
./pkcs11_ecc /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki ./pkcs11_ecc /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
echo echo
echo "# Generate ECC example"
./pkcs11_genecc /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
echo
echo "# AES-GCM example" echo "# AES-GCM example"
./pkcs11_aesgcm /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki ./pkcs11_aesgcm /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
echo echo

View File

@ -0,0 +1,135 @@
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/wc_pkcs11.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
static WC_RNG rng;
int gen_ec_keys(Pkcs11Token* token, ecc_key* key, unsigned char* id, int idLen,
int devId)
{
int ret;
ret = wc_ecc_init_id(key, id, idLen, NULL, devId);
if (ret != 0)
fprintf(stderr, "Failed to initialize EC key: %d\n", ret);
if (ret == 0) {
ret = wc_ecc_make_key_ex(&rng, 32, key, ECC_CURVE_DEF);
if (ret != 0)
fprintf(stderr, "Failed to generate EC key: %d\n", ret);
}
return ret;
}
int ecdsa_sign_verify(int devId, Pkcs11Token* token)
{
int ret = 0;
byte hash[32], out[128];
word32 hashSz, outSz;
int verify;
ecc_key eccKey;
memset(hash, 9, sizeof(hash));
hashSz = sizeof(hash);
outSz = sizeof(out);
ret = wc_Pkcs11Token_Open(token, 1);
if (ret == 0) {
fprintf(stderr, "Generate EC Keys\n");
ret = gen_ec_keys(token, &eccKey, (unsigned char*)"123ecc", 6, devId);
if (ret == 0) {
ret = wc_ecc_sign_hash(hash, hashSz, out, &outSz, &rng, &eccKey);
if (ret < 0)
fprintf(stderr, "Failed to sign: %d\n", ret);
}
if (ret == 0) {
/* Don't use device for public key operation. */
eccKey.devId = INVALID_DEVID;
ret = wc_ecc_verify_hash(out, outSz, hash, (int)hashSz, &verify,
&eccKey);
if (ret < 0 || !verify)
fprintf(stderr, "Failed to verify: %d (%d)\n", ret, verify);
if (!verify)
ret = -1;
}
wc_Pkcs11Token_Close(token);
wc_ecc_free(&eccKey);
}
return ret;
}
int main(int argc, char* argv[])
{
int ret;
const char* library;
const char* slot;
const char* tokenName;
const char* userPin;
Pkcs11Dev dev;
Pkcs11Token token;
int slotId;
int devId = 1;
if (argc != 5) {
fprintf(stderr,
"Usage: pkcs11_genecc <libname> <slot> <tokenname> <userpin>\n");
return 1;
}
library = argv[1];
slot = argv[2];
tokenName = argv[3];
userPin = argv[4];
slotId = atoi(slot);
#if defined(DEBUG_WOLFSSL)
wolfSSL_Debugging_ON();
#endif
wolfCrypt_Init();
ret = wc_Pkcs11_Initialize(&dev, library, NULL);
if (ret != 0) {
fprintf(stderr, "Failed to initialize PKCS#11 library\n");
ret = 2;
}
if (ret == 0) {
ret = wc_Pkcs11Token_Init(&token, &dev, slotId, tokenName,
(byte*)userPin, strlen(userPin));
if (ret != 0) {
fprintf(stderr, "Failed to initialize PKCS#11 token\n");
ret = 2;
}
if (ret == 0) {
ret = wc_CryptoDev_RegisterDevice(devId, wc_Pkcs11_CryptoDevCb,
&token);
if (ret != 0) {
fprintf(stderr, "Failed to register PKCS#11 token\n");
ret = 2;
}
if (ret == 0) {
wc_InitRng_ex(&rng, NULL, devId);
ret = ecdsa_sign_verify(devId, &token);
if (ret != 0)
ret = 1;
wc_FreeRng(&rng);
}
wc_Pkcs11Token_Final(&token);
}
wc_Pkcs11_Finalize(&dev);
}
wolfCrypt_Cleanup();
return ret;
}

View File

@ -13,6 +13,9 @@ echo
echo "# ECC example" echo "# ECC example"
./pkcs11_ecc /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki ./pkcs11_ecc /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
echo echo
echo "# Generate ECC example"
./pkcs11_genecc /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
echo
echo "# AES-GCM example" echo "# AES-GCM example"
./pkcs11_aesgcm /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki ./pkcs11_aesgcm /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
echo echo