Example 9–4 demonstrates how to find a slot with a mechanism that can generate random bytes. The example performs the following steps:
Initializes the cryptoki library.
Calls GetRandSlot() to find a slot with a mechanism that can generate random bytes.
The task of finding a slot performs the following steps:
Calling the function C_GetSlotList() to get a list of the available slots.
C_GetSlotList() is called twice, as the PKCS #11 convention suggests. C_GetSlotList() is called the first time to get the number of slots for memory allocation. C_GetSlotList() is called the second time to retrieve the slots.
Finding a slot that can generate random bytes.
For each slot, the function obtains the token information by using GetTokenInfo() and checks for a match with the CKF_RNG flag set. When a slot that has the CKF_RNG flag set is found, the GetRandSlot() function returns.
Ends the session.
The program uses C_CloseSession() to close the session and C_Finalize() to close the library.
The source code for the random number generation sample is shown in the following example.
Example 9-4 Generating Random Numbers Using PKCS #11 Functions#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/types.h> #include <security/cryptoki.h> #include <security/pkcs11.h> #define RANDSIZE 64 boolean_t GetRandSlot(CK_SLOT_ID_PTR pslot); /* Example generates random bytes. */ void main(int argc, char **argv) { CK_RV rv; CK_MECHANISM mech; CK_SESSION_HANDLE hSession; CK_SESSION_INFO sessInfo; CK_SLOT_ID slotID; CK_BYTE randBytes[RANDSIZE]; boolean_t found_slot = B_FALSE; int error; int i; /* Initialize the CRYPTOKI library */ rv = C_Initialize(NULL_PTR); if (rv != CKR_OK) { fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv); exit(1); } found_slot = GetRandSlot(&slotID); if (!found_slot) { goto exit_program; } /* Open a session on the slot found */ rv = C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession); if (rv != CKR_OK) { fprintf(stderr, "C_OpenSession: rv = 0x%.8x\n", rv); error = 1; goto exit_program; } /* Generate random bytes */ rv = C_GenerateRandom(hSession, randBytes, RANDSIZE); if (rv != CKR_OK) { fprintf(stderr, "C_GenerateRandom: rv = 0x%.8x\n", rv); error = 1; goto exit_session; } fprintf(stdout, "Random value: "); for (i = 0; i < RANDSIZE; i++) { fprintf(stdout, "%.2x", randBytes[i]); } exit_session: (void) C_CloseSession(hSession); exit_program: (void) C_Finalize(NULL_PTR); exit(error); } boolean_t GetRandSlot(CK_SLOT_ID_PTR pslot) { CK_SLOT_ID_PTR pSlotList; CK_SLOT_ID SlotID; CK_TOKEN_INFO tokenInfo; CK_ULONG ulSlotCount; CK_MECHANISM_TYPE_PTR pMechTypeList = NULL_PTR; CK_ULONG ulMechTypecount; boolean_t result = B_FALSE; int i = 0; CK_RV rv; /* Get slot list for memory allocation */ rv = C_GetSlotList(0, NULL_PTR, &ulSlotCount); if ((rv == CKR_OK) && (ulSlotCount > 0)) { fprintf(stdout, "slotCount = %d\n", (int)ulSlotCount); pSlotList = malloc(ulSlotCount * sizeof (CK_SLOT_ID)); if (pSlotList == NULL) { fprintf(stderr, "System error: unable to allocate memory\n"); return (result); } /* Get the slot list for processing */ rv = C_GetSlotList(0, pSlotList, &ulSlotCount); if (rv != CKR_OK) { fprintf(stderr, "GetSlotList failed: unable to get " "slot list.\n"); free(pSlotList); return (result); } } else { fprintf(stderr, "GetSlotList failed: unable to get slot" " count.\n"); return (result); } /* Find a slot capable of doing random number generation */ for (i = 0; i < ulSlotCount; i++) { SlotID = pSlotList[i]; rv = C_GetTokenInfo(SlotID, &tokenInfo); if (rv != CKR_OK) { /* Check the next slot */ continue; } if (tokenInfo.flags & CKF_RNG) { /* Found a random number generator */ *pslot = SlotID; fprintf(stdout, "Slot # %d supports random number " "generation!\n", SlotID); result = B_TRUE; break; } } if (pSlotList) free(pSlotList); return (result); }