Example for wolfCrypt RSA non-blocking support.
parent
1ba591f2dd
commit
ce122b264a
|
@ -155,3 +155,4 @@ pkcs11/softhsm2
|
|||
crypto/rsa-pss/rsa-pss
|
||||
crypto/rsa-pss/rsa-public.der
|
||||
crypto/rsa-pss/sign.txt
|
||||
crypto/rsa/rsa-nb
|
||||
|
|
|
@ -217,6 +217,7 @@ prog_end:
|
|||
if (pRsaKey)
|
||||
free(pRsaKey);
|
||||
|
||||
wc_FreeRng(&rng);
|
||||
wolfSSL_Cleanup();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Examples Makefile
|
||||
CC = gcc
|
||||
LIB_PATH = /usr/local
|
||||
CFLAGS = -Wall -I$(LIB_PATH)/include
|
||||
LIBS = -L$(LIB_PATH)/lib -lm
|
||||
|
||||
# option variables
|
||||
DYN_LIB = -lwolfssl
|
||||
STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a
|
||||
DEBUG_FLAGS = -g -DDEBUG
|
||||
DEBUG_INC_PATHS = -MD
|
||||
OPTIMIZE = -Os
|
||||
|
||||
# Options
|
||||
#CFLAGS+=$(DEBUG_FLAGS)
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
#LIBS+=$(STATIC_LIB) -ldl -lm
|
||||
LIBS+=$(DYN_LIB)
|
||||
|
||||
# build targets
|
||||
SRC=$(wildcard *.c)
|
||||
TARGETS=$(patsubst %.c, %, $(SRC))
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
debug: CFLAGS+=$(DEBUG_FLAGS)
|
||||
debug: all
|
||||
|
||||
# build template
|
||||
%: %.c
|
||||
$(CC) -o $@ $< $(CFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
|
@ -0,0 +1,113 @@
|
|||
# RSA Non-blocking Examples
|
||||
|
||||
## Design
|
||||
|
||||
Enables RsaKey support for non-blocking exptmod operations by setting a non-blocking context using a new API `wc_RsaSetNonBlock`. If the operation is not complete it will return `FP_WOULDBLOCK` and requires being called again until success `0` or failure `<0`.
|
||||
|
||||
Example code is based on wolfCrypt test `/wolfcrypt/test/test.c` `rsa_nb_test` function.
|
||||
|
||||
## Implementation
|
||||
|
||||
* Adds RSA non-blocking support enabled with `WC_RSA_NONBLOCK`.
|
||||
* Adds new `wc_RsaSetNonBlock` function for enabling / non-block context.
|
||||
* Adds wolfCrypt test function `rsa_nb_test` to validate.
|
||||
* Adds RSA blocking time support using `WC_RSA_NONBLOCK_TIME` and `wc_RsaSetNonBlockTime`.
|
||||
|
||||
## Code Added in GitHub pull requests:
|
||||
|
||||
* 1901: https://github.com/wolfSSL/wolfssl/pull/1901
|
||||
* 1991: https://github.com/wolfSSL/wolfssl/pull/1991
|
||||
|
||||
|
||||
## Example RSA Non-block
|
||||
|
||||
This breaks RSA operations into smallest possible chunks of work.
|
||||
|
||||
### Building wolfSSL
|
||||
|
||||
```
|
||||
./autogen.sh
|
||||
./configure --enable-fastmath CFLAGS="-DWC_RSA_NONBLOCK"
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Building Example
|
||||
|
||||
```
|
||||
make
|
||||
gcc -o rsa-nb rsa-nb.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl
|
||||
```
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
./rsa-nb
|
||||
File ../../certs/client-key.der is 1192 bytes
|
||||
RSA non-block sign: 8200 times
|
||||
RSA non-block verify: 264 times
|
||||
```
|
||||
|
||||
|
||||
## Example RSA Non-block with Time
|
||||
|
||||
This adds logic to estimate blocking time based on CPU speed and desired milliseconds to block.
|
||||
|
||||
### Building wolfSSL
|
||||
|
||||
```
|
||||
./autogen.sh
|
||||
./configure --enable-fastmath CFLAGS="-DWC_RSA_NONBLOCK -DWC_RSA_NONBLOCK_TIME"
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Building Example
|
||||
|
||||
```
|
||||
make
|
||||
gcc -o rsa-nb rsa-nb.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl
|
||||
```
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
./rsa-nb
|
||||
File ../../certs/client-key.der is 1192 bytes
|
||||
CPU Speed is 3100000000, blocking ms 1
|
||||
RSA non-block sign: 1 times
|
||||
RSA non-block verify: 1 times
|
||||
```
|
||||
|
||||
|
||||
## Debugging
|
||||
|
||||
|
||||
1. Build wolfSSL adding `--enable-debug --disable-shared` to the ./configure and do a `sudo make install`:
|
||||
|
||||
```
|
||||
./configure --enable-fastmath CFLAGS="-DWC_RSA_NONBLOCK -DWC_RSA_NONBLOCK_TIME" --enable-debug --disable-shared
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
2. Edit Makefile and edit lines 15 - 18 to be:
|
||||
|
||||
```
|
||||
# Options
|
||||
CFLAGS+=$(DEBUG_FLAGS)
|
||||
#CFLAGS+=$(OPTIMIZE)
|
||||
LIBS+=$(STATIC_LIB) -ldl -lm
|
||||
#LIBS+=$(DYN_LIB)
|
||||
```
|
||||
|
||||
```
|
||||
make
|
||||
gcc -o rsa-nb rsa-nb.c -Wall -I/usr/local/include -g -DDEBUG -L/usr/local/lib -lm /usr/local/lib/libwolfssl.a -ldl -lm
|
||||
gdb ./rsa-nb
|
||||
run
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For questions please email us at support@wolfssl.com.
|
|
@ -0,0 +1,253 @@
|
|||
/* rsa-pss.c
|
||||
*
|
||||
* Copyright (C) 2006-2018 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* An implementation of RSA non-blocking wolfSSL
|
||||
* Usage:
|
||||
./rsa-nb
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/wolfcrypt/rsa.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
|
||||
static const char* kRsaKey = "../../certs/client-key.der";
|
||||
#define RSA_TEST_BYTES 256
|
||||
|
||||
#define ENABLE_RSA_NONBLOCK_TIME
|
||||
|
||||
#if !defined(NO_RSA) && defined(USE_FAST_MATH) && defined(WC_RSA_NONBLOCK)
|
||||
static int load_file_to_buffer(const char* filename, byte** fileBuf, int* fileLen)
|
||||
{
|
||||
int ret = 0;
|
||||
FILE* file = NULL;
|
||||
|
||||
/* Open file */
|
||||
file = fopen(filename, "rb");
|
||||
if (file == NULL) {
|
||||
printf("File %s does not exist!\n", filename);
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Determine length of file */
|
||||
fseek(file, 0, SEEK_END);
|
||||
*fileLen = (int) ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
printf("File %s is %d bytes\n", filename, *fileLen);
|
||||
|
||||
/* Allocate buffer for image */
|
||||
*fileBuf = malloc(*fileLen);
|
||||
if(!*fileBuf) {
|
||||
printf("File buffer malloc failed!\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Load file into buffer */
|
||||
ret = (int)fread(*fileBuf, 1, *fileLen, file);
|
||||
if(ret != *fileLen) {
|
||||
printf("Error reading file! %d", ret);
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if(file) {
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
#ifndef _MSC_VER
|
||||
#define cpuid(reg, leaf, sub)\
|
||||
__asm__ __volatile__ ("cpuid":\
|
||||
"=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\
|
||||
"a" (leaf), "c"(sub));
|
||||
|
||||
#define XASM_LINK(f) asm(f)
|
||||
#elif defined(__linux__)
|
||||
#include <intrin.h>
|
||||
|
||||
#define cpuid(a,b,c) __cpuidex((int*)a,b,c)
|
||||
|
||||
#define XASM_LINK(f)
|
||||
#endif /* _MSC_VER */
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
/* These examples require RSA, FastMath and Non-blocking */
|
||||
#if !defined(NO_RSA) && defined(USE_FAST_MATH) && defined(WC_RSA_NONBLOCK)
|
||||
RsaKey key;
|
||||
RsaNb nb;
|
||||
WC_RNG rng;
|
||||
int ret = 0, count;
|
||||
int signSz, verifySz;
|
||||
byte* derBuf = NULL;
|
||||
int derSz = 0;
|
||||
word32 idx;
|
||||
const char* in = "Everyone gets Friday off.";
|
||||
word32 inSz = (word32)XSTRLEN((char*)in);
|
||||
byte out[RSA_TEST_BYTES];
|
||||
byte plain[RSA_TEST_BYTES];
|
||||
word32 outSz = (word32)sizeof(out);
|
||||
word32 plainSz = (word32)sizeof(plain);
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
long cpuSpeed = 1000000; /* 1Mhz - default */
|
||||
word32 blockingIntervalMs = 1; /* 1ms */
|
||||
#endif
|
||||
|
||||
wolfSSL_Debugging_ON();
|
||||
|
||||
wolfSSL_Init();
|
||||
|
||||
ret = load_file_to_buffer(kRsaKey, &derBuf, &derSz);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf("Init RNG failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wc_InitRsaKey(&key, NULL);
|
||||
if (ret != 0) {
|
||||
printf("Init RSA key failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wc_RsaSetRNG(&key, &rng);
|
||||
if (ret != 0) {
|
||||
printf("Set RSA RNG failed %d\n", ret);
|
||||
goto prog_end;
|
||||
}
|
||||
|
||||
/* load RSA key */
|
||||
idx = 0;
|
||||
ret = wc_RsaPrivateKeyDecode(derBuf, &idx, &key, (word32)derSz);
|
||||
if (ret != 0) {
|
||||
printf("RSA Private Key Decode failure %d\n", ret);
|
||||
goto prog_end;
|
||||
}
|
||||
|
||||
/* Enable non-blocking RSA mode - provide context */
|
||||
ret = wc_RsaSetNonBlock(&key, &nb);
|
||||
if (ret != 0) {
|
||||
goto prog_end;
|
||||
}
|
||||
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
#ifdef cpuid
|
||||
{
|
||||
unsigned int reg[5];
|
||||
reg[4] = '\0';
|
||||
cpuid(reg, 0, 0);
|
||||
if (reg[0] >= 22) {
|
||||
cpuid(reg, 22, 0);
|
||||
/* reg[0]=proc base freq
|
||||
reg[1]=max freq
|
||||
reg[2]=bus ref freq
|
||||
*/
|
||||
cpuSpeed = reg[0] * 1000000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("CPU Speed is %ld, blocking ms %d\n", cpuSpeed, blockingIntervalMs);
|
||||
|
||||
/* Enable time based RSA blocking */
|
||||
ret = wc_RsaSetNonBlockTime(&key, blockingIntervalMs, cpuSpeed);
|
||||
if (ret != 0) {
|
||||
goto prog_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
count = 0;
|
||||
do {
|
||||
ret = wc_RsaSSL_Sign((const byte*)in, inSz, out, outSz, &key, &rng);
|
||||
count++; /* track number of would blocks */
|
||||
if (ret == FP_WOULDBLOCK) {
|
||||
/* do "other" work here */
|
||||
}
|
||||
} while (ret == FP_WOULDBLOCK);
|
||||
if (ret < 0) {
|
||||
goto prog_end;
|
||||
}
|
||||
printf("RSA non-block sign: %d times\n", count);
|
||||
signSz = ret;
|
||||
ret = 0;
|
||||
|
||||
/* Test non-blocking verify */
|
||||
XMEMSET(plain, 0, plainSz);
|
||||
count = 0;
|
||||
do {
|
||||
ret = wc_RsaSSL_Verify(out, (word32)signSz, plain, plainSz, &key);
|
||||
count++; /* track number of would blocks */
|
||||
if (ret == FP_WOULDBLOCK) {
|
||||
/* do "other" work here */
|
||||
}
|
||||
} while (ret == FP_WOULDBLOCK);
|
||||
if (ret < 0) {
|
||||
goto prog_end;
|
||||
}
|
||||
printf("RSA non-block verify: %d times\n", count);
|
||||
verifySz = ret;
|
||||
ret = 0;
|
||||
|
||||
if (signSz == ret && XMEMCMP(plain, in, (size_t)ret)) {
|
||||
ret = SIG_VERIFY_E;
|
||||
}
|
||||
|
||||
prog_end:
|
||||
|
||||
if (ret != 0) {
|
||||
printf("Failure %s (%d)\n", wc_GetErrorString(ret), ret);
|
||||
}
|
||||
|
||||
if (derBuf) {
|
||||
free(derBuf);
|
||||
derBuf = NULL;
|
||||
}
|
||||
wc_FreeRsaKey(&key);
|
||||
wc_FreeRng(&rng);
|
||||
wolfSSL_Cleanup();
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)kRsaKey;
|
||||
|
||||
printf("wolfSSL missing build features.\n");
|
||||
printf("Please build using `./configure --enable-fastmath CFLAGS=\"-DWC_RSA_NONBLOCK\"`\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue