この例では、PKCS #11 関数を使って入力ファイルからダイジェストを作成します。この例では、次の手順を実行します。
ダイジェストの機構を指定します。
この例では、CKM_MD5 ダイジェスト機構が使用されます。
指定されたダイジェストアルゴリズムをサポートするスロットを検索します。
この例では、Sun の簡易関数 SUNW_C_GetMechSession() を使用しています。SUNW_C_GetMechSession() は、cryptoki ライブラリをオープンします。このライブラリには、Solaris 暗号化フレームワークで使用されるすべての PKCS #11 関数が含まれています。続いて SUNW_C_GetMechSession() は、目的の機構を備えたスロットを検索します。そして、セッションが開始されます。この簡易関数は事実上、C_Initialize() 呼び出し、C_OpenSession() 呼び出し、および指定された機構をサポートするスロットの検索に必要なすべてのコードと同等の機能を備えています。
cryptoki の情報を取得します。
この部分は実際には、メッセージダイジェストの作成に直接関係しませんが、C_GetInfo() 関数の使用法を示す意味でここに含めてあります。この例では開発元の ID を取得しています。その他の情報のオプションとして、バージョンとライブラリデータも取得できます。
スロットを使ってダイジェスト処理を実行します。
この作業におけるメッセージダイジェストの作成手順は次のとおりです。
入力ファイルをオープンします。
C_DigestInit() を呼び出してダイジェスト処理を初期化します。
C_DigestUpdate() を使ってデータを一度に一部分ずつ処理していきます。
ダイジェスト処理を終了するために、C_DigestFinal() を使って完全なダイジェストを取得します。
セッションを終了します。
このプログラムは、C_CloseSession() を使ってセッションをクローズし、C_Finalize() を使ってライブラリをクローズします。
メッセージダイジェストのソースコード例を、次に示します。
このソースコード例は、Sun ダウンロードセンターからダウンロードすることも可能です。http://www.sun.com/download/products.xml?id=41912db5 を参照してください。
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <security/pkcs11.h>
#define BUFFERSIZ 8192
#define MAXDIGEST 64
/* Calculate the digest of a user supplied file. */
void
main(int argc, char **argv)
{
CK_BYTE digest[MAXDIGEST];
CK_INFO info;
CK_MECHANISM mechanism;
CK_SESSION_HANDLE hSession;
CK_SESSION_INFO Info;
CK_ULONG ulDatalen = BUFFERSIZ;
CK_ULONG ulDigestLen = MAXDIGEST;
CK_RV rv;
CK_SLOT_ID SlotID;
int i, bytes_read = 0;
char inbuf[BUFFERSIZ];
FILE *fs;
int error = 0;
/* Specify the CKM_MD5 digest mechanism as the target */
mechanism.mechanism = CKM_MD5;
mechanism.pParameter = NULL_PTR;
mechanism.ulParameterLen = 0;
/* 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);
}
/* Get cryptoki information, the manufacturer ID */
rv = C_GetInfo(&info);
if (rv != CKR_OK) {
fprintf(stderr, "WARNING: C_GetInfo: rv = 0x%.8X\n", rv);
}
fprintf(stdout, "Manufacturer ID = %s\n", info.manufacturerID);
/* 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;
}
/* Initialize the digest session */
if ((rv = C_DigestInit(hSession, &mechanism)) != CKR_OK) {
fprintf(stderr, "C_DigestInit: rv = 0x%.8X\n", rv);
error = 1;
goto exit_digest;
}
/* Read in the data and create digest of this portion */
while (!feof(fs) && (ulDatalen = fread(inbuf, 1, BUFFERSIZ, fs)) > 0) {
if ((rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)inbuf,
ulDatalen)) != CKR_OK) {
fprintf(stderr, "C_DigestUpdate: rv = 0x%.8X\n", rv);
error = 1;
goto exit_digest;
}
bytes_read += ulDatalen;
}
fprintf(stdout, "%d bytes read and digested!!!\n\n", bytes_read);
/* Get complete digest */
ulDigestLen = sizeof (digest);
if ((rv = C_DigestFinal(hSession, (CK_BYTE_PTR)digest,
&ulDigestLen)) != CKR_OK) {
fprintf(stderr, "C_DigestFinal: rv = 0x%.8X\n", rv);
error = 1;
goto exit_digest;
}
/* Print the results */
fprintf(stdout, "The value of the digest is: ");
for (i = 0; i < ulDigestLen; i++) {
fprintf(stdout, "%.2x", digest[i]);
}
fprintf(stdout, "\nDone!!!\n");
exit_digest:
fclose(fs);
exit_session:
(void) C_CloseSession(hSession);
exit_program:
(void) C_Finalize(NULL_PTR);
exit(error);
}