Merge pull request #2700 from JacobBarthelmeh/HardwareAcc

Hardware calls for DSP use
This commit is contained in:
toddouska
2019-12-27 13:58:43 -08:00
committed by GitHub
20 changed files with 6053 additions and 3 deletions

110
IDE/HEXAGON/DSP/Makefile Normal file
View File

@ -0,0 +1,110 @@
# Makefile
#
# Copyright (C) 2006-2019 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
ENVI=hexagon
# default to hexagon v65 Release build
ifndef V
V=hexagon_Release_dynamic_toolv83_v65
endif
SUPPORTED_VS = $(default_VS)
DEPENDENCIES = \
ATOMIC \
RPCMEM \
TEST_MAIN \
TEST_UTIL
ATOMIC_DIR = $(HEXAGON_SDK_ROOT)/libs/common/atomic
RPCMEM_DIR = $(HEXAGON_SDK_ROOT)/libs/common/rpcmem
TEST_MAIN_DIR = $(HEXAGON_SDK_ROOT)/test/common/test_main
TEST_UTIL_DIR = $(HEXAGON_SDK_ROOT)/test/common/test_util
include $(HEXAGON_SDK_ROOT)/build/make.d/$(ENVI)_vs.min
include $(HEXAGON_SDK_ROOT)/build/defines.min
QURT = $(HEXAGON_SDK_ROOT)/libs/common/qurt
QAIC_FLAGS += -I../../../
CC_FLAGS += -I../../../
CC_FLAGS += -I $(QURT)/computev65/include/posix/
CC_FLAGS += -I $(QURT)/computev65/include/qurt/
CC_FLAGS += -I../
CC_FLAGS += -DWOLFSSL_USER_SETTINGS
CC_FLAGS += -DWOLFSSL_DSP_BUILD
CC_FLAGS += -DWC_NO_RNG
#CC_FLAGS += -O3
C_FLAGS += $(MHVX_DOUBLE_FLAG) -mllvm -hexagon-eif=0
CC_FLAGS += $(MHVX_DOUBLE_FLAG) -mllvm -hexagon-eif=0
# stub library
BUILD_LIBS += libwolfssl_dsp_skel
ifeq (1,$(V_dynamic))
BUILD_DLLS += libwolfssl_dsp_skel
endif
libwolfssl_dsp_skel_QAICIDLS += wolfssl_dsp
libwolfssl_dsp_skel_C_SRCS += $V/wolfSSL_skel
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/sp_dsp32.c
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/sp_int.c
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/wc_port.c
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/logging.c
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/memory.c
libwolfssl_dsp_skel.C_SRCS += ../../../wolfcrypt/src/wolfmath.c
#libsp_dsp_skel_DLLS += libdspCV_skel
# quality test
#BUILD_QEXES += eccverify_q
#eccverify_q_QAICIDLS = wolfssl_dsp
#eccverify_q_C_SRCS = ../ecc-verify
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/wc_dsp.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sp_dsp32.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sp_int.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/wc_port.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/wc_encrypt.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/pwdbased.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/hash.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/arc4.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/hmac.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/md5.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/coding.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/aes.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/des3.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/random.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/logging.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/ecc.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/memory.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sha256.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sha.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/asn.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/wolfmath.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sp_c32.c
#eccverify_q.C_SRCS += ../../../wolfcrypt/src/sp_c64.c
#eccverify_q_LIBS = rtld rpcmem test_util atomic test_main
BUILD_COPIES = \
$(DLLS) \
$(EXES) \
$(LIBS) \
$(SHIP_DIR)/ ;
include $(RULES_MIN)

View File

@ -0,0 +1,13 @@
#ifndef WOLFSSL_DSP_INC
#define WOLFSSL_DSP_INC
#include "AEEStdDef.idl"
#include "remote.idl"
interface wolfSSL: remote_handle64{
/* ecc operations */
long DSP_ECC_Verify_256(inrout sequence<int32> hash, inrout sequence<int32> pX, inrout sequence<int32> pY,
inrout sequence<int32> pZ, inrout sequence<int32> r, inrout sequence<int32> sm, inrout long res);
};
#endif

189
IDE/HEXAGON/Makefile Normal file
View File

@ -0,0 +1,189 @@
# Makefile
#
# Copyright (C) 2006-2019 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
ENVI=UbuntuARM
# default to Ubuntu Release build
ifndef V
V=UbuntuARM_Release_aarch64
endif
SUPPORTED_VS = $(default_VS)
include $(HEXAGON_SDK_ROOT)/build/make.d/$(ENVI)_vs.min
include $(HEXAGON_SDK_ROOT)/build/defines.min
ifeq ($(CDSP_FLAG), 1)
LIB_DSPRPC = libcdsprpc
else ifeq ($(MDSP_FLAG), 1)
LIB_DSPRPC = libmdsprpc
else ifeq ($(SLPI_FLAG), 1)
LIB_DSPRPC = libsdsprpc
else
LIB_DSPRPC = libadsprpc
endif
$(info ************ LIB=$(LIB_DSPRPC) ************)
# include files
CC_FLAGS += -I../../
CC_FLAGS += -I./
CC_FLAGS += -DWOLFSSL_USER_SETTINGS
CC_FLAGS += -mcpu=generic+crypto
#CC_FLAGS += -O3
DEPENDENCIES = \
ATOMIC \
RPCMEM
ATOMIC_DIR = $(HEXAGON_SDK_ROOT)/libs/common/atomic
RPCMEM_DIR = $(HEXAGON_SDK_ROOT)/libs/common/rpcmem
# stub library
BUILD_DLLS += libwolfssl
libwolfssl_QAICIDLS += DSP/wolfssl_dsp
libwolfssl_C_SRCS += $V/wolfSSL_stub
libwolfssl_DLLS += $(LIB_DSPRPC)
libwolfssl_C_SRCS += ../../wolfcrypt/src/wc_dsp
libwolfssl_LIBS += rpcmem
libwolfssl_LD_FLAGS += -ldl
# wolfSSL crypto source files
libwolfssl_C_SRCS += \
../../wolfcrypt/src/aes \
../../wolfcrypt/src/md2 \
../../wolfcrypt/src/arc4 \
../../wolfcrypt/src/md4 \
../../wolfcrypt/src/asm \
../../wolfcrypt/src/md5 \
../../wolfcrypt/src/asn \
../../wolfcrypt/src/memory \
../../wolfcrypt/src/async \
../../wolfcrypt/src/blake2b \
../../wolfcrypt/src/pkcs12 \
../../wolfcrypt/src/blake2s \
../../wolfcrypt/src/pkcs7 \
../../wolfcrypt/src/camellia \
../../wolfcrypt/src/poly1305 \
../../wolfcrypt/src/chacha20_poly1305 \
../../wolfcrypt/src/pwdbased \
../../wolfcrypt/src/chacha \
../../wolfcrypt/src/rabbit \
../../wolfcrypt/src/cmac \
../../wolfcrypt/src/random \
../../wolfcrypt/src/coding \
../../wolfcrypt/src/ripemd \
../../wolfcrypt/src/compress \
../../wolfcrypt/src/rsa \
../../wolfcrypt/src/cpuid \
../../wolfcrypt/src/selftest \
../../wolfcrypt/src/cryptocb \
../../wolfcrypt/src/sha256 \
../../wolfcrypt/src/curve25519 \
../../wolfcrypt/src/sha3 \
../../wolfcrypt/src/des3 \
../../wolfcrypt/src/sha512 \
../../wolfcrypt/src/dh \
../../wolfcrypt/src/sha \
../../wolfcrypt/src/signature \
../../wolfcrypt/src/ecc \
../../wolfcrypt/src/ecc_fp \
../../wolfcrypt/src/ed25519 \
../../wolfcrypt/src/sp_armthumb \
../../wolfcrypt/src/error \
../../wolfcrypt/src/sp_int \
../../wolfcrypt/src/fe_low_mem \
../../wolfcrypt/src/sp_cortexm \
../../wolfcrypt/src/fe_operations \
../../wolfcrypt/src/fips \
../../wolfcrypt/src/sp_x86_64 \
../../wolfcrypt/src/fips_test \
../../wolfcrypt/src/srp \
../../wolfcrypt/src/ge_low_mem \
../../wolfcrypt/src/ge_operations \
../../wolfcrypt/src/wc_encrypt \
../../wolfcrypt/src/hash \
../../wolfcrypt/src/wc_pkcs11 \
../../wolfcrypt/src/hc128 \
../../wolfcrypt/src/wc_port \
../../wolfcrypt/src/hmac \
../../wolfcrypt/src/wolfcrypt_first \
../../wolfcrypt/src/idea \
../../wolfcrypt/src/wolfcrypt_last \
../../wolfcrypt/src/wolfevent \
../../wolfcrypt/src/logging \
../../wolfcrypt/src/sp_c32 \
../../wolfcrypt/src/sp_c64 \
../../wolfcrypt/src/sp_arm32 \
../../wolfcrypt/src/sp_arm64 \
../../wolfcrypt/src/wolfmath
# wolfSSL TLS source files
libwolfssl_C_SRCS += \
../../src/ocsp \
../../src/tls \
../../src/crl \
../../src/sniffer \
../../src/wolfio \
../../src/internal \
../../src/ssl \
../../src/keys \
../../src/tls13
# build benchmark app
BUILD_EXES += benchmark
benchmark_C_SRCS += ../../wolfcrypt/benchmark/benchmark
benchmark_LD_FLAGS += -ldl
benchmark_LD_FLAGS += -lpthread
benchmark_DLLS += libwolfssl
benchmark_LIBS += rpcmem
benchmark_DLLS += $(LIB_DSPRPC)
# build test app
BUILD_EXES += testwolfcrypt
testwolfcrypt_C_SRCS += ../../wolfcrypt/test/test
testwolfcrypt_DLLS += libwolfssl
testwolfcrypt_LD_FLAGS += -ldl
testwolfcrypt_LIBS += rpcmem
testwolfcrypt_DLLS += $(LIB_DSPRPC)
# build ecc verify test app
BUILD_EXES += eccverify
eccverify_C_SRCS += ecc-verify
eccverify_DLLS += libwolfssl
eccverify_LD_FLAGS += -ldl
eccverify_LIBS += rpcmem
eccverify_DLLS += $(LIB_DSPRPC)
# build ecc verify test app
BUILD_EXES += eccbenchmark
eccbenchmark_C_SRCS += ecc-verify-benchmark
eccbenchmark_DLLS += libwolfssl
eccbenchmark_LD_FLAGS += -lpthread
eccbenchmark_LD_FLAGS += -ldl
eccbenchmark_LIBS += rpcmem
eccbenchmark_DLLS += $(LIB_DSPRPC)
BUILD_COPIES = \
$(DLLS) \
$(EXES) \
$(LIBS) \
$(SHIP_DIR)/ ;
include $(RULES_MIN)

75
IDE/HEXAGON/README.md Normal file
View File

@ -0,0 +1,75 @@
# Building wolfSSL with DSP Use
## Intro
This directory is to help with building wolfSSL for use with DSP. It assumes that the Hexagon SDK has been setup on the machine and that the enviorment variables have been set by calling (source ~/Qualcomm/Hexagon_SDK/3.4.3/setup_sdk_env.source). Currently offloading ECC 256 verify operations to the DSP is supported. When WOLFSSL_DSP is defined ECC verify operations are offloaded to the aDSP by default. When not in SINGLE_THREADED mode a call back function must be set for getting the handle or a handle must be set in the ecc_key structure for the operation to make use of multiple threads when offloading to the DSP. This is because creating new handles for new threads must be done.
## Building
The directory is divided up into a build for the CPU portion in IDE/HEXAGON and a build for use on the DSP located in IDE/HEXAGON/DSP. Each section has their own Makefile. The Makefile default to an Ubuntu + hexagon v65 release build but can be changed by using V=<build type>. An example of building both would be:
```
cd IDE/HEXAGON
make V=UbuntuARM_Release_aarch64
cd DSP
make V=hexagon_Release_dynamic_toolv83_v65
```
The results from each build will be placed into the ship directories of each, for example ./UbuntuARM_Release_aarch64/ship/* and ./DSP/hexagon_Release_dynamic_toolv83_v65/ship/*.
The Makefile creates a DSP library libwolfssl_dsp_skel.so, library libwolfssl.so, executable benchmark, example ecc-verify, example ecc-verify-benchmark and executable testwolfcrypt.
These then need pushed to the device in order to run. An example of pushing the results to the device would be:
```
cd IDE/HEXAGON
adb push DSP/hexagon_Release_dynamic_toolv83_v65/ship/libwolfssl_dsp_skel.so /data/rfsa/adsp/
adb push UbuntuARM_Release_aarch64/ship/libwolfssl.so /data/
adb push UbuntuARM_Release_aarch64/ship/benchmark /data/
adb push UbuntuARM_Release_aarch64/ship/eccverify /data/
adb push UbuntuARM_Release_aarch64/ship/eccbenchmark /data/
```
To change the settings wolfSSL is built with macros can be set in IDE/HEXAGON/user_settings.h. It contains a default setting at this point that was used for collecting benchmark values. The macro necessary to turn on use of the DSP is WOLFSSL_DSP.
The script IDE/HEXAGON/build.sh was added to help speed up building and testing. An example of using the script would be:
```
cd IDE/HEXAGON
./build.sh Release
```
This will delete the previous build and rebuild for Release mode. Then it will try to push the resulting library and some of the executables to the device.
For increased performance uncomment the -O3 flag in IDE/HEXAGON/Makefile and IDE/HEXAGON/DSP/Makefile.
## Use
A default handle is created with the call to wolfCrypt_Init() and is set to use the aDSP. A default mutex is locked for each use of the handle to make the library stable when multiple threads are calling to DSP supported operations.
To use wolfSSL with a user created handle it can be done by calling wc_ecc_set_handle or by setting a callback function using wolfSSL_SetHandleCb(). This should be set in the case of multithreaded applications to account for having a handle for each thread being used.
#### wolfSSL_SetHandleCb
The API wolfSSL_SetHandleCb takes a function pointer of type "int (*wolfSSL_DSP_Handle_cb)(remote_handle64 *handle, int finished void *ctx);". This callback is executed right before the operation is handed off to the DSP (finished set to 0) and right after done with the handle (finished set to 1). With ECC this would be after the ECC verify function has been called but before the information is passed on to the DSP and once again with the finished flag set after the result is returned.
The callback set should return 0 on sucessfully setting the input handle. The ctx argument is for future custom context to be passed in and is currently not used.
#### Expected Performance
This is the expected results from running ./eccbenchmark using the -O3 flag
benchmarking using default (locks on handle for aDSP)
5000 verifies on 1 threads took 17.481616 seconds
10000 verifies on 2 threads took 35.324308 seconds
benchmarking using software (+NEON if built in)
5000 verifies on 1 threads took 1.398336 seconds
10000 verifies on 2 threads took 1.383992 seconds
benchmarking using threads on aDSP
5000 verifies on 1 threads took 17.616811 seconds
10000 verifies on 2 threads took 19.215413 seconds
15000 verifies on 3 threads took 20.410200 seconds
20000 verifies on 4 threads took 23.261446 seconds
benchmarking 1 thread on cDSP
5000 verifies on 1 threads took 18.560995 seconds

38
IDE/HEXAGON/build.sh Executable file
View File

@ -0,0 +1,38 @@
#!/bin/bash
if [ -z $1 ]; then
echo "./build <Debug | Release>"
exit -1
fi
printf "Erasing previous hexagon_$1_dynamic_toolv83_v65 and UbuntuARM_$1_aarch64\n"
rm -rf hexagon_$1_dynamic_toolv83_v65 &> /dev/null
rm -rf UbuntuARM_$1_aarch64 &> /dev/null
cd ./DSP &> /dev/null
rm -rf hexagon_$1_dynamic_toolv83_v65 &> /dev/null
printf "Building hexagon_$1_dynamic_toolv83_v65 ..."
make V=hexagon_$1_dynamic_toolv83_v65 &> /dev/null
if [ $? != 0 ]; then
printf "failed\n"
else
printf "done\n"
fi
cd ../ &> /dev/null
printf "Building UbuntuARM_$1_aarch64 ..."
make V=UbuntuARM_$1_aarch64 &> /dev/null
if [ $? != 0 ]; then
printf "failed\n"
else
printf "done\n"
fi
printf "Trying to push libwolfssl_Dsp_skel.so, libwolfssl.so, benchmark, eccverify, eccbenchmark\n"
adb push DSP/hexagon_$1_dynamic_toolv83_v65/ship/libwolfssl_dsp_skel.so /data/rfsa/adsp/
adb push UbuntuARM_$1_aarch64/ship/libwolfssl.so /data/
adb push UbuntuARM_$1_aarch64/ship/benchmark /data/
adb push UbuntuARM_$1_aarch64/ship/eccverify /data/
adb push UbuntuARM_$1_aarch64/ship/eccbenchmark /data/
#adb push UbuntuARM_$1_aarch64/ship/testwolfcrypt /data/wolfcrypt/test/
printf "done\n"
exit 0

View File

@ -0,0 +1,186 @@
/* ecc-verify-benchmark.c
*
* Copyright (C) 2006-2019 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 <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <pthread.h>
#define USE_CERT_BUFFERS_256
#include <wolfssl/certs_test.h>
#define MAX_TIMES 5000
#define MAX_BLOCK_SIZE 1024
#include <sys/time.h>
static double get_time()
{
struct timeval tv;
gettimeofday(&tv, 0);
return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
}
/* software version */
void* hash_firmware_verify(void* key)
{
int ret, i;
int verify;
const byte hash[] = {
0XFB, 0XBA, 0XB2, 0X89, 0XF7, 0XF9, 0X4B, 0X25, 0X73, 0X6C, 0X58, 0XBE, 0X46, 0XA9, 0X94, 0XC4, 0X41, 0XFD, 0X02, 0X55, 0X2C, 0XC6, 0X02, 0X23, 0X52, 0XE3, 0XD8, 0X6D, 0X2F, 0XAB, 0X7C, 0X83
};
const byte sigBuf[] = {
0X30, 0X44, 0X02, 0X20, 0X05, 0X38, 0XBC, 0X16, 0XC7, 0X67, 0X18, 0XEC, 0XE6, 0X1E, 0X43, 0X7B, 0X29, 0X8F, 0X85, 0X01, 0X33, 0XA8, 0X9B, 0XDD, 0X91, 0X32, 0X1F, 0XEC, 0XF7, 0X91, 0X18, 0X72, 0X9C, 0XE2, 0X6F, 0X31, 0X02, 0X20, 0X3E, 0X31, 0XD6, 0X40, 0XF7, 0X38, 0X3C, 0X1B, 0X6D, 0XAD, 0XE3, 0X93, 0X20, 0XE8, 0XB1, 0XBD, 0X3C, 0X59, 0XF2, 0XD2, 0X7C, 0X46, 0X1B, 0XE5, 0XE1, 0XE3, 0XAB, 0X5E, 0X76, 0X73, 0X6F, 0XFB
};
word32 sigLen = (word32)sizeof(sigBuf);
word32 hashLen = (word32)sizeof(hash);
for (i = 0; i < MAX_TIMES; i++) {
ret = wc_ecc_verify_hash((byte*)sigBuf, sigLen, hash, hashLen, &verify, (ecc_key*)key);
if (ret < 0 || verify != 1) {
printf("failed on try %d\n", i);
break;
}
}
if (ret < 0 || verify != 1) {
printf("unable to verify, ret = %d verify = %d\n", ret, verify);
}
return NULL;
}
/* when flag is set then try to use software only if DSP is built in */
static int hash_firmware_verify_default(int numThreads)
{
int ret, i;
word32 idx;
double t;
char *sp_URI_value;
pthread_t threads[numThreads];
ecc_key eccKey[numThreads];
for (i = 0; i < numThreads; i++) {
wc_ecc_init(&(eccKey[i]));
idx = 0;
ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &(eccKey[i]), sizeof_ecc_clikey_der_256);
if (ret < 0)
return ret;
}
t = get_time();
for (i = 0; i < numThreads; i++) {
pthread_create(&threads[i], NULL, hash_firmware_verify, (void*)&(eccKey[i]));
}
for (i = 0; i < numThreads; i++) {
pthread_join(threads[i], NULL);
}
t = get_time() - t;
printf("%d verifies on %d threads took %f seconds\n", MAX_TIMES * numThreads, numThreads, t);
return 0;
}
#ifdef WOLFSSL_DSP
/* domain 0 = cDSP 1 = aDSP */
static int hash_firmware_verify_dsp(int numThreads, int domain)
{
int ret, i;
word32 idx;
double t;
remote_handle64 handle[numThreads];
char *sp_URI_value;
pthread_t threads[numThreads];
ecc_key eccKey[numThreads];
if (domain == 0) {
sp_URI_value = wolfSSL_URI "&_dom=cdsp";
}
else {
sp_URI_value = wolfSSL_URI "&_dom=adsp";
}
for (i = 0; i < numThreads; i++) {
wc_ecc_init(&(eccKey[i]));
idx = 0;
ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &(eccKey[i]), sizeof_ecc_clikey_der_256);
if (ret < 0)
return ret;
ret = wolfSSL_open(sp_URI_value, &(handle[i]));
if (ret != 0) {
printf("unable to open CDSP? retVal = %d\n", ret);
return -1;
}
wc_ecc_set_handle(&(eccKey[i]), handle[i]);
}
t = get_time();
for (i = 0; i < numThreads; i++) {
pthread_create(&threads[i], NULL, hash_firmware_verify, (void*)&(eccKey[i]));
}
for (i = 0; i < numThreads; i++) {
pthread_join(threads[i], NULL);
wolfSSL_close(handle[i]);
}
t = get_time() - t;
printf("%d verifies on %d threads took %f seconds\n", MAX_TIMES * numThreads, numThreads, t);
return 0;
}
#endif /* WOLFSSL_DSP */
int main(int argc, char* argv[])
{
wolfCrypt_Init();
printf("benchmarking using default (locks on handle for aDSP)\n");
hash_firmware_verify_default(1);
hash_firmware_verify_default(2);
printf("\nbenchmarking using software (+NEON if built in)\n");
#ifdef WOLFSSL_DSP
wolfSSL_SetHandleCb(NULL); /* remove calls to DSP by default */
#endif
hash_firmware_verify_default(1);
hash_firmware_verify_default(2);
#ifdef WOLFSSL_DSP
printf("\nbenchmarking using threads on aDSP\n");
hash_firmware_verify_dsp(1, 1);
hash_firmware_verify_dsp(2, 1);
hash_firmware_verify_dsp(3, 1);
hash_firmware_verify_dsp(4, 1);
printf("\nbenchmarking 1 thread on cDSP\n");
hash_firmware_verify_dsp(1, 0);
#endif /* WOLFSSL_DSP */
wolfCrypt_Cleanup();
return 0;
}

91
IDE/HEXAGON/ecc-verify.c Normal file
View File

@ -0,0 +1,91 @@
/* ecc-verify.c
*
* Copyright (C) 2006-2019 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 <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#define USE_CERT_BUFFERS_256
#include <wolfssl/certs_test.h>
#define MAX_BLOCK_SIZE 1024
#ifdef WOLFSSL_DSP
static char *sp_URI_value = wolfSSL_URI "&_dom=cdsp";
int hash_firmware_verify(const byte* hash, word32 hashLen, const byte* sigBuf, word32 sigLen)
{
int ret;
ecc_key eccKey;
word32 idx;
int verify;
remote_handle64 handle = -1;
idx = 0;
ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &eccKey, sizeof_ecc_clikey_der_256);
if (ret < 0)
goto exit;
int retVal = wolfSSL_open(sp_URI_value, &handle);
if (retVal != 0) {
printf("unable to open CDSP? retVal = %d\n", retVal);
ret = -1;
goto exit;
}
wc_ecc_set_handle(&eccKey, handle);
ret = wc_ecc_verify_hash((byte*)sigBuf, sigLen, hash, hashLen, &verify, &eccKey);
printf("verify = %d\n", verify);
if (ret < 0)
goto exit;
wolfSSL_close(handle);
exit:
return ret;
}
int main(void)
{
int ret;
const byte hash[] = {
0XFB, 0XBA, 0XB2, 0X89, 0XF7, 0XF9, 0X4B, 0X25, 0X73, 0X6C, 0X58, 0XBE, 0X46, 0XA9, 0X94, 0XC4, 0X41, 0XFD, 0X02, 0X55, 0X2C, 0XC6, 0X02, 0X23, 0X52, 0XE3, 0XD8, 0X6D, 0X2F, 0XAB, 0X7C, 0X83
};
const byte sigBuf[] = {
0X30, 0X44, 0X02, 0X20, 0X05, 0X38, 0XBC, 0X16, 0XC7, 0X67, 0X18, 0XEC, 0XE6, 0X1E, 0X43, 0X7B, 0X29, 0X8F, 0X85, 0X01, 0X33, 0XA8, 0X9B, 0XDD, 0X91, 0X32, 0X1F, 0XEC, 0XF7, 0X91, 0X18, 0X72, 0X9C, 0XE2, 0X6F, 0X31, 0X02, 0X20, 0X3E, 0X31, 0XD6, 0X40, 0XF7, 0X38, 0X3C, 0X1B, 0X6D, 0XAD, 0XE3, 0X93, 0X20, 0XE8, 0XB1, 0XBD, 0X3C, 0X59, 0XF2, 0XD2, 0X7C, 0X46, 0X1B, 0XE5, 0XE1, 0XE3, 0XAB, 0X5E, 0X76, 0X73, 0X6F, 0XFB
};
word32 sigLen = (word32)sizeof(sigBuf);
wolfCrypt_Init();
ret = hash_firmware_verify(hash, sizeof(hash), sigBuf, sigLen);
printf("hash_firmware_verify: %d\n", ret);
wolfCrypt_Cleanup();
return 0;
}
#else
int main()
{
printf("WOLFSSL_DSP expected to be defined when building\n");
return 0;
}
#endif /* WOLFSSL_DSP */

14
IDE/HEXAGON/include.am Normal file
View File

@ -0,0 +1,14 @@
# vim:ft=automake
# included from Top Level Makefile.am
# All paths should be given relative to the root
EXTRA_DIST+= IDE/HEXAGON/Makefile
EXTRA_DIST+= IDE/HEXAGON/user_settings.h
EXTRA_DIST+= IDE/HEXAGON/README.md
EXTRA_DIST+= IDE/HEXAGON/build.sh
EXTRA_DIST+= IDE/HEXAGON/ecc-verify.c
EXTRA_DIST+= IDE/HEXAGON/ecc-verify-benchmark.c
EXTRA_DIST+= IDE/HEXAGON/DSP/Makefile
EXTRA_DIST+= IDE/HEXAGON/DSP/wolfssl_dsp.idl

View File

@ -0,0 +1,37 @@
#ifndef USER_SETTINGS_H
#define USER_SETTINGS_H
#define WOLFCRYPT_ONLY
#define HAVE_ECC
#define FP_ECC
//#define FP_ENTRIES 1
#define NO_DSA
#define NO_DH
#define NO_RSA
//#define DEBUG_WOLFSSL
#define USE_FAST_MATH
#define TFM_TIMING_RESISTANT
#ifdef HAVE_ECC
#define ECC_TIMING_RESISTANT
#endif
#ifndef NO_RSA
#define WC_RSA_BLINDING
#endif
#if 1
#define WOLFSSL_HAVE_SP_RSA
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_MATH
#if 1
/* ARM NEON instructions */
#define WOLFSSL_SP_ARM64_ASM
#endif
#if 1
/* Use DSP */
#define WOLFSSL_DSP
#endif
#endif
#endif

View File

@ -26,6 +26,7 @@ include IDE/Renesas/e2studio/Projects/include.am
include IDE/WICED-STUDIO/include.am
include IDE/CRYPTOCELL/include.am
include IDE/M68K/include.am
include IDE/HEXAGON/include.am
include IDE/RISCV/include.am
EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif IDE/zephyr

View File

@ -6745,7 +6745,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
break;
}
#endif /* !NO_RSA */
#ifdef HAVE_ECC
#if defined(HAVE_ECC)
case ECDSAk:
{
#ifdef HAVE_PK_CALLBACKS

View File

@ -4367,6 +4367,9 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
key->heap, devId);
#endif
#if defined(WOLFSSL_DSP)
key->handle = -1;
#endif
return ret;
}
@ -5807,6 +5810,16 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
}
}
#if defined(WOLFSSL_DSP) && !defined(FREESCALE_LTC_ECC)
if (key->handle != -1) {
return sp_dsp_ecc_verify_256(key->handle, hash, hashlen, key->pubkey.x, key->pubkey.y,
key->pubkey.z, r, s, res, key->heap);
}
if (wolfSSL_GetHandleCbSet() == 1) {
return sp_dsp_ecc_verify_256(0, hash, hashlen, key->pubkey.x, key->pubkey.y,
key->pubkey.z, r, s, res, key->heap);
}
#endif
#if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC)
if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y,

View File

@ -6,6 +6,8 @@ EXTRA_DIST += wolfcrypt/src/misc.c
EXTRA_DIST += wolfcrypt/src/evp.c
EXTRA_DIST += wolfcrypt/src/asm.c
EXTRA_DIST += wolfcrypt/src/aes_asm.asm
EXTRA_DIST += wolfcrypt/src/wc_dsp.c
EXTRA_DIST += wolfcrypt/src/sp_dsp32.c
EXTRA_DIST += \
wolfcrypt/src/ecc_fp.c \

4909
wolfcrypt/src/sp_dsp32.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -979,7 +979,7 @@ int sp_tohex(sp_int* a, char* str)
}
#endif /* WC_MP_TO_RADIX */
#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH)
#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) && !defined(WC_NO_RNG)
/* Set a bit of a: a |= 1 << i
* The field 'used' is updated in a.
*

327
wolfcrypt/src/wc_dsp.c Normal file
View File

@ -0,0 +1,327 @@
/* wc_dsp.c
*
* Copyright (C) 2006-2019 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/cpuid.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if defined(WOLFSSL_DSP)
#include "remote.h"
#include "rpcmem.h"
static wolfSSL_DSP_Handle_cb handle_function = NULL;
static remote_handle64 defaultHandle;
static wolfSSL_Mutex handle_mutex; /* mutex for access to single default handle */
#define WOLFSSL_HANDLE_DONE 1
#define WOLFSSL_HANDLE_GET 0
/* callback function for setting the default handle in single threaded
* use cases */
static int default_handle_cb(remote_handle64 *handle, int finished, void *ctx)
{
(void)ctx;
if (finished == WOLFSSL_HANDLE_DONE) {
if (wc_UnLockMutex(&handle_mutex) != 0) {
WOLFSSL_MSG("Unlock handle mutex failed");
return -1;
}
}
else {
if (wc_LockMutex(&handle_mutex) != 0) {
WOLFSSL_MSG("Lock handle mutex failed");
return -1;
}
*handle = defaultHandle;
}
return 0;
}
/* Set global callback for getting handle to use
* return 0 on success */
int wolfSSL_SetHandleCb(wolfSSL_DSP_Handle_cb in)
{
handle_function = in;
return 0;
}
/* returns 1 if global handle callback is set and 0 if not */
int wolfSSL_GetHandleCbSet()
{
return (handle_function != NULL)? 1: 0;
}
/* Local function for setting up default handle
* returns 0 on success */
int wolfSSL_InitHandle()
{
char *sp_URI_value;
int ret;
sp_URI_value = wolfSSL_URI "&_dom=adsp";
ret = wolfSSL_open(sp_URI_value, &defaultHandle);
if (ret != 0) {
WOLFSSL_MSG("Unable to open aDSP?");
return -1;
}
wolfSSL_SetHandleCb(default_handle_cb);
ret = wc_InitMutex(&handle_mutex);
if (ret != 0) {
WOLFSSL_MSG("Unable to init handle mutex");
return -1;
}
return 0;
}
/* internal function that closes default handle and frees mutex */
void wolfSSL_CleanupHandle()
{
wolfSSL_close(defaultHandle);
wc_FreeMutex(&handle_mutex);
}
#if defined(WOLFSSL_HAVE_SP_ECC)
/* ecc conversion from sp_c32.c */
#include <wolfssl/wolfcrypt/sp.h>
#ifndef WOLFSSL_SP_NO_256
#ifdef HAVE_ECC_VERIFY
/* Read big endian unsigned byte array into r.
*
* r A single precision integer.
* size Maximum number of bytes to convert
* a Byte array.
* n Number of bytes in array to read.
*/
static void int_256_from_bin(int32* r, int size, const byte* a, int n)
{
int i, j = 0;
word32 s = 0;
r[0] = 0;
for (i = n-1; i >= 0; i--) {
r[j] |= (((int32)a[i]) << s);
if (s >= 18U) {
r[j] &= 0x3ffffff;
s = 26U - s;
if (j + 1 >= size) {
break;
}
r[++j] = (int32)a[i] >> s;
s = 8U - s;
}
else {
s += 8U;
}
}
for (j++; j < size; j++) {
r[j] = 0;
}
}
/* Convert an mp_int to an array of sp_digit.
*
* r A single precision integer.
* size Maximum number of bytes to convert
* a A multi-precision integer.
*/
static void int_256_from_mp(int32* r, int size, const mp_int* a)
{
#if DIGIT_BIT == 26
int j;
XMEMCPY(r, a->dp, sizeof(int32) * a->used);
for (j = a->used; j < size; j++) {
r[j] = 0;
}
#elif DIGIT_BIT > 26
int i, j = 0;
word32 s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
r[j] |= ((int32)a->dp[i] << s);
r[j] &= 0x3ffffff;
s = 26U - s;
if (j + 1 >= size) {
break;
}
/* lint allow cast of mismatch word32 and mp_digit */
r[++j] = (int32)(a->dp[i] >> s); /*lint !e9033*/
while ((s + 26U) <= (word32)DIGIT_BIT) {
s += 26U;
r[j] &= 0x3ffffff;
if (j + 1 >= size) {
break;
}
if (s < (word32)DIGIT_BIT) {
/* lint allow cast of mismatch word32 and mp_digit */
r[++j] = (int32)(a->dp[i] >> s); /*lint !e9033*/
}
else {
r[++j] = 0L;
}
}
s = (word32)DIGIT_BIT - s;
}
for (j++; j < size; j++) {
r[j] = 0;
}
#else
int i, j = 0, s = 0;
r[0] = 0;
for (i = 0; i < a->used && j < size; i++) {
r[j] |= ((int32)a->dp[i]) << s;
if (s + DIGIT_BIT >= 26) {
r[j] &= 0x3ffffff;
if (j + 1 >= size) {
break;
}
s = 26 - s;
if (s == DIGIT_BIT) {
r[++j] = 0;
s = 0;
}
else {
r[++j] = a->dp[i] >> s;
s = DIGIT_BIT - s;
}
}
else {
s += DIGIT_BIT;
}
}
for (j++; j < size; j++) {
r[j] = 0;
}
#endif
}
/* Verify the signature values with the hash and public key.
* e = Truncate(hash, 256)
* u1 = e/s mod order
* u2 = r/s mod order
* r == (u1.G + u2.Q)->x mod order
* Optimization: Leave point in projective form.
* (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
* The hash is truncated to the first 256 bits.
*
* hash Hash to sign.
* hashLen Length of the hash data.
* rng Random number generator.
* priv Private part of key - scalar.
* rm First part of result as an mp_int.
* sm Sirst part of result as an mp_int.
* heap Heap to use for allocation.
* returns RNG failures, MEMORY_E when memory allocation fails and
* MP_OKAY on success.
*/
int sp_dsp_ecc_verify_256(remote_handle64 handleIn, const byte* hash, word32 hashLen, mp_int* pX,
mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap)
{
int ret;
remote_handle64 handle = handleIn;
#if 0
/* calling to alloc memory on the ION using these settings slowed the performance down slightly */
int32 *x = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
int32 *y = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
int32 *z = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
int32 *s = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
int32 *u1 = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
int32 *u2 = (int32*)rpcmem_alloc(RPCMEM_HEAP_ID_SYSTEM, RPCMEM_DEFAULT_FLAGS, 10*sizeof(int));
#endif
int32 x[10] __attribute__((aligned(128)));
int32 y[10] __attribute__((aligned(128)));
int32 z[10] __attribute__((aligned(128)));
int32 s[10] __attribute__((aligned(128)));
int32 u1[10] __attribute__((aligned(128)));
int32 u2[10] __attribute__((aligned(128)));
if (hashLen > 32U) {
hashLen = 32U;
}
int_256_from_bin(u1, 10, hash, (int)hashLen);
int_256_from_mp(u2, 10, r);
int_256_from_mp(s, 10, sm);
int_256_from_mp(x, 10, pX);
int_256_from_mp(y, 10, pY);
int_256_from_mp(z, 10, pZ);
if (handle_function != NULL) {
handle_function(&handle, WOLFSSL_HANDLE_GET, NULL);
}
*res = 0;
ret = wolfSSL_DSP_ECC_Verify_256(handle, u1, 10, u2, 10, s, 10, x, 10, y, 10, z, 10, res);
if (handle_function != NULL) {
handle_function(&handle, WOLFSSL_HANDLE_DONE, NULL);
}
#if 0
rpcmem_free(x);
rpcmem_free(y);
rpcmem_free(z);
rpcmem_free(s);
rpcmem_free(u1);
rpcmem_free(u2);
#endif
return ret;
}
/* Used to assign a handle to an ecc_key structure.
* returns 0 on success */
int wc_ecc_set_handle(ecc_key* key, remote_handle64 handle)
{
if (key == NULL) {
return BAD_FUNC_ARG;
}
key->handle = handle;
return 0;
}
#endif /* HAVE_ECC_VERIFY */
#endif /* !WOLFSSL_SP_NO_256 */
#endif /* WOLFSSL_HAVE_SP_ECC */
#endif /* WOLFSSL_DSP */

View File

@ -82,6 +82,10 @@
#include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
#endif
#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
#include "rpcmem.h"
#endif
#ifdef _MSC_VER
/* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
#pragma warning(disable: 4996)
@ -226,6 +230,13 @@ int wolfCrypt_Init(void)
return ret;
}
#endif
#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
if ((ret = wolfSSL_InitHandle()) != 0) {
return ret;
}
rpcmem_init();
#endif
}
initRefCount++;
@ -276,6 +287,10 @@ int wolfCrypt_Cleanup(void)
#if defined(WOLFSSL_RENESAS_TSIP_CRYPT)
tsip_Close();
#endif
#if defined(WOLFSSL_DSP) && !defined(WOLFSSL_DSP_BUILD)
rpcmem_deinit();
wolfSSL_CleanupHandle();
#endif
}
return ret;

View File

@ -404,6 +404,10 @@ struct ecc_key {
mp_int* z;
#endif
#endif
#ifdef WOLFSSL_DSP
remote_handle64 handle;
#endif
};
@ -725,6 +729,14 @@ WOLFSSL_API void wc_ecc_curve_cache_free(void);
WOLFSSL_API
int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order);
#ifdef WOLFSSL_DSP
WOLFSSL_API
int wc_ecc_set_handle(ecc_key* key, remote_handle64 handle);
WOLFSSL_LOCAL
int sp_dsp_ecc_verify_256(remote_handle64 handle, const byte* hash, word32 hashLen, mp_int* pX,
mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -56,7 +56,13 @@
#endif
#endif
#ifndef WOLFSSL_SP_ASM
#ifdef WOLFSSL_DSP_BUILD
typedef int32 sp_digit;
typedef uint32 sp_int_digit;
typedef uint64 sp_int_word;
#undef SP_WORD_SIZE
#define SP_WORD_SIZE 32
#elif !defined(WOLFSSL_SP_ASM)
#if SP_WORD_SIZE == 32
typedef int32_t sp_digit;
typedef uint32_t sp_int_digit;

View File

@ -755,6 +755,18 @@ WOLFSSL_API int wolfCrypt_Cleanup(void);
#define WOLFSSL_GLOBAL
#endif
#ifdef WOLFSSL_DSP
#include "wolfssl_dsp.h"
/* callbacks for setting handle */
typedef int (*wolfSSL_DSP_Handle_cb)(remote_handle64 *handle, int finished,
void *ctx);
WOLFSSL_API int wolfSSL_GetHandleCbSet();
WOLFSSL_API int wolfSSL_SetHandleCb(wolfSSL_DSP_Handle_cb in);
WOLFSSL_LOCAL int wolfSSL_InitHandle();
WOLFSSL_LOCAL void wolfSSL_CleanupHandle();
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif