Developer's Guide to Oracle Solaris Security

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


Note –

The source code for this example is also available through the Sun download center. See http://www.sun.com/download/products.xml?id=41912db5.



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

}