面向开发者的 Oracle® Solaris 11 安全性指南

退出打印视图

更新时间: 2014 年 7 月
 
 

随机字节生成示例

    Example 9–4 说明如何使用可生成随机字节的机制查找插槽。此示例执行以下步骤:

  1. 初始化 cryptoki 库。

  2. 调用 GetRandSlot(),以便使用可以生成随机字节的机制来查找插槽。

      插槽查找任务执行以下步骤:

    1. 调用 C_GetSlotList() 函数以获取可用插槽的列表。

      与 PKCS #11 约定中所建议的一样,C_GetSlotList() 需要调用两次。第一次调用 C_GetSlotList() 用于获取进行内存分配的插槽数量,第二次调用 C_GetSlotList() 用于检索插槽。

    2. 查找可以生成随机字节的插槽。

      对于每个插槽,该函数都可以使用 GetTokenInfo() 来获取令牌信息,并在设置了 CKF_RNG 标志的情况下检查匹配项。如果找到设置了 CKF_RNG 标志的插槽,则 GetRandSlot() 函数将返回。

  3. 使用 C_OpenSession() 来打开会话。

  4. 使用 C_GenerateRandom() 来生成随机字节。

  5. 结束会话。

    程序使用 C_CloseSession() 关闭会话,使用 C_Finalize() 关闭库。

随机数生成样例的源代码如以下示例所示。

示例 9-4  使用 PKCS #11 函数生成随机数
#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);

}