Developer's Guide to Oracle® Solaris 11 Security

Exit Print View

Updated: July 2014

Message Digest Example

    This example uses PKCS #11 functions to create a digest from an input file. The example performs the following steps:

  1. Specifies the digest mechanism.

    In this example, the CKM_MD5 digest mechanism is used.

  2. 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.

  3. 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.

  4. Conducts a digest operation with the slot.

      The message digest is created in this task through these steps:

    1. Opening the input file.

    2. Initializing the digest operation by calling C_DigestInit().

    3. Processing the data a piece at a time with C_DigestUpdate().

    4. Ending the digest process by using C_DigestFinal() to get the complete digest.

  5. 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. */
main(int argc, char **argv)
	CK_INFO info;
	CK_MECHANISM mechanism;
	CK_RV rv;

	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);

	/* 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) {
		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");


	(void) C_CloseSession(hSession);

	(void) C_Finalize(NULL_PTR);