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-pss
|
||||||
crypto/rsa-pss/rsa-public.der
|
crypto/rsa-pss/rsa-public.der
|
||||||
crypto/rsa-pss/sign.txt
|
crypto/rsa-pss/sign.txt
|
||||||
|
crypto/rsa/rsa-nb
|
||||||
|
|
|
@ -217,6 +217,7 @@ prog_end:
|
||||||
if (pRsaKey)
|
if (pRsaKey)
|
||||||
free(pRsaKey);
|
free(pRsaKey);
|
||||||
|
|
||||||
|
wc_FreeRng(&rng);
|
||||||
wolfSSL_Cleanup();
|
wolfSSL_Cleanup();
|
||||||
|
|
||||||
return 0;
|
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