485 lines
13 KiB
C++
Executable File
485 lines
13 KiB
C++
Executable File
/* Benchmarks.cpp
|
|
*
|
|
* Copyright (C) 2006-2020 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "Benchmarks.h" /* contains include of Enclave_u.h which has wolfSSL header files */
|
|
|
|
/* Check settings of wolfSSL */
|
|
#if !defined(HAVE_AESGCM) || defined(NO_RSA) || defined(NO_SHA256)
|
|
#error please enable AES-GCM, RSA, and SHA256
|
|
#endif
|
|
|
|
/* Use Debug SGX ? */
|
|
#if _DEBUG
|
|
#define DEBUG_VALUE SGX_DEBUG_FLAG
|
|
#else
|
|
#define DEBUG_VALUE 1
|
|
#endif
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
|
|
|
|
/* Choose AES Key size */
|
|
//#define WC_AES_KEY_SZ 16 /* 128 bit key */
|
|
#define WC_AES_KEY_SZ 24 /* 192 bit key */
|
|
|
|
static double current_time(int reset)
|
|
{
|
|
static int init = 0;
|
|
static LARGE_INTEGER freq;
|
|
LARGE_INTEGER count;
|
|
|
|
(void)reset;
|
|
|
|
if (!init) {
|
|
QueryPerformanceFrequency(&freq);
|
|
init = 1;
|
|
}
|
|
|
|
QueryPerformanceCounter(&count);
|
|
return (double)count.QuadPart / freq.QuadPart;
|
|
}
|
|
|
|
|
|
static void free_resources(byte* plain, byte* cipher) {
|
|
delete[] plain;
|
|
delete[] cipher;
|
|
}
|
|
|
|
|
|
/* benchmark is performed calling into Enclave on each update
|
|
* This function tests speeds at different message sizes during update */
|
|
static double sha256_getTime_multiple(sgx_enclave_id_t id, double* total) {
|
|
double start, end;
|
|
int ret, sgxStatus;
|
|
byte* plain;
|
|
byte digest[64];
|
|
int plainSz = (1024 * 1024);
|
|
int tSz = (1024 * 1024) * numBlocks;
|
|
int i, k;
|
|
|
|
Sha256 sha256;
|
|
|
|
ret = 0;
|
|
k = numBlocks;
|
|
printf("\n");
|
|
for (k = 1; k <= numBlocks; k++) {
|
|
plainSz = tSz / k;
|
|
plain = new byte[plainSz];
|
|
ret |= wc_sha256_init(id, &sgxStatus, &sha256);
|
|
start = current_time(1);
|
|
for (i = 0; i < k; i++) {
|
|
ret |= wc_sha256_update(id, &sgxStatus, &sha256, plain, plainSz);
|
|
}
|
|
ret |= wc_sha256_final(id, &sgxStatus, &sha256, digest);
|
|
end = current_time(0);
|
|
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("Error in SHA256 operation with Enclave: %d sgxStatus = %d.\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
*total = end - start;
|
|
printf("%8.3f\n", *total);
|
|
delete[] plain;
|
|
}
|
|
printf("\n");
|
|
*total = end - start;
|
|
return 1 / *total * numBlocks;
|
|
}
|
|
|
|
|
|
/* benchmark is performed calling into Enclave on each update */
|
|
static double sha256_getTime(sgx_enclave_id_t id, double* total) {
|
|
double start, end;
|
|
int ret = 0;
|
|
int sgxStatus = 0;
|
|
int i;
|
|
byte* plain;
|
|
byte digest[64];
|
|
int plainSz = (1024 * 1024);
|
|
|
|
Sha256 sha256;
|
|
|
|
plain = new byte[plainSz];
|
|
ret |= wc_sha256_init(id, &sgxStatus, &sha256);
|
|
start = current_time(1);
|
|
|
|
/* perform work and get digest */
|
|
for (i = 0; i < numBlocks; i++) {
|
|
ret |= wc_sha256_update(id, &sgxStatus, &sha256, plain, plainSz);
|
|
}
|
|
ret |= wc_sha256_final(id, &sgxStatus, &sha256, digest);
|
|
end = current_time(0);
|
|
|
|
delete[] plain;
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("Error in SHA256 operation with Enclave: %d sgxStatus = %d.\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
*total = end - start;
|
|
return 1 / *total * numBlocks;
|
|
}
|
|
|
|
|
|
static int sha256_print(sgx_enclave_id_t id)
|
|
{
|
|
double total, persec;
|
|
|
|
printf("SHA-256 ");
|
|
persec = sha256_getTime(id, &total);
|
|
printf("%d megs took %5.3f seconds , %8.3f MB/s\n", numBlocks, total, persec);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* return time in MB/s with crossing into enclave boundary with each encrypt */
|
|
static double aesgcm_encrypt_getTime(sgx_enclave_id_t id, double* total, byte* plain, byte* cipher, word32 sz, byte* tag, word32 tagSz)
|
|
{
|
|
Aes aes;
|
|
double start, end;
|
|
int i;
|
|
int ret, sgxStatus;
|
|
|
|
const byte ad[13] = { 0 };
|
|
|
|
const XGEN_ALIGN byte iv[] =
|
|
{
|
|
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81
|
|
};
|
|
|
|
const XGEN_ALIGN byte key[] =
|
|
{
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
0xfe, 0xde, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
|
|
0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67
|
|
};
|
|
|
|
ret = wc_aesgcm_setKey(id, &sgxStatus, &aes, key, WC_AES_KEY_SZ);
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("AES set key failed %d sgxStatus = %d\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
start = current_time(1);
|
|
for (i = 0; i < numBlocks; i++) {
|
|
ret = wc_aesgcm_encrypt(id, &sgxStatus, &aes, cipher, plain, sz, iv, 12, tag, tagSz, ad, 13);
|
|
}
|
|
end = current_time(0);
|
|
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("Error in AES-GCM encrypt operation with Enclave: %d sgxStatus = %d.\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
*total = end - start;
|
|
return 1 / *total * numBlocks;
|
|
}
|
|
|
|
|
|
static int aesgcm_encrypt_print(sgx_enclave_id_t id, byte* plain, byte* cipher, word32 sz, byte* tag, word32 tagSz)
|
|
{
|
|
double total, persec;
|
|
|
|
printf("AES-GCM encrypt ");
|
|
persec = aesgcm_encrypt_getTime(id, &total, plain, cipher, sz, tag, tagSz);
|
|
printf("%d megs took %5.3f seconds , %8.3f MB/s\n", numBlocks, total, persec);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* return MB/s with crossing into Enclave boundary with each decrypt */
|
|
static double aesgcm_decrypt_getTime(sgx_enclave_id_t id, double* total, byte* plain, const byte* cipher, word32 sz, const byte* tag, word32 tagSz)
|
|
{
|
|
Aes aes;
|
|
double start, end;
|
|
int ret, sgxStatus;
|
|
int i;
|
|
|
|
const byte ad[13] = { 0 };
|
|
|
|
const XGEN_ALIGN byte iv[] =
|
|
{
|
|
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81
|
|
};
|
|
|
|
const XGEN_ALIGN byte key[] =
|
|
{
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
0xfe, 0xde, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
|
|
0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67
|
|
};
|
|
|
|
ret = wc_aesgcm_setKey(id, &sgxStatus, &aes, key, WC_AES_KEY_SZ);
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("AES set key failed %d sgxStatus = %d\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
start = current_time(1);
|
|
for (i = 0; i < numBlocks; i++) {
|
|
ret = wc_aesgcm_decrypt(id, &sgxStatus, &aes, plain, cipher, sz, iv, 12, tag, tagSz, ad, 13);
|
|
}
|
|
end = current_time(0);
|
|
|
|
if (ret != SGX_SUCCESS || sgxStatus < 0) {
|
|
printf("Error in AES-GCM decrypt operation with Enclave: %d sgxStatus = %d.\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
*total = end - start;
|
|
return 1 / *total * numBlocks;
|
|
}
|
|
|
|
|
|
static int aesgcm_decrypt_print(sgx_enclave_id_t id, byte* plain, byte* cipher, word32 sz, const byte* tag, word32 tagSz)
|
|
{
|
|
double total, persec;
|
|
|
|
printf("AES-GCM decrypt ");
|
|
persec = aesgcm_decrypt_getTime(id, &total, plain, cipher, sz, tag, tagSz);
|
|
printf("%d megs took %5.3f seconds , %8.3f MB/s\n", numBlocks, total, persec);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* return time for each in milliseconds */
|
|
static double rsa_encrypt_getTime(sgx_enclave_id_t id, int* sgxStatus, double* total, const byte* message, word32 mSz, byte* cipher, word32 cSz)
|
|
{
|
|
double start, end;
|
|
int ret, i;
|
|
int freeStatus = 0;
|
|
RsaKey rsa;
|
|
|
|
ret = 0; *sgxStatus = 0;
|
|
ret = wc_rsa_init(id, sgxStatus, &rsa); /* loads RSA key from buffer and inits RNG */
|
|
if (ret != SGX_SUCCESS || *sgxStatus != 0) {
|
|
printf("Initializing RSA failed %d sgxStatus = %d\n", ret, *sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
start = current_time(1);
|
|
for (i = 0; i < ntimes; i++) {
|
|
ret = wc_rsa_encrypt(id, sgxStatus, message, mSz, cipher, cSz, &rsa);
|
|
}
|
|
end = current_time(0);
|
|
|
|
if (ret != SGX_SUCCESS || *sgxStatus < 0) {
|
|
printf("Error in rsa encrypt operation with Enclave: %d sgxStatus = %d.\n", ret, *sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
ret = wc_rsa_free(id, &freeStatus, &rsa);
|
|
if (ret != 0 || freeStatus != 0) {
|
|
printf("Failed to free RSA key %d sgxStatus = %d\n", ret, freeStatus);
|
|
return -1;
|
|
}
|
|
|
|
*total = end - start;
|
|
return (*total / ntimes) * 1000;
|
|
}
|
|
|
|
|
|
static int rsa_encrypt_print(sgx_enclave_id_t id, int* sgxStatus, byte* plain, word32 pSz, byte* cipher, word32 cSz)
|
|
{
|
|
double total, each;
|
|
|
|
printf("RSA-2048 encrypt ");
|
|
each = rsa_encrypt_getTime(id, sgxStatus, &total, plain, pSz, cipher, cSz);
|
|
printf("took %6.3f milliseconds, avg over %d\n", each, ntimes);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* return time in milliseconds for each */
|
|
static double rsa_decrypt_getTime(sgx_enclave_id_t id, double* total, byte* m, word32 mSz, const byte* c, word32 cSz)
|
|
{
|
|
double start, end;
|
|
int ret, sgxStatus, i;
|
|
RsaKey rsa;
|
|
|
|
ret = wc_rsa_init(id, &sgxStatus, &rsa); /* loads RSA key from buffer and inits RNG */
|
|
if (ret != SGX_SUCCESS || sgxStatus != 0) {
|
|
printf("Initializing RSA failed %d sgxStatus = %d\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
start = current_time(1);
|
|
for (i = 0; i < ntimes; i++) {
|
|
ret = wc_rsa_decrypt(id, &sgxStatus, c, cSz, m, mSz, &rsa);
|
|
}
|
|
end = current_time(0);
|
|
|
|
if (ret != SGX_SUCCESS || sgxStatus < 0) {
|
|
printf("Error in rsa decrypt operation with Enclave: %d sgxStatus = %d.\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
ret = wc_rsa_free(id, &sgxStatus, &rsa);
|
|
if (ret != 0 || sgxStatus != 0) {
|
|
printf("Failed to free RSA key %d sgxStatus = %d\n", ret, sgxStatus);
|
|
return -1;
|
|
}
|
|
|
|
*total = end - start;
|
|
return (*total / ntimes) * 1000;
|
|
}
|
|
|
|
|
|
static int rsa_decrypt_print(sgx_enclave_id_t id, byte* m, word32 mSz, const byte* c, word32 cSz)
|
|
{
|
|
double total, each;
|
|
|
|
printf("RSA-2048 decrypt ");
|
|
each = rsa_decrypt_getTime(id, &total, m, mSz, c, cSz);
|
|
printf("took %6.3f milliseconds, avg over %d\n", each, ntimes);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
sgx_enclave_id_t id;
|
|
sgx_launch_token_t t;
|
|
|
|
int ret = 0;
|
|
int sgxStatus = 0;
|
|
int updated = 0;
|
|
byte message[] = "Secure wolfSSL.";
|
|
|
|
byte* plain = new byte[1024 * 1024];
|
|
byte* cipher = new byte[1024 * 1024];
|
|
const byte tag[16] = { 0 };
|
|
int plainSz = 1024 * 1024;
|
|
int i;
|
|
|
|
/* only print off if no command line arguments were passed in */
|
|
if (argc == 1) {
|
|
printf("Setting up Enclave ... ");
|
|
}
|
|
|
|
memset(t, 0, sizeof(sgx_launch_token_t));
|
|
|
|
ret = sgx_create_enclave(_T("Enclave.signed.dll"), DEBUG_VALUE, &t, &updated, &id, NULL);
|
|
if (ret != SGX_SUCCESS) {
|
|
printf("Failed to create Enclave : error %d - %#x.\n", ret, ret);
|
|
free_resources(plain, cipher);
|
|
return 1;
|
|
}
|
|
|
|
/* test if only printing off times */
|
|
if (argc > 1) {
|
|
double total;
|
|
int idx = 1;
|
|
while (1) {
|
|
for (idx = 1; idx < argc; idx++) {
|
|
if (strncmp(argv[idx], "-s256", 6) == 0) {
|
|
printf("%8.3f - SHA-256\n", sha256_getTime(id, &total));
|
|
fflush(stdout);
|
|
}
|
|
else if (strncmp(argv[idx], "-ag", 3) == 0) {
|
|
printf("%8.3f - AES-GCM\n", aesgcm_encrypt_getTime(id, &total, plain, cipher, plainSz, (byte*)tag, sizeof(tag)));
|
|
fflush(stdout);
|
|
}
|
|
else if (strncmp(argv[idx], "-re", 4) == 0) {
|
|
printf("%8.3f - RSA-ENC\n", rsa_encrypt_getTime(id, &sgxStatus, &total, message, sizeof(message), cipher, plainSz));
|
|
fflush(stdout);
|
|
}
|
|
else if (strncmp(argv[idx], "-rd", 4) == 0) {
|
|
rsa_encrypt_getTime(id, &sgxStatus, &total, message, sizeof(message), cipher, plainSz);
|
|
printf("%8.3f - RSA-DEC\n", rsa_decrypt_getTime(id, &total, plain, plainSz, cipher, sgxStatus));
|
|
fflush(stdout);
|
|
}
|
|
else {
|
|
printf("\"%s\" Not yet implemented\n\t-s256 for SHA256\n\t-ag for AES-GCM\n\t-re for RSA encrypt", argv[idx]);
|
|
fflush(stdout);
|
|
free_resources(plain, cipher);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("Success\nCollecting benchmark values for wolfSSL using SGX\n");
|
|
|
|
/*********** SHA-256 ***************/
|
|
if (sha256_print(id) != 0) {
|
|
free_resources(plain, cipher);
|
|
return -1;
|
|
}
|
|
printf("\n");
|
|
|
|
|
|
/*********** AES-GCM ***************/
|
|
/* place message in first bytes of plain and test encrypt/decrypt with aesgcm */
|
|
memcpy(plain, message, sizeof(message));
|
|
|
|
if (aesgcm_encrypt_print(id, plain, cipher, plainSz, (byte*)tag, sizeof(tag)) != 0) {
|
|
free_resources(plain, cipher);
|
|
return -1;
|
|
}
|
|
|
|
memset(plain, 0, plainSz);
|
|
if (aesgcm_decrypt_print(id, plain, cipher, plainSz, tag, sizeof(tag)) != 0) {
|
|
free_resources(plain, cipher);
|
|
return -1;
|
|
}
|
|
|
|
printf("\tdecrypted message = ");
|
|
for (i = 0; i < sizeof(message); i++) { printf("%c", plain[i]); }
|
|
printf("\n\n");
|
|
|
|
/*********** RSA ***************/
|
|
memset(cipher, 0, 256);
|
|
ret = rsa_encrypt_print(id, &sgxStatus, message, sizeof(message), cipher, plainSz);
|
|
if (ret < 0) {
|
|
free_resources(plain, cipher);
|
|
return -1;
|
|
}
|
|
|
|
memset(plain, 0, plainSz);
|
|
ret = rsa_decrypt_print(id, plain, plainSz, cipher, sgxStatus);
|
|
if (ret != 0) {
|
|
free_resources(plain, cipher);
|
|
return -1;
|
|
}
|
|
|
|
printf("\tdecrypted message = ");
|
|
for (i = 0; i < 15; i++){ printf("%c", plain[i]); }
|
|
printf("\n");
|
|
|
|
|
|
/*********** Free arrays and exit ***************/
|
|
free_resources(plain, cipher);
|
|
return 0;
|
|
}
|
|
|