Oracle® Solaris 11 セキュリティー開発者ガイド

印刷ビューの終了

更新: 2014 年 7 月
 
 

ランダムバイト生成の例

    Example 9–4 は、ランダムバイトを生成できるメカニズムを備えたスロットを検索する方法を示しています。この例では、次の手順を実行します。

  1. cryptoki ライブラリを初期化します。

  2. GetRandSlot() を呼び出して、ランダムバイトを生成できるメカニズムを備えたスロットを検索します。

      このタスクにおけるスロット検索手順は次のとおりです。

    1. 関数 C_GetSlotList() を呼び出して利用可能なスロットのリストを取得します。

      PKCS #11 の規約で推奨されているように、C_GetSlotList() は 2 回呼び出されます。1 回目の C_GetSlotList() 呼び出しでは、メモリーを割り当てる目的でスロット数を取得します。そして 2 回目の 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);

}