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);
}