Sample openCryptoki program

View a completely coded example of an openCryptoki application that performs an RSA key generation operation.

Note: This sample program does not include the operation to encrypt data with the previously generated RSA private key as described in step 7 of Structure of an openCryptoki application.
/*
 * Build:
 *   cc -o pkcs11 pkcs11.c -ldl
 *
 * Usage:
 *   pkcs11 <so_name> <slot_id> <user_pin>
 *
 * Description:
 *   Loads the PKCS11 shared library <so_name>,
 *   opens a session with slot <slot_id>,
 *   logs the user in using the PIN <user_pin>,
 *   and performs an RSA key generation operation.
 */
/* Step 1 */ 
#include <opencryptoki/pkcs11.h>                           
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
 
#define NELEM(array) (sizeof(array) / sizeof((array)[0]))
 
int main(int argc, char *argv[])
{
    CK_C_GetFunctionList get_functionlist = {NULL};
    CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
    CK_FUNCTION_LIST *fn = NULL;
    void *pkcs11so = NULL;
    CK_SLOT_ID slot_id;
    CK_FLAGS flags;
    int rc = -1;
    char *ptr;
    CK_RV rv;
 
    if (argc != 4) goto err;
 
    pkcs11so = dlopen(argv[1], RTLD_NOW);
    if (pkcs11so == NULL) goto err;
 
    slot_id = strtoul(argv[2], &ptr, 0);
    if (*(argv[2]) == '\0' || *ptr != '\0') goto err;
 
    *(void **)(&get_functionlist) = dlsym(pkcs11so, "C_GetFunctionList");
    if (get_functionlist == NULL) goto err;
 
    rv = get_functionlist(&fn);                               
    if (rv != CKR_OK || fn == NULL) goto err;

/* Step 2 */ 
    rv = fn->C_Initialize(NULL);                         
    if (rv != CKR_OK) goto err;
 
    flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
/* Step 4  (Step 3 assumed to be done by pkcsconf) */
    rv = fn->C_OpenSession(slot_id, flags, NULL, NULL, &session);
    if (rv != CKR_OK || session == CK_INVALID_HANDLE) goto err;

/* Step 5 */
    rv = fn->C_Login(session, CKU_USER, (CK_UTF8CHAR *)argv[3], strlen(argv[3]));
    if (rv != CKR_OK) goto err;

 /* Step 6  (Step 7 not coded in this example */
    {
        CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0};
        CK_BYTE e[] = {0x01, 0x00, 0x01};
        CK_ULONG modbits = 4096;
        CK_BYTE subject[] = "RSA4096 Test";
        CK_BYTE id[] = {1};
        CK_BBOOL true_ = CK_TRUE;
 
        CK_ATTRIBUTE template_publ[] = {
            {CKA_ENCRYPT,         &true_,   sizeof(true_)},
            {CKA_VERIFY,          &true_,   sizeof(true_)},
            {CKA_WRAP,            &true_,   sizeof(true_)},
            {CKA_MODULUS_BITS,    &modbits, sizeof(modbits)},
            {CKA_PUBLIC_EXPONENT, e,        sizeof(e)}
        };
        CK_ATTRIBUTE template_priv[] = {
            {CKA_SUBJECT,         subject,  sizeof(subject)},
            {CKA_ID,              id,       sizeof(id)},
            {CKA_TOKEN,           &true_,   sizeof(true_)},
            {CKA_PRIVATE,         &true_,   sizeof(true_)},
            {CKA_SENSITIVE,       &true_,   sizeof(true_)},
            {CKA_DECRYPT,         &true_,   sizeof(true_)},
            {CKA_SIGN,            &true_,   sizeof(true_)},
            {CKA_UNWRAP,          &true_,   sizeof(true_)}
        };
 
        CK_OBJECT_HANDLE publ, priv;
 
        rv = fn->C_GenerateKeyPair(session, &mechanism,
                                   template_publ, NELEM(template_publ),
                                   template_priv, NELEM(template_priv),
                                   &publ, &priv);
        if (rv != CKR_OK) goto err;
    }

/* Step 8 */ 
    rv = fn->C_Logout(session);
    if (rv != CKR_OK) goto err;
 
    rv = fn->C_CloseSession(session);
    if (rv != CKR_OK) goto err;

 /* Step 9 */   
    rv = fn->C_Finalize(NULL);
    if (rv != CKR_OK) goto err;
 
    rc = 0;
err:
    if (pkcs11so != NULL)
        dlclose(pkcs11so);
    return rc;
}