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

印刷ビューの終了

更新: 2014 年 7 月
 
 

対称暗号化の例

    Example 9–2 は、DES アルゴリズムの CBC モードを使って暗号化するための鍵オブジェクトを作成します。このソースコードは次の手順を実行します。

  1. 鍵データを宣言します。

    DES と初期化ベクトルを定義します。ここでは初期化ベクトルを静的に宣言していますが、これはあくまでもデモ用です。初期化ベクトルは常に動的に定義し、決して再利用しないでください。

  2. 鍵オブジェクトを定義します。

    このタスクでは、鍵のテンプレートを設定する必要があります。

  3. 指定された暗号化メカニズムをサポートするスロットを検索します。

    この例では、Oracle Solaris の簡易関数 SUNW_C_GetMechSession() を使用しています。SUNW_C_GetMechSession() は、cryptoki ライブラリをオープンします。このライブラリには、Oracle Solaris 暗号化フレームワークで使用されるすべての PKCS #11 関数が含まれています。続いて SUNW_C_GetMechSession() は、目的のメカニズムを備えたスロットを検索します。そして、セッションが開始されます。この簡易関数は事実上、C_Initialize() 呼び出し、C_OpenSession() 呼び出し、および指定されたメカニズムをサポートするスロットの検索に必要なすべてのコードと同等の機能を備えています。

  4. このスロットで暗号化処理を実行します。

      このタスクにおける暗号化の実行手順は次のとおりです。

    1. 入力ファイルをオープンします。

    2. 鍵のオブジェクトハンドルを作成します。

    3. mechanism 構造体を使って暗号化メカニズムを CKM_DES_CBC_PAD に設定します。

    4. C_EncryptInit() を呼び出して暗号化処理を初期化します。

    5. C_EncryptUpdate() を使ってデータを一度に一部分ずつ処理します。

    6. 暗号化処理を終了するために、C_EncryptFinal() を使って暗号化データの最後の部分を取得します。

  5. このスロットで復号化処理を実行します。

      このタスクにおける復号化の実行手順は次のとおりです。この復号化処理は、テスト目的でのみ提供されています。

    1. C_DecryptInit() を呼び出して復号化処理を初期化します。

    2. C_Decrypt() で文字列全体を処理します。

  6. セッションを終了します。

    このプログラムは、C_CloseSession() を使ってセッションをクローズし、C_Finalize() を使ってライブラリをクローズします。

対称暗号化のソースコード例を、次に示します。

使用例 9-2  PKCS #11 関数による暗号化鍵オブジェクトの作成
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <security/pkcs11.h>

#define BUFFERSIZ    8192

/* Declare values for the key materials. DO NOT declare initialization 
 * vectors statically like this in real life!! */
uchar_t des_key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
uchar_t des_cbc_iv[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef};

/* Key template related definitions. */
static CK_BBOOL truevalue = TRUE;
static CK_BBOOL falsevalue = FALSE;
static CK_OBJECT_CLASS class = CKO_SECRET_KEY;
static CK_KEY_TYPE keyType = CKK_DES;


/* Example encrypts and decrypts a file provided by the user. */
void
main(int argc, char **argv)
{
	CK_RV rv;
	CK_MECHANISM mechanism;
	CK_OBJECT_HANDLE hKey;
	CK_SESSION_HANDLE hSession;
	CK_ULONG ciphertext_len = 64, lastpart_len = 64;
	long ciphertext_space = BUFFERSIZ;
	CK_ULONG decrypttext_len;
	CK_ULONG total_encrypted = 0;
	CK_ULONG ulDatalen = BUFFERSIZ;

	int i, bytes_read = 0;
	int error = 0;
	char inbuf[BUFFERSIZ];
	FILE *fs;
	uchar_t ciphertext[BUFFERSIZ], *pciphertext, decrypttext[BUFFERSIZ];

	/* Set the key object */
	CK_ATTRIBUTE template[] = {
		{CKA_CLASS, &class, sizeof (class) },
		{CKA_KEY_TYPE, &keyType, sizeof (keyType) },
		{CKA_TOKEN, &falsevalue, sizeof (falsevalue) },
		{CKA_ENCRYPT, &truevalue, sizeof (truevalue) },
		{CKA_VALUE, &des_key, sizeof (des_key) }
	};

	/* Set the encryption mechanism to CKM_DES_CBC_PAD */
	mechanism.mechanism = CKM_DES_CBC_PAD;
	mechanism.pParameter = des_cbc_iv;
	mechanism.ulParameterLen = 8;

	/* Use SUNW convenience function to initialize the cryptoki
	 * library, and open a session with a slot that supports
	 * the mechanism we plan on using. */
	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);

	if (rv != CKR_OK) {
		fprintf(stderr, "SUNW_C_GetMechSession: rv = 0x%.8X\n", rv);
		exit(1);
	}

	/* Open the input file */
	if ((fs = fopen(argv[1], "r")) == NULL) {
		perror("fopen");
		fprintf(stderr, "\n\tusage: %s filename>\n", argv[0]);
		error = 1;
		goto exit_session;
	}

	/* Create an object handle for the key */
	rv = C_CreateObject(hSession, template,
	    sizeof (template) / sizeof (CK_ATTRIBUTE),
	    &hKey);

	if (rv != CKR_OK) {
		fprintf(stderr, "C_CreateObject: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}


	/* Initialize the encryption operation in the session */
	rv = C_EncryptInit(hSession, &mechanism, hKey);

	if (rv != CKR_OK) {
		fprintf(stderr, "C_EncryptInit: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_session;
	}

	/* Read in the data and encrypt this portion */
	pciphertext = &ciphertext[0];
	while (!feof(fs) && (ciphertext_space > 0) &&
	    (ulDatalen = fread(inbuf, 1, ciphertext_space, fs)) > 0) {
		ciphertext_len = ciphertext_space;

		/* C_EncryptUpdate is only being sent one byte at a
		 * time, so we are not checking for CKR_BUFFER_TOO_SMALL.
		 * Also, we are checking to make sure we do not go
		 * over the alloted buffer size.  A more robust program
		 * could incorporate realloc to enlarge the buffer
		 * dynamically.	 */
		rv = C_EncryptUpdate(hSession, (CK_BYTE_PTR)inbuf, ulDatalen,
		    pciphertext, &ciphertext_len);
		if (rv != CKR_OK) {
			fprintf(stderr, "C_EncryptUpdate: rv = 0x%.8X\n", rv);
			error = 1;
			goto exit_encrypt;
		}
		pciphertext += ciphertext_len;
		total_encrypted += ciphertext_len;
		ciphertext_space -= ciphertext_len;
		bytes_read += ulDatalen;
	}

	if (!feof(fs) || (ciphertext_space < 0)) {
		fprintf(stderr, "Insufficient space for encrypting the file\n");
		error = 1;
		goto exit_encrypt;
	}

	/* Get the last portion of the encrypted data */
	lastpart_len = ciphertext_space;
	rv = C_EncryptFinal(hSession, pciphertext, &lastpart_len);
	if (rv != CKR_OK) {
		fprintf(stderr, "C_EncryptFinal: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_encrypt;
	}
	total_encrypted += lastpart_len;

	fprintf(stdout, "%d bytes read and encrypted. Size of the "
	    "ciphertext: %d!\n\n", bytes_read, total_encrypted);

	/* Print the encryption results */
	fprintf(stdout, "The value of the encryption is:\n");
	for (i = 0; i < ciphertext_len; i++) {
		if (ciphertext[i] < 16)
			fprintf(stdout, "0%x", ciphertext[i]);
		else
			fprintf(stdout, "%2x", ciphertext[i]);
	}

	/* Initialize the decryption operation in the session */
	rv = C_DecryptInit(hSession, &mechanism, hKey);

	/* Decrypt the entire ciphertext string */
	decrypttext_len = sizeof (decrypttext);
	rv = C_Decrypt(hSession, (CK_BYTE_PTR)ciphertext, total_encrypted,
	    decrypttext, &decrypttext_len);

	if (rv != CKR_OK) {
		fprintf(stderr, "C_Decrypt: rv = 0x%.8X\n", rv);
		error = 1;
		goto exit_encrypt;
	}

	fprintf(stdout, "\n\n%d bytes decrypted!!!\n\n", decrypttext_len);

	/* Print the decryption results */
	fprintf(stdout, "The value of the decryption is:\n%s", decrypttext);

	fprintf(stdout, "\nDone!!!\n");

exit_encrypt:
	fclose(fs);

exit_session:
	(void) C_CloseSession(hSession);

exit_program:
	(void) C_Finalize(NULL_PTR);
	exit(error);
}