From ee5a11b8d960a810ccab928f016bb892433e48b1 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 28 Sep 2015 10:06:30 -0600 Subject: [PATCH] Add Intel IPP crypto for RSA add user-crypto makefile update README for IPP crypto place user crypto in wolfcrypt and use autotools adjust distributed files move openssl compatibility consumption auto use IPP RSA -- IPP directory containing shared libraries local return value of wolfSSL_BN and formating of debug openssh testing make sure IPP not built when fips is ipp init to select correct optimizations -- static libraries on linux -- fast-rsa disabled by default try to only set library once only use static IPP if fast rsa is enabled make print out for user crypto more pretty --- .gitignore | 15 + Makefile.am | 11 + configure.ac | 198 +- examples/client/include.am | 2 +- examples/echoclient/include.am | 2 +- examples/echoserver/include.am | 2 +- examples/server/include.am | 2 +- src/include.am | 23 +- src/ssl.c | 8 +- sslSniffer/sslSnifferTest/include.am | 2 +- tests/include.am | 2 +- testsuite/include.am | 2 +- wolfcrypt/benchmark/include.am | 2 +- wolfcrypt/src/asn.c | 30 +- wolfcrypt/test/include.am | 2 +- wolfcrypt/user-crypto/Makefile.am | 9 + wolfcrypt/user-crypto/README.txt | 77 + wolfcrypt/user-crypto/autogen.sh | 23 + wolfcrypt/user-crypto/configure.ac | 44 + wolfcrypt/user-crypto/include/user_rsa.h | 129 + wolfcrypt/user-crypto/lib/.gitkeep | 0 wolfcrypt/user-crypto/lib/libusercrypto.dylib | Bin 0 -> 26808 bytes wolfcrypt/user-crypto/src/rsa.c | 2227 +++++++++++++++++ wolfssl/ssl.h | 4 + wolfssl/wolfcrypt/rsa.h | 11 +- 25 files changed, 2804 insertions(+), 23 deletions(-) create mode 100644 wolfcrypt/user-crypto/Makefile.am create mode 100644 wolfcrypt/user-crypto/README.txt create mode 100755 wolfcrypt/user-crypto/autogen.sh create mode 100644 wolfcrypt/user-crypto/configure.ac create mode 100644 wolfcrypt/user-crypto/include/user_rsa.h create mode 100644 wolfcrypt/user-crypto/lib/.gitkeep create mode 100755 wolfcrypt/user-crypto/lib/libusercrypto.dylib create mode 100644 wolfcrypt/user-crypto/src/rsa.c diff --git a/.gitignore b/.gitignore index dfedec021..5b0786786 100644 --- a/.gitignore +++ b/.gitignore @@ -152,3 +152,18 @@ mqx/wolfcrypt_test/SaAnalysispointsManager.apconfig mqx/wolfcrypt_benchmark/.settings mqx/wolfcrypt_benchmark/.cwGeneratedFileSetLog mqx/wolfcrypt_benchmark/SaAnalysispointsManager.apconfig + +# User Crypto example build +wolfcrypt/user-crypto/aclocal.m4 +wolfcrypt/user-crypto/config.guess +wolfcrypt/user-crypto/autom4te.cache +wolfcrypt/user-crypto/config.log +wolfcrypt/user-crypto/config.status +wolfcrypt/user-crypto/config.sub +wolfcrypt/user-crypto/depcomp +wolfcrypt/user-crypto/install-sh +wolfcrypt/user-crypto/libtool +wolfcrypt/user-crypto/ltmain.sh +wolfcrypt/user-crypto/m4 +wolfcrypt/user-crypto/missing +wolfcrypt/user-crypto/Makefile.in diff --git a/Makefile.am b/Makefile.am index 65b4d3d82..bcbf8c2c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,7 @@ BUILT_SOURCES= EXTRA_DIST= dist_doc_DATA= dist_noinst_SCRIPTS = +noinst_SCRIPTS = check_SCRIPTS = #includes additional rules from aminclude.am @@ -58,6 +59,16 @@ EXTRA_DIST+= gencertbuf.pl EXTRA_DIST+= README.md EXTRA_DIST+= LICENSING EXTRA_DIST+= INSTALL +EXTRA_DIST+= IPP/ + +# user crypto plug in example +EXTRA_DIST+= wolfcrypt/user-crypto/configure.ac +EXTRA_DIST+= wolfcrypt/user-crypto/autogen.sh +EXTRA_DIST+= wolfcrypt/user-crypto/include/user_rsa.h +EXTRA_DIST+= wolfcrypt/user-crypto/src/rsa.c +EXTRA_DIST+= wolfcrypt/user-crypto/lib/.gitkeep +EXTRA_DIST+= wolfcrypt/user-crypto/README.txt +EXTRA_DIST+= wolfcrypt/user-crypto/Makefile.am include cyassl/include.am include wolfssl/include.am diff --git a/configure.ac b/configure.ac index f3060325e..f900c044c 100644 --- a/configure.ac +++ b/configure.ac @@ -106,6 +106,8 @@ OPTIMIZE_CFLAGS="-Os -fomit-frame-pointer" OPTIMIZE_FAST_CFLAGS="-O2 -fomit-frame-pointer" OPTIMIZE_HUGE_CFLAGS="-funroll-loops -DTFM_SMALL_SET -DTFM_HUGE_SET" DEBUG_CFLAGS="-g -DDEBUG -DDEBUG_WOLFSSL" +LIB_ADD= +LIB_STATIC_ADD= thread_ls_on=no # Thread local storage @@ -1483,11 +1485,68 @@ fi AM_CONDITIONAL([BUILD_CRL_MONITOR], [test "x$ENABLED_CRL_MONITOR" = "xyes"]) +# USER CRYPTO +ENABLED_USER_CRYPTO="no" +ENABLED_USER_RSA="no" +AC_DEFINE([BUILD_USER_RSA], [], [User RSA is being defined]) +trycryptodir="" +AC_ARG_WITH([user-crypto], + [AS_HELP_STRING([--with-user-crypto=PATH],[Path to USER_CRYPTO install (default /usr/local)])], + [ + CPPFLAGS="$CPPFLAGS -DHAVE_USER_CRYPTO" + LIBS="$LIBS -lusercrypto" + + if test "x$withval" != "xno" ; then + trycryptodir=$withval + fi + if test "x$withval" == "xyes" ; then + trycryptodir="/usr/local" + fi + + LDFLAGS="$LDFLAGS -L$trycryptodir/lib" + CPPFLAGS="$CPPFLAGS -I$trycryptodir/include" + + #Look for RSA Init function in usercrypto lib + AC_CHECK_LIB([usercrypto], [wc_InitRsaKey], [user_rsa_linked=yes], [user_rsa_linked=no]) + + if test "x$user_rsa_linked" == "xyes" ; then + AC_MSG_NOTICE([User user_rsa.h being used]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_RSA" + ENABLED_USER_RSA=yes + ENABLED_USER_CRYPTO=yes + fi + + + #Display check and find result of link attempts + AC_MSG_CHECKING([for USER_CRYPTO]) + if test "x$ENABLED_USER_CRYPTO" == "xno" ; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([USER_CRYPTO not found. Either move to /usr/include and /usr/lib or + Specify its path using --with-user-crypto=/dir/]) + else + AC_MSG_RESULT([yes]) + # Check if .la is available if not then rely on exported path + AC_CHECK_FILE($trycryptodir/lib/libusercrypto.la, [LIB_ADD="$trycryptodir/lib/libusercrypto.la $LIB_ADD"], [LIB_ADD="-lusercrypto $LIB_ADD"]) + AM_LDFLAGS="$AM_LDFLAGS -L$trycryptodir/lib" + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_CRYPTO" + fi + ] +) + +AM_CONDITIONAL([BUILD_USER_RSA], [test "x$ENABLED_USER_RSA" == "xyes"] ) +AM_CONDITIONAL([BUILD_USER_CRYPTO], [test "x$ENABLED_USER_CRYPTO" = "xyes"]) + +if test "$ENABLED_USER_CRYPTO" = "yes" && test "$ENABLED_FIPS" = "yes" +then + AC_MSG_ERROR([cannot enable user crypto and fips, user crypto posibility of using code in fips boundary.]) +fi + + # NTRU ENABLED_NTRU="no" tryntrudir="" AC_ARG_WITH([ntru], - [ --with-ntru=PATH Path to NTRU install (default /usr/) ], + [AS_HELP_STRING([--with-ntru=PATH],[Path to NTRU install (default /usr/)])], [ AC_MSG_CHECKING([for NTRU]) CPPFLAGS="$CPPFLAGS -DHAVE_NTRU -DHAVE_QSH -DHAVE_TLS_EXTENSIONS" @@ -1503,7 +1562,7 @@ AC_ARG_WITH([ntru], tryntrudir="/usr" fi - LDFLAGS="$AM_LDFLAGS -L$tryntrudir/lib" + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryntrudir/lib" CPPFLAGS="$CPPFLAGS -I$tryntrudir/include" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) @@ -2095,6 +2154,137 @@ AC_ARG_WITH([cavium], ) +# Fast RSA using Intel IPP +ippdir="${srcdir}/IPP" +ipplib="lib" # if autoconf guesses 32 changes lib directory +fastRSA_headers=no + +# set up variables used +IPPLIBS= +IPPHEADERS= +IPPLINK= + +AC_ARG_ENABLE([fast-rsa], + [AS_HELP_STRING([--enable-fast-rsa],[Enable RSA using Intel IPP (default: disabled)])], + [ ENABLED_FAST_RSA=$enableval ], + [ ENABLED_FAST_RSA=no ], + ) + +if test "$ENABLED_USER_RSA" = "no" && test "$ENABLED_FIPS" = "no"; then + +if test "$enable_shared" = "no" && test "$ENABLED_USER_RSA" = "yes"; then + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + + case $host_os in + *darwin*) + ipplib="$ipplib/mac_static" + AC_MSG_ERROR([Issue with static linking to libippcp.a on Mac. + Dynamic IPP libraries supported on Mac]) + break;; + + *linux*) + ipplib="$ipplib/linux_static" + break;; + *) + ENABLED_FAST_RSA=no + esac + + AC_CHECK_FILES([$srcdir/IPP/$ipplib/libippcore.a $srcdir/IPP/$ipplib/libippcp.a], [], [ENABLED_FAST_RSA=no]) + AC_CHECK_FILES([$srcdir/IPP/include/ipp.h $srcdir/IPP/include/ippcp.h], [AM_CPPFLAGS="-I$srcdir/IPP/include $AM_CPPFLAGS"], [ENABLED_FAST_RSA=no]) + LIB_STATIC_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a" +else +# just check link and see if user has already exported paths +if test "$ENABLED_FAST_RSA" = "yes" + then + AC_MSG_NOTICE([Checking if IPP crypto library installed]) + AC_CHECK_HEADER([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], [LIBS="$LIBS -lippcore"; fastRSA_headers=yes], [AS_UNSET([ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15]); fastRSA_headers=no])], [fastRSA_headers=no]) + if test "$fastRSA_headers" = "yes"; then + AM_LDFLAGS="${AM_LDFLAGS} -lippcore -lippcp" + fi +fi + +# Don't cache the result so it can be checked again +AS_UNSET([ac_cv_header_ippcp_h]) +AS_UNSET([ac_cv_header_ipp_h]) + +if test "$fastRSA_headers" = "no"; then +dnl set default paths +if test "$ENABLED_FAST_RSA" = "yes"; then + AC_MSG_NOTICE([Using local IPP crypto library]) + # build and default locations on linux and mac + STORE_LDFLAGS=${LDFLAGS} + STORE_CPPFLAGS=${CPPFLAGS} + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + # using LDFLAGS instead of AM_ temporarily to test link to library + LDFLAGS="-L$ippdir/$ipplib -lippcp -lippcore" + CPPFLAGS="-I$ippdir/include" + AC_CHECK_HEADERS([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], [], [ENABLED_FAST_RSA=no])], [ENABLED_FAST_RSA=no]) + + if test "$ENABLED_FAST_RSA" = "yes"; then + # was succesfull so add tested LDFLAGS to AM_ flags + AM_LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" + AM_CPPFLAGS="${AM_CPPFLAGS} ${CPPFLAGS}" + + case $host_os in + *darwin*) + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.dylib ${name}-9.0.dylib ${name}e9-9.0.dylib ${name}g9-9.0.dylib ${name}h9-9.0.dylib ${name}k0-9.0.dylib ${name}l9-9.0.dylib ${name}n8-9.0.dylib ${name}p8-9.0.dylib ${name}s8-9.0.dylib ${name}y8-9.0.dylib IPP/lib/libippcore.dylib IPP/lib/libippcore-9.0.dylib" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.dylib src/.libs/libippcp.dylib && ln -f ${srcdir}/${name}-9.0.dylib src/.libs/libippcp-9.0.dylib && ln -f ${srcdir}/${name}e9-9.0.dylib src/.libs/libippcpe9-9.0.dylib && ln -f ${srcdir}/${name}g9-9.0.dylib src/.libs/libippcpg9-9.0.dylib && ln -f ${srcdir}/${name}h9-9.0.dylib src/.libs/libippcph9-9.0.dylib && ln -f ${srcdir}/${name}k0-9.0.dylib src/.libs/libippcpk0-9.0.dylib && ln -f ${srcdir}/${name}l9-9.0.dylib src/.libs/libippcpl9-9.0.dylib && ln -f ${srcdir}/${name}n8-9.0.dylib src/.libs/libippcpn8-9.0.dylib && ln -f ${srcdir}/${name}p8-9.0.dylib src/.libs/libippcpp8-9.0.dylib && ln -f ${srcdir}/${name}s8-9.0.dylib src/.libs/libippcps8-9.0.dylib && ln -f ${srcdir}/${name}y8-9.0.dylib src/.libs/libippcpy8-9.0.dylib && ln -f ${srcdir}/IPP/lib/libippcore.dylib src/.libs/libippcore.dylib && ln -f ${srcdir}/IPP/lib/libippcore-9.0.dylib src/.libs/libippcore-9.0.dylib" + break;; + + *linux*) + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.so.9.0 ${name}g9.so.9.0 ${name}h9.so.9.0 ${name}p8.so.9.0 ${name}px.so.9.0 ${name}s8.so.9.0 ${name}.so ${name}w7.so.9.0 IPP/$ipplib/libippcore.so" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}g9.so.9.0 src/.libs/libippcpg9.so.9.0 && ln -f ${name}h9.so.9.0 src/.libs/libippcph9.so.9.0 && ln -f ${name}p8.so.9.0 src/.libs/libippcpp8.so.9.0 && ln -f ${name}px.so.9.0 src/.libs/libippcppx.so.9.0 && ln -f ${name}s8.so.9.0 src/.libs/libippcps8.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}w7.so.9.0 src/.libs/libippcpw7.so.9.0 && ln -f IPP/$ipplib/libippcore.so src/.libs/libippcore.so && ln -f IPP/$ipplib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + else + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.so.9.0 ${name}e9.so.9.0 ${name}k0.so.9.0 ${name}l9.so.9.0 ${name}m7.so.9.0 ${name}mx.so.9.0 ${name}.so ${name}n8.so.9.0 ${name}y8.so.9.0 IPP/lib/libippcore.so" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}e9.so.9.0 src/.libs/libippcpe9.so.9.0 && ln -f ${name}k0.so.9.0 src/.libs/libippcpk0.so.9.0 && ln -f ${name}l9.so.9.0 src/.libs/libippcpl9.so.9.0 && ln -f ${name}m7.so.9.0 src/.libs/libippcpm7.so.9.0 && ln -f ${name}mx.so.9.0 src/.libs/libippcpmx.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}n8.so.9.0 src/.libs/libippcpn8.so.9.0 && ln -f ${name}y8.so.9.0 src/.libs/libippcpy8.so.9.0 && ln -f IPP/lib/libippcore.so src/.libs/libippcore.so && ln -f IPP/lib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + fi + break;; + *) + ENABLED_FAST_RSA=no + esac + fi + # restore LDFLAGS to user set + LDFLAGS=${STORE_LDFLAGS} + CPPFLAGS=${STORE_CPPFLAGS} + IPPHEADERS="${srcdir}/IPP/include/*.h" +fi +fi # end of if found exported paths +fi # end of if for shared library +else # if user rsa is set than do not use fast rsa option + ENABLED_FAST_RSA=no +fi # end of if for user rsa crypto + +AC_MSG_CHECKING([for fast RSA]) +if test "$ENABLED_FAST_RSA" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FAST_RSA -DHAVE_USER_RSA" + # add in user crypto header that uses Intel IPP + AM_CPPFLAGS="$AM_CPPFLAGS -I$srcdir/wolfcrypt/user-crypto/include" + if test "$enable_shared" = "yes"; then + LIBS="$LIBS -lippcore" + LIB_ADD="-lippcp -lippcore $LIB_ADD" + else + LIB_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_ADD" + fi + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST([IPPLIBS]) +AC_SUBST([IPPHEADERS]) +AC_SUBST([IPPLINK]) +# Found IPP library now build in user crypto to use it +AM_CONDITIONAL([BUILD_FAST_RSA], [test "x$ENABLED_FAST_RSA" = "xyes"]) + + # microchip api AC_ARG_ENABLE([mcapi], [ --enable-mcapi Enable Microchip API (default: disabled)], @@ -2263,6 +2453,8 @@ CREATE_HEX_VERSION AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_LDFLAGS]) +AC_SUBST([LIB_ADD]) +AC_SUBST([LIB_STATIC_ADD]) # FINAL AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) @@ -2470,5 +2662,7 @@ echo " * Small Stack: $ENABLED_SMALL_STACK" echo " * valgrind unit tests: $ENABLED_VALGRIND" echo " * LIBZ: $ENABLED_LIBZ" echo " * Examples: $ENABLED_EXAMPLES" +echo " * User Crypto: $ENABLED_USER_CRYPTO" +echo " * Fast RSA: $ENABLED_FAST_RSA" echo "" echo "---" diff --git a/examples/client/include.am b/examples/client/include.am index d0ddcdfaa..862cdfa08 100644 --- a/examples/client/include.am +++ b/examples/client/include.am @@ -5,7 +5,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/client/client noinst_HEADERS += examples/client/client.h examples_client_client_SOURCES = examples/client/client.c -examples_client_client_LDADD = src/libwolfssl.la +examples_client_client_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_client_client_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/client/client.sln diff --git a/examples/echoclient/include.am b/examples/echoclient/include.am index 179cf9907..f0d5868c2 100644 --- a/examples/echoclient/include.am +++ b/examples/echoclient/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/echoclient/echoclient noinst_HEADERS += examples/echoclient/echoclient.h examples_echoclient_echoclient_SOURCES = examples/echoclient/echoclient.c -examples_echoclient_echoclient_LDADD = src/libwolfssl.la +examples_echoclient_echoclient_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoclient_echoclient_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoclient/echoclient.sln diff --git a/examples/echoserver/include.am b/examples/echoserver/include.am index a84312191..767da6c46 100644 --- a/examples/echoserver/include.am +++ b/examples/echoserver/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/echoserver/echoserver noinst_HEADERS += examples/echoserver/echoserver.h examples_echoserver_echoserver_SOURCES = examples/echoserver/echoserver.c -examples_echoserver_echoserver_LDADD = src/libwolfssl.la +examples_echoserver_echoserver_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoserver_echoserver_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoserver/echoserver.sln diff --git a/examples/server/include.am b/examples/server/include.am index bd7037682..f42490591 100644 --- a/examples/server/include.am +++ b/examples/server/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/server/server noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c -examples_server_server_LDADD = src/libwolfssl.la +examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_server_server_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/server/server.sln diff --git a/src/include.am b/src/include.am index f594b1cf9..68c790ee4 100644 --- a/src/include.am +++ b/src/include.am @@ -4,12 +4,25 @@ lib_LTLIBRARIES+= src/libwolfssl.la src_libwolfssl_la_SOURCES = - src_libwolfssl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSL_LIBRARY_VERSION} -src_libwolfssl_la_LIBADD = $(LIBM) +src_libwolfssl_la_LIBADD = $(LIBM) $(LIB_ADD) $(LIB_STATIC_ADD) src_libwolfssl_la_CFLAGS = -DBUILDING_WOLFSSL $(AM_CFLAGS) src_libwolfssl_la_CPPFLAGS = -DBUILDING_WOLFSSL $(AM_CPPFLAGS) +# install the packaged IPP libraries +if BUILD_FAST_RSA + +# Link needed IPP libraries +noinst_SCRIPTS+=IPP_links +IPP_links: + @$(IPPLINK) + +ippdir = $(libdir) +ipp_DATA = $(IPPLIBS) + +include_HEADERS+=$(IPPHEADERS) +endif # BUILD_FAST_RSA + # fips first file if BUILD_FIPS src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_first.c @@ -52,9 +65,15 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/sha256.c \ wolfcrypt/src/hash.c +if !BUILD_USER_RSA if BUILD_RSA +if BUILD_FAST_RSA +src_libwolfssl_la_SOURCES += wolfcrypt/user-crypto/src/rsa.c +else src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c endif +endif +endif if BUILD_AES src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c diff --git a/src/ssl.c b/src/ssl.c index 11eed46d7..5a21be090 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -12407,7 +12407,8 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) #endif /* NO_RSA */ -#if !defined(NO_RSA) || !defined(NO_DSA) +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) \ + || !defined(NO_DSA) || defined(HAVE_ECC) static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) { WOLFSSL_MSG("Entering SetIndividualExternal"); @@ -12559,7 +12560,8 @@ static int SetDsaInternal(WOLFSSL_DSA* dsa) #endif /* NO_DSA */ -#ifndef NO_RSA +#if !defined(NO_RSA) +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) /* WolfSSL -> OpenSSL */ static int SetRsaExternal(WOLFSSL_RSA* rsa) { @@ -12688,7 +12690,7 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) return SSL_SUCCESS; } - +#endif /* HAVE_USER_RSA */ /* return compliant with OpenSSL * 1 if success, 0 if error diff --git a/sslSniffer/sslSnifferTest/include.am b/sslSniffer/sslSnifferTest/include.am index 222777c7f..23de07f91 100644 --- a/sslSniffer/sslSnifferTest/include.am +++ b/sslSniffer/sslSnifferTest/include.am @@ -5,7 +5,7 @@ if BUILD_SNIFFTEST noinst_PROGRAMS += sslSniffer/sslSnifferTest/snifftest sslSniffer_sslSnifferTest_snifftest_SOURCES = sslSniffer/sslSnifferTest/snifftest.c -sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap +sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap $(LIB_STATIC_ADD) sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += sslSniffer/sslSniffer.vcproj diff --git a/tests/include.am b/tests/include.am index 802ec5ad1..2a3f9baf0 100644 --- a/tests/include.am +++ b/tests/include.am @@ -15,7 +15,7 @@ tests_unit_test_SOURCES = \ examples/client/client.c \ examples/server/server.c tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -tests_unit_test_LDADD = src/libwolfssl.la +tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h diff --git a/testsuite/include.am b/testsuite/include.am index 62edb4a30..86b6f9784 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -14,7 +14,7 @@ testsuite_testsuite_test_SOURCES = \ examples/server/server.c \ testsuite/testsuite.c testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -testsuite_testsuite_test_LDADD = src/libwolfssl.la +testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += testsuite/testsuite.sln diff --git a/wolfcrypt/benchmark/include.am b/wolfcrypt/benchmark/include.am index db70ba79c..eee26235f 100644 --- a/wolfcrypt/benchmark/include.am +++ b/wolfcrypt/benchmark/include.am @@ -3,7 +3,7 @@ noinst_PROGRAMS += wolfcrypt/benchmark/benchmark wolfcrypt_benchmark_benchmark_SOURCES = wolfcrypt/benchmark/benchmark.c -wolfcrypt_benchmark_benchmark_LDADD = src/libwolfssl.la +wolfcrypt_benchmark_benchmark_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) wolfcrypt_benchmark_benchmark_DEPENDENCIES = src/libwolfssl.la EXTRA_DIST += wolfcrypt/benchmark/benchmark.sln EXTRA_DIST += wolfcrypt/benchmark/benchmark.vcproj diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a1a42e12d..fce9c5833 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -802,6 +802,7 @@ static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx, #endif /* HAVE_CAVIUM */ +#ifndef HAVE_USER_RSA int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { @@ -831,7 +832,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, return 0; } - +#endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ /* Remove PKCS8 header, move beginning of traditional to beginning of input */ @@ -1256,6 +1257,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) #ifndef NO_RSA +#ifndef HAVE_USER_RSA int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { @@ -1350,7 +1352,7 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, return 0; } - +#endif /* HAVE_USER_RSA */ #endif #ifndef NO_DH @@ -5051,7 +5053,9 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, #endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ -#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA))) +/* USER RSA ifdef portions used instead of refactor in consideration for + possible fips build */ /* Write a public RSA key to output */ static int SetRsaPublicKey(byte* output, RsaKey* key, int outLen, int with_header) @@ -5084,15 +5088,24 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, return MEMORY_E; #endif +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->n); + rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; +#else leadingBit = mp_leading_bit(&key->n); rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; +#endif n[0] = ASN_INTEGER; nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { if (leadingBit) n[nSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); +#else err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); +#endif if (err == MP_OKAY) nSz += rawLen; else { @@ -5120,15 +5133,24 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, } #endif +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->e); + rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; +#else leadingBit = mp_leading_bit(&key->e); rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; +#endif e[0] = ASN_INTEGER; eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ if ( (eSz + rawLen) < MAX_RSA_E_SZ) { if (leadingBit) e[eSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); +#else err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); +#endif if (err == MP_OKAY) eSz += rawLen; else { @@ -5227,7 +5249,7 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, defined(WOLFSSL_KEY_GEN)) */ -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) static mp_int* GetRsaInt(RsaKey* key, int idx) diff --git a/wolfcrypt/test/include.am b/wolfcrypt/test/include.am index fcb07979f..18805a3e2 100644 --- a/wolfcrypt/test/include.am +++ b/wolfcrypt/test/include.am @@ -7,7 +7,7 @@ check_PROGRAMS+= wolfcrypt/test/testwolfcrypt endif noinst_PROGRAMS+= wolfcrypt/test/testwolfcrypt wolfcrypt_test_testwolfcrypt_SOURCES = wolfcrypt/test/test.c -wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la +wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) wolfcrypt_test_testwolfcrypt_DEPENDENCIES = src/libwolfssl.la noinst_HEADERS += wolfcrypt/test/test.h EXTRA_DIST += wolfcrypt/test/test.sln diff --git a/wolfcrypt/user-crypto/Makefile.am b/wolfcrypt/user-crypto/Makefile.am new file mode 100644 index 000000000..d9c3ae391 --- /dev/null +++ b/wolfcrypt/user-crypto/Makefile.am @@ -0,0 +1,9 @@ +AM_CFLAGS=-I m4 + +#add in wolfssl directory +AM_CPPFLAGS+=-I$(abs_srcdir)/../../ -I$(srcdir)/include/ +lib_LTLIBRARIES = lib/libusercrypto.la +lib_libusercrypto_la_CPPFLAGS = $(AM_CPPFLAGS) +lib_libusercrypto_la_LDFLAGS = $(AM_LDFLAGS) +lib_libusercrypto_la_SOURCES = src/rsa.c +include_HEADERS = include/user_rsa.h diff --git a/wolfcrypt/user-crypto/README.txt b/wolfcrypt/user-crypto/README.txt new file mode 100644 index 000000000..50bc8b709 --- /dev/null +++ b/wolfcrypt/user-crypto/README.txt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +/* + Created to use intel's IPP see their license for linking to intel's IPP library + */ + + +##BUILDING ON 64BIT MAC OSX +Tested and developed on MAC OSX linking to IPP v9.0 + +for me exporting the IPP library was needed. As an example it was +export DYLD_LIBRARY_PATH="/opt/intel/ipp/lib" + +first go to the root wolfssl dir and run ./autogen.sh && ./configure it with desired settings then make. This is to set up the define options and wolfssl library for the user crypto to link to. + +Then go to the wolfssl/user-crypto directory and run ./autogen.sh && ./configure then make make install this creates a usercrypto library to use + +Finally go back to the root wolfssl directory and follow these build instructions + +building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files +An example build would be +./configure --with-user-crypto CPPFLAGS=-I/opt/intel/ipp/include --enable-lighty + + +##BUILDING IN 32BIT UBUNTU +Tested on UBUNTU 32 bit linking to IPP v9.0 + +for me exporting the IPP library. As an example it was +export LD_LIBRARY_PATH="/opt/intel/ipp/lib/ia32_lin/:$LD_LIBRARY_PATH" + +first go to the root wolfssl dir and configure it with desired settings and make install. This is to set up the define options and wolfssl library for the user crypto to link to. + +For me on Ubuntu the IPP libraries had been installed into /opt/intel/ipp/lib/ia32_lin/ so the ./configure LDFLAGS=-L/opt/intel/ipp/lib/ia32_lin was needed to be looking at that directory. +Run make && make install from the directory wolfssl_root/wolfssl/user-crypto/ this creates a usercrypto library to use + +Finally go back to the root wolfssl directory and follow these build instructions + +building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files + +./configure --with-user-crypto=root_wolfssl/wolfssl/user-crypto CPPFLAGS=-I/opt/intel/ipp/include (plus any desired additional flags) + + +##THINGS TO CHECK FOR IF NOT ABLE TO LINK WITH USERCRYPTO LIB +Check that the path has been exported for the IPP library. If usercrypto is unable to use the function to init an RSA key then the link to it will fail in configure. Check for this by $DYLD_LIBRARY_PATH on mac or $LD_LIBRARY_PATH on ubuntu. If the directory for the Intel IPP libraries are not displayed than use "export DYLD_LIBRARY_PATH=path_to_ipp_libraries:$DYLD_LIBRARY_PATH". + + +##CREATING OWN RSA CRYPTO PLUGIN + +It is required to have a header file named user_rsa.h. This is what is looked for by wolfssl/wolfcrypt/rsa.h and should contain the user defined rsa key struct. + +It is required to have a library called usercrypto. This is linked to when configuring wolfSSL with the option --with-user-crypto + +It is required when compiled with RSA cert generation to have key struct elements named n and e containing the corresponding big numbers. And the three helper functions to work with the big numbers. These functions are called by wolfcrypt/src/asn.c when working with certificates. +To view the needed functions look at wolfssl/wolfcrypt/rsa.h they will be extern functions surronded by HAVE_USER_RSA define. +Cert Generation for other sign and verify such as ECC are not yet supported. + +When building with openssl compatibility layer extra developent needs to be done, having the two functions SetRsaExernal and SetRsaInternal + +wolfSSL does not take responsibility for the strength of security of third party cryptography libraries plugged in by the user. diff --git a/wolfcrypt/user-crypto/autogen.sh b/wolfcrypt/user-crypto/autogen.sh new file mode 100755 index 000000000..89e475c0b --- /dev/null +++ b/wolfcrypt/user-crypto/autogen.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Create configure and makefile stuff... +# + +# Git hooks should come before autoreconf. +if test -d .git; then + if ! test -d .git/hooks; then + mkdir .git/hooks + fi + ln -s -f ../../pre-commit.sh .git/hooks/pre-commit + ln -s -f ../../pre-push.sh .git/hooks/pre-push +fi + +# If this is a source checkout then call autoreconf with error as well +if test -d .git; then + WARNINGS="all,error" +else + WARNINGS="all" +fi + +autoreconf --install --force --verbose + diff --git a/wolfcrypt/user-crypto/configure.ac b/wolfcrypt/user-crypto/configure.ac new file mode 100644 index 000000000..561b9ccd9 --- /dev/null +++ b/wolfcrypt/user-crypto/configure.ac @@ -0,0 +1,44 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.63]) +AC_INIT([usercypto], [0.1], []) +AC_CONFIG_SRCDIR([src/rsa.c]) + +AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) + +LT_PREREQ([2.2]) +LT_INIT([disable-static]) +LT_LANG([C++]) +LT_LANG([C]) + +# Checks for programs. +AC_PROG_CC +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for libraries. +AM_LDFLAGS=$LDFLAGS +LDFLAGS="$LDFLAGS -L/opt/intel/ipp/lib -lippcp -lippcore" + +# Path to find wolfssl/options and other includes +AM_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS -I../../ -I/opt/intel/ipp/include" +AC_CHECK_LIB([ippcore], [ippGetStatusString], [], [AC_MSG_ERROR([ippcore library needed ./configure LDFLAGS=/path/to/ipp/lib])]) +AC_CHECK_LIB([ippcp], [ippsRSA_InitPublicKey], [], [AC_MSG_ERROR([ippcp library needed ./configure LDFLAGS=/path/to/ipp/lib])]) + +# check headers +AC_CHECK_HEADER([ippcp.h], [], [AC_MSG_ERROR([ippcp.h not found ./configure CPPFLAGS=-I/ipp/headers])]) +AC_CHECK_HEADER([ipp.h], [], [AC_MSG_ERROR([ipp.h not found ./configure CPPFLAGS=-I/ipp/headers])]) + +LDFLAGS=$AM_LDFLAGS +CPPFLAGS=$AM_CPPFLAGS + +AM_LDFLAGS="-L/opt/intel/ipp/lib -lippcp -lippcore" +AM_CPPFLAGS="-I/opt/intel/ipp/include" + +AC_SUBST([AM_CPPFLAGS]) +AC_SUBST([AM_LDFLAGS]) +AC_C_INLINE + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h new file mode 100644 index 000000000..ab5436203 --- /dev/null +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -0,0 +1,129 @@ +/* user_rsa.h + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +/* + Created to use intel's IPP see their license for linking to intel's IPP library + */ + +#ifndef USER_WOLF_CRYPT_RSA_H +#define USER_WOLF_CRYPT_RSA_H + +#include + +#ifndef NO_RSA + +#include +#include + +/* intels crypto */ +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* needed for WOLFSSL_RSA type but use macro guard against redefine */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TYPES_DEFINED) \ + && !defined(WOLFSSL_RSA_TYPE_DEFINED) + struct WOLFSSL_RSA; + typedef struct WOLFSSL_RSA WOLFSSL_RSA; + #define WOLFSSL_RSA_TYPE_DEFINED +#endif + +enum { + RSA_PUBLIC = 0, + RSA_PRIVATE = 1, +}; + + +/* RSA */ +typedef struct RsaKey { + IppsBigNumState* n; + IppsBigNumState* e; + IppsBigNumState* dipp; + IppsBigNumState* pipp; + IppsBigNumState* qipp; + IppsBigNumState* dPipp; + IppsBigNumState* dQipp; + IppsBigNumState* uipp; + int nSz, eSz, dSz; + IppsRSAPublicKeyState* pPub; + IppsRSAPrivateKeyState* pPrv; + word32 prvSz; /* size of private key */ + word32 sz; /* size of signature */ + int type; /* public or private */ + void* heap; /* for user memory overrides */ +} RsaKey; + +WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); +WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); + +WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); + +WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, RsaKey* key); +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); + WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); +#endif +WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, + word32*); + + +#ifdef WOLFSSL_CERT_GEN + /* abstracted BN operations with RSA key */ + WOLFSSL_API int wc_Rsa_leading_bit(void* BN); + WOLFSSL_API int wc_Rsa_unsigned_bin_size(void* BN); + + /* return MP_OKAY on success */ + WOLFSSL_API int wc_Rsa_to_unsigned_bin(void* BN, byte* in, int inLen); +#endif + +#ifdef OPENSSL_EXTRA /* abstracted functions to deal with rsa key */ + WOLFSSL_API int SetRsaExternal(WOLFSSL_RSA* rsa); + WOLFSSL_API int SetRsaInternal(WOLFSSL_RSA* rsa); +#endif +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RSA */ +#endif /* USER_WOLF_CRYPT_RSA_H */ + + diff --git a/wolfcrypt/user-crypto/lib/.gitkeep b/wolfcrypt/user-crypto/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/wolfcrypt/user-crypto/lib/libusercrypto.dylib b/wolfcrypt/user-crypto/lib/libusercrypto.dylib new file mode 100755 index 0000000000000000000000000000000000000000..99a5f8d03e4880df9f547c85e7bfce6979391fa7 GIT binary patch literal 26808 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 +#endif + +#include +#include + +#ifndef NO_RSA + +#define USER_CRYPTO_ERROR -101 + +#ifdef OPENSSL_EXTRA + #include /* include for openssl compatibility */ + #include +#endif +#include "user_rsa.h" + +#ifdef DEBUG_WOLFSSL /* debug done without variadric to allow older compilers */ + #include + #define USER_DEBUG(x) printf x +#else + #define USER_DEBUG(x) +#endif + +#define ASN_INTEGER 0x02 +#define ASN_BIT_STRING 0x03 +#define ASN_TAG_NULL 0x05 +#define ASN_OBJECT_ID 0x06 + + +/* Make sure compiler doesn't skip -- used from wolfSSL */ +static inline void ForceZero(const void* mem, word32 len) +{ + volatile byte* z = (volatile byte*)mem; + + while (len--) *z++ = 0; +} + +enum { + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, /* max allowed in IPP library */ + + RSA_MIN_PAD_SZ = 11 /* seperator + 0 + pad value + 8 pads */ +}; + + +static int ippSet = 0; +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + if (key == NULL) + return USER_CRYPTO_ERROR; + + if (!ippSet) { + /* Selects the right optimizations to use */ + if (ippInit() != ippStsNoErr) { + USER_DEBUG(("Error setting up optimized library to use!\n")); + return USER_CRYPTO_ERROR; + } + ippSet = 1; + } + /* set full struct as 0 */ + ForceZero(key, sizeof(RsaKey)); + + (void)heap; + return 0; +} + + +#ifdef WOLFSSL_CERT_GEN /* three functions needed for cert gen */ +/* return 1 if there is a leading bit*/ +int wc_Rsa_leading_bit(void* bn) +{ + int ret = 0; + if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa leading bit error\n")); + return USER_CRYPTO_ERROR; + } + return (ret % 8)? 1 : 0; /* if mod 8 bit then an extra byte is needed */ +} + + +/* get the size in bytes of BN + cuts off if extra byte is needed so recommended to check wc_Rsa_leading_bit + and adding it to this return value before mallocing memory needed */ +int wc_Rsa_unsigned_bin_size(void* bn) +{ + int ret = 0; + if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa unsigned bin size error\n")); + return USER_CRYPTO_ERROR; + } + return ret / 8; /* size in bytes */ +} + +#ifndef MP_OKAY +#define MP_OKAY 0 +#endif + +/* extract the bn value to a unsigned byte array and return MP_OKAY on succes */ +int wc_Rsa_to_unsigned_bin(void* bn, byte* in, int inLen) +{ + if (ippsGetOctString_BN((Ipp8u*)in, inLen, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa unsigned bin error\n")); + return USER_CRYPTO_ERROR; + } + return MP_OKAY; +} +#endif /* WOLFSSL_CERT_GEN */ + + +#ifdef OPENSSL_EXTRA /* functions needed for openssl compatibility layer */ +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, IppsBigNumState* in) +{ + IppStatus ret; + byte* data; + int sz; + + USER_DEBUG(("Entering SetIndividualExternal\n")); + + if (bn == NULL || in == NULL) { + USER_DEBUG(("inputs NULL error\n")); + return USER_CRYPTO_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + USER_DEBUG(("SetIndividualExternal alloc failed\n")); + return USER_CRYPTO_ERROR; + } + } + + /* get size of array needed and extract oct array of data */ + ret = ippsGetSize_BN(in, &sz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + data = XMALLOC(sz, NULL, DYNAMIC_TYPE_ARRAYS); + if (data == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(data, sz, in); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* store the data into a wolfSSL Big Number */ + *bn = wolfSSL_BN_bin2bn(data, sz, *bn); + + XFREE(data, NULL, DYNAMIC_TYPE_ARRAYS); + + return 0; +} + + +static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, IppsBigNumState** mpi) +{ + int length, ctxSz, sz; + IppStatus ret; + Ipp8u* data; + + USER_DEBUG(("Entering SetIndividualInternal\n")); + + if (bn == NULL || bn->internal == NULL) { + USER_DEBUG(("bn NULL error\n")); + return USER_CRYPTO_ERROR; + } + + length = wolfSSL_BN_num_bytes(bn); + + /* if not IPP BN then create one */ + if (*mpi == NULL) { + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + } + + /* get the size of array needed and check IPP BigNum */ + if (ippsGetSize_BN(*mpi, &sz) != ippStsNoErr) + return USER_CRYPTO_ERROR; + + if (sz < length) { + USER_DEBUG(("big num size is too small\n")); + return USER_CRYPTO_ERROR; + } + + data = XMALLOC(length, NULL, DYNAMIC_TYPE_ARRAYS); + if (data == NULL) + return USER_CRYPTO_ERROR; + + /* extract the wolfSSL BigNum and store it into IPP BigNum */ + if (wolfSSL_BN_bn2bin(bn, data) < 0) { + USER_DEBUG(("error in getting bin from wolfssl bn\n")); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN(data, length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + XFREE(data, NULL, DYNAMIC_TYPE_ARRAYS); + + return 0; +} + + +/* WolfSSL -> OpenSSL */ +int SetRsaExternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + USER_DEBUG(("Entering SetRsaExternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->e, key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->d, key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->p, key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->q, key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmp1, key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + + rsa->exSet = 1; + + /* SSL_SUCCESS */ + return 1; +} + + +/* Openssl -> WolfSSL */ +int SetRsaInternal(WOLFSSL_RSA* rsa) +{ + int ctxSz, pSz, qSz; + IppStatus ret; + RsaKey* key; + USER_DEBUG(("Entering SetRsaInternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + + rsa->inSet = 1; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_KEY); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + if (key->pipp != NULL && key->qipp != NULL && key->dipp != NULL && + key->dPipp != NULL && key->dQipp != NULL && key->uipp != NULL) { + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_KEY); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + } + + /* SSL_SUCCESS */ + return 1; +} +#endif /* OPENSSLEXTRA */ + + +/* Padding scheme function used in wolfSSL for signing needed for matching + existing API signing scheme + input : the msg to be signed + inputLen : length of input msg + pkcsBlock : the outputed padded msg + pkcsBlockLen : length of outptued padded msg buffer + padValue : the padded value after first 00 , is either 01 or 02 + rng : random number generator structure + */ +static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (inputLen == 0) + return 0; + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = padValue; /* insert padValue */ + + if (padValue == RSA_BLOCK_TYPE_1) + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + else { + /* pad with non-zero random bytes */ + word32 padLen = pkcsBlockLen - inputLen - 1, i; + int ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + + if (ret != 0) + return ret; + + /* remove zeros */ + for (i = 1; i < padLen; i++) + if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ + XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); + + return 0; +} + + +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, byte padValue) +{ + word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, + invalid = 0, + i = 1, + outputLen; + + if (pkcsBlock[0] != 0x0) /* skip past zero */ + invalid = 1; + pkcsBlock++; pkcsBlockLen--; + + /* Require block type padValue */ + invalid = (pkcsBlock[0] != padValue) || invalid; + + /* verify the padding until we find the separator */ + if (padValue == RSA_BLOCK_TYPE_1) { + while (i maxOutputLen) || invalid; + + if (invalid) { + USER_DEBUG(("RsaUnPad error, bad formatting\n")); + return USER_CRYPTO_ERROR; + } + + *output = (byte *)(pkcsBlock + i); + return outputLen; +} + + +int wc_FreeRsaKey(RsaKey* key) +{ + if (key == NULL) + return 0; + + if (key->pPub != NULL) + XFREE(key->pPub, NULL, DYNAMIC_TYPE_KEY); + + if (key->pPrv != NULL) { + /* write over senstive information */ + ForceZero(key->pPrv, key->prvSz); + XFREE(key->pPrv, NULL, DYNAMIC_TYPE_KEY); + } + + if (key->n != NULL) + XFREE(key->n, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->e != NULL) + XFREE(key->e, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->dipp != NULL) + XFREE(key->dipp, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->pipp != NULL) + XFREE(key->pipp, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->qipp != NULL) + XFREE(key->qipp, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->dPipp != NULL) + XFREE(key->dPipp, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->dQipp != NULL) + XFREE(key->dQipp, NULL, DYNAMIC_TYPE_ARRAYS); + + if (key->uipp != NULL) + XFREE(key->uipp, NULL, DYNAMIC_TYPE_ARRAYS); + + (void)key; + + return 0; +} + + +/* Some parsing functions from wolfSSL code needed to match wolfSSL API used */ +static int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = 0; + word32 i = *inOutIdx; + byte b; + + *len = 0; /* default length */ + + if ( (i+1) > maxIdx) { /* for first read */ + USER_DEBUG(("GetLength bad index on input\n")); + return USER_CRYPTO_ERROR; + } + + b = input[i++]; + if (b >= 0x80) { + word32 bytes = b & 0x7F; + + if ( (i+bytes) > maxIdx) { /* for reading bytes */ + USER_DEBUG(("GetLength bad long length\n")); + return USER_CRYPTO_ERROR; + } + + while (bytes--) { + b = input[i++]; + length = (length << 8) | b; + } + } + else + length = b; + + if ( (i+length) > maxIdx) { /* for user of length */ + USER_DEBUG(("GetLength value exceeds buffer length\n")); + return USER_CRYPTO_ERROR; + } + + *inOutIdx = i; + if (length > 0) + *len = length; + + return length; +} + + +static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, + word32 maxIdx) +{ + IppStatus ret; + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + int ctxSz; + + if (b != 0x02) + return USER_CRYPTO_ERROR; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)input + i, length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *inOutIdx = i + length; + return 0; +} + + +static int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = -1; + word32 idx = *inOutIdx; + + if (input[idx++] != (0x10 | 0x20) || + GetLength(input, &idx, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + *len = length; + *inOutIdx = idx; + + return length; +} + + +static int GetMyVersion(const byte* input, word32* inOutIdx, + int* version) +{ + word32 idx = *inOutIdx; + + if (input[idx++] != 0x02) + return USER_CRYPTO_ERROR; + + if (input[idx++] != 0x01) + return USER_CRYPTO_ERROR; + + *version = input[idx++]; + *inOutIdx = idx; + + return *version; +} + + +int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int version, length; + int ctxSz, pSz, qSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaPrivateKeyDecode\n")); + + /* read in key information */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + if (GetMyVersion(input, inOutIdx, &version) < 0) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + GetInt(&key->dipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->pipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->qipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dPipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->uipp, input, inOutIdx, inSz) < 0 ) + return USER_CRYPTO_ERROR; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_KEY); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_KEY); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + return 0; +} + + +/* read in a public RSA key */ +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int length; + int ctxSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + key->type = RSA_PUBLIC; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + { + byte b = input[*inOutIdx]; + if (b != ASN_INTEGER) { + /* not from decoded cert, will have algo id, skip past */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + *inOutIdx += length; /* skip past */ + + /* could have NULL tag and 0 terminator, but may not */ + b = input[(*inOutIdx)++]; + + if (b == ASN_TAG_NULL) { + b = input[(*inOutIdx)++]; + if (b != 0) + return USER_CRYPTO_ERROR; + } + else + /* go back, didn't have it */ + (*inOutIdx)--; + + /* should have bit tag length and seq next */ + b = input[(*inOutIdx)++]; + if (b != ASN_BIT_STRING) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + /* could have 0 */ + b = input[(*inOutIdx)++]; + if (b != 0) + (*inOutIdx)--; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + } /* end if */ + } /* openssl var block */ +#endif /* OPENSSL_EXTRA */ + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return USER_CRYPTO_ERROR; + + /* get sizes set for IPP BN states */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_KEY); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + USER_DEBUG(("\tExit RsaPublicKeyDecode\n")); + + return 0; +} + + +/* import RSA public key elements (n, e) into RsaKey structure (key) */ +int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, + word32 eSz, RsaKey* key) +{ + IppStatus ret; + int ctxSz; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecodeRaw\n")); + + if (n == NULL || e == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + /* set up IPP key states -- read in n */ + ret = ippsBigNumGetSize(nSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->n = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->n == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(nSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)n, nSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* read in e */ + ret = ippsBigNumGetSize(eSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->e = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->e == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(eSz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)e, eSz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* store size and convert to binary */ + key->sz = nSz; + nSz = nSz * 8; + eSz = eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(nSz, eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_KEY); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(nSz, eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n,key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->nSz = nSz; + key->eSz = eSz; + key->type = RSA_PUBLIC; + + return USER_CRYPTO_ERROR; +} + + +/* encrypt using PKCS v15 */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + + if (key == NULL || in == NULL || out == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPub == NULL || outLen < key->sz) + return USER_CRYPTO_ERROR; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, key->pPub); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, DYNAMIC_TYPE_ARRAYS); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSAEncrypt_PKCSv15((Ipp8u*)in, inLen, NULL, (Ipp8u*)out, + key->pPub, scratchBuffer); + if (ret != ippStsNoErr) { + USER_DEBUG(("encrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_ARRAYS); + + (void)rng; + return key->sz; +} + + +/* decrypt using PLCS v15 */ +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + int outSz; + + if (in == NULL || out == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPrv == NULL || inLen != key->sz) + return USER_CRYPTO_ERROR; + + outSz = outLen; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, DYNAMIC_TYPE_ARRAYS); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + /* perform decryption using IPP */ + ret = ippsRSADecrypt_PKCSv15((Ipp8u*)in, (Ipp8u*)out, &outSz, key->pPrv, + scratchBuffer); + if (ret != ippStsNoErr) { + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_ARRAYS); + + return outSz; +} + + +/* out is a pointer that is set to the location in byte array "in" where input + data has been decrypted */ +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + int outSz; + + USER_DEBUG(("Entering wc_RsaPrivateDecryptInline\n")); + + outSz = wc_RsaPrivateDecrypt(in, inLen, in, inLen, key); + *out = in; + + return outSz; +} + + +/* for Rsa Verify + in : byte array to be verified + inLen : length of input array + out : pointer to location of in byte array that has been verified + */ +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + + int ctxSz; + int scratchSz; + Ipp8u* scratchBuffer; + IppStatus ret; + IppsRSAPrivateKeyState* pPub; + IppsBigNumState* pTxt; + IppsBigNumState* cTxt; + + USER_DEBUG(("Entering wc_RsaSSL_VerifyInline\n")); + + if (key == NULL || key->n == NULL || key->e == NULL) { + USER_DEBUG(("n or e element was null\n")); + return USER_CRYPTO_ERROR; + } + + if (in == NULL || out == NULL) + return USER_CRYPTO_ERROR; + + /* set up a private key state using public key values */ + ret = ippsRSA_GetSizePrivateKeyType1(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + pPub = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_KEY); + if (pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType1(key->nSz, key->eSz, pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + + ret = ippsRSA_SetPrivateKeyType1(key->n, key->e, pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, pPub); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, DYNAMIC_TYPE_ARRAYS); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + /* load plain and cipher into big num states */ + ret = ippsBigNumGetSize(key->sz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + pTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (pTxt == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(key->sz, pTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up cipher to hold signature */ + ret = ippsBigNumGetSize(key->sz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + cTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (pTxt == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(key->sz, cTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, cTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* decrypt using public key information */ + ret = ippsRSA_Decrypt(cTxt, pTxt, pPub, scratchBuffer); + if (ret != ippStsNoErr) { + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* extract big num struct to octect string */ + ret = ippsGetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) { + USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* clean up memory used */ + XFREE(pTxt, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(cTxt, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(pPub, NULL, DYNAMIC_TYPE_ARRAYS); + + /* unpad the decrypted information and return size of array */ + return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); +} + + +/* sets up and call VerifyInline to verify a signature */ +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + + if (out == NULL || in == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) { + return USER_CRYPTO_ERROR; + } + + XMEMCPY(tmp, in, inLen); + + /* verify signature and test if output buffer is large enough */ + plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key); + if (plainLen < 0) + return plainLen; + + if (plainLen > (int)outLen) + plainLen = USER_CRYPTO_ERROR; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, NULL, DYNAMIC_TYPE_RSA); + + return plainLen; +} + + +/* for Rsa Sign */ +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + int sz; + int scratchSz; + int ctxSz; + int prvSz; + IppStatus ret; + Ipp8u* scratchBuffer; + IppsRSAPublicKeyState* pPrv; + IppsBigNumState* pTxt; + IppsBigNumState* cTxt; + + sz = key->sz; + + /* set up public key state using private key values */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->dSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + prvSz = ctxSz; /* used later to overright sensitive memory */ + pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_KEY); + if (pPrv == NULL) { + USER_DEBUG(("memeory error assinging pPrv\n")); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_InitPublicKey(key->nSz, key->dSz, pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->dipp, pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetBufferSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, DYNAMIC_TYPE_ARRAYS); + if (scratchBuffer == NULL) { + USER_DEBUG(("memory error assigning scratch buffer\n")); + return USER_CRYPTO_ERROR; + } + + /* Set up needed pkcs v15 padding */ + if (wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng) != 0) + return USER_CRYPTO_ERROR; + + /* load plain and cipher into big num states */ + ret = ippsBigNumGetSize(sz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + pTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (pTxt == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(sz, pTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)out, sz, pTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up cipher to hold signature */ + ret = ippsBigNumGetSize(outLen, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + cTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (pTxt == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(outLen, cTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)out, outLen, cTxt); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* encrypt using private key */ + ret = ippsRSA_Encrypt(pTxt, cTxt, pPrv, scratchBuffer); + if (ret != ippStsNoErr) { + USER_DEBUG(("sign error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get output string from big number structure */ + ret = ippsGetOctString_BN((Ipp8u*)out, sz, cTxt); + if (ret != ippStsNoErr) { + USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* clean up memory used */ + ForceZero(pPrv, prvSz); /* clear senstive memory */ + XFREE(pPrv, 0, DYNAMIC_TYPE_ARRAYS); + XFREE(pTxt, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(cTxt, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_ARRAYS); + + return sz; +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ + if (key == NULL) + return 0; + + return key->sz; +} + + +/* flatten RsaKey structure into individual elements (e, n) */ +int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, + word32* nSz) +{ + int sz, bytSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaFlattenPublicKey\n")); + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) + return USER_CRYPTO_ERROR; + + bytSz = sizeof(byte); + ret = ippsExtGet_BN(NULL, &sz, NULL, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* sz is in bits change to bytes */ + sz = (sz / bytSz) + (sz % bytSz); + + if (*eSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(e, sz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *eSz = (word32)sz; + + /* flatten n */ + ret = ippsExtGet_BN(NULL, &sz, NULL, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* sz is in bits change to bytes */ + sz = (sz / bytSz) + (sz % bytSz); + + if (*nSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(n, sz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *nSz = (word32)sz; + + return 0; +} + +#ifdef WOLFSSL_KEY_GEN +/* Make an RSA key for size bits, with e specified, 65537 is a good e */ +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ + IppStatus ret; + int scratchSz; + int i; /* for trys on calling make key */ + int ctxSz; + + IppsBigNumState* pSrcPublicExp; + Ipp8u* scratchBuffer; + int trys = 8; /* Miller-Rabin test parameter */ + IppsPrimeState* pPrime; + IppBitSupplier rndFunc; + IppsPRNGState* rndParam; /* rng context */ + + int qBitSz; /* size of q factor */ + int bytSz; /* size of key in bytes */ + int leng; + + USER_DEBUG(("Entering wc_MakeRsaKey\n")); + + qBitSz = size / 2; + bytSz = size / 8; + + if (key == NULL) + return USER_CRYPTO_ERROR; + + if (e < 3 || (e&1) == 0) + return USER_CRYPTO_ERROR; + + if (size > RSA_MAX_SIZE || size < RSA_MIN_SIZE) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + + /* set up rng */ + ret = ippsPRNGGetSize(&ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPRNGGetSize error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + rndParam = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_ARRAYS); + if (rndParam == NULL) + return USER_CRYPTO_ERROR; + + /*@TODO size of seed bits used hard set at 256 */ + ret = ippsPRNGInit(256, rndParam); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPRNGInit error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* initialize prime number */ + ret = ippsPrimeGetSize(size, &ctxSz); /* size in bits */ + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeGetSize error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + pPrime = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_ARRAYS); + if (pPrime == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsPrimeInit(size, pPrime); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeInit error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsPrimeGen(size, 100, pPrime, ippsPRNGen, rndParam); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeGen error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* define RSA privete key type 2 */ + /* length in bits of p and q factors */ + ret = ippsRSA_GetSizePrivateKeyType2(qBitSz, qBitSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKeyType2 error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; /* used when freeing private key */ + key->pPrv = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_ARRAYS); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + /* length in bits of p and q factors */ + ret = ippsRSA_InitPrivateKeyType2(qBitSz, qBitSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKeyType2 error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* allocate scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetBufferSizePrivateKey error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz, 0, DYNAMIC_TYPE_ARRAYS); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + /* set up initial value of pScrPublicExp */ + leng = (int)sizeof(long); /* # of Ipp32u in long */ + ret = ippsBigNumGetSize(leng, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + pSrcPublicExp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (pSrcPublicExp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, pSrcPublicExp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + ret = ippsSetOctString_BN((Ipp8u*)&e, leng, pSrcPublicExp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* initializing key->n */ + ret = ippsBigNumGetSize(bytSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->n = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->n == NULL) + return USER_CRYPTO_ERROR; + + key->nSz = size; + ret = ippsBigNumInit(bytSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* initializing public exponent key->e */ + ret = ippsBigNumGetSize(leng, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->e = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->e == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* private exponent key->dipp */ + ret = ippsBigNumGetSize(bytSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->dipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->dipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(bytSz, key->dipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + rndFunc = ippsPRNGen; + /* call IPP to generate keys, if inseficent entropy error call again + using for loop to avoid infinte loop */ + for (i = 0; i < 5; i++) { + ret = ippsRSA_GenerateKeys(pSrcPublicExp, key->n, key->e, + key->dipp, key->pPrv, scratchBuffer, trys, pPrime, + rndFunc, rndParam); + if (ret == ippStsNoErr) { + break; + } + + /* catch all errors other than entropy error */ + if (ret != ippStsInsufficientEntropy) { + USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + } + + /* get bn sizes needed for private key set up */ + ret = ippsExtGet_BN(NULL, &key->eSz, NULL, key->e); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsExtGet_BN(NULL, &key->nSz, NULL, key->n); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s nSz = %d eSz = %d\n", + ippGetStatusString(ret), key->nSz, key->eSz)); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_KEY); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get private key information for key struct */ + leng = size/16; /* size of q, p, u, dP, dQ */ + ret = ippsBigNumGetSize(leng, &ctxSz); /* get needed ctxSz and use */ + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->pipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->pipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->pipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up q BN for key */ + key->qipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->qipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->qipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up dP BN for key */ + key->dPipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->dPipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->dPipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up dQ BN for key */ + key->dQipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->dQipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->dQipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up u BN for key */ + key->uipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_ARRAYS); + if (key->uipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->uipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* get values from created key */ + ret = ippsRSA_GetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetPrivateKeyType2 error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* clean up memory used */ + XFREE(pSrcPublicExp, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(pPrime, NULL, DYNAMIC_TYPE_ARRAYS); + XFREE(rndParam, NULL, DYNAMIC_TYPE_ARRAYS); + + (void)rng; + + return 0; +} + +/********** duplicate code needed -- future refactor */ +#define MAX_VERSION_SZ 5 +#define MAX_SEQ_SZ 5 +#define ASN_CONTEXT_SPECIFIC 0x80 +#define ASN_CONSTRUCTED 0x20 +#define ASN_LONG_LENGTH 0x80 +#define ASN_SEQUENCE 0x10 +#define RSA_INTS 8 +#define FALSE 0 +#define TRUE 1 + +#define MAX_LENGTH_SZ 4 +#define RSAk 645 +#define keyType 2 +#define MAX_RSA_INT_SZ 517 +#define MAX_RSA_E_SZ 16 +#define MAX_ALGO_SZ 20 + +static word32 BytePrecision(word32 value) +{ + word32 i; + for (i = sizeof(value); i; --i) + if (value >> ((i - 1) * WOLFSSL_BIT_SIZE)) + break; + + return i; +} + + +static int SetMyVersion(word32 version, byte* output, int header) +{ + int i = 0; + + if (output == NULL) + return USER_CRYPTO_ERROR; + + if (header) { + output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; + output[i++] = ASN_BIT_STRING; + } + output[i++] = ASN_INTEGER; + output[i++] = 0x01; + output[i++] = (byte)version; + + return i; +} + + +static word32 SetLength(word32 length, byte* output) +{ + word32 i = 0, j; + + if (length < 0x80) + output[i++] = (byte)length; + else { + output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); + + for (j = BytePrecision(length); j; --j) { + output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); + i++; + } + } + + return i; +} + + +static word32 SetSequence(word32 len, byte* output) +{ + output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + + +static word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) +{ + /* adding TAG_NULL and 0 to end */ + + /* RSA keyType */ + #ifndef NO_RSA + static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00}; + #endif /* NO_RSA */ + + int algoSz = 0; + int tagSz = 2; /* tag null and terminator */ + word32 idSz, seqSz; + const byte* algoName = 0; + byte ID_Length[MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + + if (type == keyType) { /* keyType */ + switch (algoOID) { + #ifndef NO_RSA + case RSAk: + algoSz = sizeof(RSA_AlgoID); + algoName = RSA_AlgoID; + break; + #endif /* NO_RSA */ + default: + /* unknown key algo */ + return 0; + } + } + else { + /* unknown algo type */ + return 0; + } + + idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */ + seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); + /* +1 for object id, curveID of curveSz follows for ecc */ + seqArray[seqSz++] = ASN_OBJECT_ID; + + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + + return seqSz + idSz + algoSz; + +} + + +/* Write a public RSA key to output */ +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* n = NULL; + byte* e = NULL; +#else + byte n[MAX_RSA_INT_SZ]; + byte e[MAX_RSA_E_SZ]; +#endif + byte seq[MAX_SEQ_SZ]; + byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + int nSz; + int eSz; + int seqSz; + int lenSz; + int idx; + int rawLen; + int leadingBit; + int err; + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + return USER_CRYPTO_ERROR; + + /* n */ +#ifdef WOLFSSL_SMALL_STACK + n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (n == NULL) + return USER_CRYPTO_ERROR; +#endif + + if (ippsExtGet_BN(NULL, &rawLen, NULL, key->n) != ippStsNoErr) + return USER_CRYPTO_ERROR; + leadingBit = rawLen % 8; /* check for if an extra byte is needed */ + rawLen = rawLen/8; /* convert to byte size */ + rawLen = rawLen + leadingBit; + n[0] = ASN_INTEGER; + nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ + + if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { + if (leadingBit) + n[nSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)n + nSz, rawLen, key->n); + if (err == ippStsNoErr) + nSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } +#endif + + if (ippsExtGet_BN(NULL, &rawLen, NULL, key->e) != ippStsNoErr) + return USER_CRYPTO_ERROR; + leadingBit = rawLen % 8; + rawLen = rawLen/8; + rawLen = rawLen + leadingBit; + e[0] = ASN_INTEGER; + eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ + + if ( (eSz + rawLen) < MAX_RSA_E_SZ) { + if (leadingBit) + e[eSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)e + eSz, rawLen, key->e); + if (err == ippStsNoErr) + eSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return USER_CRYPTO_ERROR; + } + + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return USER_CRYPTO_ERROR; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, keyType, 0); + lenSz = SetLength(seqSz + nSz + eSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return USER_CRYPTO_ERROR; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + else + idx = 0; + + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + /* n */ + XMEMCPY(output + idx, n, nSz); + idx += nSz; + /* e */ + XMEMCPY(output + idx, e, eSz); + idx += eSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +static IppsBigNumState* GetRsaInt(RsaKey* key, int idx) +{ + if (idx == 0) + return key->n; + if (idx == 1) + return key->e; + if (idx == 2) + return key->dipp; + if (idx == 3) + return key->pipp; + if (idx == 4) + return key->qipp; + if (idx == 5) + return key->dPipp; + if (idx == 6) + return key->dQipp; + if (idx == 7) + return key->uipp; + + return NULL; +} + + +/* Release Tmp RSA resources */ +static INLINE void FreeTmpRsas(byte** tmps, void* heap) +{ + int i; + + (void)heap; + + for (i = 0; i < RSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA); +} + + +/* Convert RsaKey key to DER format, write to output (inLen), return bytes + written */ +int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) +{ + word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 sizes[RSA_INTS]; + int i, j, outLen, ret = 0, lbit; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[RSA_INTS]; + + USER_DEBUG(("Entering RsaKeyToDer\n")); + + if (!key || !output) + return USER_CRYPTO_ERROR; + + if (key->type != RSA_PRIVATE) + return USER_CRYPTO_ERROR; + + for (i = 0; i < RSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < RSA_INTS; i++) { + Ipp32u isZero; + IppsBigNumState* keyInt = GetRsaInt(key, i); + + /* leading zero */ + ippsCmpZero_BN(keyInt, &isZero); /* makes isZero 0 if true */ + ippsExtGet_BN(NULL, (int*)&rawLen, NULL, keyInt); /* bit length */ + if (rawLen % 8 || !isZero) + lbit = 1; + else + lbit = 0; + + rawLen /= 8; /* convert to bytes */ + rawLen += lbit; + + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_RSA); + if (tmps[i] == NULL) { + ret = USER_CRYPTO_ERROR; + break; + } + + tmps[i][0] = ASN_INTEGER; + sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ + + if (sizes[i] <= MAX_SEQ_SZ) { + int err; + + /* leading zero */ + if (lbit) + tmps[i][sizes[i]-1] = 0x00; + + /* extract data*/ + err = ippsGetOctString_BN((Ipp8u*)(tmps[i] + sizes[i]), + rawLen, keyInt); + if (err == ippStsOk) { + sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ + intTotalLen += sizes[i]; + ret = 0; + } + else { + ret = USER_CRYPTO_ERROR; + break; + } + } + else { + ret = USER_CRYPTO_ERROR; + break; + } + } + + if (ret != 0) { + FreeTmpRsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (outLen > (int)inLen) { + return USER_CRYPTO_ERROR; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < RSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + FreeTmpRsas(tmps, key->heap); + + return outLen; +} + + +/* Convert Rsa Public key to DER format, write to output (inLen), return bytes + written +*/ +int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) +{ + return SetRsaPublicKey(output, key, inLen, 1); +} + + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* NO_RSA */ + diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 8df18bd37..dbe99c201 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -78,7 +78,11 @@ typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; #define WOLFSSL_TYPES_DEFINED +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + typedef struct WOLFSSL_DSA WOLFSSL_DSA; typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 9da3becf2..ba9f29f26 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -26,6 +26,11 @@ #ifndef NO_RSA +/* allow for user to plug in own crypto */ +#if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA)) + #include "user_rsa.h" +#else + #ifdef HAVE_FIPS /* for fips @wc_fips */ #include @@ -41,7 +46,8 @@ extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefinition of structs */ +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) #define WOLFSSL_RSA_CAVIUM_MAGIC 0xBEEF0006 enum { @@ -72,7 +78,6 @@ typedef struct RsaKey { } RsaKey; #endif /*HAVE_FIPS */ - WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); @@ -113,7 +118,7 @@ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, WOLFSSL_API int wc_RsaInitCavium(RsaKey*, int); WOLFSSL_API void wc_RsaFreeCavium(RsaKey*); #endif - +#endif /* HAVE_USER_RSA */ #ifdef __cplusplus } /* extern "C" */ #endif