This example uses PKCS #11 functions to create a digest from an input file. The example performs the following steps:
Specifies the digest mechanism.
In this example, the CKM_MD5 digest mechanism is used.
Finds a slot that is capable of the specified digest algorithm.
This example uses the Oracle Solaris convenience function SUNW_C_GetMechSession(). SUNW_C_GetMechSession() opens the cryptoki library, which holds all the PKCS #11 functions that are used in the Oracle Solaris cryptographic framework. SUNW_C_GetMechSession() then finds the slot with the desired mechanism. The session is then started. Effectively, this convenience function replaces the C_Initialize() call, the C_OpenSession() call, and any code needed to find a slot that supports the specified mechanism.
Obtains cryptoki information.
This part is not actually needed to create the message digest, but is included to demonstrate use of the C_GetInfo() function. This example gets the manufacturer ID. The other information options retrieve version and library data.
Conducts a digest operation with the slot.
The message digest is created in this task through these steps:
Opening the input file.
Initializing the digest operation by calling C_DigestInit().
Processing the data a piece at a time with C_DigestUpdate().
Ending the digest process by using C_DigestFinal() to get the complete digest.
Ends the session.
The program uses C_CloseSession() to close the session and C_Finalize() to close the library.
The source code for the message digest example is shown in the following example.
Example 9-1 Creating a Message Digest 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 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); }