Example 9–2 creates a key object for encryption with the DES algorithm in the CBC mode. This source code performs the following steps:
Declares key materials.
Defines DES and initialization vector. The initialization vector is declared statically for demonstration purposes only. Initialization vectors should always be defined dynamically and never reused.
Defines a key object.
For this task, you have to set up a template for the key.
Finds a slot that is capable of the specified encryption mechanism.
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.
Conducts an encryption operation in the slot.
The encryption is performed in this task through these steps:
Opening the input file.
Creating an object handle for the key.
Setting the encryption mechanism to CKM_DES_CBC_PAD by using the mechanism structure.
Initializing the encryption operation by calling C_EncryptInit().
Processing the data a piece at a time with C_EncryptUpdate().
Ending the encryption process by using C_EncryptFinal() to get the last portion of the encrypted data.
Conducts a decryption operation in the slot.
Ends the session.
The program uses C_CloseSession() to close the session and C_Finalize() to close the library.
The source code for the symmetric encryption example is shown in the following example.
Example 9-2 Creating an Encryption Key Object 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
/* 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);
}