From 85511067e454441fa8e74ab17abd8cd1bf0ac212 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 21 May 2018 13:03:49 -0700 Subject: [PATCH 1/7] Added crypto device framework to handle PK RSA/ECC operations using callbacks. Adds new build option `./configure --enable-cryptodev` or `#define WOLF_CRYPTO_DEV`. Added devId support to PKCS7. --- configure.ac | 14 +++ wolfcrypt/src/cryptodev.c | 207 ++++++++++++++++++++++++++++++++++ wolfcrypt/src/ecc.c | 37 +++++- wolfcrypt/src/include.am | 4 + wolfcrypt/src/pkcs7.c | 29 ++--- wolfcrypt/src/rsa.c | 22 +++- wolfcrypt/src/wc_port.c | 8 ++ wolfcrypt/test/test.c | 37 +++++- wolfssl/wolfcrypt/cryptodev.h | 114 +++++++++++++++++++ wolfssl/wolfcrypt/ecc.h | 2 +- wolfssl/wolfcrypt/include.am | 3 +- wolfssl/wolfcrypt/pkcs7.h | 1 + wolfssl/wolfcrypt/rsa.h | 3 + wolfssl/wolfcrypt/types.h | 32 +++++- 14 files changed, 486 insertions(+), 27 deletions(-) create mode 100644 wolfcrypt/src/cryptodev.c create mode 100644 wolfssl/wolfcrypt/cryptodev.h diff --git a/configure.ac b/configure.ac index 9c8dfd4d3..a240142ab 100644 --- a/configure.ac +++ b/configure.ac @@ -3868,6 +3868,20 @@ else fi +# Support for crypto device hardware +AC_ARG_ENABLE([cryptodev], + [AS_HELP_STRING([--enable-cryptodev],[Enable crypto hardware support (default: disabled)])], + [ ENABLED_CRYPTODEV=$enableval ], + [ ENABLED_CRYPTODEV=no ] + ) + +if test "$ENABLED_CRYPTODEV" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_DEV" +fi +AM_CONDITIONAL([BUILD_CRYPTODEV], [test "x$ENABLED_CRYPTODEV" = "xyes"]) + + # Session Export AC_ARG_ENABLE([sessionexport], [AS_HELP_STRING([--enable-sessionexport],[Enable export and import of sessions (default: disabled)])], diff --git a/wolfcrypt/src/cryptodev.c b/wolfcrypt/src/cryptodev.c new file mode 100644 index 000000000..80179e0e1 --- /dev/null +++ b/wolfcrypt/src/cryptodev.c @@ -0,0 +1,207 @@ +/* cryptodev.c + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 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, see . + */ + +/* This framework provides a central place for crypto hardware integration + using the devId scheme. If not supported return `NOT_COMPILED_IN`. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLF_CRYPTO_DEV + +#include +#include +#include + + +/* TODO: Consider linked list with mutex */ +#ifndef MAX_CRYPTO_DEVICES +#define MAX_CRYPTO_DEVICES 8 +#endif + +typedef struct CryptoDev { + int devId; + CryptoDevCallbackFunc cb; + void* ctx; +} CryptoDev; +static CryptoDev gCryptoDev[MAX_CRYPTO_DEVICES]; + +static CryptoDev* wc_CryptoDev_FindDevice(int devId) +{ + int i; + for (i=0; idevId = devId; + dev->cb = cb; + dev->ctx = ctx; + + return 0; +} + +void wc_CryptoDev_UnRegisterDevice(int devId) +{ + CryptoDev* dev = wc_CryptoDev_FindDevice(devId); + if (dev) { + XMEMSET(dev, 0, sizeof(*dev)); + dev->devId = INVALID_DEVID; + } +} + +#ifndef NO_RSA +int wc_CryptoDev_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = NOT_COMPILED_IN; + CryptoDev* dev; + + /* locate registered callback */ + dev = wc_CryptoDev_FindDevice(key->devId); + if (dev) { + if (dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA; + cryptoInfo.pk.rsa.in = in; + cryptoInfo.pk.rsa.inLen = inLen; + cryptoInfo.pk.rsa.out = out; + cryptoInfo.pk.rsa.outLen = outLen; + cryptoInfo.pk.rsa.type = type; + cryptoInfo.pk.rsa.key = key; + cryptoInfo.pk.rsa.rng = rng; + + ret = dev->cb(key->devId, &cryptoInfo, dev->ctx); + } + } + + return ret; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +int wc_CryptoDev_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen) +{ + int ret = NOT_COMPILED_IN; + CryptoDev* dev; + + /* locate registered callback */ + dev = wc_CryptoDev_FindDevice(private_key->devId); + if (dev) { + if (dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDH; + cryptoInfo.pk.ecdh.private_key = private_key; + cryptoInfo.pk.ecdh.public_key = public_key; + cryptoInfo.pk.ecdh.out = out; + cryptoInfo.pk.ecdh.outlen = outlen; + + ret = dev->cb(private_key->devId, &cryptoInfo, dev->ctx); + } + } + + return ret; +} + +int wc_CryptoDev_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key) +{ + int ret = NOT_COMPILED_IN; + CryptoDev* dev; + + /* locate registered callback */ + dev = wc_CryptoDev_FindDevice(key->devId); + if (dev) { + if (dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_SIGN; + cryptoInfo.pk.eccsign.in = in; + cryptoInfo.pk.eccsign.inlen = inlen; + cryptoInfo.pk.eccsign.out = out; + cryptoInfo.pk.eccsign.outlen = outlen; + cryptoInfo.pk.eccsign.rng = rng; + cryptoInfo.pk.eccsign.key = key; + + ret = dev->cb(key->devId, &cryptoInfo, dev->ctx); + } + } + + return ret; +} + +int wc_CryptoDev_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key) +{ + int ret = NOT_COMPILED_IN; + CryptoDev* dev; + + /* locate registered callback */ + dev = wc_CryptoDev_FindDevice(key->devId); + if (dev) { + if (dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_VERIFY; + cryptoInfo.pk.eccverify.sig = sig; + cryptoInfo.pk.eccverify.siglen = siglen; + cryptoInfo.pk.eccverify.hash = hash; + cryptoInfo.pk.eccverify.hashlen = hashlen; + cryptoInfo.pk.eccverify.res = res; + cryptoInfo.pk.eccverify.key = key; + + ret = dev->cb(key->devId, &cryptoInfo, dev->ctx); + } + } + + return ret; +} +#endif /* HAVE_ECC */ + +#endif /* WOLF_CRYPTO_DEV */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 9801a51c5..d53847ae7 100755 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -122,6 +122,10 @@ ECC Curve Sizes: #include #endif +#ifdef WOLF_CRYPTO_DEV + #include +#endif + #ifdef NO_INLINE #include #else @@ -2793,6 +2797,15 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_DEV + if (private_key->devId != INVALID_DEVID) { + err = wc_CryptoDev_Ecdh(private_key, public_key, out, outlen); + if (err != NOT_COMPILED_IN) + return err; + err = 0; /* reset error code and try using software */ + } +#endif + /* type valid? */ if (private_key->type != ECC_PRIVATEKEY && private_key->type != ECC_PRIVATEKEY_ONLY) { @@ -3495,8 +3508,10 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) XMEMSET(key, 0, sizeof(ecc_key)); key->state = ECC_STATE_NONE; -#ifdef PLUTON_CRYPTO_ECC +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV) key->devId = devId; +#else + (void)devId; #endif #ifdef WOLFSSL_ATECC508A @@ -3532,8 +3547,6 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) /* handle as async */ ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, key->heap, devId); -#else - (void)devId; #endif return ret; @@ -3641,6 +3654,15 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, return ECC_BAD_ARG_E; } +#ifdef WOLF_CRYPTO_DEV + if (key->devId != INVALID_DEVID) { + err = wc_CryptoDev_EccSign(in, inlen, out, outlen, rng, key); + if (err != NOT_COMPILED_IN) + return err; + err = 0; /* reset error code and try using software */ + } +#endif + #ifdef WOLFSSL_ASYNC_CRYPT err = wc_ecc_alloc_async(key); if (err != 0) @@ -4291,6 +4313,15 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, return ECC_BAD_ARG_E; } +#ifdef WOLF_CRYPTO_DEV + if (key->devId != INVALID_DEVID) { + err = wc_CryptoDev_EccVerify(sig, siglen, hash, hashlen, res, key); + if (err != NOT_COMPILED_IN) + return err; + err = 0; /* reset error code and try using software */ + } +#endif + #ifdef WOLFSSL_ASYNC_CRYPT err = wc_ecc_alloc_async(key); if (err != 0) diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 315388e12..cf181f82f 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -63,6 +63,10 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/caam/caam_doc.pdf \ wolfcrypt/src/port/st/stm32.c +if BUILD_CRYPTODEV +src_libwolfssl_la_SOURCES += wolfcrypt/src/cryptodev.c +endif + if BUILD_CAVIUM src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 807d90e00..835f58209 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -247,8 +247,8 @@ int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) XMEMSET(pkcs7, 0, sizeof(PKCS7)); pkcs7->heap = heap; + pkcs7->devId = devId; - (void)devId; /* silence unused warning */ return 0; } @@ -600,8 +600,7 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) return MEMORY_E; #endif - ret = wc_InitRsaKey(privKey, pkcs7->heap); - + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); if (ret == 0) { idx = 0; ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, @@ -649,7 +648,7 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) return MEMORY_E; #endif - ret = wc_ecc_init_ex(privKey, pkcs7->heap, INVALID_DEVID); + ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); if (ret == 0) { idx = 0; @@ -1309,7 +1308,7 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - ret = wc_InitRsaKey(key, pkcs7->heap); + ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1384,7 +1383,7 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - ret = wc_ecc_init_ex(key, pkcs7->heap, INVALID_DEVID); + ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2124,6 +2123,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) typedef struct WC_PKCS7_KARI { DecodedCert* decoded; /* decoded recip cert */ void* heap; /* user heap, points to PKCS7->heap */ + int devId; /* device ID for HW based private key */ ecc_key* recipKey; /* recip key (pub | priv) */ ecc_key* senderKey; /* sender key (pub | priv) */ byte* senderKeyExport; /* sender ephemeral key DER */ @@ -2249,6 +2249,7 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) kari->direction = direction; kari->heap = pkcs7->heap; + kari->devId = pkcs7->devId; return kari; } @@ -2333,7 +2334,7 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, return BAD_FUNC_ARG; } - ret = wc_ecc_init_ex(kari->recipKey, kari->heap, INVALID_DEVID); + ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId); if (ret != 0) return ret; @@ -2384,7 +2385,7 @@ static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) kari->senderKeyExportSz = kari->decoded->pubKeySize; - ret = wc_ecc_init_ex(kari->senderKey, kari->heap, INVALID_DEVID); + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); if (ret != 0) return ret; @@ -2986,7 +2987,7 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, #endif /* EncryptedKey */ - ret = wc_InitRsaKey(pubKey, 0); + ret = wc_InitRsaKey_ex(pubKey, heap, INVALID_DEVID); if (ret != 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK @@ -3250,7 +3251,7 @@ static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) if (rnd == NULL) return MEMORY_E; - ret = wc_InitRng_ex(rnd, pkcs7->heap, INVALID_DEVID); + ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId); if (ret != 0) { XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); return ret; @@ -3384,7 +3385,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate random content encryption key */ - ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret != 0) return ret; @@ -3712,7 +3713,7 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } #endif - ret = wc_InitRsaKey(privKey, 0); + ret = wc_InitRsaKey_ex(privKey, NULL, INVALID_DEVID); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3735,7 +3736,7 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decrypt encryptedKey */ #ifdef WC_RSA_BLINDING - ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret == 0) { ret = wc_RsaSetRNG(privKey, &rng); } @@ -3823,7 +3824,7 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, return ASN_EXPECT_0_E; /* get sender ephemeral public ECDSA key */ - ret = wc_ecc_init_ex(kari->senderKey, kari->heap, INVALID_DEVID); + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); if (ret != 0) return ret; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 658b5a29c..6108aa583 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -190,6 +190,9 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #include #include +#ifdef WOLF_CRYPTO_DEV + #include +#endif #ifdef NO_INLINE #include #else @@ -237,8 +240,6 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) return BAD_FUNC_ARG; } - (void)devId; - XMEMSET(key, 0, sizeof(RsaKey)); key->type = RSA_TYPE_UNKNOWN; @@ -251,6 +252,12 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) key->rng = NULL; #endif +#ifdef WOLF_CRYPTO_DEV + key->devId = devId; +#else + (void)devId; +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_CERT_GEN XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx)); @@ -263,8 +270,6 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) if (ret != 0) return ret; #endif /* WC_ASYNC_ENABLE_RSA */ -#else - (void)devId; #endif /* WOLFSSL_ASYNC_CRYPT */ ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL); @@ -1619,6 +1624,15 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_DEV + if (key->devId != INVALID_DEVID) { + ret = wc_CryptoDev_Rsa(in, inLen, out, outLen, type, key, rng); + if (ret != NOT_COMPILED_IN) + return ret; + ret = 0; /* reset error code and try using software */ + } +#endif + #ifndef NO_RSA_BOUNDS_CHECK if (type == RSA_PRIVATE_DECRYPT && key->state == RSA_STATE_DECRYPT_EXPTMOD) { diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index b0d2c1998..9b2868be0 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -64,6 +64,10 @@ #include #endif +#ifdef WOLF_CRYPTO_DEV + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) @@ -82,6 +86,10 @@ int wolfCrypt_Init(void) if (initRefCount == 0) { WOLFSSL_ENTER("wolfCrypt_Init"); + #ifdef WOLF_CRYPTO_DEV + wc_CryptoDev_Init(); + #endif + #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_HardwareStart(); if (ret != 0) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 314285f0c..3945d57ce 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -119,6 +119,9 @@ #ifdef WOLFSSL_IMX6_CAAM_BLOB #include #endif +#ifdef WOLF_CRYPTO_DEV + #include +#endif #define WOLFSSL_MISC_INCLUDED #include @@ -341,6 +344,9 @@ int blob_test(void); #endif int misc_test(void); +#ifdef WOLF_CRYPTO_DEV +int cryptodev_test(void); +#endif /* General big buffer size for many tests. */ #define FOURK_BUF 4096 @@ -960,6 +966,13 @@ initDefaultName(); else printf( "misc test passed!\n"); +#ifdef WOLF_CRYPTO_DEV + if ( (ret = cryptodev_test()) != 0) + return err_sys("crypto dev test failed!\n", ret); + else + printf( "crypto dev test passed!\n"); +#endif + #ifdef WOLFSSL_ASYNC_CRYPT wolfAsync_DevClose(&devId); #endif @@ -8297,7 +8310,7 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) * -101 = USER_CRYPTO_ERROR */ if (ret == 0) -#elif defined(WOLFSSL_ASYNC_CRYPT) +#elif defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_DEV) /* async may not require RNG */ if (ret != 0 && ret != MISSING_RNG_E) #elif defined(HAVE_FIPS) || defined(WOLFSSL_ASYNC_CRYPT) || \ @@ -18561,6 +18574,28 @@ int misc_test(void) return 0; } +#ifdef WOLF_CRYPTO_DEV +int cryptodev_test(void) +{ + int ret = 0; + + /* set devId to something other than INVALID_DEVID */ + devId = 1; + +#ifndef NO_RSA + if (ret == 0) + ret = rsa_test(); +#endif +#ifdef HAVE_ECC + if (ret == 0) + ret = ecc_test(); +#endif + + return ret; +} +#endif /* WOLF_CRYPTO_DEV */ + + #undef ERROR_OUT #else diff --git a/wolfssl/wolfcrypt/cryptodev.h b/wolfssl/wolfcrypt/cryptodev.h new file mode 100644 index 000000000..98be93cb4 --- /dev/null +++ b/wolfssl/wolfcrypt/cryptodev.h @@ -0,0 +1,114 @@ +/* cryptodev.h + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 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, see . + */ + +#ifndef _WOLF_CRYPTO_DEV_H_ +#define _WOLF_CRYPTO_DEV_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLF_CRYPTO_DEV + +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif + +/* Crypto Information Structure for callbacks */ +typedef struct wc_CryptoInfo { + int algo_type; /* enum wc_AlgoType */ + struct { + int type; /* enum wc_PkType */ + union { + #ifndef NO_RSA + struct { + const byte* in; + word32 inLen; + byte* out; + word32* outLen; + int type; + RsaKey* key; + WC_RNG* rng; + } rsa; + #endif + #ifdef HAVE_ECC + struct { + ecc_key* private_key; + ecc_key* public_key; + byte* out; + word32* outlen; + } ecdh; + struct { + const byte* in; + word32 inlen; + byte* out; + word32 *outlen; + WC_RNG* rng; + ecc_key* key; + } eccsign; + struct { + const byte* sig; + word32 siglen; + const byte* hash; + word32 hashlen; + int* res; + ecc_key* key; + } eccverify; + #endif + }; + } pk; +} wc_CryptoInfo; + +typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx); + +WOLFSSL_LOCAL void wc_CryptoDev_Init(void); + +WOLFSSL_API int wc_CryptoDev_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); +WOLFSSL_API void wc_CryptoDev_UnRegisterDevice(int devId); + + +#ifndef NO_RSA +WOLFSSL_LOCAL int wc_CryptoDev_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_LOCAL int wc_CryptoDev_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen); + +WOLFSSL_LOCAL int wc_CryptoDev_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoDev_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key); +#endif /* HAVE_ECC */ + +#endif /* WOLF_CRYPTO_DEV */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_CRYPTO_DEV_H_ */ diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index f6fdf219b..7554c2963 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -319,7 +319,7 @@ struct ecc_key { int slot; /* Key Slot Number (-1 unknown) */ byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE]; #endif -#ifdef PLUTON_CRYPTO_ECC +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_DEV) int devId; #endif #ifdef WOLFSSL_ASYNC_CRYPT diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 6e84ed9d5..95221ef1d 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -61,7 +61,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/pkcs12.h \ wolfssl/wolfcrypt/wolfmath.h \ wolfssl/wolfcrypt/sha3.h \ - wolfssl/wolfcrypt/cpuid.h + wolfssl/wolfcrypt/cpuid.h \ + wolfssl/wolfcrypt/cryptodev.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 764e2668e..f0b4deed1 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -133,6 +133,7 @@ typedef struct PKCS7 { int encryptOID; /* key encryption algorithm OID */ int keyWrapOID; /* key wrap algorithm OID */ int keyAgreeOID; /* key agreement algorithm OID */ + int devId; /* device ID for HW based private key */ byte issuerHash[KEYID_SIZE]; /* hash of all alt Names */ byte issuerSn[MAX_SN_SZ]; /* singleCert's serial number */ byte publicKey[MAX_RSA_INT_SZ + MAX_RSA_E_SZ ];/*MAX RSA key size (m + e)*/ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 5cbc76770..ecf41413d 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -121,6 +121,9 @@ struct RsaKey { #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif +#ifdef WOLF_CRYPTO_DEV + int devId; +#endif #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; #ifdef WOLFSSL_CERT_GEN diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 3329b794f..37a982bf8 100755 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -102,7 +102,7 @@ (defined(LP64) || defined(_LP64)) /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits * and int uses 32 bits. When using Solaris Studio sparc and __sparc are - * avialable for 32 bit detection but __sparc64__ could be missed. This + * available for 32 bit detection but __sparc64__ could be missed. This * uses LP64 for checking 64 bit CPU arch. */ typedef word64 wolfssl_word; #define WC_64BIT_CPU @@ -201,7 +201,7 @@ /* idea to add global alloc override by Moises Guimaraes */ /* default to libc stuff */ /* XREALLOC is used once in normal math lib, not in fast math lib */ - /* XFREE on some embeded systems doesn't like free(0) so test */ + /* XFREE on some embedded systems doesn't like free(0) so test */ #if defined(HAVE_IO_POOL) WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type); WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type); @@ -496,6 +496,17 @@ MIN_STACK_BUFFER = 8 }; + + /* Algorithm Types */ + enum wc_AlgoType { + WC_ALGO_TYPE_NONE = 0, + WC_ALGO_TYPE_HASH = 1, + WC_ALGO_TYPE_CIPHER = 2, + WC_ALGO_TYPE_PK = 3, + + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_PK + }; + /* hash types */ enum wc_HashType { WC_HASH_TYPE_NONE = 0, @@ -518,7 +529,7 @@ }; /* cipher types */ - enum CipherTypes { + enum wc_CipherType { WC_CIPHER_NONE = 0, WC_CIPHER_AES = 1, WC_CIPHER_AES_CBC = 2, @@ -530,10 +541,25 @@ WC_CIPHER_DES = 8, WC_CIPHER_CHACHA = 9, WC_CIPHER_HC128 = 10, + WC_CIPHER_IDEA = 11, WC_CIPHER_MAX = WC_CIPHER_HC128 }; + /* PK=public key (asymmetric) based algorithms */ + enum wc_PkType { + WC_PK_TYPE_NONE = 0, + WC_PK_TYPE_RSA = 1, + WC_PK_TYPE_DH = 2, + WC_PK_TYPE_ECDH = 3, + WC_PK_TYPE_ECDSA_SIGN = 4, + WC_PK_TYPE_ECDSA_VERIFY = 5, + WC_PK_TYPE_ED25519 = 6, + WC_PK_TYPE_CURVE25519 = 7, + + WC_PK_TYPE_MAX = WC_PK_TYPE_CURVE25519 + }; + /* settings detection for compile vs runtime math incompatibilities */ enum { From 9a75e5cf68f883526b82f8d43d923fd6145845d9 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 23 May 2018 14:48:10 -0700 Subject: [PATCH 2/7] Fixes in PKCS7 for handling hardware based devId and no private key. Fix to handle scenario where `kari->decoded` is allocated, but not initalized (was causing use of unitliaized in `FreeDecodedCert`). Fix to handle hardware base RSA key size. --- tests/api.c | 1 + wolfcrypt/src/pkcs7.c | 76 ++++++++++++++++++++++++++----------------- wolfcrypt/src/rsa.c | 13 +++++++- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/tests/api.c b/tests/api.c index 2c87e39db..b42c48804 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14537,6 +14537,7 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) printf(testingFmt, "wc_PKCS7_EncodeEnvelopedData()"); testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); for (i = 0; i < testSz; i++) { + AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId), 0); AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (testVectors + i)->cert, (word32)(testVectors + i)->certSz), 0); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 835f58209..1f54df3d9 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -259,7 +259,7 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) { int ret = 0; void* heap; - + int devId; if (pkcs7 == NULL || (cert == NULL && certSz != 0)) { return BAD_FUNC_ARG; @@ -270,9 +270,11 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) #else heap = pkcs7->heap; #endif + devId = pkcs7->devId; XMEMSET(pkcs7, 0, sizeof(PKCS7)); pkcs7->heap = heap; + pkcs7->devId = devId; if (cert != NULL && certSz > 0) { #ifdef WOLFSSL_SMALL_STACK @@ -590,9 +592,9 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) RsaKey* privKey = &stack_privKey; #endif - if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || - in == NULL || esd == NULL) + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { return BAD_FUNC_ARG; + } #ifdef WOLFSSL_SMALL_STACK privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -602,11 +604,15 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); if (ret == 0) { - idx = 0; - ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, - pkcs7->privateKeySz); + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } } - if (ret == 0) { ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, sizeof(esd->encContentDigest), @@ -638,9 +644,9 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) ecc_key* privKey = &stack_privKey; #endif - if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || - in == NULL || esd == NULL) + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { return BAD_FUNC_ARG; + } #ifdef WOLFSSL_SMALL_STACK privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -649,13 +655,16 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) #endif ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); - if (ret == 0) { - idx = 0; - ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, - pkcs7->privateKeySz); + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } } - if (ret == 0) { outSz = sizeof(esd->encContentDigest); ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, @@ -1032,9 +1041,9 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || - pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 || - output == NULL || outputSz == 0) + output == NULL || outputSz == 0) { return BAD_FUNC_ARG; + } #ifdef WOLFSSL_SMALL_STACK esd = (ESD*)XMALLOC(sizeof(ESD), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2136,6 +2145,7 @@ typedef struct WC_PKCS7_KARI { word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ + byte decodedInit : 1; /* indicates decoded was intiialized */ } WC_PKCS7_KARI; @@ -2247,6 +2257,7 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) kari->sharedInfo = NULL; kari->sharedInfoSz = 0; kari->direction = direction; + kari->decodedInit = 0; kari->heap = pkcs7->heap; kari->devId = pkcs7->devId; @@ -2264,7 +2275,9 @@ static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) heap = kari->heap; if (kari->decoded) { - FreeDecodedCert(kari->decoded); + if (kari->decodedInit) { + FreeDecodedCert(kari->decoded); + } XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); } if (kari->senderKey) { @@ -2318,12 +2331,9 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, cert == NULL || certSz == 0) return BAD_FUNC_ARG; - if (kari->direction == WC_PKCS7_DECODE && - (key == NULL || keySz == 0)) - return BAD_FUNC_ARG; - /* decode certificate */ InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap); + kari->decodedInit = 1; ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) return ret; @@ -2349,9 +2359,13 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, } /* get recip private key */ else if (kari->direction == WC_PKCS7_DECODE) { - - idx = 0; - ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); + if (key != NULL && keySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); + } + else if (kari->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } if (ret != 0) return ret; @@ -3722,9 +3736,14 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, return ret; } - keyIdx = 0; - ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey, - pkcs7->privateKeySz); + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + keyIdx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } if (ret != 0) { WOLFSSL_MSG("Failed to decode RSA private key"); #ifdef WOLFSSL_SMALL_STACK @@ -4381,8 +4400,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, int explicitOctet; if (pkcs7 == NULL || pkcs7->singleCert == NULL || - pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL || - pkcs7->privateKeySz == 0) + pkcs7->singleCertSz == 0) return BAD_FUNC_ARG; if (pkiMsg == NULL || pkiMsgSz == 0 || diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 6108aa583..18045d47b 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -2282,10 +2282,21 @@ int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen, int wc_RsaEncryptSize(RsaKey* key) { + int ret; + if (key == NULL) { return BAD_FUNC_ARG; } - return mp_unsigned_bin_size(&key->n); + + ret = mp_unsigned_bin_size(&key->n); + +#ifdef WOLF_CRYPTO_DEV + if (ret == 0 && key->devId != INVALID_DEVID) { + ret = 2048/8; /* hardware handles, use 2048-bit as default */ + } +#endif + + return ret; } From 72d168028e81c7041ca00325656fac8b1fc46b4d Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 23 May 2018 15:29:33 -0700 Subject: [PATCH 3/7] Fixes to better handle PKCS7 error cases. --- tests/api.c | 4 +++- wolfcrypt/src/pkcs7.c | 21 ++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/api.c b/tests/api.c index b42c48804..9d89de83c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14535,9 +14535,11 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) }; /* END pkcs7EnvelopedVector */ printf(testingFmt, "wc_PKCS7_EncodeEnvelopedData()"); + + AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId), 0); + testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); for (i = 0; i < testSz; i++) { - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId), 0); AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (testVectors + i)->cert, (word32)(testVectors + i)->certSz), 0); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 1f54df3d9..2da4c5e15 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2145,7 +2145,9 @@ typedef struct WC_PKCS7_KARI { word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ - byte decodedInit : 1; /* indicates decoded was intiialized */ + byte decodedInit : 1; /* indicates decoded was initialized */ + byte recipKeyInit : 1; /* indicates recipKey was initialized */ + byte senderKeyInit : 1; /* indicates senderKey was initialized */ } WC_PKCS7_KARI; @@ -2258,6 +2260,8 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) kari->sharedInfoSz = 0; kari->direction = direction; kari->decodedInit = 0; + kari->recipKeyInit = 0; + kari->senderKeyInit = 0; kari->heap = pkcs7->heap; kari->devId = pkcs7->devId; @@ -2275,17 +2279,18 @@ static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) heap = kari->heap; if (kari->decoded) { - if (kari->decodedInit) { + if (kari->decodedInit) FreeDecodedCert(kari->decoded); - } XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); } if (kari->senderKey) { - wc_ecc_free(kari->senderKey); + if (kari->senderKeyInit) + wc_ecc_free(kari->senderKey); XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7); } if (kari->recipKey) { - wc_ecc_free(kari->recipKey); + if (kari->recipKeyInit) + wc_ecc_free(kari->recipKey); XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); } if (kari->senderKeyExport) { @@ -2348,6 +2353,8 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, if (ret != 0) return ret; + kari->recipKeyInit = 1; + /* get recip public key */ if (kari->direction == WC_PKCS7_ENCODE) { @@ -2403,6 +2410,8 @@ static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) if (ret != 0) return ret; + kari->senderKeyInit = 1; + ret = wc_ecc_make_key_ex(rng, kari->recipKey->dp->size, kari->senderKey, kari->recipKey->dp->id); if (ret != 0) @@ -3847,6 +3856,8 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, if (ret != 0) return ret; + kari->senderKeyInit = 1; + /* length-1 for unused bits counter */ ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey); if (ret != 0) From 6f221ff75ceca49c260a0e0d2d46dd956126b357 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 23 May 2018 16:21:49 -0700 Subject: [PATCH 4/7] Fix possible leak in PKCS for failure case with small stack enabled. --- wolfcrypt/src/pkcs7.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 2da4c5e15..4f7e6bf0c 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -4186,6 +4186,9 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, pkcs7->privateKeySz); if (ret != 0) { wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, NULL, DYNAMIC_TYPE_PKCS7); + #endif return ret; } From fc482235b0bebf4285ef09bf631c477ebf4b6fe0 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 30 May 2018 09:11:44 -0700 Subject: [PATCH 5/7] Improved the CryptoDev test to include example callback with context. --- wolfcrypt/test/test.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3945d57ce..5c442435e 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18575,12 +18575,110 @@ int misc_test(void) } #ifdef WOLF_CRYPTO_DEV + +/* Example custom context for crypto callback */ +typedef struct { + int exampleVar; /* example, not used */ +} myCryptoDevCtx; + + +/* Example crypto dev callback function that calls software version */ +static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int ret = NOT_COMPILED_IN; /* return this to bypass HW and use SW */ + myCryptoDevCtx* myCtx = (myCryptoDevCtx*)ctx; + + if (info == NULL) + return BAD_FUNC_ARG; + + if (info->algo_type == WC_ALGO_TYPE_PK) { + #ifdef DEBUG_WOLFSSL + printf("CryptoDevCb: Pk Type %d\n", info->pk.type); + #endif + + #ifndef NO_RSA + if (info->pk.type == WC_PK_TYPE_RSA) { + /* set devId to invalid, so software is used */ + info->pk.rsa.key->devId = INVALID_DEVID; + + switch (info->pk.rsa.type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + /* perform software based RSA public op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + /* perform software based RSA private op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + } + + /* reset devId */ + info->pk.rsa.key->devId = devIdArg; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { + /* set devId to invalid, so software is used */ + info->pk.eccsign.key->devId = INVALID_DEVID; + + ret = wc_ecc_sign_hash( + info->pk.eccsign.in, info->pk.eccsign.inlen, + info->pk.eccsign.out, info->pk.eccsign.outlen, + info->pk.eccsign.rng, info->pk.eccsign.key); + + /* reset devId */ + info->pk.eccsign.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) { + /* set devId to invalid, so software is used */ + info->pk.eccverify.key->devId = INVALID_DEVID; + + ret = wc_ecc_verify_hash( + info->pk.eccverify.sig, info->pk.eccverify.siglen, + info->pk.eccverify.hash, info->pk.eccverify.hashlen, + info->pk.eccverify.res, info->pk.eccverify.key); + + /* reset devId */ + info->pk.eccverify.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDH) { + /* set devId to invalid, so software is used */ + info->pk.ecdh.private_key->devId = INVALID_DEVID; + + ret = wc_ecc_shared_secret( + info->pk.ecdh.private_key, info->pk.ecdh.public_key, + info->pk.ecdh.out, info->pk.ecdh.outlen); + + /* reset devId */ + info->pk.ecdh.private_key->devId = devIdArg; + } + #endif /* HAVE_ECC */ + } + + (void)myCtx; + + return ret; +} + int cryptodev_test(void) { int ret = 0; + myCryptoDevCtx myCtx; + + /* example data for callback */ + myCtx.exampleVar = 1; /* set devId to something other than INVALID_DEVID */ devId = 1; + ret = wc_CryptoDev_RegisterDevice(devId, myCryptoDevCb, &myCtx); #ifndef NO_RSA if (ret == 0) @@ -18591,6 +18689,9 @@ int cryptodev_test(void) ret = ecc_test(); #endif + /* reset devId */ + devId = INVALID_DEVID; + return ret; } #endif /* WOLF_CRYPTO_DEV */ From d7b560f2aba1629b5dc0bf6190bd19cdfe4b7c96 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 30 May 2018 12:44:55 -0700 Subject: [PATCH 6/7] Fix for scan-build warning about value being stored and not used. Changed the `wc_RsaFunction` API to public. Added ability to expose `wc_RsaDirect` with new define `WC_RSA_DIRECT`. --- wolfcrypt/src/ecc.c | 1 - wolfcrypt/src/rsa.c | 4 ++-- wolfssl/wolfcrypt/rsa.h | 6 +++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index d53847ae7..6bf7a5851 100755 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2802,7 +2802,6 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, err = wc_CryptoDev_Ecdh(private_key, public_key, out, outlen); if (err != NOT_COMPILED_IN) return err; - err = 0; /* reset error code and try using software */ } #endif diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 18045d47b..7d1055172 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -1517,7 +1517,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, } #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ -#ifdef WC_RSA_NO_PADDING +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) /* Function that does the RSA operation directly with no padding. * * in buffer to do operation on @@ -1611,7 +1611,7 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, return ret; } -#endif /* WC_RSA_NO_PADDING */ +#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING */ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index ecf41413d..e2337c77a 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -152,7 +152,7 @@ WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); #endif /* WOLFSSL_XILINX_CRYPT */ -WOLFSSL_LOCAL int wc_RsaFunction(const byte* in, word32 inLen, byte* out, +WOLFSSL_API int wc_RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, @@ -238,9 +238,13 @@ WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, RsaKey* key, int type, enum wc_HashType hash, int mgf, byte* label, word32 lableSz); +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, RsaKey* key, int type, WC_RNG* rng); +#endif + #endif /* HAVE_FIPS*/ + WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, word32*); WOLFSSL_API int wc_RsaExportKey(RsaKey* key, From 33d416a060e2c3a57d829b600c8552e519ac003e Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 30 May 2018 13:23:08 -0700 Subject: [PATCH 7/7] Fix two more scan-build issues with set but not used. --- wolfcrypt/src/ecc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 6bf7a5851..7ecaaeff6 100755 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -3658,7 +3658,6 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, err = wc_CryptoDev_EccSign(in, inlen, out, outlen, rng, key); if (err != NOT_COMPILED_IN) return err; - err = 0; /* reset error code and try using software */ } #endif @@ -4317,7 +4316,6 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, err = wc_CryptoDev_EccVerify(sig, siglen, hash, hashlen, res, key); if (err != NOT_COMPILED_IN) return err; - err = 0; /* reset error code and try using software */ } #endif