diff --git a/.gitignore b/.gitignore
index 2d1f211d..d0f2295f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -139,6 +139,7 @@ rsa/verify
pkcs11/pkcs11_test
pkcs11/pkcs11_rsa
pkcs11/pkcs11_ecc
+pkcs11/pkcs11_genecc
pkcs11/pkcs11_aesgcm
pkcs11/softhsm2.conf
pkcs11/softhsm2
diff --git a/pkcs11/PKCS11.md b/pkcs11/PKCS11.md
new file mode 100644
index 00000000..e7564af8
--- /dev/null
+++ b/pkcs11/PKCS11.md
@@ -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.
+ * 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.
+
+
diff --git a/pkcs11/opencryptoki.sh b/pkcs11/opencryptoki.sh
index 457b3933..c6167b87 100755
--- a/pkcs11/opencryptoki.sh
+++ b/pkcs11/opencryptoki.sh
@@ -9,6 +9,9 @@ echo
echo "# ECC example"
./pkcs11_ecc /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
echo
+echo "# Generate ECC example"
+./pkcs11_genecc /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
+echo
echo "# AES-GCM example"
./pkcs11_aesgcm /usr/local/lib/opencryptoki/libopencryptoki.so 3 SoftToken cryptoki
echo
diff --git a/pkcs11/pkcs11_genecc.c b/pkcs11/pkcs11_genecc.c
new file mode 100644
index 00000000..94ba11be
--- /dev/null
+++ b/pkcs11/pkcs11_genecc.c
@@ -0,0 +1,135 @@
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+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 \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;
+}
+
diff --git a/pkcs11/softhsm2.sh b/pkcs11/softhsm2.sh
index 8b645dec..299a17ea 100755
--- a/pkcs11/softhsm2.sh
+++ b/pkcs11/softhsm2.sh
@@ -13,6 +13,9 @@ echo
echo "# ECC example"
./pkcs11_ecc /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
echo
+echo "# Generate ECC example"
+./pkcs11_genecc /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
+echo
echo "# AES-GCM example"
./pkcs11_aesgcm /usr/local/lib/softhsm/libsofthsm2.so $SOFTHSM2_SLOTID SoftToken cryptoki
echo