/*
* COPYRIGHT (c) International Business Machines Corp. 2005-2017
*
* This program is provided under the terms of the Common Public License,
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
* found in the file LICENSE file or at
* https://opensource.org/licenses/cpl1.0.php
*/
/* File: speed.c
*
* Performance tests for Opencryptoki
*
* RSA keygen (with keylength 1024, 2048, 4096)
* RSA sign and verify (with keylength 1024, 2048, 4096)
* RSA encrypt and decrypt (with keylength 1024, 2048, 4096)
* DES3 encrypt and decrypt (with modes ECB and CBC)
* AES encrypt and decrypt (with modes ECB and CBC, with keylength 128, 192,
* 256), SHA1, SHA256, SHA512
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include "pkcs11types.h"
#include "regress.h"
#include "common.c"
#define SHA1_HASH_LEN 20
#define SHA256_HASH_LEN 32
#define SHA512_HASH_LEN 64
#define MAX_HASH_LEN SHA512_HASH_LEN
// the GetSystemTime and SYSTEMTIME implementation
// from regress.h only has a ms resolution
// and produces absolut inacceptable measurements.
// So we use gettimeofday() and struct timeval
// with us resolution instead.
#ifdef SYSTEMTIME
#undef SYSTEMTIME
#endif
#define SYSTEMTIME struct timeval
#ifdef GetSystemTime
#undef GetSystemTime
#endif
#define GetSystemTime(x) gettimeofday((x),NULL)
static inline unsigned long delta_time_us(struct timeval *t1,
struct timeval *t2)
{
unsigned long d;
struct timeval td;
timersub(t2, t1, &td);
d = td.tv_sec * 1000 * 1000 + td.tv_usec;
return (d ? d : 1); // return 1us if delta is 0
}
int do_GetFunctionList(void);
// keylength: 512, 1024, 2048, 4096
int do_RSA_PKCS_EncryptDecrypt(int keylength)
{
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_RV rv, rc;
CK_OBJECT_HANDLE publ_key, priv_key;
CK_BYTE data1[100];
CK_BYTE data2[512];
CK_BYTE encdata[512];
CK_ULONG len1, len2, encdata_len;
CK_ULONG i;
CK_ULONG iterations = 2000;
SYSTEMTIME t1, t2;
CK_ULONG diff, avg_time, min_time, max_time, tot_time;
CK_ULONG bits = keylength;
CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01 };
CK_ATTRIBUTE pub_tmpl[] = {
{CKA_MODULUS_BITS, &bits, sizeof(bits)},
{CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp)}
};
testcase_begin("RSA PKCS Encrypt with keylen=%d datalen=%d",
keylength, (int) sizeof(data1));
slot_id = SLOT_ID;
testcase_rw_session();
testcase_user_login();
mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_GenerateKeyPair(session, &mech, pub_tmpl, 2, NULL, 0,
&publ_key, &priv_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
len1 = sizeof(data1);
encdata_len = sizeof(encdata);
for (i = 0; i < len1; i++)
data1[i] = (unsigned char) i;
mech.mechanism = CKM_RSA_PKCS;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_EncryptInit(session, &mech, publ_key);
if (rc != CKR_OK) {
testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
encdata_len = sizeof(encdata);
rc = funcs->C_Encrypt(session, data1, len1, encdata, &encdata_len);
if (rc != CKR_OK) {
testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
avg_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
printf("RSA PKCS Decrypt with keylen=%d datalen=%d\n",
keylength, (int) encdata_len);
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_DecryptInit(session, &mech, priv_key);
if (rc != CKR_OK) {
testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
len2 = sizeof(data2);
rc = funcs->C_Decrypt(session, encdata, encdata_len, data2, &len2);
if (rc != CKR_OK) {
testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
if (len2 != len1) {
testcase_error("len1=%lu and len2=%lu do not match ?!?",
len1, len2);
rc = CKR_FUNCTION_FAILED;;
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
avg_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseAllSessions(slot_id);
if (rv != CKR_OK) {
testcase_error("C_CloseAllSessions rv=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
// keylength: 512, 1024, 2048, 4096
int do_RSA_KeyGen(int keylength)
{
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_RV rv, rc;
CK_ULONG iterations = 10;
SYSTEMTIME t1, t2;
CK_ULONG diff, avg_time, max_time, min_time, tot_time, i;
CK_ULONG bits = 2048;
CK_OBJECT_HANDLE publ_key, priv_key;
CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01 };
CK_ATTRIBUTE pub_tmpl[] = {
{CKA_MODULUS_BITS, &bits, sizeof(bits)},
{CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp)}
};
testcase_begin("RSA KeyGen with keylen=%d", keylength);
testcase_rw_session();
testcase_user_login();
mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_GenerateKeyPair(session, &mech, pub_tmpl, 2, NULL, 0,
&publ_key, &priv_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
min_time = 0xFFFFFFFF;
max_time = 0x00000000;
tot_time = 0x00000000;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_GenerateKeyPair(session, &mech, pub_tmpl, 2,
NULL, 0, &publ_key, &priv_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
avg_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseSession(session);
if (rv != CKR_OK) {
testcase_error("C_CloseSession rv=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
// keylength: 512, 1024, 2048, 4096
int do_RSA_PKCS_SignVerify(int keylength)
{
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_RV rv, rc;
CK_ULONG i, len1, sig_len;
CK_BYTE signature[512];
CK_BYTE data1[100];
CK_OBJECT_HANDLE publ_key, priv_key;
SYSTEMTIME t1, t2;
CK_ULONG diff, avg_time, min_time, max_time, tot_time;
CK_ULONG iterations = 1000;
CK_ULONG bits = keylength;
CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01 };
CK_ATTRIBUTE pub_tmpl[] = {
{CKA_MODULUS_BITS, &bits, sizeof(bits)},
{CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp)}
};
slot_id = SLOT_ID;
testcase_begin("RSA PKCS Sign with keylen=%d datalen=%d",
keylength, (int) sizeof(data1));
testcase_rw_session();
testcase_user_login();
mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_GenerateKeyPair(session, &mech, pub_tmpl, 2, NULL, 0,
&publ_key, &priv_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKeyPair rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
// sign some data
len1 = sizeof(data1);
sig_len = sizeof(signature);
for (i = 0; i < len1; i++)
data1[i] = (unsigned char) i;
mech.mechanism = CKM_RSA_PKCS;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_SignInit(session, &mech, priv_key);
if (rc != CKR_OK) {
testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
sig_len = sizeof(signature);
rc = funcs->C_Sign(session, data1, len1, signature, &sig_len);
if (rc != CKR_OK) {
testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
avg_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
printf("RSA PKCS Verify with keylen=%d datalen=%d\n",
keylength, (int) sizeof(data1));
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_VerifyInit(session, &mech, publ_key);
if (rc != CKR_OK) {
testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
rc = funcs->C_Verify(session, data1, len1, signature, sig_len);
if (rc != CKR_OK) {
testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
avg_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseAllSessions(slot_id);
if (rv != CKR_OK) {
testcase_error("C_CloseAllSession rv=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
// mode: ECB CBC
int do_DES3_EncrDecr(const char *mode)
{
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_RV rv, rc;
CK_OBJECT_HANDLE h_key;
CK_BYTE original[BIG_REQUEST];
CK_BYTE cipher[BIG_REQUEST];
CK_BYTE clear[BIG_REQUEST];
CK_ULONG orig_len, cipher_len, clear_len;
CK_BYTE init_v[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
SYSTEMTIME t1, t2;
CK_ULONG i, iterations = 10000;
CK_ULONG avg_time, tot_time, min_time, max_time, diff;
slot_id = SLOT_ID;
testcase_begin("DES3 Encrypt with mode=%s datalen=%d\n", mode, BIG_REQUEST);
if (is_cca_token(SLOT_ID) && strcmp(mode, "ECB") == 0) {
testcase_skip("Slot %u doesn't support DES3 ECB En/Decrypt\n",
(unsigned) SLOT_ID);
return TRUE;
}
testcase_rw_session();
testcase_user_login();
mech.mechanism = CKM_DES3_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
// generate a DES3 key
rc = funcs->C_GenerateKey(session, &mech, NULL, 0, &h_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
// clear buffers
memset(clear, 0, BIG_REQUEST);
memset(original, 0, BIG_REQUEST);
memset(cipher, 0, BIG_REQUEST);
// encrypt some data
orig_len = BIG_REQUEST;
for (i = 0; i < orig_len; i++)
original[i] = i % 255;
if (strcmp(mode, "ECB") == 0) {
mech.mechanism = CKM_DES3_ECB;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
} else if (strcmp(mode, "CBC") == 0) {
mech.mechanism = CKM_DES3_CBC;
mech.ulParameterLen = 8;
mech.pParameter = init_v;
} else {
testcase_error("unknown mode %s in do_DES3_EncrDecr()", mode);
rc = CKR_MECHANISM_INVALID;
goto testcase_cleanup;
}
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
cipher_len = BIG_REQUEST;
rc = funcs->C_Encrypt(session, original, orig_len, cipher, &cipher_len);
if (rc != CKR_OK) {
testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus "
"op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time,
(((double) (iterations * 1000) / (double) (1024 * 1024)) *
BIG_REQUEST) / (double) tot_time);
printf("DES3 Decrypt with mode=%s datalen=%d\n", mode, BIG_REQUEST);
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
clear_len = BIG_REQUEST;
rc = funcs->C_Decrypt(session, cipher, cipher_len, clear, &clear_len);
if (rc != CKR_OK) {
testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus "
"op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time,
(((double) (iterations * 1000) / (double) (1024 * 1024)) *
BIG_REQUEST) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseAllSessions(slot_id);
if (rv != CKR_OK) {
testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
// keylength: 128...256
// mode: ECB CBC
int do_AES_EncrDecr(int keylength, const char *mode)
{
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
CK_ULONG user_pin_len;
CK_RV rv, rc;
CK_OBJECT_HANDLE h_key;
CK_BYTE original[BIG_REQUEST];
CK_BYTE cipher[BIG_REQUEST];
CK_BYTE clear[BIG_REQUEST];
CK_ULONG orig_len, cipher_len, clear_len;
CK_ULONG key_len = keylength / 8;
CK_BYTE init_v[16] = {
0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10
};
CK_ULONG i, iterations = 50000;
SYSTEMTIME t1, t2;
CK_ULONG avg_time, tot_time, min_time, max_time, diff;
testcase_begin("AES Encrypt with mode=%s keylen=%ld datalen=%d\n",
mode, key_len * 8, BIG_REQUEST);
slot_id = SLOT_ID;
testcase_rw_session();
testcase_user_login();
mech.mechanism = CKM_AES_KEY_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = generate_AESKey(session, key_len, &mech, &h_key);
if (rc != CKR_OK) {
testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
// clear buffers
memset(original, 0, BIG_REQUEST);
memset(clear, 0, BIG_REQUEST);
memset(cipher, 0, BIG_REQUEST);
// encrypt some data
orig_len = BIG_REQUEST;
for (i = 0; i < orig_len; i++)
original[i] = i % 255;
if (strcmp(mode, "ECB") == 0) {
mech.mechanism = CKM_AES_ECB;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
} else if (strcmp(mode, "CBC") == 0) {
mech.mechanism = CKM_AES_CBC;
mech.ulParameterLen = 16;
mech.pParameter = init_v;
} else {
testcase_error("unknown mode %s in do_AES_EncrDecr()", mode);
rc = CKR_MECHANISM_INVALID;
goto testcase_cleanup;
}
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_EncryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
cipher_len = BIG_REQUEST;
rc = funcs->C_Encrypt(session, original, orig_len, cipher, &cipher_len);
if (rc != CKR_OK) {
testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus "
"op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time,
(((double) (iterations * 1000) / (double) (1024 * 1024)) *
BIG_REQUEST) / (double) tot_time);
printf("AES Decrypt with mode=%s keylen=%ld datalen=%d\n",
mode, key_len * 8, BIG_REQUEST);
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_DecryptInit(session, &mech, h_key);
if (rc != CKR_OK) {
testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
clear_len = BIG_REQUEST;
rc = funcs->C_Decrypt(session, cipher, cipher_len, clear, &clear_len);
if (rc != CKR_OK) {
testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus "
"op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time,
(((double) (iterations * 1000) / (double) (1024 * 1024)) *
BIG_REQUEST) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseAllSessions(slot_id);
if (rv != CKR_OK) {
testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
int do_SHA(const char *mode)
{
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_FLAGS flags;
CK_RV rc, rv;
CK_BYTE data[BIG_REQUEST];
CK_BYTE hash[MAX_HASH_LEN];
CK_ULONG data_len, hash_len, h_len;
SYSTEMTIME t1, t2;
CK_ULONG diff, avg_time, tot_time, min_time, max_time;
CK_ULONG i, iterations = 20000;
printf("SHA (%s) with datalen=%d\n", mode, BIG_REQUEST);
slot_id = SLOT_ID;
testcase_rw_session();
mech.ulParameterLen = 0;
mech.pParameter = NULL;
if (strcmp(mode, "SHA1") == 0) {
mech.mechanism = CKM_SHA_1;
hash_len = SHA1_HASH_LEN;
} else if (strcmp(mode, "SHA256") == 0) {
mech.mechanism = CKM_SHA256;
hash_len = SHA256_HASH_LEN;
} else if (strcmp(mode, "SHA512") == 0) {
mech.mechanism = CKM_SHA512;
hash_len = SHA512_HASH_LEN;
} else {
testcase_error("unknown mode %s in do_SHA()", mode);
rc = CKR_MECHANISM_INVALID;
goto testcase_cleanup;
}
// generate some data to hash
//
data_len = BIG_REQUEST;
memset(data, 0, data_len);
for (i = 0; i < data_len; i++)
data[i] = i % 255;
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
rc = funcs->C_DigestInit(session, &mech);
if (rc != CKR_OK) {
testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
h_len = sizeof(hash);
rc = funcs->C_Digest(session, data, data_len, hash, &h_len);
if (rc != CKR_OK) {
testcase_error("C_Digest rc=%s", p11_get_ckr(rc));
goto testcase_cleanup;
}
if (h_len != hash_len) {
testcase_error
("returned hashlen %ld doesn't match to expected len %ld\n",
h_len, hash_len);
rc = CKR_FUNCTION_FAILED;
goto testcase_cleanup;
}
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldus max=%ldus avg=%ldus "
"op/s=%.3f %.3fMB/s\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time,
(((double) (iterations * 1000) / (double) (1024 * 1024)) *
BIG_REQUEST) / (double) tot_time);
testcase_cleanup:
rv = funcs->C_CloseAllSessions(slot_id);
if (rv != CKR_OK) {
testcase_error("C_CloseAllSessions rv=%s", p11_get_ckr(rv));
return FALSE;
}
return TRUE;
}
int do_DummyFunction(void)
{
#if DUMMY
CK_SLOT_ID slot_id;
CK_ULONG i, diff, avg_time, min_time, max_time;
CK_ULONG iterations = 1000;
SYSTEMTIME t1, t2;
testcase_begin("do_DummyFunction...");
slot_id = SLOT_ID;
tot_time = 0;
max_time = 0;
min_time = 0xFFFFFFFF;
for (i = 0; i < iterations + 2; i++) {
GetSystemTime(&t1);
DummyFunction(slot_id);
GetSystemTime(&t2);
diff = delta_time_us(&t1, &t2);
tot_time += diff;
if (diff < min_time)
min_time = diff;
if (diff > max_time)
max_time = diff;
}
tot_time -= min_time;
tot_time -= max_time;
avg_time = tot_time / iterations;
// us -> ms
tot_time /= 1000;
min_time /= 1000;
max_time /= 1000;
printf("%ld iterations: total=%ldms min=%ldms max=%ldms avg=%ldms "
"op/s=%.3f\n\n", iterations, tot_time, min_time, max_time,
avg_time, (double) (iterations * 1000) / (double) tot_time);
#endif
return TRUE;
}
void speed_usage(char *fct)
{
printf("usage: %s -slot <num>", fct);
printf(" [-rsa_keygen] [-rsa_signverify]");
printf(" [-rsa_endecrypt] [-des3] [-aes] [-sha]");
printf(" [-h] \n\n");
return;
}
int main(int argc, char **argv)
{
CK_C_INITIALIZE_ARGS cinit_args;
int rc, i;
int do_rsa_keygen = 0;
int do_rsa_signverify = 0;
int do_rsa_endecrypt = 0;
int do_des3_endecrypt = 0;
int do_aes_endecrypt = 0;
int do_sha = 0;
SLOT_ID = 1000;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-slot") == 0) {
SLOT_ID = atoi(argv[i + 1]);
i++;
continue;
}
if (strcmp(argv[i], "-rsa_keygen") == 0) {
do_rsa_keygen = 1;
} else if (strcmp(argv[i], "-rsa_signverify") == 0) {
do_rsa_signverify = 1;
} else if (strcmp(argv[i], "-rsa_endecrypt") == 0) {
do_rsa_endecrypt = 1;
} else if (strcmp(argv[i], "-des3") == 0) {
do_des3_endecrypt = 1;
} else if (strcmp(argv[i], "-aes") == 0) {
do_aes_endecrypt = 1;
} else if (strcmp(argv[i], "-sha") == 0) {
do_sha = 1;
} else if (strcmp(argv[i], "-h") == 0) {
speed_usage(argv[0]);
return 0;
} else {
printf("unknown option '%s'\n", argv[i]);
speed_usage(argv[0]);
return 1;
}
}
// error if slot has not been identified.
if (SLOT_ID == 1000) {
printf("Please specify the slot to be tested.\n");
speed_usage(argv[0]);
return 1;
}
if (do_rsa_keygen + do_rsa_signverify + do_rsa_endecrypt
+ do_des3_endecrypt + do_aes_endecrypt + do_sha == 0) {
do_rsa_keygen = 1;
do_rsa_signverify = 1;
do_rsa_endecrypt = 1;
do_des3_endecrypt = 1;
do_aes_endecrypt = 1;
do_sha = 1;
}
printf("Using slot #%lu...\n\n", SLOT_ID);
rc = do_GetFunctionList();
if (!rc)
return rc;
memset(&cinit_args, 0x0, sizeof(cinit_args));
cinit_args.flags = CKF_OS_LOCKING_OK;
funcs->C_Initialize(&cinit_args);
if (do_rsa_keygen) {
rc = do_RSA_KeyGen(1024);
if (!rc)
return rc;
rc = do_RSA_KeyGen(2048);
if (!rc)
return rc;
rc = do_RSA_KeyGen(4096);
if (!rc)
return rc;
}
if (do_rsa_signverify) {
rc = do_RSA_PKCS_SignVerify(1024);
if (!rc)
return rc;
rc = do_RSA_PKCS_SignVerify(2048);
if (!rc)
return rc;
rc = do_RSA_PKCS_SignVerify(4096);
if (!rc)
return rc;
}
if (do_rsa_endecrypt) {
rc = do_RSA_PKCS_EncryptDecrypt(1024);
if (!rc)
return rc;
rc = do_RSA_PKCS_EncryptDecrypt(2048);
if (!rc)
return rc;
rc = do_RSA_PKCS_EncryptDecrypt(4096);
if (!rc)
return rc;
}
if (do_des3_endecrypt) {
rc = do_DES3_EncrDecr("ECB");
if (!rc)
return rc;
rc = do_DES3_EncrDecr("CBC");
if (!rc)
return rc;
}
if (do_aes_endecrypt) {
rc = do_AES_EncrDecr(128, "ECB");
if (!rc)
return rc;
rc = do_AES_EncrDecr(128, "CBC");
if (!rc)
return rc;
rc = do_AES_EncrDecr(192, "ECB");
if (!rc)
return rc;
rc = do_AES_EncrDecr(192, "CBC");
if (!rc)
return rc;
rc = do_AES_EncrDecr(256, "ECB");
if (!rc)
return rc;
rc = do_AES_EncrDecr(256, "CBC");
if (!rc)
return rc;
}
if (do_sha) {
rc = do_SHA("SHA1");
if (!rc)
return rc;
rc = do_SHA("SHA256");
if (!rc)
return rc;
rc = do_SHA("SHA512");
if (!rc)
return rc;
}
funcs->C_Finalize(NULL);
return 0;
}