blob: c48f465e39b14ac322bf8da0806d98aa063128cb [file] [log] [blame]
// File: aes_func.c
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <dlfcn.h>
#include "pkcs11types.h"
#include "regress.h"
void *dl_handle;
unsigned long SlotID = 0;
int do_GetFunctionList(void);
#define AES_KEY_SIZE_256 32
#define AES_BLOCK_SIZE 16
#define AES_KEY_LEN 32
CK_FUNCTION_LIST *funcs;
CK_SESSION_HANDLE sess;
#define OC_ERR_MSG(a,b) oc_err_msg(__FILE__, __LINE__, a, b)
//
//
int do_EncryptAES_ECB(void)
{
CK_BYTE data1[BIG_REQUEST];
CK_BYTE data2[BIG_REQUEST];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_ULONG i;
CK_ULONG len1, len2, key_size = AES_KEY_SIZE_256;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
printf("do_EncryptAES_ECB...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
// now, encrypt some data
//
len1 = len2 = BIG_REQUEST;
for (i = 0; i < len1; i++) {
data1[i] = i % 255;
data2[i] = i % 255;
}
mech.mechanism = CKM_AES_ECB;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Encrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// now, decrypt the data
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (len1 != len2) {
printf(" ERROR: lengths don't match\n");
return FALSE;
}
for (i = 0; i < len1; i++) {
if (data1[i] != data2[i]) {
printf(" ERROR: mismatch at byte %ld\n", i);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_EncryptAES_Multipart_ECB(void)
{
CK_BYTE original[BIG_REQUEST];
CK_BYTE crypt1[BIG_REQUEST];
CK_BYTE crypt2[BIG_REQUEST];
CK_BYTE decrypt1[BIG_REQUEST];
CK_BYTE decrypt2[BIG_REQUEST];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_ULONG i, k, key_size = AES_KEY_SIZE_256;
CK_ULONG orig_len;
CK_ULONG crypt1_len, crypt2_len, decrypt1_len, decrypt2_len;
CK_ULONG tmp;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
printf("do_EncryptAES_Multipart_ECB...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
// now, encrypt some data
//
orig_len = sizeof(original);
for (i = 0; i < orig_len; i++) {
original[i] = i % 255;
}
mech.mechanism = CKM_AES_ECB;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
// use normal ecb mode to encrypt data1
//
crypt1_len = sizeof(crypt1);
rc = funcs->C_Encrypt(session, original, orig_len, crypt1,
&crypt1_len);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// use multipart ecb mode to encrypt data2 in 5 byte chunks
//
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #2", rc);
return FALSE;
}
i = k = 0;
crypt2_len = sizeof(crypt2);
while (i < orig_len) {
CK_ULONG rem = orig_len - i;
CK_ULONG chunk;
if (rem < 100)
chunk = rem;
else
chunk = 100;
tmp = crypt2_len - k; // how much room is left in crypt2?
rc = funcs->C_EncryptUpdate(session, &original[i], chunk,
&crypt2[k], &tmp);
if (rc != CKR_OK) {
show_error(" C_EncryptUpdate #1", rc);
return FALSE;
}
k += tmp;
i += chunk;
}
crypt2_len = k;
// AES-ECB shouldn't return anything for EncryptFinal per the spec
//
rc = funcs->C_EncryptFinal(session, NULL, &tmp);
if (rc != CKR_OK) {
show_error(" C_EncryptFinal #2", rc);
return FALSE;
}
if (tmp != 0) {
printf
(" ERROR: DecryptFinal wants to return %ld bytes\n",
tmp);
return FALSE;
}
if (crypt2_len != crypt1_len) {
printf(" ERROR: crypt1_len = %ld, crypt2_len = %ld\n",
crypt1_len, crypt2_len);
return FALSE;
}
// compare both encrypted blocks. they'd better be equal
//
for (i = 0; i < crypt1_len; i++) {
if (crypt1[i] != crypt2[i]) {
printf
(" ERROR: mismatch. crypt1 != crypt2 at byte %ld\n",
i);
return FALSE;
}
}
// now, decrypt the data
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
decrypt1_len = sizeof(decrypt1);
rc = funcs->C_Decrypt(session, crypt1, crypt1_len, decrypt1,
&decrypt1_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
// use multipart ecb mode to encrypt data2 in 1024 byte chunks
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
i = k = 0;
decrypt2_len = sizeof(decrypt2);
while (i < crypt1_len) {
CK_ULONG rem = crypt1_len - i;
CK_ULONG chunk;
if (rem < 101)
chunk = rem;
else
chunk = 101;
tmp = decrypt2_len - k;
rc = funcs->C_DecryptUpdate(session, &crypt1[i], chunk,
&decrypt2[k], &tmp);
if (rc != CKR_OK) {
show_error(" C_DecryptUpdate #1", rc);
return FALSE;
}
k += tmp;
i += chunk;
}
decrypt2_len = k;
// AES-ECB shouldn't return anything for EncryptFinal per the spec
//
rc = funcs->C_DecryptFinal(session, NULL, &tmp);
if (rc != CKR_OK) {
show_error(" C_DecryptFinal #2", rc);
return FALSE;
}
if (tmp != 0) {
printf
(" ERROR: DecryptFinal wants to return %ld bytes\n",
tmp);
return FALSE;
}
if (decrypt1_len != decrypt2_len) {
printf(" ERROR: decrypt1_len = %ld, decrypt2_len = %ld\n",
decrypt1_len, decrypt2_len);
return FALSE;
}
if (decrypt1_len != orig_len) {
printf
(" ERROR: decrypted lengths = %ld, original length = %ld\n",
decrypt1_len, orig_len);
return FALSE;
}
// compare both decrypted blocks. they'd better be equal
//
for (i = 0; i < decrypt1_len; i++) {
if (decrypt1[i] != decrypt2[i]) {
printf
(" ERROR: mismatch. decrypt1 != decrypt2 at byte %ld\n",
i);
return FALSE;
}
}
// compare the multi-part decrypted block with the 'control' block
//
for (i = 0; i < orig_len; i++) {
if (original[i] != decrypt1[i]) {
printf
(" ERROR: decrypted mismatch: original != decrypt at byte %ld\n",
i);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_EncryptAES_CBC(void)
{
CK_BYTE data1[BIG_REQUEST];
CK_BYTE data2[BIG_REQUEST];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_BYTE init_v[AES_BLOCK_SIZE];
CK_ULONG i, key_size = AES_KEY_SIZE_256;
CK_ULONG len1, len2;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
printf("do_EncryptAES_CBC...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
// now, encrypt some data
//
len1 = len2 = BIG_REQUEST;
for (i = 0; i < len1; i++) {
data1[i] = i % 255;
data2[i] = i % 255;
}
memcpy(init_v, "0123456789abcdef", 8);
mech.mechanism = CKM_AES_CBC;
mech.ulParameterLen = AES_BLOCK_SIZE;
mech.pParameter = init_v;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Encrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// now, decrypt the data
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (len1 != len2) {
printf(" ERROR: lengths don't match\n");
return FALSE;
}
for (i = 0; i < len1; i++) {
if (data1[i] != data2[i]) {
printf(" ERROR: mismatch at byte %ld\n", i);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_EncryptAES_Multipart_CBC(void)
{
CK_BYTE original[BIG_REQUEST];
CK_BYTE crypt1[BIG_REQUEST];
CK_BYTE crypt2[BIG_REQUEST];
CK_BYTE decrypt1[BIG_REQUEST];
CK_BYTE decrypt2[BIG_REQUEST];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_FLAGS flags;
CK_BYTE init_v[AES_BLOCK_SIZE];
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_ULONG i, k, key_size = AES_KEY_SIZE_256;
CK_ULONG orig_len;
CK_ULONG crypt1_len, crypt2_len, decrypt1_len, decrypt2_len;
CK_ULONG tmp;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
printf("do_EncryptAES_Multipart_CBC...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
// now, encrypt some data
//
orig_len = sizeof(original);
for (i = 0; i < orig_len; i++) {
original[i] = i % 255;
}
memcpy(init_v, "0123456789abcdef", 16);
mech.mechanism = CKM_AES_CBC;
mech.ulParameterLen = AES_BLOCK_SIZE;
mech.pParameter = init_v;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
// use normal ecb mode to encrypt data1
//
crypt1_len = sizeof(crypt1);
rc = funcs->C_Encrypt(session, original, orig_len, crypt1,
&crypt1_len);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// use multipart cbc mode to encrypt data2 in 1024 byte chunks
//
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #2", rc);
return FALSE;
}
i = k = 0;
crypt2_len = sizeof(crypt2);
while (i < orig_len) {
CK_ULONG rem = orig_len - i;
CK_ULONG chunk;
if (rem < 100)
chunk = rem;
else
chunk = 100;
tmp = crypt2_len - k; // how much room is left in crypt2?
rc = funcs->C_EncryptUpdate(session, &original[i], chunk,
&crypt2[k], &tmp);
if (rc != CKR_OK) {
show_error(" C_EncryptUpdate #1", rc);
return FALSE;
}
k += tmp;
i += chunk;
}
crypt2_len = k;
rc = funcs->C_EncryptFinal(session, NULL, &tmp);
if (rc != CKR_OK) {
show_error(" C_EncryptFinal #2", rc);
return FALSE;
}
if (tmp != 0) {
printf
(" ERROR: EncryptFinal wants to return %ld bytes\n",
tmp);
return FALSE;
}
if (crypt2_len != crypt1_len) {
printf(" ERROR: crypt1_len = %ld, crypt2_len = %ld\n",
crypt1_len, crypt2_len);
return FALSE;
}
// compare both encrypted blocks. they'd better be equal
//
for (i = 0; i < crypt1_len; i++) {
if (crypt1[i] != crypt2[i]) {
printf
(" ERROR: mismatch. crypt1 != crypt2 at byte %ld\n",
i);
return FALSE;
}
}
// now, decrypt the data
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
decrypt1_len = sizeof(decrypt1);
rc = funcs->C_Decrypt(session, crypt1, crypt1_len, decrypt1,
&decrypt1_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
// use multipart cbc mode to encrypt data2 in 1024 byte chunks
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
i = k = 0;
decrypt2_len = sizeof(decrypt2);
while (i < crypt1_len) {
CK_ULONG rem = crypt1_len - i;
CK_ULONG chunk;
if (rem < 101)
chunk = rem;
else
chunk = 101;
tmp = decrypt2_len - k;
rc = funcs->C_DecryptUpdate(session, &crypt1[i], chunk,
&decrypt2[k], &tmp);
if (rc != CKR_OK) {
show_error(" C_DecryptUpdate #1", rc);
return FALSE;
}
k += tmp;
i += chunk;
}
decrypt2_len = k;
rc = funcs->C_DecryptFinal(session, NULL, &tmp);
if (rc != CKR_OK) {
show_error(" C_DecryptFinal #2", rc);
return FALSE;
}
if (tmp != 0) {
printf
(" ERROR: DecryptFinal wants to return %ld bytes\n",
tmp);
return FALSE;
}
if (decrypt2_len != decrypt1_len) {
printf(" ERROR: decrypt1_len = %ld, decrypt2_len = %ld\n",
decrypt1_len, decrypt2_len);
return FALSE;
}
// compare both decrypted blocks. they'd better be equal
//
for (i = 0; i < decrypt1_len; i++) {
if (crypt1[i] != crypt2[i]) {
printf
(" ERROR: mismatch. decrypt1 != decrypt2 at byte %ld\n",
i);
return FALSE;
}
}
// compare the multi-part decrypted block with the 'control' block
//
for (i = 0; i < orig_len; i++) {
if (original[i] != decrypt1[i]) {
printf
(" ERROR: decrypted mismatch: original != decrypt at byte %ld\n",
i);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_EncryptAES_Multipart_CBC_PAD(void)
{
CK_BYTE original[BIG_REQUEST];
CK_BYTE crypt1[BIG_REQUEST + AES_BLOCK_SIZE]; // account for padding
CK_BYTE crypt2[BIG_REQUEST + AES_BLOCK_SIZE]; // account for padding
CK_BYTE decrypt1[BIG_REQUEST + AES_BLOCK_SIZE]; // account for padding
CK_BYTE decrypt2[BIG_REQUEST + AES_BLOCK_SIZE]; // account for padding
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_FLAGS flags;
CK_BYTE init_v[AES_BLOCK_SIZE];
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_ULONG i, k, key_size = AES_KEY_SIZE_256;
CK_ULONG orig_len, crypt1_len, crypt2_len, decrypt1_len,
decrypt2_len;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
printf("do_EncryptAES_Multipart_CBC_PAD...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
// now, encrypt some data
//
orig_len = sizeof(original);
for (i = 0; i < orig_len; i++) {
original[i] = i % 255;
}
memcpy(init_v, "0123456789abcdef", 16);
mech.mechanism = CKM_AES_CBC_PAD;
mech.ulParameterLen = AES_BLOCK_SIZE;
mech.pParameter = init_v;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
// use normal ecb mode to encrypt data1
//
crypt1_len = sizeof(crypt1);
rc = funcs->C_Encrypt(session, original, orig_len, crypt1,
&crypt1_len);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// use multipart cbc mode to encrypt data2 in chunks
//
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #2", rc);
return FALSE;
}
i = k = 0;
crypt2_len = sizeof(crypt2);
while (i < orig_len) {
CK_ULONG rem = orig_len - i;
CK_ULONG chunk, len;
if (rem < 100)
chunk = rem;
else
chunk = 100;
len = crypt2_len - k;
rc = funcs->C_EncryptUpdate(session, &original[i], chunk,
&crypt2[k], &len);
if (rc != CKR_OK) {
show_error(" C_EncryptUpdate #1", rc);
return FALSE;
}
k += len;
i += chunk;
}
crypt2_len = sizeof(crypt2) - k;
rc = funcs->C_EncryptFinal(session, &crypt2[k], &crypt2_len);
if (rc != CKR_OK) {
show_error(" C_EncryptFinal #2", rc);
return FALSE;
}
crypt2_len += k;
if (crypt2_len != crypt1_len) {
printf(" ERROR: encrypted lengths don't match\n");
printf(" crypt2_len == %ld, crypt1_len == %ld\n",
crypt2_len, crypt1_len);
return FALSE;
}
// compare both encrypted blocks. they'd better be equal
//
for (i = 0; i < crypt2_len; i++) {
if (crypt1[i] != crypt2[i]) {
printf
(" ERROR: encrypted mismatch: crypt1 != crypt2 at byte %ld\n",
i);
return FALSE;
}
}
// now, decrypt the data
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
decrypt1_len = sizeof(decrypt1);
rc = funcs->C_Decrypt(session, crypt1, crypt1_len, decrypt1,
&decrypt1_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
// use multipart cbc mode to encrypt data2 in 1024 byte chunks
//
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
i = k = 0;
decrypt2_len = sizeof(decrypt2);
while (i < crypt2_len) {
CK_ULONG rem = crypt2_len - i;
CK_ULONG chunk, len;
if (rem < 101)
chunk = rem;
else
chunk = 101;
len = decrypt2_len - k;
rc = funcs->C_DecryptUpdate(session, &crypt2[i], chunk,
&decrypt2[k], &len);
if (rc != CKR_OK) {
show_error(" C_DecryptUpdate #1", rc);
return FALSE;
}
k += len;
i += chunk;
}
decrypt2_len = sizeof(decrypt2) - k;
rc = funcs->C_DecryptFinal(session, &decrypt2[k], &decrypt2_len);
if (rc != CKR_OK) {
show_error(" C_DecryptFinal #2", rc);
return FALSE;
}
decrypt2_len += k;
if (decrypt2_len != decrypt1_len) {
printf(" ERROR: decrypted lengths don't match\n");
printf
(" decrypt1_len == %ld, decrypt2_len == %ld\n",
decrypt1_len, decrypt2_len);
return FALSE;
}
if (decrypt2_len != orig_len) {
printf
(" ERROR: decrypted lengths don't match the original\n");
printf(" decrypt_len == %ld, orig_len == %ld\n",
decrypt1_len, orig_len);
return FALSE;
}
// compare both decrypted blocks. they'd better be equal
//
for (i = 0; i < decrypt1_len; i++) {
if (decrypt1[i] != decrypt2[i]) {
printf
(" ERROR: decrypted mismatch: data1 != data2 at byte %ld\n",
i);
return FALSE;
}
}
// compare the multi-part decrypted block with the 'control' block
//
for (i = 0; i < orig_len; i++) {
if (original[i] != decrypt2[i]) {
printf
(" ERROR: decrypted mismatch: original != decrypted at byte %ld\n",
i);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_WrapUnwrapAES_ECB(void)
{
CK_BYTE data1[BIG_REQUEST];
CK_BYTE data2[BIG_REQUEST];
#if 0
CK_BYTE sanity[BIG_REQUEST];
#endif
CK_BYTE wrapped_data[AES_BLOCK_SIZE];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_OBJECT_HANDLE w_key;
CK_OBJECT_HANDLE uw_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_ULONG wrapped_data_len;
CK_ULONG i, key_size = AES_KEY_SIZE_256;
CK_ULONG len1, len2, sanity_len;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
CK_KEY_TYPE key_type = CKK_AES;
CK_ULONG tmpl_count = 3;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &key_class, sizeof(key_class)},
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
{CKA_VALUE_LEN, &key_size, sizeof(key_size)}
};
printf("do_WrapUnwrapAES_ECB...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key and a wrapping key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &w_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #2", rc);
return FALSE;
}
// now, encrypt some data
//
sanity_len = len1 = len2 = BIG_REQUEST;
for (i = 0; i < len1; i++) {
data1[i] = i % 255;
data2[i] = i % 255;
}
mech.mechanism = CKM_AES_ECB;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Encrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
#if 0
rc = funcs->C_DecryptInit(session, &mech, h_key);
printf("Sanity chec #1: Decrypting using original, unwrapped key.\n");
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, sanity, &sanity_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (sanity_len != len2) {
printf(" ERROR: lengths don't match\n");
return FALSE;
}
for (i = 0; i < len1; i++) {
if (sanity[i] != data2[i]) {
printf(" Sanity Check #1 Failed. ERROR: mismatch at byte %d\n", i);
return FALSE;
}
}
printf("Sanity Check 1 PASSED\n");
#endif
// now, wrap the key. we'll just use the same ECB mechanism
//
wrapped_data_len = AES_KEY_LEN;
rc = funcs->C_WrapKey(session, &mech,
w_key, h_key,
(CK_BYTE *) & wrapped_data,
&wrapped_data_len);
if (rc != CKR_OK) {
show_error(" C_WrapKey #1", rc);
return FALSE;
}
#if 0
rc = funcs->C_DecryptInit(session, &mech, h_key);
printf("Sanity Check #2: Decrypting using original, unwrapped key after C_WrapKey.\n");
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, sanity, &sanity_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (sanity_len != len2) {
printf(" ERROR: lengths don't match\n");
return FALSE;
}
for (i = 0; i < len1; i++) {
if (sanity[i] != data2[i]) {
printf(" Sanity Check #2 failed. ERROR: mismatch at byte %d\n", i);
return FALSE;
}
}
printf("Sanity Check 2 PASSED\n");
#endif
rc = funcs->C_UnwrapKey(session, &mech,
w_key,
wrapped_data, wrapped_data_len,
template, tmpl_count, &uw_key);
if (rc != CKR_OK) {
show_error(" C_UnWrapKey #1", rc);
return FALSE;
}
// now, decrypt the data using the unwrapped key.
//
rc = funcs->C_DecryptInit(session, &mech, uw_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (len1 != len2) {
printf(" ERROR: lengths don't match\n");
return FALSE;
}
for (i = 0; i < len1; i++) {
if (data1[i] != data2[i]) {
printf("line %d ERROR: mismatch at byte %ld\n", __LINE__, i);
return FALSE;
}
}
// now, try to wrap an RSA private key. this should fail. we'll
// create a fake key object instead of generating a new one
//
{
CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keytype = CKK_RSA;
CK_BYTE modulus[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE publ_exp[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE priv_exp[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE prime_1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE prime_2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE exp_1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE exp_2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE coeff[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_ATTRIBUTE tmpl[] = {
{CKA_CLASS, &keyclass, sizeof(keyclass)},
{CKA_KEY_TYPE, &keytype, sizeof(keytype)},
{CKA_MODULUS, modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, publ_exp, sizeof(publ_exp)},
{CKA_PRIVATE_EXPONENT, priv_exp, sizeof(priv_exp)},
{CKA_PRIME_1, prime_1, sizeof(prime_1)},
{CKA_PRIME_2, prime_2, sizeof(prime_2)},
{CKA_EXPONENT_1, exp_1, sizeof(exp_1)},
{CKA_EXPONENT_2, exp_2, sizeof(exp_2)},
{CKA_COEFFICIENT, coeff, sizeof(coeff)}
};
CK_OBJECT_HANDLE priv_key;
CK_BYTE data[1024];
CK_ULONG data_len = sizeof(data);
rc = funcs->C_CreateObject(session, tmpl, 10, &priv_key);
if (rc != CKR_OK) {
show_error(" C_CreateObject #1", rc);
return FALSE;
}
rc = funcs->C_WrapKey(session, &mech,
w_key, priv_key, data, &data_len);
if (rc != CKR_KEY_NOT_WRAPPABLE) {
show_error(" C_WrapKey #2", rc);
printf(" Expected CKR_KEY_NOT_WRAPPABLE\n");
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_WrapUnwrapAES_CBC(void)
{
CK_BYTE data1[BIG_REQUEST];
CK_BYTE data2[BIG_REQUEST];
CK_BYTE wrapped_data[AES_KEY_SIZE_256];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_OBJECT_HANDLE w_key;
CK_OBJECT_HANDLE uw_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_BYTE init_v[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f' };
CK_ULONG user_pin_len;
CK_ULONG wrapped_data_len;
CK_ULONG i, key_size = AES_KEY_SIZE_256;
CK_ULONG len1 = BIG_REQUEST, len2 = BIG_REQUEST;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
CK_KEY_TYPE key_type = CKK_AES;
CK_ULONG tmpl_count = 3;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &key_class, sizeof(key_class)},
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
{CKA_VALUE_LEN, &key_size, sizeof(key_size)}
};
printf("do_WrapUnwrapAES_CBC...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key and a wrapping key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &w_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #2", rc);
return FALSE;
}
// now, encrypt some data
//
for (i = 0; i < len1; i++) {
data1[i] = i % 255;
data2[i] = i % 255;
}
mech.mechanism = CKM_AES_CBC;
mech.ulParameterLen = sizeof(init_v);
mech.pParameter = init_v;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Encrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// now, wrap the key. we'll just use the same ECB mechanism
//
wrapped_data_len = AES_KEY_LEN;
rc = funcs->C_WrapKey(session, &mech,
w_key, h_key,
(CK_BYTE *) & wrapped_data,
&wrapped_data_len);
if (rc != CKR_OK) {
show_error(" C_WrapKey #1", rc);
return FALSE;
}
rc = funcs->C_UnwrapKey(session, &mech,
w_key,
wrapped_data, wrapped_data_len,
template, tmpl_count, &uw_key);
if (rc != CKR_OK) {
show_error(" C_UnWrapKey #1", rc);
return FALSE;
}
// now, decrypt the data using the unwrapped key.
//
rc = funcs->C_DecryptInit(session, &mech, uw_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
rc = funcs->C_Decrypt(session, data1, len1, data1, &len1);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (len1 != len2) {
printf("line %d ERROR: lengths don't match\n", __LINE__);
return FALSE;
}
for (i = 0; i < len1; i++) {
if (data1[i] != data2[i]) {
printf("line %d ERROR: mismatch at byte %ld\n", __LINE__, i);
return FALSE;
}
}
// now, try to wrap an RSA private key. this should fail. we'll
// create a fake key object instead of generating a new one
//
{
CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keytype = CKK_RSA;
CK_BYTE modulus[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE publ_exp[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE priv_exp[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE prime_1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE prime_2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE exp_1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE exp_2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_BYTE coeff[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
CK_ATTRIBUTE tmpl[] = {
{CKA_CLASS, &keyclass, sizeof(keyclass)},
{CKA_KEY_TYPE, &keytype, sizeof(keytype)},
{CKA_MODULUS, modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, publ_exp, sizeof(publ_exp)},
{CKA_PRIVATE_EXPONENT, priv_exp, sizeof(priv_exp)},
{CKA_PRIME_1, prime_1, sizeof(prime_1)},
{CKA_PRIME_2, prime_2, sizeof(prime_2)},
{CKA_EXPONENT_1, exp_1, sizeof(exp_1)},
{CKA_EXPONENT_2, exp_2, sizeof(exp_2)},
{CKA_COEFFICIENT, coeff, sizeof(coeff)}
};
CK_OBJECT_HANDLE priv_key;
CK_BYTE data[1024];
CK_ULONG data_len = sizeof(data);
rc = funcs->C_CreateObject(session, tmpl, 10, &priv_key);
if (rc != CKR_OK) {
show_error(" C_CreateObject #1", rc);
return FALSE;
}
rc = funcs->C_WrapKey(session, &mech,
w_key, priv_key, data, &data_len);
if (rc != CKR_KEY_NOT_WRAPPABLE) {
show_error(" C_WrapKey #2", rc);
printf("line %d Expected CKR_KEY_NOT_WRAPPABLE\n", __LINE__);
return FALSE;
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
//
//
int do_WrapUnwrapAES_CBC_PAD(void)
{
CK_BYTE original[BIG_REQUEST];
CK_BYTE cipher[BIG_REQUEST + AES_BLOCK_SIZE];
CK_BYTE decipher[BIG_REQUEST + AES_BLOCK_SIZE];
CK_BYTE wrapped_data[BIG_REQUEST + AES_BLOCK_SIZE];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE h_key;
CK_OBJECT_HANDLE w_key;
CK_OBJECT_HANDLE uw_key;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_BYTE init_v[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f' };
CK_ULONG user_pin_len;
CK_ULONG wrapped_data_len;
CK_ULONG i, key_size = AES_KEY_SIZE_256;
CK_ULONG orig_len, cipher_len, decipher_len;
CK_RV rc;
CK_ATTRIBUTE key_gen_tmpl[] = {
{CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG) }
};
CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
CK_KEY_TYPE key_type = CKK_AES;
CK_ULONG tmpl_count = 3;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &key_class, sizeof(key_class)},
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
{CKA_VALUE_LEN, &key_size, sizeof(key_size)}
};
printf("do_WrapUnwrapAES_CBC_PAD...\n");
slot_id = SlotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &session);
if (rc != CKR_OK) {
show_error(" C_OpenSession #1", rc);
return FALSE;
}
if (get_user_pin(user_pin))
return CKR_FUNCTION_FAILED;
user_pin_len = (CK_ULONG)strlen((char *)user_pin);
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
if (rc != CKR_OK) {
show_error(" C_Login #1", rc);
return FALSE;
}
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// first, generate an AES key and a wrapping key
//
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &h_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #1", rc);
return FALSE;
}
rc = funcs->C_GenerateKey(session, &mech, key_gen_tmpl, 1, &w_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKey #2", rc);
return FALSE;
}
// now, encrypt some data
//
orig_len = sizeof(original);
for (i = 0; i < orig_len; i++) {
original[i] = i % 255;
}
mech.mechanism = CKM_AES_CBC_PAD;
mech.ulParameterLen = sizeof(init_v);
mech.pParameter = init_v;
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #1", rc);
return FALSE;
}
cipher_len = sizeof(cipher);
rc = funcs->C_Encrypt(session, original, orig_len, cipher,
&cipher_len);
if (rc != CKR_OK) {
show_error(" C_Encrypt #1", rc);
return FALSE;
}
// now, wrap the key.
//
wrapped_data_len = sizeof(wrapped_data);
rc = funcs->C_WrapKey(session, &mech,
w_key, h_key,
wrapped_data, &wrapped_data_len);
if (rc != CKR_OK) {
show_error(" C_WrapKey #1", rc);
return FALSE;
}
rc = funcs->C_UnwrapKey(session, &mech,
w_key,
wrapped_data, wrapped_data_len,
template, tmpl_count, &uw_key);
if (rc != CKR_OK) {
show_error(" C_UnWrapKey #1", rc);
return FALSE;
}
// now, decrypt the data using the unwrapped key.
//
rc = funcs->C_DecryptInit(session, &mech, uw_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
decipher_len = sizeof(decipher);
rc = funcs->C_Decrypt(session, cipher, cipher_len, decipher,
&decipher_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (orig_len != decipher_len) {
printf(" ERROR: lengths don't match: %ld vs %ld\n",
orig_len, decipher_len);
return FALSE;
}
for (i = 0; i < orig_len; i++) {
if (original[i] != decipher[i]) {
printf(" ERROR: mismatch at byte %ld\n", i);
return FALSE;
}
}
// we'll generate an RSA keypair here so we can make sure it works
//
{
CK_MECHANISM mech2;
CK_OBJECT_HANDLE publ_key, priv_key;
CK_ULONG bits = 1024;
CK_BYTE pub_exp[] = { 0x3 };
CK_ATTRIBUTE pub_tmpl[] = {
{CKA_MODULUS_BITS, &bits, sizeof(bits)}
,
{CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp)}
};
CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keytype = CKK_RSA;
CK_ATTRIBUTE uw_tmpl[] = {
{CKA_CLASS, &keyclass, sizeof(keyclass)}
,
{CKA_KEY_TYPE, &keytype, sizeof(keytype)}
};
mech2.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
mech2.ulParameterLen = 0;
mech2.pParameter = NULL;
rc = funcs->C_GenerateKeyPair(session, &mech2,
pub_tmpl, 2,
NULL, 0,
&publ_key, &priv_key);
if (rc != CKR_OK) {
show_error(" C_GenerateKeyPair #1", rc);
return FALSE;
}
// now, wrap the key.
//
wrapped_data_len = sizeof(wrapped_data);
rc = funcs->C_WrapKey(session, &mech,
w_key, priv_key,
wrapped_data, &wrapped_data_len);
if (rc != CKR_OK) {
show_error(" C_WrapKey #2", rc);
return FALSE;
}
rc = funcs->C_UnwrapKey(session, &mech,
w_key,
wrapped_data, wrapped_data_len,
uw_tmpl, 2, &uw_key);
if (rc != CKR_OK) {
show_error(" C_UnWrapKey #2", rc);
return FALSE;
}
// encrypt something with the public key
//
mech2.mechanism = CKM_RSA_PKCS;
mech2.ulParameterLen = 0;
mech2.pParameter = NULL;
rc = funcs->C_EncryptInit(session, &mech2, publ_key);
if (rc != CKR_OK) {
show_error(" C_EncryptInit #2", rc);
return FALSE;
}
// for RSA operations, keep the input data size smaller than
// the modulus
//
orig_len = 30;
cipher_len = sizeof(cipher);
rc = funcs->C_Encrypt(session, original, orig_len, cipher,
&cipher_len);
if (rc != CKR_OK) {
show_error(" C_Encrypt #2", rc);
return FALSE;
}
// now, decrypt the data using the unwrapped private key.
//
rc = funcs->C_DecryptInit(session, &mech2, uw_key);
if (rc != CKR_OK) {
show_error(" C_DecryptInit #1", rc);
return FALSE;
}
decipher_len = sizeof(decipher);
rc = funcs->C_Decrypt(session, cipher, cipher_len,
decipher, &decipher_len);
if (rc != CKR_OK) {
show_error(" C_Decrypt #1", rc);
return FALSE;
}
if (orig_len != decipher_len) {
printf
(" ERROR: lengths don't match: %ld vs %ld\n",
orig_len, decipher_len);
return FALSE;
}
for (i = 0; i < orig_len; i++) {
if (original[i] != decipher[i]) {
printf(" ERROR: mismatch at byte %ld\n",
i);
return FALSE;
}
}
}
rc = funcs->C_CloseAllSessions(slot_id);
if (rc != CKR_OK) {
show_error(" C_CloseAllSessions #1", rc);
return FALSE;
}
printf("Looks okay...\n");
return TRUE;
}
int main(int argc, char **argv)
{
int i;
CK_C_INITIALIZE_ARGS initialize_args;
CK_RV rc;
SYSTEMTIME t1, t2;
/* Parse the command line */
for (i = 1; i < argc; i++) {
if (strncmp(argv[i], "-slot", 5) == 0) {
SlotID = (unsigned long)atoi(argv[i + 1]);
i++;
break;
}
}
printf("Using slot %ld...\n\n", SlotID);
if (do_GetFunctionList())
return -1;
/* There will be no multi-threaded Cryptoki access in this app */
memset(&initialize_args, 0, sizeof(initialize_args));
if ((rc = funcs->C_Initialize(&initialize_args)) != CKR_OK) {
show_error("C_Initialize", rc);
return -1;
}
GetSystemTime(&t1);
rc = do_EncryptAES_ECB();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_EncryptAES_CBC();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_EncryptAES_Multipart_ECB();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_EncryptAES_Multipart_CBC();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_EncryptAES_Multipart_CBC_PAD();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_WrapUnwrapAES_ECB();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_WrapUnwrapAES_CBC();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
GetSystemTime(&t1);
rc = do_WrapUnwrapAES_CBC_PAD();
if (!rc)
goto done;
GetSystemTime(&t2);
process_time(t1, t2);
done:
if( (rc = funcs->C_Finalize(NULL)) != CKR_OK)
show_error("C_Finalize", rc);
/* Decrement the reference count to libopencryptoki.so */
dlclose(dl_handle);
return rc;
}