Developer's Guide to Oracle Solaris Security

Random Byte Generation Example

    Example 9–4 demonstrates how to find a slot with a mechanism that can generate random bytes. The example performs the following steps:

  1. Initializes the cryptoki library.

  2. Calls GetRandSlot() to find a slot with a mechanism that can generate random bytes.

      The task of finding a slot performs the following steps:

    1. 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.

    2. 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.

  3. Opens the session by using C_OpenSession().

  4. Generates random bytes by using C_GenerateRandom().

  5. 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.


Note –

The source code for this example is also available through the Sun download center. See http://www.sun.com/download/products.xml?id=41912db5.



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

}