From 45bf793b5a3277750d1abf6b812e4da6b3b0005e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 19 Oct 2022 10:10:48 -0600 Subject: [PATCH] SE050 expansion: add RSA support, allow for larger key IDs, get/set key ID from ecc_key/RsaKey, fixes for SE050 hashing, remove XREALLOC dependency, API to store/get binary object, API to erase object, test.c compatibility --- configure.ac | 10 +- wolfcrypt/src/aes.c | 110 +- wolfcrypt/src/asn.c | 5 +- wolfcrypt/src/cmac.c | 15 +- wolfcrypt/src/ecc.c | 65 +- wolfcrypt/src/ed25519.c | 4 +- wolfcrypt/src/port/nxp/README.md | 113 +- wolfcrypt/src/port/nxp/README_SE050.md | 559 +++++++ wolfcrypt/src/port/nxp/se050_port.c | 1872 +++++++++++++++++++++-- wolfcrypt/src/random.c | 2 +- wolfcrypt/src/rsa.c | 120 +- wolfcrypt/src/sha.c | 3 + wolfcrypt/src/wc_port.c | 4 + wolfcrypt/test/test.c | 59 +- wolfssl/wolfcrypt/aes.h | 4 +- wolfssl/wolfcrypt/cmac.h | 3 + wolfssl/wolfcrypt/curve25519.h | 3 +- wolfssl/wolfcrypt/des3.h | 5 + wolfssl/wolfcrypt/ecc.h | 13 +- wolfssl/wolfcrypt/ed25519.h | 3 +- wolfssl/wolfcrypt/include.am | 5 +- wolfssl/wolfcrypt/port/nxp/se050_port.h | 101 +- wolfssl/wolfcrypt/rsa.h | 10 +- 23 files changed, 2708 insertions(+), 380 deletions(-) create mode 100644 wolfcrypt/src/port/nxp/README_SE050.md diff --git a/configure.ac b/configure.ac index d401392e8..b7abe026b 100644 --- a/configure.ac +++ b/configure.ac @@ -1916,7 +1916,7 @@ AC_ARG_WITH([cryptoauthlib], ENABLED_SE050="no" trylibse050dir="" AC_ARG_WITH([se050], - [AS_HELP_STRING([--with-se050=PATH],[PATH to SE050 install (default /usr/local/lib/)])], + [AS_HELP_STRING([--with-se050=PATH],[PATH to SE050 install (default /usr/local)])], [ AC_MSG_CHECKING([for SE050]) @@ -1928,9 +1928,11 @@ AC_ARG_WITH([se050], trylibse050dir=$withval fi if test "x$withval" = "xyes" ; then - trylibse050dir="/usr/local/lib/" + trylibse050dir="/usr/local" fi + LDFLAGS="$LDFLAGS -L$trylibse050dir/lib" LDFLAGS="$LDFLAGS -L$trylibse050dir/build/sss" + CPPFLAGS="$CPPFLAGS -I$trylibse050dir/include/se05x" CPPFLAGS="$CPPFLAGS -I$trylibse050dir/build" CPPFLAGS="$CPPFLAGS -I$trylibse050dir/sss/inc" CPPFLAGS="$CPPFLAGS -I$trylibse050dir/sss/ex/inc" @@ -1960,7 +1962,7 @@ AC_ARG_WITH([se050], fi # Requires AES direct - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB" # Does not support SHA2-512 224/256 AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA512_224 -DWOLFSSL_NOSHA512_256" @@ -7686,7 +7688,7 @@ AS_IF([test "x$ENABLED_STRONGSWAN" = "xyes"], AS_IF([test "x$ENABLED_OPENLDAP" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SIGNER_DER_CERT"]) -if test "$ENABLED_ED25519_STREAM" != "no" +if test "$ENABLED_ED25519_STREAM" != "no" && test "$ENABLED_SE050" != "yes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ED25519_STREAMING_VERIFY" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ED25519_STREAMING_VERIFY" diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 8cf8d7184..a87da5282 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -895,30 +895,6 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #elif defined(WOLFSSL_DEVCRYPTO_AES) /* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */ -#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) - static WARN_UNUSED_RESULT int AES_ECB_encrypt( - Aes* aes, const byte* inBlock, byte* outBlock, int sz) - { - return se050_aes_crypt(aes, inBlock, outBlock, sz, AES_ENCRYPTION, - kAlgorithm_SSS_AES_ECB); - } - static WARN_UNUSED_RESULT int AES_ECB_decrypt( - Aes* aes, const byte* inBlock, byte* outBlock, int sz) - { - return se050_aes_crypt(aes, inBlock, outBlock, sz, AES_DECRYPTION, - kAlgorithm_SSS_AES_ECB); - } - static WARN_UNUSED_RESULT int wc_AesEncrypt( - Aes* aes, const byte* inBlock, byte* outBlock) - { - return AES_ECB_encrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); - } - static WARN_UNUSED_RESULT int wc_AesDecrypt( - Aes* aes, const byte* inBlock, byte* outBlock) - { - return AES_ECB_decrypt(aes, inBlock, outBlock, AES_BLOCK_SIZE); - } - #elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) #include "hal_data.h" @@ -1853,6 +1829,13 @@ static WARN_UNUSED_RESULT int wc_AesEncrypt( } #endif +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + if (aes->useSWCrypt == 0) { + return se050_aes_crypt(aes, inBlock, outBlock, AES_BLOCK_SIZE, + AES_ENCRYPTION, kAlgorithm_SSS_AES_ECB); + } +#endif + /* * map byte array block to cipher state * and add initial round key: @@ -2185,6 +2168,12 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( return 0; } #endif +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + if (aes->useSWCrypt == 0) { + return se050_aes_crypt(aes, inBlock, outBlock, AES_BLOCK_SIZE, + AES_DECRYPTION, kAlgorithm_SSS_AES_ECB); + } +#endif /* * map byte array block to cipher state @@ -2644,35 +2633,6 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( return wc_AesSetKey(aes, userKey, keylen, iv, dir); } -#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) - { - int ret; - - if (aes == NULL || (keylen != 16 && keylen != 24 && keylen != 32)) { - return BAD_FUNC_ARG; - } - - aes->ctxInitDone = 0; - #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) || \ - defined(WOLFSSL_AES_OFB) - aes->left = 0; - #endif - - ret = se050_aes_set_key(aes, userKey, keylen, iv, dir); - if (ret == 0) { - ret = wc_AesSetIV(aes, iv); - } - return ret; - } - - int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, - const byte* iv, int dir) - { - return wc_AesSetKey(aes, userKey, keylen, iv, dir); - } - #elif defined(WOLFSSL_NRF51_AES) int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) @@ -2964,6 +2924,18 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( ((psa_algorithm_t)0), dir); #endif +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + /* wolfSSL HostCrypto in SE05x SDK can request to use SW crypto + * instead of SE05x crypto by setting useSWCrypt */ + if (aes->useSWCrypt == 0) { + ret = se050_aes_set_key(aes, userKey, keylen, iv, dir); + if (ret == 0) { + ret = wc_AesSetIV(aes, iv); + } + return ret; + } +#endif + rk = aes->key; XMEMCPY(rk, userKey, keylen); #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \ @@ -3973,18 +3945,6 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #elif defined(WOLFSSL_DEVCRYPTO_CBC) /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ -#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) - int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) - { - return se050_aes_crypt(aes, in, out, sz, AES_ENCRYPTION, - kAlgorithm_SSS_AES_CBC); - } - int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) - { - return se050_aes_crypt(aes, in, out, sz, AES_DECRYPTION, - kAlgorithm_SSS_AES_CBC); - } - #elif defined(WOLFSSL_SILABS_SE_ACCEL) /* implemented in wolfcrypt/src/port/silabs/silabs_hash.c */ @@ -4051,6 +4011,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv) } #endif /* WOLFSSL_ASYNC_CRYPT */ + #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + /* Implemented in wolfcrypt/src/port/nxp/se050_port.c */ + if (aes->useSWCrypt == 0) { + return se050_aes_crypt(aes, in, out, sz, AES_ENCRYPTION, + kAlgorithm_SSS_AES_CBC); + } + #endif + #ifdef WOLFSSL_AESNI if (haveAESNI) { #ifdef DEBUG_AESNI @@ -4176,6 +4144,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv) } #endif + #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + /* Implemented in wolfcrypt/src/port/nxp/se050_port.c */ + if (aes->useSWCrypt == 0) { + return se050_aes_crypt(aes, in, out, sz, AES_DECRYPTION, + kAlgorithm_SSS_AES_CBC); + } + #endif + #ifdef WOLFSSL_AESNI if (haveAESNI) { #ifdef DEBUG_AESNI @@ -10804,7 +10780,9 @@ void wc_AesFree(Aes* aes) #endif #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) - se050_aes_free(aes); + if (aes->useSWCrypt == 0) { + se050_aes_free(aes); + } #endif #if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e8018ea0e..738b50f3a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -6305,7 +6305,7 @@ static int DecodeRsaPssParams(const byte* params, word32 sz, #ifndef HAVE_USER_RSA #if defined(WOLFSSL_ASN_TEMPLATE) || (!defined(NO_CERTS) && \ (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ - defined(WOLFSSL_KCAPI_RSA))) + defined(WOLFSSL_KCAPI_RSA) || defined(WOLFSSL_SE050))) /* Byte offset of numbers in RSA key. */ size_t rsaIntOffset[] = { OFFSETOF(RsaKey, n), @@ -24202,7 +24202,8 @@ int wc_RsaKeyToPublicDer_ex(RsaKey* key, byte* output, word32 inLen, ((OPENSSL_EXTRA || WOLFSSL_KEY_GEN) && !HAVE_USER_RSA))) */ #if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ - defined(WOLFSSL_KCAPI_RSA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) + defined(WOLFSSL_KCAPI_RSA) || defined(WOLFSSL_SE050)) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) /* Encode private RSA key in DER format. * diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 9338c146c..2a2ebf681 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -97,6 +97,9 @@ int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz, int type, void* unused, void* heap, int devId) { int ret; +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + byte useSW = 0; +#endif (void)unused; (void)heap; @@ -105,6 +108,10 @@ int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz, return BAD_FUNC_ARG; } +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + /* save if we should use SW crypt, restore after memset */ + useSW = cmac->useSWCrypt; +#endif XMEMSET(cmac, 0, sizeof(Cmac)); #ifdef WOLF_CRYPTO_CB @@ -126,6 +133,13 @@ int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz, return BAD_FUNC_ARG; } +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + cmac->useSWCrypt = useSW; + if (cmac->useSWCrypt == 1) { + cmac->aes.useSWCrypt = 1; + } +#endif + ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION); if (ret == 0) { byte l[AES_BLOCK_SIZE]; @@ -328,5 +342,4 @@ int wc_AesCmacVerify(const byte* check, word32 checkSz, return ret; } - #endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 3a92563ee..2f9c1bc6c 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -5748,7 +5748,8 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) #endif #ifdef WOLFSSL_SE050 - key->keyId = -1; + key->keyId = 0; + key->keyIdSet = 0; #endif #ifdef WOLFSSL_CHECK_MEM_ZERO @@ -5964,7 +5965,7 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, } (void)rng; #elif defined(WOLFSSL_SE050) - err = se050_ecc_sign_hash_ex(in, inlen, out, outlen, key); + err = se050_ecc_sign_hash_ex(in, inlen, r, s, out, outlen, key); if (err != MP_OKAY) { return err; } @@ -6040,7 +6041,8 @@ error_out: } #endif /* HW-specific #if-#elif chain */ - /* Load R and S */ + #ifndef WOLFSSL_SE050 + /* Load R and S, SE050 does this in port layer */ err = mp_read_unsigned_bin(r, &out[0], keysize); if (err != MP_OKAY) { return err; @@ -6049,6 +6051,7 @@ error_out: if (err != MP_OKAY) { return err; } + #endif /* Check for zeros */ if (mp_iszero(r) || mp_iszero(s)) { @@ -8044,12 +8047,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, byte sigRS[ECC_MAX_CRYPTO_HW_SIZE * 2]; #elif defined(WOLFSSL_KCAPI_ECC) byte sigRS[MAX_ECC_BYTES*2]; -#elif defined(WOLFSSL_SE050) - byte sigRS[ECC_MAX_CRYPTO_HW_SIZE * 2]; #elif defined(WOLFSSL_XILINX_CRYPT_VERSAL) byte sigRS[ECC_MAX_CRYPTO_HW_SIZE * 2]; byte hashcopy[ECC_MAX_CRYPTO_HW_SIZE] = {0}; -#elif !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) +#elif (!defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC)) && \ + !defined(WOLFSSL_SE050) int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; #ifdef WOLFSSL_NO_MALLOC @@ -8115,7 +8117,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, defined(WOLFSSL_KCAPI_ECC) || defined(WOLFSSL_SE050) || \ defined(WOLFSSL_XILINX_CRYPT_VERSAL) - /* Extract R and S with front zero padding (if required) */ +#ifndef WOLFSSL_SE050 + /* Extract R and S with front zero padding (if required), + * SE050 does this in port layer */ XMEMSET(sigRS, 0, sizeof(sigRS)); err = mp_to_unsigned_bin(r, sigRS + (keySz - mp_unsigned_bin_size(r))); @@ -8127,6 +8131,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, if (err != MP_OKAY) { return err; } +#endif /* WOLFSSL_SE050 */ #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res); @@ -8171,7 +8176,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, *res = 1; } #elif defined(WOLFSSL_SE050) - err = se050_ecc_verify_hash_ex(hash, hashlen, sigRS, keySz * 2, key, res); + err = se050_ecc_verify_hash_ex(hash, hashlen, r, s, key, res); #elif defined(WOLFSSL_XILINX_CRYPT_VERSAL) if (hashlen > sizeof(hashcopy)) return ECC_BAD_ARG_E; @@ -10043,6 +10048,12 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #elif defined(WOLFSSL_SILABS_SE_ACCEL) if (err == MP_OKAY) err = silabs_ecc_import(key, keysize); +#elif defined(WOLFSSL_SE050) + if (err == MP_OKAY) { + /* reset key ID, in case used before */ + key->keyId = 0; + key->keyIdSet = 0; + } #elif defined(WOLFSSL_XILINX_CRYPT_VERSAL) #ifndef HAVE_COMP_KEY if (err == MP_OKAY) { @@ -14519,6 +14530,44 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #endif /* HAVE_X963_KDF */ +#ifdef WOLFSSL_SE050 +/* Use specified hardware key ID with ecc_key operations. Unlike devId, + * keyId is a word32, can be used for key IDs larger than an int. + * + * key initialized ecc_key struct + * keyId hardware key ID which stores ECC key + * flags optional flags, currently unused + * + * Return 0 on success, negative on error */ +int wc_ecc_use_key_id(ecc_key* key, word32 keyId, word32 flags) +{ + (void)flags; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + return se050_ecc_use_key_id(key, keyId); +} + +/* Get hardware key ID associated with this ecc_key structure. + * + * key initialized ecc_key struct + * keyId [OUT] output for key ID associated with this structure + * + * Returns 0 on success, negative on error. + */ +int wc_ecc_get_key_id(ecc_key* key, word32* keyId) +{ + if (key == NULL || keyId == NULL) { + return BAD_FUNC_ARG; + } + + return se050_ecc_get_key_id(key, keyId); +} +#endif /* WOLFSSL_SE050 */ + + #ifdef WC_ECC_NONBLOCK /* Enable ECC support for non-blocking operations */ int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx) diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 42fae4ff5..cfdaa079f 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -697,7 +697,7 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, } #endif /* WOLFSSL_SE050 */ -#ifdef WOLFSSL_ED25519_STREAMING_VERIFY +#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && !defined(WOLFSSL_SE050) int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, byte type, const byte* context, byte contextLen) { @@ -717,7 +717,7 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, key, &key->sha); } -#endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ +#endif /* WOLFSSL_ED25519_STREAMING_VERIFY && !WOLFSSL_SE050 */ /* sig is array of bytes containing the signature diff --git a/wolfcrypt/src/port/nxp/README.md b/wolfcrypt/src/port/nxp/README.md index 26fab2e35..a2820a4dc 100644 --- a/wolfcrypt/src/port/nxp/README.md +++ b/wolfcrypt/src/port/nxp/README.md @@ -1,116 +1,11 @@ -# NXP Ports +# wolfSSL NXP Hardware Acceleration Ports -Support for the NXP DCP, KSDK and SE050 hardware acceleration boards. +wolfSSL supports hardware acceleration on NXP DCP, LTC (KSDK), and SE050. ## NXP SE050 -Support for the SE050 on-board crypto hardware acceleration for symmetric AES, SHA1/SHA256/SHA384/SHA512, ECC (including ed25519) and RNG. - -## SE050 Acceleration - -For details about SE050 HW acceleration, see [NXP's SE050 page](https://www.nxp.com/products/security-and-authentication/authentication/edgelock-se050-plug-trust-secure-element-family-enhanced-iot-security-with-maximum-flexibility:SE050). - -## Building simw-top - -The code required to communicate with the SE050 is the `EdgeLock SE05x Plug & Trust Middleware (03.03.00)`, which can be found here [link](https://www.nxp.com/products/security-and-authentication/authentication/edgelock-se050-plug-trust-secure-element-family-enhanced-iot-security-with-maximum-flexibility:SE050?tab=Design_Tools_Tab) (An NXP account is required to download). - -Follow the build instruction in AN12570 (EdgeLockTM SE05x Quick start guide with Raspberry Pi) [here](https://www.nxp.com/docs/en/application-note/AN12570.pdf). - -In summary here are the steps for building: - -``` -# from simw-top directory -mkdir build -cd build -ccmake .. -# Change: -# `Host OS` to `Raspbian` -# `Host Crypto` to `None` -# `SMCOM` to `T1oI2C` -c # to configure -q -make -``` - -## Building wolfSSL - -To enable support run: - -``sh -./configure --with-se050=PATH -make -`` - -Where `PATH` is the directory location of `simw-top`. -Example: `./configure --with-se050=/home/pi/simw-top CFLAGS="-DWOLFSSL_SE050_INIT"` - -To enable AES Cipher support use `WOLFSSL_SE050_CRYPT` -To enable SHA-1 and SHA-2 support use `WOLFSSL_SE050_HASH` - -## Building Examples - -Confirm that you are able to run the examples from the directory: - -``sh -/simw-top_build/raspbian_native_se050_t1oi2c/bin/ -`` - -Modify one of those examples in order to tie into wolfSSL. The `./se05x_Minimal` is the easiest one to modify. - -Open the `simw-top/demos/se05x/se05x_Minimal` directory and edit `se05x_Minimal.c`. Add these headers to source file: - -``c -#include -#include -#include -`` - -If you would like to run our wolfcrypt test or benchmark tool, add: `#include "test.h"` or `#include benchmark.h`. - -Below is the code that was replaced in `ex_sss_entry()` to run the wolfcrypt test: - -``c -sss_status_t status = kStatus_SSS_Success; -int ret; - -sss_session_t *pSession2 = (sss_session_t *)&pCtx->session; -sss_key_store_t *pHostSession = (sss_key_store_t *)&pCtx->host_ks; - -LOG_I("running setconfig"); -ret = wc_se050_set_config(pSession2, pHostSession); -if (ret != 0) { - return kStatus_SSS_Fail; -} -LOG_I("ran setconfig correctly"); -wolfcrypt_test(NULL); - -LOG_I("ran wolfcrypt test"); -return status; -`` - -Note: `wolfcrypt_test(NULL);` can be replaced with `benchmark_test();` - -The two variables used in `wc_se050_set_config` are session and key store variables that are required to reference parts of the hardware. - -The Makefile needs to be edited. At the top of the Makefile, the base wolfssl directory needs to be added to `INCLUDE_FLAGS`. - -Next, Inside `CFLAGS`, the `se05x_Minimal` directory needs to be added so that test.c and benchmark.c are included. - -Finally, underneath 'all', test.c, test.h, benchmark.c and benchmark.h need to be added, along with `-L[wolfssl directory] -lwolfssl` at the end of the line. - -### Wolfcrypt Test - -To run the wolfcrypt test, two files, `test.h` and `test.c` need to be added to the `./se05x_Minimal` directory. These files can be found inside of `/wolfcrypt/test`. -Make sure `NO_MAIN_DRIVER` is defined to avoid `int main()` conflicts. Either in the Makefile or modify test.h to define it. - -You should be able to run `wolfcrypt_test()` now. - -### wolfCrypt Benchmark - -To run the benchmark, both `benchmark.c` and `benchmark.h` need to be copied from wolfcrypt/benchmark to the `./se05x_Minimal` directory. -In addition, the entire `./certs` directory will need to copied into the directory. -Make sure `NO_MAIN_DRIVER` is defined to avoid `int main()` conflicts. Either in the Makefile or modify test.h to define it. -Now you can run `benchmark_test()`. +For details on wolfSSL integration with NXP SE050, +see [README_SE050.md](./README_SE050.md). ## Support diff --git a/wolfcrypt/src/port/nxp/README_SE050.md b/wolfcrypt/src/port/nxp/README_SE050.md new file mode 100644 index 000000000..b236f3b8e --- /dev/null +++ b/wolfcrypt/src/port/nxp/README_SE050.md @@ -0,0 +1,559 @@ +# wolfSSL NXP SE050 Support + +wolfSSL includes support for the NXP SE050 Plug & Trust Secure Element. + +For details about the NXP SE050, see [NXP's SE050 page](https://www.nxp.com/products/security-and-authentication/authentication/edgelock-se050-plug-trust-secure-element-family-enhanced-iot-security-with-maximum-flexibility:SE050). + +## SE050 Acceleration + +wolfSSL supports the following hardware acceleration with SE050: + +- TRNG +- AES (128, 192, 256) encrypt/decrypt +- SHA-1, SHA2-224, SHA2-256, SHA2-384, SHA2-512 +- ECC support and key generation (NIST 192-521 bit, Brainpool, Koblitz) + * ECDSA sign/verify and key generation + * ECDH shared secret generation +- Ed25519 sign/verify and key generation (Twisted Edwards) +- Curve25519 shared secret and key generation +- RSA sign/verify/encrypt/decrypt and key generation (up to 4096-bit) + +## Building SE05x Plug & Trust Middleware (simw-top) + +wolfSSL uses the "EdgeLock SE05x Plug & Trust Middleware" to interface with +SE050. This can be downloaded from the NXP website [here](https://www.nxp.com/products/security-and-authentication/authentication/edgelock-se050-plug-trust-secure-element-family-enhanced-iot-security-with-high-flexibility:SE050#design-resources). +An free NXP account is required to download the middleware. + +wolfSSL last tested with SE05x middleware version 04.02.00. + +Instructions for building will vary on target platform and host operating +system. A Raspberry Pi with an NXP EdgeLock SE050 Development Kit can be used +to easily set up and test the SE050. For build instructions on this combination, +follow the AN12570 application note (EdgeLock SE05x Quick start guide with +Raspberry Pi, [here](https://www.nxp.com/docs/en/application-note/AN12570.pdf). + +Summarizing the build steps for Raspberry Pi: + +```sh +$ cd ~ +$ mkdir se_mw +$ unzip SE-PLUG-TRUST-MW.zip -d se_mw +$ cd se_mw/simw-top/scripts +$ python create_cmake_projects.py rpi +$ cd ~/se_mw/simw-top_build/raspbian_native_se050_t1oi2c +$ ccmake . +# Make sure the following are set: +# `Host OS` to `Raspbian` +# `Host Crypto` to `None` (see HostCrypto section below) +# `SMCOM` to `T1oI2C` +$ c # to configure +$ g # to generate +$ q +$ cmake --build . +$ sudo make install +``` + +This will also compile several demo apps which can be run if wanted, ie: + +```sh +$ cd ~/se_mw/simw-top_build/raspbian_native_se050_t1oi2c/bin +$ ./ex_ecc # (or, ./se05x_GetInfo, etc) +``` + +Running `sudo make install` will install SE050 library and header files to: + + /usr/local/lib + /usr/local/include/se05x + +### Customizing SE05x Middleware + +The SE05x Middleware can be configured to use a custom `fsl_sss_ftr.h` header +file when **`SSS_USE_FTR_FILE`** is defined when compiling the SDK. + +When wolfSSL tested SE050 integration on an embedded target, `fsl_sss_ftr.h`: + +- Enabled SE050 variant C (`SSS_HAVE_APPLET_SE05X_C`) +- Enabled SE05X applet version 03 for SE050 (`SSS_HAVE_SE05X_VER_03_XX`) +- Enabled wolfSSL HostCrypto support (`SSS_HAVE_HOSTCRYPTO_WOLFSSL`) +- Disabled mbedTLS alt API (`SSS_HAVE_MBEDTLS_ALT_NONE`) +- Enabled SSS layer for SCP03 (`SSS_HAVE_SCP_SCP03_SSS`) +- Enabled Platform SCP03 (`SSS_HAVE_SE05X_AUTH_PLATFSCP03`) +- Set default SCP03 ENC/MAC/DEK keys to match variant in use +- Algorithm selection left same as default configuration + +## Building wolfSSL + +To compile wolfSSL with SE050 support using Autoconf/configure: + +```sh +$ cd wolfssl-X.X.X +$ ./configure --with-se050 +OR +$ ./configure --with-se050=PATH +$ make +``` + +If no installation path is provided to `--with-se05x`, wolfSSL will use the +default installation locations above. + +If the SE05x middleware libraries have been linked against OpenSSL (on Linux), +and you run into compiler errors in wolfSSL due to conflicts with the wolfSSL +compatibility layer headers when compiling wolfSSL's examples and test apps, +you can compile and install only the wolfSSL library proper using: + +```sh +$ cd wolfssl-X.X.X +$ ./configure --with-se050 +$ make src/libwolfssl.la +$ sudo make install-binPROGRAMS +$ sudo make install-nobase_includeHEADERS +``` + +### wolfSSL Key Generation Inside SE050 + +wolfSSL can generate RSA and ECC keys inside the SE050. To include that support, +wolfSSL should be configured with `--enable-keygen` or `-DWOLFSSL_KEY_GEN`. + +```sh +$ ./configure --with-se0500 --enable-keygen +``` + +### wolfSSL HostCrypto support for SCP03 Authentication + +wolfSSL can be used on the host side (HostCrypto) for secure SCP03 +authentication, in place of OpenSSL or mbedTLS. See the HostCrypto section +below. To support SCP03, wolfSSL also needs to be compiled with CMAC support: + +``` +$ cd wolfssl-X.X.X +$ ./configure --with-se050 --enable-keygen --enable-cmac +``` + +To disable SCP03 and use a non-authenticated I2C connection, wolfSSL was using +the following define set in `fsl_sss_ftr.h`, with other defines left to the +defaults: + +```c +#define SSS_HAVE_APPLET_SE05X_C 1 +#define SSS_HAVE_SE05X_VER_03_XX 1 +#define SSS_HAVE_HOSTCRYPTO_NONE 1 +#define SSS_HAVE_MBEDTLS_ALT_NONE 1 +#define SSS_HAVE_SCP_NONE 1 +#define SSS_HAVE_SCP_SCP03_SSS 0 +#define SSS_HAVE_SCP_SCP03_HOSTCRYPTO 0 +#define SSS_HAVE_SE05X_AUTH_NONE 1 +#define SSS_HAVE_SE05X_AUTH_PLATFSCP03 0 +``` + +To enable SCP03 authentication, wolfSSL was using the following defines: + +```c +#define SSS_HAVE_APPLET_SE05X_C 1 +#define SSS_HAVE_SE05X_VER_03_XX 1 +#define SSS_HAVE_HOSTCRYPTO_WOLFSSL 1 +#define SSS_HAVE_HOSTCRYPTO_NONE 0 +#define SSS_HAVE_MBEDTLS_ALT_NONE 1 +#define SSS_HAVE_SCP_NONE 0 +#define SSS_HAVE_SCP_SCP03_SSS 1 +#define SSS_HAVE_SCP_SCP03_HOSTCRYPTO 0 +#define SSS_HAVE_SE05X_AUTH_NONE 0 +#define SSS_HAVE_SE05X_AUTH_PLATFSCP03 1 +``` + +Default ENC, MAC, and DEK keys for SCP03 should be set by defining the +following values. Thes are the default keys wolfSSL used for the SE50C2 +variant (OEF OID: A201). The variant can be seen by running the +`se05x_GetInfo` sample application. + +```c +#define EX_SSS_AUTH_SE05X_KEY_ENC SSS_AUTH_SE050C2_KEY_ENC +#define EX_SSS_AUTH_SE05X_KEY_MAC SSS_AUTH_SE050C2_KEY_MAC +#define EX_SSS_AUTH_SE05X_KEY_DEK SSS_AUTH_SE050C2_KEY_DEK +``` + +Default SCP03 keys are located in the following middleware file: + +```sh +/simw-top/sss/ex/inc/ex_sss_tp_scp03_keys.h +``` + +### wolfSSL SE050 Build Customization + +There are several preprocessor defines that can control wolfSSL's SE050 +integration behavior, including: + +**`WOLFSSL_SE050_INIT`** + +wolfSSL will initialize the SE050 internally. When this is used, developers +also need to define `SE050_DEFAULT_PORT`. See wolfSSL library initialization +below. + +**`SE050_DEFAULT_PORT`** + +Mentinoed above, this should be defined to match the mount location of the +SE050 if on Linux. Or defined to **NULL** for embedded targets. + +**`SE050_KEYID_START`** + +When generating keys inside SE050, wolfSSL will automatically pick a key ID +value based on an incrementing counter past the value defined by this define. + +If not defined, this value will default to **100**. + +**`WOLFSSL_SE050_FACTORY_RESET`** + +When defined, calls to `wolfSSL_Init()` or `wolfCrypt_Init()` will factory +reset the SE050 board by calling `ex_sss_boot_factory_reset()` internally. + +This will erase all user-provisioned key and credential material, leaving only +the NXP pre-provisioned credentials in place. + +**`WOLFSSL_SE050_HASH`** + +wolfSSL supports offloading hash operations (SHA-1, SHA2-224, SHA2-256, +SHA2-384, SHA2-512) to the SE050. This is MUCH slower than using wolfCrypt +software cryptography due to the I2C communication channel. This support is +disabled by default unless this define explicitly enables it. + +**`WOLFSSL_SE050_CRYPT`** + +wolfSSL supports offloading symmetric crypto operations (AES-ECB/CBC) to the +SE050. Also due to the I2C communication channel, this is MUCH slower than using +wolfCrypt software crypto. This support is disabled by default unless this +define explicitly enables it. + +**`WOLFSSL_SE050_NO_TRNG`** + +By default when `WOLFSSL_SE050` is defined, wolfSSL will try to use the TRNG +on the SE050 device as a TRNG for seeding wolfCrypt's PRNG/DRBG. To disable +the use of the SE050 TRNG inside wolfCrypt and instead fall back to the system +default, this can be defined. This might be used for example when working on +a Raspberry Pi with SE05x EdgeLock dev kit. If `WOLFSSL_SE050_NO_TRNG` is +defined, wolfCrypt will instead fall back to using `/dev/random` and +`/dev/urandom` on the Raspberry Pi. + +## wolfSSL HostCrypto Support + +The NXP SE05x Plug & Trust Middleware by default can use either OpenSSL or +mbedTLS has a HostCrypto provider to support secure SCP03 authenticated +communication between the host and SE050. The HostCrypto provider is used +for AES CMAC operations on the host side to set up and authenticate the SE050. +If SCP03 is not used, a plaintext communication channel can be used. + +wolfSSL has implemented a HostCrypto layer that can integrate into the +SE05x Middleware to provide an alternative crypto provider to OpenSSL or +mbedTLS. To learn more about access to this layer, please contact wolfSSL +at support@wolfssl.com. + +Once a SE05x Middleware source tree has been updated with wolfSSL HostCrypto +support, wolfSSL support can be enabled by defining +`SSS_HAVE_HOSTCRYPTO_WOLFSSL` in `fsl_sss_ftr.h`. In this scenario, all of the +following must be defined to 0 in `fsl_sss_ftr.h`: + +```c +#define SSS_HAVE_HOSTCRYPTO_WOLFSSL 1 +#define SSS_HAVE_HOSTCRYPTO_MBEDTLS 0 +#define SSS_HAVE_HOSTCRYPTO_OPENSSL 0 +#define SSS_HAVE_HOSTCRYPTO_USER 0 +#define SSS_HAVE_HOSTCRYPTO_NONE 0 +``` +## wolfSSL Usage with NXP SE050 + +### Library and SE050 Initialization and Cleanup + +When looking at NXP's SE050 demo applications, developers will notice that the +connection to SE050 is handled by shared code in +`/sss/ex/inc/ex_sss_main_inc.h`. This code calls +`ex_sss_boot_open()` to open the connection to SE050. NXP demo applications then +implement an `ex_sss_entry()` function, which is called by `main()` in +`ex_sss_main_inc.h`. + +wolfSSL has the ability to open the connection to SE050 internally upon library +initialization. This can make it much easier and simpler for developers who will +be using the SE050 primarily underneath the wolfSSL APIs. + +wolfSSL will initialize the SE050 when the wolfSSL library has been compiled +with `WOLFSSL_SE050_INIT` defined. When this is used, applications need to: + +1. Also define `SE050_DEFAULT_PORT` when compiling wolfSSL +(ie: `user_settings.h`) to match the mount location of SE050 if on Linux. Or, if +on an embedded target, this should be defined to **NULL**. + +2. Application code should initialize the wolfSSL library like normal with +`wolfSSL_Init()` or `wolfCrypt_Init()`. When the application is done using +wolfSSL, resources can be freed and the SE050 connection closed using +`wolfSSL_Cleanup()` or `wolfCrypt_Cleanup()`. For example: + +```c +/* Initialize wolfCrypt, debugging, logging */ +wolfCrypt_Init(); +wolfSSL_SetLoggingCb(my_logging_cb); +wolfSSL_Debugging_ON(); +... +wolfCrypt_Cleanup(); +``` + +If `WOLFSSL_SE050_INIT` has not been defined when compiling wolfSSL, the +following API can be called after wolfSSL library initialization to pass the +correct pre-initialized `sss_session_t` and `sss_key_store_t` structure +pointers to wolfSSL for internal use. These structures would need to be set up +by the application using NXP's SSS API from the middleware SDK. + +```c +#include +int wc_se050_set_config( + sss_session_t *pSession, + sss_key_store_t *pHostKeyStore, + sss_key_store_t *pKeyStore); +``` + +### wolfSSL SE050 Key Generation + +wolfSSL includes APIs for key generation when `WOLFSSL_KEY_GEN` has been +defined while compiling wolfSSL. When wolfSSL has been compiled with SE050 +support (`WOLFSSL_SE050`), it will delegate these key generation operations to +the SE050 and the private keys will remain in the SE050 for added security. + +wolfSSL APIs that will generate keys internal to SE050 are: + +```c +int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); +int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key); +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key); +``` + +wolfSSL will also use the SE050 for ECDH shared secret generation, but will +extract the shared secret to hand back to the application. + +When generating keys in SE050 wolfSSL will automatically pick a key ID value +based on an incrementing counter past the value defined by `SE050_KEYID_START`. +`SE050_KEYID_START` should be defined when compiling wolfSSL +(`user_settings.h`), otherwise it will default to 100. + +### wolfSSL SE050 Key Insertion + +Applications can insert public or private RSA and ECC keys into the SE050 at a +specific key ID using the following wolfSSL helper functions: + +```c +#include + +int wc_se050_ecc_insert_public_key(word32 keyId, + const byte* eccDer, word32 eccDerSize); +int wc_se050_ecc_insert_private_key(word32 keyId, + const byte* eccDer, word32 eccDerSize); + +int wc_se050_rsa_insert_public_key(word32 keyId, + const byte* rsaDer, word32 rsaDerSize); +int wc_se050_rsa_insert_private_key(word32 keyId, + const byte* rsaDer, word32 rsaDerSize); +``` + +These APIs will all return 0 on success or a negative error code on failure. +The input to all these functions is a DER-encoded key and the size of that DER +array in bytes. + +### wolfSSL SE050 Certificate Insertion and Retrieval + +Applications can insert or retrieve certificates or binary data into an SE050 +key ID using the following wolfSSL helper functions: + +```c +int wc_se050_insert_binary_object(word32 keyId, + const byte* object, word32 objectSz); +int wc_se050_get_binary_object(word32 keyId, + byte* out, word32* outSz); +``` + +These APIs will all return 0 on success or a negative error code on failure. +The input to `wc_se050_insert_binary_object()` is a byte array to be stored in +the SE050 along with the size of that array in bytes. + +The arguments to `wc_se050_get_binary_object()` are the key ID to retrieve data +from, the output array for data to be placed, and an IN/OUT variable “outSz” +representing the size of the “out” buffer on input, and on output “outSz” gets +set to the number of bytes written into “out”. + +### wolfSSL SE050 Credential Deletion + +wolfSSL will not auto-delete generated keys associated with wolfCrypt +structures (ex: `RsaKey`, `ecc_key`, etc) when the respective key free function +is called (ex: `wc_ecc_free()`, `wc_FreeRsaKey()`). This is done by design in +case the application wants to re-use that key that has been generated and +stored in the SE050. + +Credentials can be deleted from the SE050 storage by calling the wolfSSL helper +function `wc_se050_erase_object(int keyId)`. This function is available through +``, and should be passed the key ID +to be deleted. + +### wolfSSL SE050 Factory Reset + +If wolfSSL is compiled with `WOLFSSL_SE050_FACTORY_RESET` defined, when +`wolfSSL_Init()` or `wolfCrypt_Init()` is called, wolfSSL will factory reset +the SE050 board by calling `ex_sss_boot_factory_reset()` internally. + +This will erase all user-provisioned key and credential material, leaving only +the NXP pre-provisioned credentials in place. + +## Building wolfSSL SE050 Examples + +wolfSSL demos can be easily added to the SE05x middleware source tree such that +they are build with CMake when the middleware is compiled. + +Assuming a Raspberry Pi host platform is being used, with an SE05x EdgeLock +dev kit: + +1. Create a `wolfssl` directory under the demos directory for wolfSSL demos: + +```sh +$ mkdir /home/pi/se_mw/simw-top/demos/wolfssl +``` + +2. Create a directory for a wolfSSL demo, for example to create one for the +wolfCrypt test application: + +```sh +$ mkdir /home/pi/se_mw/simw-top/demos/wolfssl/wolfcrypt_test +``` + +3. Create a CMakeLists.txt to put inside `demos/wolfssl`, tying the +`wolfcrypt_test` app into CMake. This CMakeLists.txt would contain: + +```cmake +ADD_SUBDIRECTORY(wolfcrypt_test) +``` + +4. Add the `demos/wolfssl` directory to the top `demos/CMakeLists.txt` file. +At the bottom of that file, place: + +```cmake +ADD_SUBDIRECTORY(wolfssl) +``` + +5. Inside `demos/wolfssl/wolfcrypt_test`, copy the wolfCrypt `test.c` and +`test.h` files from a wolfSSL installation: + +```sh +$ cd /home/pi/se_mw/simw-top/demos/wolfssl/wolfcrypt_test +$ cp wolfssl-X.X.X/wolfcrypt/test/test.c ./ +$ cp wolfssl-X.X.X/wolfcrypt/test/test.h ./ +``` + +6. Create a file called `wolfcrypt_test.c` which will act as the demo +application. That file would look similar to: + +```c +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include "test.h" + +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#if defined(SIMW_DEMO_ENABLE__DEMO_WOLFCRYPTTEST) + +static ex_sss_boot_ctx_t gex_sss_boot_ctx; + +#define EX_SSS_BOOT_PCONTEXT (&gex_sss_boot_ctx) +#define EX_SSS_BOOT_DO_ERASE 1 +#define EX_SSS_BOOT_EXPOSE_ARGC_ARGV 0 + +#include + +sss_status_t ex_sss_entry(ex_sss_boot_ctx_t *pCtx) +{ + int ret = 0; + sss_status_t status = kStatus_SSS_Success; + sss_session_t *pSession = (sss_session_t*)&pCtx->session; + sss_key_store_t *pKeyStore = (sss_key_store_t*)&pCtx->ks; + + LOG_I("running setconfig"); + ret = wc_se050_set_config(pSession, NULL, pKeyStore); + if (ret != 0) { + LOG_E("wc_se050_set_config failed"); + return kStatus_SSS_Fail; + } + LOG_I("Ran setconfig successfully"); + + wolfSSL_Init(); + wolfcrypt_test(NULL); + wolfSSL_Cleanup(); + + LOG_I("Ran wolfCrypt test"); + return status; +} + +#endif /* SIMW_DEMO_ENABLE__DEMO_WOLFCRYPTTEST */ +``` + +7. Create a CMakeLists.txt inside `demos/wolfssl/wolfcrypt_test` so that it +can be compiled with CMake: + +```cmake +PROJECT(wolfcrypt_test) +FILE( + GLOB + files + *.c +) + +ADD_EXECUTABLE( + ${PROJECT_NAME} + ${KSDK_STARTUP_FILE} ${files} +) + +TARGET_COMPILE_DEFINITIONS( + ${PROJECT_NAME} + PRIVATE SIMW_DEMO_ENABLE__DEMO_WOLFCRYPTTEST NO_MAIN_DRIVER BENCH_EMBEDDED USE_CERT_BUFFERS_2048 USE_CERT_BUFFERS_256 +) + +TARGET_INCLUDE_DIRECTORIES( + ${PROJECT_NAME} + PRIVATE ${SIMW_TOP_DIR}/sss/ex/inc /home/pi/se_mw/wolfssl +) + +TARGET_LINK_LIBRARIES( + ${PROJECT_NAME} + SSS_APIs + ex_common + wolfssl +) + +CREATE_BINARY(${PROJECT_NAME}) + +IF(SSS_HAVE_HOST_LINUX_LIKE) + INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) +ENDIF() +``` + +8. Build the demo app with CMake + +The wolfCrypt test demo app should now compile along with the SE05x middleware. +This assumes that the NXP instructions for setting up the build have been +completed. + +```sh +$ cd /home/pi/se_mw/simw-top_build/raspbian_native_se050_t1oi2c +$ cmake --build . +``` + +Once the build has finished, the `wolfcrypt_test` executable can be run with: + +```sh +$ cd /home/pi/se_mw/simw-top_build/raspbian_native_se050_t1oi2c/bin +$ ./wolfcrypt_test +``` + diff --git a/wolfcrypt/src/port/nxp/se050_port.c b/wolfcrypt/src/port/nxp/se050_port.c index 4de2c81d0..87730c744 100644 --- a/wolfcrypt/src/port/nxp/se050_port.c +++ b/wolfcrypt/src/port/nxp/se050_port.c @@ -57,13 +57,18 @@ struct mp_int; #define MATH_INT_T struct mp_int #endif -struct ecc_key; -#include -#include - -#ifndef SE050_ECC_DER_MAX -#define SE050_ECC_DER_MAX 256 +#ifdef HAVE_ECC + #include + struct ecc_key; + #ifndef SE050_ECC_DER_MAX + #define SE050_ECC_DER_MAX 256 + #endif #endif +#ifndef NO_RSA + #include + struct RsaKey; +#endif +#include #ifndef SE050_KEYID_START #define SE050_KEYID_START 100 @@ -117,19 +122,71 @@ int wc_se050_init(const char* portName) #endif } else { + WOLFSSL_MSG("Failed to open SE050 context"); ret = WC_HW_E; } return ret; } #endif -int se050_allocate_key(int keyType) +/** + * Erase and free an object stored in SE050. + * + * keyId ID of object to erase + * + * Returns 0 on success, negative on error. + */ +int wc_se050_erase_object(word32 id) { - int keyId = -1; - static int keyId_allocator = SE050_KEYID_START; + int ret = 0; + sss_object_t object; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + +#ifdef SE050_DEBUG + printf("wc_se050_erase_object: id %d\n", id); +#endif + + if (cfg_se050_i2c_pi == NULL) { + return BAD_FUNC_ARG; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, + SE050_KEYSTOREID_GENERIC); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&object, &host_keystore); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_get_handle(&object, id); + } + if (status == kStatus_SSS_Success) { + sss_key_store_erase_key(&host_keystore, &object); + sss_key_object_free(&object); + } + wolfSSL_CryptHwMutexUnLock(); + + if (status != kStatus_SSS_Success) { + ret = WC_HW_E; + } + + return ret; +} + +word32 se050_allocate_key(int keyType) +{ + word32 keyId = 0; + static word32 keyId_allocator = SE050_KEYID_START; switch (keyType) { case SE050_AES_KEY: case SE050_ECC_KEY: + case SE050_RSA_KEY: case SE050_ED25519_KEY: case SE050_CURVE25519_KEY: case SE050_ANY_KEY: @@ -142,7 +199,7 @@ int se050_allocate_key(int keyType) return keyId; } -#ifndef WC_NO_RNG +#if !defined(WC_NO_RNG) && !defined(WOLFSSL_SE050_NO_TRNG) int se050_get_random_number(uint32_t count, uint8_t* rand_out) { int ret = 0; @@ -175,7 +232,9 @@ int se050_get_random_number(uint32_t count, uint8_t* rand_out) return ret; } -#endif /* !WC_NO_RNG */ +#endif /* !WC_NO_RNG && !WOLFSSL_SE050_NO_TRNG */ + +#ifdef WOLFSSL_SE050_HASH /* Used for sha/sha224/sha384/sha512 */ int se050_hash_init(SE050_HASH_Context* se050Ctx, void* heap) @@ -187,8 +246,38 @@ int se050_hash_init(SE050_HASH_Context* se050Ctx, void* heap) return 0; } +int se050_hash_copy(SE050_HASH_Context* src, SE050_HASH_Context* dst) +{ + if (src == NULL || dst == NULL || (src->used != dst->used)) { + return BAD_FUNC_ARG; + } + + if (src->used > 0) { + /* dst->msg points to same buffer as src->msg, needs to be allocated + * and dep copied over instead of plain pointer copy */ + dst->msg = (byte*)XMALLOC(src->used, dst->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (dst->msg == NULL) { + PRINTF("Tried to allocate %d bytes\n", dst->used); + return MEMORY_E; + } + XMEMSET(dst->msg, 0, dst->used); + XMEMCPY(dst->msg, src->msg, src->used); + dst->used = src->used; + dst->len = src->used; + } else { + dst->msg = NULL; + dst->len = 0; + dst->used = 0; + } + + return 0; +} + int se050_hash_update(SE050_HASH_Context* se050Ctx, const byte* data, word32 len) { + byte* tmp = NULL; + if (se050Ctx == NULL || (len > 0 && data == NULL)) { return BAD_FUNC_ARG; } @@ -197,10 +286,18 @@ int se050_hash_update(SE050_HASH_Context* se050Ctx, const byte* data, word32 len if (se050Ctx->msg == NULL) { se050Ctx->msg = (byte*)XMALLOC(se050Ctx->used + len, se050Ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + XMEMSET(se050Ctx->msg, 0, se050Ctx->used + len); } else { - se050Ctx->msg = (byte*)XREALLOC(se050Ctx->msg, se050Ctx->used + len, - se050Ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(se050Ctx->used + len, se050Ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + XMEMSET(tmp, 0, se050Ctx->used + len); + XMEMCPY(tmp, se050Ctx->msg, se050Ctx->used); + XFREE(se050Ctx->msg, se050Ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + se050Ctx->msg = tmp; } if (se050Ctx->msg == NULL) { return MEMORY_E; @@ -208,7 +305,7 @@ int se050_hash_update(SE050_HASH_Context* se050Ctx, const byte* data, word32 len se050Ctx->len = se050Ctx->used + len; } - XMEMCPY(se050Ctx->msg + se050Ctx->used, data , len); + XMEMCPY(se050Ctx->msg + se050Ctx->used, data, len); se050Ctx->used += len; return 0; @@ -221,8 +318,8 @@ int se050_hash_final(SE050_HASH_Context* se050Ctx, byte* hash, size_t digestLen, sss_status_t status; sss_digest_t digest_ctx; const byte* data = se050Ctx->msg; - int size = (se050Ctx->len) / SSS_BLOCK_SIZE; - int leftover = (se050Ctx->len) % SSS_BLOCK_SIZE; + int size = (se050Ctx->used) / SSS_BLOCK_SIZE; + int leftover = (se050Ctx->used) % SSS_BLOCK_SIZE; const byte* blocks = data; if (cfg_se050_i2c_pi == NULL) { @@ -253,7 +350,12 @@ int se050_hash_final(SE050_HASH_Context* se050Ctx, byte* hash, size_t digestLen, sss_digest_context_free(&digest_ctx); } - ret = (status == kStatus_SSS_Success) ? 0 : WC_HW_E; + if (status == kStatus_SSS_Success) { + /* reset state */ + ret = se050_hash_init(se050Ctx, se050Ctx->heap); + } else { + ret = WC_HW_E; + } wolfSSL_CryptHwMutexUnLock(); @@ -264,9 +366,14 @@ void se050_hash_free(SE050_HASH_Context* se050Ctx) { XFREE(se050Ctx->msg, se050Ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); se050Ctx->msg = NULL; + se050Ctx->len = 0; + se050Ctx->used = 0; } -#ifndef NO_AES +#endif /* WOLFSSL_SE050_HASH */ + +#if defined(WOLFSSL_SE050_CRYPT) && !defined(NO_AES) + int se050_aes_set_key(Aes* aes, const byte* key, word32 keylen, const byte* iv, int dir) { @@ -274,7 +381,7 @@ int se050_aes_set_key(Aes* aes, const byte* key, word32 keylen, sss_status_t status; sss_object_t newKey; sss_key_store_t host_keystore; - int keyId; + word32 keyId; int keyCreated = 0; if (cfg_se050_i2c_pi == NULL) { @@ -290,6 +397,13 @@ int se050_aes_set_key(Aes* aes, const byte* key, word32 keylen, aes->rounds = keylen/4 + 6; + /* free existing key in slot first before storing new one */ + ret = wc_se050_erase_object(aes->keyId); + if (ret != 0) { + return ret; + } + aes->keyIdSet = 0; + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); if (status == kStatus_SSS_Success) { status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_AES); @@ -304,13 +418,14 @@ int se050_aes_set_key(Aes* aes, const byte* key, word32 keylen, kKeyObject_Mode_Transient); } if (status == kStatus_SSS_Success) { - keyCreated = 1; status = sss_key_store_set_key(&host_keystore, &newKey, key, keylen, keylen * 8, NULL, 0); } if (status == kStatus_SSS_Success) { + keyCreated = 1; aes->keyId = keyId; + aes->keyIdSet = 1; ret = 0; } else { @@ -337,7 +452,7 @@ int se050_aes_crypt(Aes* aes, const byte* in, byte* out, word32 sz, int dir, if (cfg_se050_i2c_pi == NULL) { return WC_HW_E; } - if (aes->keyId <= 0) { + if (aes->keyIdSet == 0) { return BAD_FUNC_ARG; } @@ -391,18 +506,7 @@ int se050_aes_crypt(Aes* aes, const byte* in, byte* out, word32 sz, int dir, void se050_aes_free(Aes* aes) { - sss_status_t status; - sss_key_store_t host_keystore; - sss_object_t keyObject; - - if (cfg_se050_i2c_pi == NULL) { - return; - } - if (aes->keyId <= 0) { - return; - } - - if (wolfSSL_CryptHwMutexLock() != 0) { + if (aes == NULL) { return; } @@ -413,24 +517,1286 @@ void se050_aes_free(Aes* aes) aes->ctxInitDone = 0; } + aes->keyId = 0; + aes->keyIdSet = 0; +} + +#endif /* WOLFSSL_SE050_CRYPT && !NO_AES */ + +/** + * Get size of a SE05X secure object at specified object ID. + * + * keystore SE050 keystore associated with object + * keyId SE050 key ID in which object is stored + * + * Size returned depends on object type: + * ECC key: curve size + * RSA/AES/DES/HMAC key: key size + * Binary file: file size + * + * Return size or negative on error + */ +static int se050_get_object_size(sss_key_store_t* keystore, word32 keyId) +{ + uint16_t size = 0; + smStatus_t status = SM_NOT_OK; + sss_se05x_key_store_t* se05x_keystore = NULL; + + if (keystore == NULL) { + return BAD_FUNC_ARG; + } + + se05x_keystore = (sss_se05x_key_store_t*)keystore; + status = Se05x_API_ReadSize(&se05x_keystore->session->s_ctx, + keyId, &size); + if (status != SM_OK) { + return WC_HW_E; + } + + return (int)size; +} + +/** + * Insert binary object into SE050 as persistent object. + * + * keyId SE050 key ID to store object in + * object binary object data + * objectSz size of binary object, bytes + * + * Returns 0 on success, negative on error + */ +int wc_se050_insert_binary_object(word32 keyId, const byte* object, + word32 objectSz) +{ + int ret = 0; + sss_object_t newObj; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + /* Avoid key ID conflicts with temporary key storage */ + if (keyId >= SE050_KEYID_START) { + return BAD_FUNC_ARG; + } + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); if (status == kStatus_SSS_Success) { - status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_AES); + status = sss_key_object_init(&newObj, &host_keystore); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_allocate_handle(&newObj, keyId, + kSSS_KeyPart_Default, kSSS_CipherType_Binary, objectSz, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + status = sss_key_store_set_key(&host_keystore, &newObj, object, + objectSz, (objectSz * 8), NULL, 0); + } + wolfSSL_CryptHwMutexUnLock(); + + if (status != kStatus_SSS_Success) { + ret = WC_HW_E; + } + + return ret; +} + +/** + * Get binary object from SE050 from specified key ID. + * + * keyId SE050 key ID to get binary object from + * out output buffer to place binary object + * outSz size of output buffer on input, size of written object on output + * + * Returns 0 on success, LENGTH_ONLY_E if out is NULL with outSz set to + * required buffer size, and other negative on error. + */ +int wc_se050_get_binary_object(word32 keyId, byte* out, word32* outSz) +{ + int ret = 0; + sss_object_t object; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + size_t outBitSz = 0; + + /* If out is NULL, outSz set to required size and LENGTH_ONLY_E returned */ + if (outSz == NULL) { + return BAD_FUNC_ARG; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&object, &host_keystore); + } + if (status == kStatus_SSS_Success) { + ret = se050_get_object_size(&host_keystore, keyId); + if (ret < 0) { + status = kStatus_SSS_Fail; + } + else { + if (out == NULL) { + *outSz = ret; + return LENGTH_ONLY_E; + } + if ((word32)ret > *outSz) { + WOLFSSL_MSG("Output buffer not large enough for object"); + return BAD_LENGTH_E; + } + ret = 0; + } + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_get_handle(&object, keyId); + } + if (status == kStatus_SSS_Success) { + outBitSz = (*outSz) * 8; + status = sss_key_store_get_key(&host_keystore, &object, out, outSz, + &outBitSz); + } + wolfSSL_CryptHwMutexUnLock(); + + if (status != kStatus_SSS_Success) { + ret = WC_HW_E; + } + + return ret; +} + +#ifndef NO_RSA + +/** + * Use specified SE050 key ID with this RsaKey struct. + * Should be called by wc_RsaUseKeyId() for using pre-populated + * SE050 keys. + * + * key Pointer to initialized RsaKey structure + * keyId SE050 key ID containing RSA key object + * + * Return 0 on success, negative on error. + */ +int se050_rsa_use_key_id(struct RsaKey* key, word32 keyId) +{ + int ret = 0; + sss_object_t keyObject; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + uint8_t* derBuf = NULL; + size_t derSz = 0; + size_t derSzBits = 0; + word32 idx = 0; + +#ifdef SE050_DEBUG + printf("se050_rsa_use_key_id: key %p, keyId %d\n", key, keyId); +#endif + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); } if (status == kStatus_SSS_Success) { status = sss_key_object_init(&keyObject, &host_keystore); } if (status == kStatus_SSS_Success) { - status = sss_key_object_get_handle(&keyObject, aes->keyId); - aes->keyId = -1; + status = sss_key_object_get_handle(&keyObject, keyId); } - sss_key_store_erase_key(&host_keystore, &keyObject); + if (status == kStatus_SSS_Success) { + ret = se050_get_object_size(&host_keystore, keyObject.keyId); + if (ret <= 0) { + status = kStatus_SSS_Fail; + } + else { + /* double derSz to allow for ASN.1 encoding space */ + derSz = ((size_t)ret) * 2; + ret = 0; + derBuf = (uint8_t*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("Error calling malloc for RSA DER buffer"); + status = kStatus_SSS_Fail; + } + } + } + if (status == kStatus_SSS_Success) { + derSzBits = derSz * 8; + XMEMSET(derBuf, 0, derSz); + status = sss_key_store_get_key(&host_keystore, &keyObject, + derBuf, &derSz, &derSzBits); + (void)derSzBits; /* not used */ + } + if (status == kStatus_SSS_Success) { + /* Populate RsaKey with general key info, for wolfCrypt to use */ + ret = wc_RsaPublicKeyDecode(derBuf, &idx, key, (word32)derSz); + if (ret != 0) { + status = kStatus_SSS_Fail; + } + } + if (derBuf != NULL) { + XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + key->type = RSA_PRIVATE; + ret = 0; + } + else if (ret == 0) { + ret = WC_HW_E; + } + sss_key_object_free(&keyObject); wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_use_key_id: ret %d\n", ret); +#endif + + return ret; } -#endif /* !NO_AES */ +/** + * Get SE050 key ID associated with this RsaKey struct. + * Should be called by wc_RsaGetKeyId() for the application to get + * what key ID wolfCrypt picked for this RsaKey struct when generating + * a key inside the SE050. + * + * key Pointer to initialized RsaKey structure + * keyId [OUT] SE050 key ID associated with this key structure + * + * Return 0 on success, negative on error. + */ +int se050_rsa_get_key_id(struct RsaKey* key, word32* keyId) +{ + int ret = 0; + + if (key == NULL || keyId == NULL) { + return BAD_FUNC_ARG; + } + + if (key->keyIdSet == 1) { + *keyId = key->keyId; + + } else { + WOLFSSL_MSG("SE050 key ID not set for RsaKey struct"); + ret = WC_HW_E; + } + + return ret; +} + +/** + * Create RSA key pair inside SE050. + * + * key RsaKey structure to store generated key information in + * size RSA key size to generate in bytes + * e RSA exponent, must be 65537 for SE050 compatibility + * + * Returns 0 on success, negative on error. + */ +int se050_rsa_create_key(struct RsaKey* key, int size, long e) +{ + int ret = 0; + word32 keyId; + int keyCreated = 0; + sss_status_t status = kStatus_SSS_Success; + sss_object_t keyPair; + sss_key_store_t host_keystore; + uint8_t* derBuf = NULL; + size_t derSz = 0; + size_t derSzBits = 0; + word32 idx = 0; + +#ifdef SE050_DEBUG + printf("se050_rsa_create_key: key %p, size %d, e %ld\n", key, size, e); +#endif + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (e != 65537) { + WOLFSSL_MSG("SE050 RSA key create only supports exponent of 65537"); + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&keyPair, &host_keystore); + } + if (status == kStatus_SSS_Success) { + keyId = se050_allocate_key(SE050_RSA_KEY); + status = sss_key_object_allocate_handle(&keyPair, keyId, + kSSS_KeyPart_Pair, kSSS_CipherType_RSA, (size / 8), + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + /* Try to delete existing key first. Ignore return since will fail + * if no key exists */ + sss_key_store_erase_key(&host_keystore, &keyPair); + + keyCreated = 1; + status = sss_key_store_generate_key(&host_keystore, &keyPair, + size, NULL); + } + if (status == kStatus_SSS_Success) { + ret = se050_get_object_size(&host_keystore, keyPair.keyId); + if (ret <= 0) { + status = kStatus_SSS_Fail; + } + else { + /* double derSz to allow for ASN.1 encoding space */ + derSz = ((size_t)ret) * 2; + ret = 0; + derBuf = (uint8_t*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("Error calling malloc for RSA DER buffer"); + status = kStatus_SSS_Fail; + } + } + } + if (status == kStatus_SSS_Success) { + derSzBits = derSz * 8; + XMEMSET(derBuf, 0, derSz); + status = sss_key_store_get_key(&host_keystore, &keyPair, + derBuf, &derSz, &derSzBits); + (void)derSzBits; /* not used */ + } + if (status == kStatus_SSS_Success) { + ret = wc_RsaPublicKeyDecode(derBuf, &idx, key, (word32)derSz); + if (ret != 0) { + status = kStatus_SSS_Fail; + } + } + if (derBuf != NULL) { + XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + key->type = RSA_PRIVATE; + ret = 0; + } + else { + if (keyCreated) { + sss_key_store_erase_key(&host_keystore, &keyPair); + sss_key_object_free(&keyPair); + } + if (ret == 0) { + ret = WC_HW_E; + } + } + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_create_key: key %p, ret %d, keyId %d\n", + key, ret, key->keyId); +#endif + + return ret; +} + +static int se050_rsa_insert_key(word32 keyId, const byte* rsaDer, + word32 rsaDerSize, int keyType) +{ + int ret = 0; + int keySize; + word32 idx = 0; + sss_object_t newKey; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + struct RsaKey key; + sss_key_part_t keyPart = kSSS_KeyPart_Pair; + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + /* Avoid key ID conflicts with temporary key storage */ + if (keyId >= SE050_KEYID_START) { + return BAD_FUNC_ARG; + } + + ret = wc_InitRsaKey(&key, NULL); + if (ret != 0) { + status = kStatus_SSS_Fail; + } + else { + if (keyType == RSA_PUBLIC) { + keyPart = kSSS_KeyPart_Public; + ret = wc_RsaPublicKeyDecode(rsaDer, &idx, &key, rsaDerSize); + } + else if (keyType == RSA_PRIVATE) { + keyPart = kSSS_KeyPart_Pair; + ret = wc_RsaPrivateKeyDecode(rsaDer, &idx, &key, rsaDerSize); + } + else { + ret = BAD_FUNC_ARG; + } + + if (ret != 0) { + status = kStatus_SSS_Fail; + } + } + + if (status == kStatus_SSS_Success) { + keySize = wc_RsaEncryptSize(&key); + if (keySize < 0) { + status = kStatus_SSS_Fail; + } + } + if (status == kStatus_SSS_Success) { + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&newKey, &host_keystore); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_allocate_handle(&newKey, keyId, + keyPart, kSSS_CipherType_RSA, keySize, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + status = sss_key_store_set_key(&host_keystore, &newKey, rsaDer, + rsaDerSize, (keySize * 8), NULL, 0); + } + wolfSSL_CryptHwMutexUnLock(); + + wc_FreeRsaKey(&key); + if (status != kStatus_SSS_Success) { + if (ret == 0) { + ret = WC_HW_E; + } + } + + return ret; +} + +/** + * Insert DER encoded RSA private key into SE050 as a persistent key. + * + * keyId SE050 key ID to store key into + * rsaDer DER encoded RSA private key + * rsaDerSize size of DER buffer, bytes + * + * Returns 0 on success, negative on error + */ +int wc_se050_rsa_insert_private_key(word32 keyId, const byte* rsaDer, + word32 rsaDerSize) +{ + return se050_rsa_insert_key(keyId, rsaDer, rsaDerSize, RSA_PRIVATE); +} + +/** + * Insert DER encoded RSA public key into SE050 as a persistent key. + * + * keyId SE050 key ID to store key into + * rsaDer DER encoded RSA public key + * rsaDerSize size of DER buffer, bytes + * + * Returns 0 on success, negative on error + */ +int wc_se050_rsa_insert_public_key(word32 keyId, const byte* rsaDer, + word32 rsaDerSize) +{ + return se050_rsa_insert_key(keyId, rsaDer, rsaDerSize, RSA_PUBLIC); +} + +/** + * Return sss_algorithm_t type for RSA sign/verify based on wolfCrypt pad type, + * hash value, and mask generation function (mgf). + * + * padType padding type + * hash hash function + * mgf mask generation function (for PSS) + * + * Returns algorithm type or kAlgorithm_None if none supported found + */ +static sss_algorithm_t se050_get_rsa_signature_type(int padType, + enum wc_HashType hash, int mgf) +{ + sss_algorithm_t alg = kAlgorithm_None; + + switch (padType) { + case WC_RSA_PKCSV15_PAD: + if (hash == WC_HASH_TYPE_NONE) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH; + } else if (hash == WC_HASH_TYPE_SHA) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1; + } else if (hash == WC_HASH_TYPE_SHA224) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA224; + } else if (hash == WC_HASH_TYPE_SHA256) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA256; + } else if (hash == WC_HASH_TYPE_SHA384) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA384; + } else if (hash == WC_HASH_TYPE_SHA512) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512; + } + break; + case WC_RSA_OAEP_PAD: + if (hash == WC_HASH_TYPE_SHA) { + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA1; + } else if (hash == WC_HASH_TYPE_SHA224) { + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA224; + } else if (hash == WC_HASH_TYPE_SHA256) { + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256; + } else if (hash == WC_HASH_TYPE_SHA384) { + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA384; + } else if (hash == WC_HASH_TYPE_SHA512) { + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA512; + } + break; + case WC_RSA_PSS_PAD: + if (mgf == WC_MGF1SHA1) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1; + } else if (mgf == WC_MGF1SHA224) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA224; + } else if (mgf == WC_MGF1SHA256) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA256; + } else if (mgf == WC_MGF1SHA384) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA384; + } else if (mgf == WC_MGF1SHA512) { + alg = kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512; + } + break; + case WC_RSA_NO_PAD: + alg = kAlgorithm_SSS_RSASSA_NO_PADDING; + break; + default: + break; + } + + return alg; +} + +static sss_algorithm_t se050_get_rsa_encrypt_type(int padType, + enum wc_HashType hash) +{ + sss_algorithm_t alg = kAlgorithm_None; + (void)hash; + + switch (padType) { + case WC_RSA_PKCSV15_PAD: + alg = kAlgorithm_SSS_RSAES_PKCS1_V1_5; + break; + case WC_RSA_OAEP_PAD: + /* lower level Se05x API translation maps OAEP-SHA1 alg type to + * kSE05x_RSAEncryptionAlgo_PKCS1_OAEP (generic) */ + alg = kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA1; + break; + case WC_RSA_NO_PAD: + alg = kAlgorithm_SSS_RSASSA_NO_PADDING; + break; + default: + break; + } + + return alg; +} + +/** + * RSA sign operation. + * + * in input data to be signed + * inLen length of input data, bytes + * out output buffer containing signature + * outLen length of output buffer, bytes + * key pointer to initialized/populated RsaKey structure + * rsa_type type of RSA: must be RSA_PRIVATE_ENCRYPT + * pad_value should be RSA_BLOCK_TYPE_1 for signing + * pad_type type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + * WC_RSA_NO_PAD, WC_RSA_PSS_PAD + * hash type of hash algorithm, found in wolfssl/wolfcrypt/hash.h + * mgf type of mask generation function to use + * label optional label, not supported by SE050, must be NULL + * labelSz size of label, not supported by SE050, must be 0 + * keySz size of RSA key, bytes + * + * Return size of signature on success, negative on error. + */ +int se050_rsa_sign(const byte* in, word32 inLen, byte* out, + word32 outLen, struct RsaKey* key, int rsa_type, + byte pad_value, int pad_type, enum wc_HashType hash, + int mgf, byte* label, word32 labelSz, int keySz) +{ + int ret = 0; + int keyCreated = 0; + word32 keyId; + size_t sigSz; + sss_object_t newKey; + sss_status_t status; + sss_key_store_t host_keystore; + sss_algorithm_t algorithm = kAlgorithm_None; + sss_asymmetric_t ctx_asymm; + byte* derBuf = NULL; + int derSz = 0; + + /* SE050 does not support optional label */ + (void)label; + (void)labelSz; + +#ifdef SE050_DEBUG + printf("se050_rsa_sign: key %p, in %p (%d), out %p (%d), " + "key %p, type %d, pad_value = %d, pad_type = %d, mgf = %d\n", + key, in, inLen, out, outLen, key, rsa_type, pad_value, + pad_type, mgf); +#endif + + if (in == NULL || out == NULL || key == NULL || + rsa_type != RSA_PRIVATE_ENCRYPT || pad_value != RSA_BLOCK_TYPE_1) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + algorithm = se050_get_rsa_signature_type(pad_type, hash, mgf); + if (algorithm == kAlgorithm_None) { + WOLFSSL_MSG("Unsupported padding/hash/mgf combination for SE050"); + return BAD_FUNC_ARG; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&newKey, &host_keystore); + } + if (status == kStatus_SSS_Success) { + keyId = key->keyId; + if (key->keyIdSet == 0) { + /* key was not generated in SE050, export RsaKey to DER + * and use that to store into SE050 keystore */ + derSz = wc_RsaKeyToDer(key, NULL, 0); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + else { + derBuf = (byte*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed when converting RsaKey to DER"); + status = kStatus_SSS_Fail; + ret = MEMORY_E; + } + } + if (status == kStatus_SSS_Success) { + derSz = wc_RsaKeyToDer(key, derBuf, derSz); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + } + if (status == kStatus_SSS_Success) { + keyId = se050_allocate_key(SE050_RSA_KEY); + status = sss_key_object_allocate_handle(&newKey, keyId, + kSSS_KeyPart_Pair, kSSS_CipherType_RSA, keySz, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + + keyCreated = 1; + status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, + derSz, (keySz * 8), NULL, 0); + } + + if (derBuf != NULL) { + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } + else { + status = sss_key_object_get_handle(&newKey, keyId); + } + } + + if (status == kStatus_SSS_Success) { + status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, + &newKey, algorithm, kMode_SSS_Sign); + if (status == kStatus_SSS_Success) { + sigSz = outLen; + status = sss_asymmetric_sign_digest(&ctx_asymm, (uint8_t*)in, inLen, + out, &sigSz); + } + sss_asymmetric_context_free(&ctx_asymm); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + ret = sigSz; + } + else { + if (keyCreated) { + sss_key_store_erase_key(&host_keystore, &newKey); + sss_key_object_free(&newKey); + } + if (ret == 0) { + ret = WC_HW_E; + } + } + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_sign: ret %d, outLen %d\n", ret, outLen); +#endif + + return ret; +} + +/** + * RSA verify operation. + * + * in input signature to be verified + * inLen length of sig, bytes + * out output buffer containing decoded data + * outLen length of output buffer, bytes + * key pointer to initialized/populated RsaKey structure + * rsa_type type of RSA: must be RSA_PUBLIC_DECRYPT + * pad_value should be RSA_BLOCK_TYPE_1 for sign/verify + * pad_type type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + * WC_RSA_NO_PAD, WC_RSA_PSS_PAD + * hash type of hash algorithm, found in wolfssl/wolfcrypt/hash.h + * mgf type of mask generation function to use + * label optional label, not supported by SE050, must be NULL + * labelSz size of label, not supported by SE050, must be 0 + * + * Returns size of decoded data on success, negative on error. + */ +int se050_rsa_verify(const byte* in, word32 inLen, byte* out, word32 outLen, + struct RsaKey* key, int rsa_type, byte pad_value, + int pad_type, enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + int ret = 0; + word32 keyId; + int keySz; + int keyCreated = 0; + size_t decLen = 0; + sss_status_t status; + sss_object_t newKey; + sss_key_store_t host_keystore; + sss_asymmetric_t ctx_asymm = {0}; + sss_se05x_asymmetric_t* se050_ctx_asymm = NULL; + sss_algorithm_t algorithm = kAlgorithm_None; + smStatus_t smStatus = SM_NOT_OK; + byte* pad = NULL; + byte* derBuf = NULL; + int derSz = 0; + +#ifdef SE050_DEBUG + printf("se050_rsa_pkcs1v15_verify: key %p, in %p (%d), out %p (%d)\n", + key, in, inLen, out, outLen); +#endif + + if (in == NULL || out == NULL || key == NULL || + rsa_type != RSA_PUBLIC_DECRYPT || pad_value != RSA_BLOCK_TYPE_1) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + algorithm = se050_get_rsa_signature_type(pad_type, hash, mgf); + if (algorithm == kAlgorithm_None) { + WOLFSSL_MSG("Unsupported padding/hash/mgf combination for SE050"); + return BAD_FUNC_ARG; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&newKey, &host_keystore); + } + if (status == kStatus_SSS_Success) { + keySz = wc_RsaEncryptSize(key); + if (keySz < 0) { + WOLFSSL_MSG("Failed to get RSA key size from struct"); + status = kStatus_SSS_Fail; + } + } + if (status == kStatus_SSS_Success) { + keyId = key->keyId; + if (key->keyIdSet == 0) { + /* key was not generated in SE050, export RsaKey to DER + * and use that to store into SE050 keystore */ + derSz = wc_RsaKeyToDer(key, NULL, 0); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + else { + derBuf = (byte*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed when converting RsaKey to DER"); + status = kStatus_SSS_Fail; + ret = MEMORY_E; + } + } + if (status == kStatus_SSS_Success) { + derSz = wc_RsaKeyToDer(key, derBuf, derSz); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + } + if (status == kStatus_SSS_Success) { + keyId = se050_allocate_key(SE050_RSA_KEY); + status = sss_key_object_allocate_handle(&newKey, keyId, + kSSS_KeyPart_Pair, kSSS_CipherType_RSA, keySz, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + + keyCreated = 1; + status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, + derSz, (keySz * 8), NULL, 0); + } + + if (derBuf != NULL) { + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } + else { + status = sss_key_object_get_handle(&newKey, keyId); + } + } + + if (status == kStatus_SSS_Success) { + status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, + &newKey, algorithm, kMode_SSS_Verify); + if (status == kStatus_SSS_Success) { + /* Use lower Se05x API instead of sss_asymmetric_verify_digest() + * since we need to return decoded data not just verify result */ + decLen = outLen; + se050_ctx_asymm = (sss_se05x_asymmetric_t*)&ctx_asymm; + smStatus = Se05x_API_RSAEncrypt(&se050_ctx_asymm->session->s_ctx, + se050_ctx_asymm->keyObject->keyId, + kSE05x_RSAEncryptionAlgo_NO_PAD, + in, inLen, out, &decLen); + if (smStatus == SM_OK) { + /* find end of padding, pad points to start of actual data */ + ret = wc_RsaUnPad_ex(out, decLen, &pad, pad_value, + pad_type, hash, mgf, + label, labelSz, RSA_PSS_SALT_LEN_DEFAULT, (keySz * 8), + key->heap); + if (ret >= 0) { + XMEMCPY(out, pad, ret); + } + else { + WOLFSSL_MSG("Error in wc_RsaUnPad_ex for RSA verify"); + status = kStatus_SSS_Fail; + } + } + else { + WOLFSSL_MSG("Se05x_API_RSAEncrypt failed"); + status = kStatus_SSS_Fail; + } + } + + sss_asymmetric_context_free(&ctx_asymm); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + } + else { + if (keyCreated) { + sss_key_store_erase_key(&host_keystore, &newKey); + sss_key_object_free(&newKey); + } + if (ret == 0) { + ret = WC_HW_E; + } + } + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_verify: key %p, ret %d\n", key, ret); +#endif + + return ret; +} + +/** + * RSA public encrypt operation. + * + * in input data to be encrypted + * inLen length of input data, bytes + * out output buffer containing encrypted data + * outLen length of output buffer, bytes + * key pointer to initialized/populated RsaKey structure + * rsa_type type of RSA: must be RSA_PUBLIC_ENCRYPT + * pad_value should be RSA_BLOCK_TYPE_2 for encrypting + * pad_type type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + * WC_RSA_NO_PAD, WC_RSA_PSS_PAD + * hash type of hash algorithm, found in wolfssl/wolfcrypt/hash.h + * mgf type of mask generation function to use + * label optional label, not supported by SE050, must be NULL + * labelSz size of label, not supported by SE050, must be 0 + * keySz size of RSA key, bytes + * + * Returns size of encrypted data on success, negative on error. + */ +int se050_rsa_public_encrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, struct RsaKey* key, int rsa_type, + byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz, int keySz) +{ + int ret = 0; + int keyCreated = 0; + word32 keyId; + size_t encSz; + sss_object_t newKey; + sss_status_t status; + sss_key_store_t host_keystore; + sss_algorithm_t algorithm = kAlgorithm_None; + sss_asymmetric_t ctx_asymm; + byte* derBuf = NULL; + int derSz = 0; + + /* SE050 does not support optional label */ + (void)label; + (void)labelSz; + (void)mgf; + +#ifdef SE050_DEBUG + printf("se050_rsa_public_encrypt: key %p, in %p (%d), out %p (%d), " + "key %p\n", key, in, inLen, out, outLen, key); +#endif + + if (in == NULL || out == NULL || key == NULL || + rsa_type != RSA_PUBLIC_ENCRYPT || pad_value != RSA_BLOCK_TYPE_2) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + algorithm = se050_get_rsa_encrypt_type(pad_type, hash); + if (algorithm == kAlgorithm_None) { + WOLFSSL_MSG("Unsupported padding/hash/mgf combination for SE050"); + return BAD_FUNC_ARG; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&newKey, &host_keystore); + } + if (status == kStatus_SSS_Success) { + keyId = key->keyId; + if (key->keyIdSet == 0) { + /* key was not generated in SE050, export RsaKey to DER + * and use that to store into SE050 keystore */ + derSz = wc_RsaKeyToDer(key, NULL, 0); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + else { + derBuf = (byte*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed when converting RsaKey to DER"); + status = kStatus_SSS_Fail; + ret = MEMORY_E; + } + } + if (status == kStatus_SSS_Success) { + derSz = wc_RsaKeyToDer(key, derBuf, derSz); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + } + if (status == kStatus_SSS_Success) { + keyId = se050_allocate_key(SE050_RSA_KEY); + status = sss_key_object_allocate_handle(&newKey, keyId, + kSSS_KeyPart_Pair, kSSS_CipherType_RSA, keySz, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + + keyCreated = 1; + status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, + derSz, (keySz * 8), NULL, 0); + } + } + else { + status = sss_key_object_get_handle(&newKey, keyId); + } + + if (derBuf != NULL) { + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } + + if (status == kStatus_SSS_Success) { + status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, + &newKey, algorithm, kMode_SSS_Encrypt); + if (status == kStatus_SSS_Success) { + encSz = outLen; + status = sss_asymmetric_encrypt(&ctx_asymm, (uint8_t*)in, inLen, + out, &encSz); + } + sss_asymmetric_context_free(&ctx_asymm); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + ret = encSz; + } + else { + if (keyCreated) { + sss_key_store_erase_key(&host_keystore, &newKey); + sss_key_object_free(&newKey); + } + if (ret == 0) { + ret = WC_HW_E; + } + } + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_public_encrypt: ret %d, outLen %d\n", ret, outLen); +#endif + + return ret; +} + +/** + * RSA public decrypt operation. + * + * in input data to be decrypted + * inLen length of input data, bytes + * out output buffer containing decrypted data + * outLen length of output buffer, bytes + * key pointer to initialized/populated RsaKey structure + * rsa_type type of RSA: must be RSA_PRIVATE_DECRYPT + * pad_value should be RSA_BLOCK_TYPE_2 for encrypting + * pad_type type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + * WC_RSA_NO_PAD, WC_RSA_PSS_PAD + * hash type of hash algorithm, found in wolfssl/wolfcrypt/hash.h + * mgf type of mask generation function to use + * label optional label, not supported by SE050, must be NULL + * labelSz size of label, not supported by SE050, must be 0 + * + * Returns size of decrypted data on success, negative on error. + */ +int se050_rsa_private_decrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, struct RsaKey* key, int rsa_type, + byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + int ret = 0; + int keyCreated = 0; + word32 keyId; + int keySz; + size_t decSz; + sss_object_t newKey; + sss_status_t status; + sss_key_store_t host_keystore; + sss_algorithm_t algorithm = kAlgorithm_None; + sss_asymmetric_t ctx_asymm; + byte* derBuf = NULL; + int derSz = 0; + + /* SE050 does not support optional label */ + (void)label; + (void)labelSz; + (void)mgf; + +#ifdef SE050_DEBUG + printf("se050_rsa_public_decrypt: key %p, in %p (%d), out %p (%d), " + "key %p\n", key, in, inLen, out, outLen, key); +#endif + + if (in == NULL || out == NULL || key == NULL || + rsa_type != RSA_PRIVATE_DECRYPT || pad_value != RSA_BLOCK_TYPE_2) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + algorithm = se050_get_rsa_encrypt_type(pad_type, hash); + if (algorithm == kAlgorithm_None) { + WOLFSSL_MSG("Unsupported padding/hash/mgf combination for SE050"); + return BAD_FUNC_ARG; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_RSA); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&newKey, &host_keystore); + } + if (status == kStatus_SSS_Success) { + keySz = wc_RsaEncryptSize(key); + if (keySz < 0) { + WOLFSSL_MSG("Failed to get RSA key size from struct"); + status = kStatus_SSS_Fail; + } + } + if (status == kStatus_SSS_Success) { + keyId = key->keyId; + if (key->keyIdSet == 0) { + /* key was not generated in SE050, export RsaKey to DER + * and use that to store into SE050 keystore */ + derSz = wc_RsaKeyToDer(key, NULL, 0); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + else { + derBuf = (byte*)XMALLOC(derSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed when converting RsaKey to DER"); + status = kStatus_SSS_Fail; + ret = MEMORY_E; + } + } + if (status == kStatus_SSS_Success) { + derSz = wc_RsaKeyToDer(key, derBuf, derSz); + if (derSz < 0) { + status = kStatus_SSS_Fail; + ret = derSz; + } + } + if (status == kStatus_SSS_Success) { + keyId = se050_allocate_key(SE050_RSA_KEY); + status = sss_key_object_allocate_handle(&newKey, keyId, + kSSS_KeyPart_Pair, kSSS_CipherType_RSA, keySz, + kKeyObject_Mode_Persistent); + } + if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + + keyCreated = 1; + status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, + derSz, (keySz * 8), NULL, 0); + } + } + else { + status = sss_key_object_get_handle(&newKey, keyId); + } + + if (derBuf != NULL) { + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } + + if (status == kStatus_SSS_Success) { + status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, + &newKey, algorithm, kMode_SSS_Decrypt); + if (status == kStatus_SSS_Success) { + decSz = outLen; + status = sss_asymmetric_decrypt(&ctx_asymm, (uint8_t*)in, inLen, + out, &decSz); + } + sss_asymmetric_context_free(&ctx_asymm); + } + + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + ret = decSz; + } + else { + if (keyCreated) { + sss_key_store_erase_key(&host_keystore, &newKey); + sss_key_object_free(&newKey); + } + if (ret == 0) { + ret = WC_HW_E; + } + } + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_rsa_public_decrypt: ret %d, outLen %d\n", ret, outLen); +#endif + + return ret; +} + +#endif /* NO_RSA */ #ifdef HAVE_ECC @@ -438,7 +1804,8 @@ static int se050_map_curve(int curve_id, int keySize, int* keySizeBits, sss_cipher_type_t* pcurve_type) { int ret = 0; - sss_cipher_type_t curve_type; + sss_cipher_type_t curve_type = kSSS_CipherType_NONE; + *keySizeBits = keySize * 8; /* set default */ switch (curve_id) { case ECC_SECP160K1: @@ -464,10 +1831,6 @@ static int se050_map_curve(int curve_id, int keySize, ret = ECC_CURVE_OID_E; #endif break; - case ECC_SECP521R1: - curve_type = kSSS_CipherType_EC_NIST_P; - *keySizeBits = 521; - break; case ECC_CURVE_DEF: case ECC_SECP160R1: case ECC_SECP192R1: @@ -476,6 +1839,10 @@ static int se050_map_curve(int curve_id, int keySize, case ECC_SECP384R1: curve_type = kSSS_CipherType_EC_NIST_P; break; + case ECC_SECP521R1: + curve_type = kSSS_CipherType_EC_NIST_P; + *keySizeBits = 521; + break; case ECC_PRIME239V1: case ECC_PRIME192V2: case ECC_PRIME192V3: @@ -499,24 +1866,26 @@ static sss_algorithm_t se050_map_hash_alg(int hashLen) algorithm = kAlgorithm_SSS_SHA256; } else if (hashLen == 48) { algorithm = kAlgorithm_SSS_SHA384; - } else if (hashLen == 64) { + } else if (hashLen == 64 || hashLen == 66) { + /* ECC P-521 can pass key size 66, use SHA-512 */ algorithm = kAlgorithm_SSS_SHA512; } return algorithm; } -int se050_ecc_insert_private_key(int keyId, const byte* eccDer, - word32 eccDerSize) +static int se050_ecc_insert_key(word32 keyId, const byte* eccDer, + word32 eccDerSize, int keyType) { int ret = 0; struct ecc_key key; sss_object_t newKey; sss_key_store_t host_keystore; sss_status_t status = kStatus_SSS_Success; - int keySizeBits; - int keySize; + int keySizeBits = 0; + int keySize = 0; word32 idx = 0; - sss_cipher_type_t curveType; + sss_cipher_type_t curveType = kSSS_CipherType_NONE; + sss_key_part_t keyPart = kSSS_KeyPart_Pair; if (wolfSSL_CryptHwMutexLock() != 0) { return BAD_MUTEX_E; @@ -531,7 +1900,18 @@ int se050_ecc_insert_private_key(int keyId, const byte* eccDer, if (ret != 0) { status = kStatus_SSS_Fail; } else { - ret = wc_EccPrivateKeyDecode(eccDer, &idx, &key, eccDerSize); + if (keyType == ECC_PUBLICKEY) { + keyPart = kSSS_KeyPart_Public; + ret = wc_EccPublicKeyDecode(eccDer, &idx, &key, eccDerSize); + } + else if (keyType == ECC_PRIVATEKEY) { + keyPart = kSSS_KeyPart_Pair; + ret = wc_EccPrivateKeyDecode(eccDer, &idx, &key, eccDerSize); + } + else { + ret = BAD_FUNC_ARG; + } + if (ret != 0) { status = kStatus_SSS_Fail; } @@ -550,7 +1930,7 @@ int se050_ecc_insert_private_key(int keyId, const byte* eccDer, } if (status == kStatus_SSS_Success) { status = sss_key_object_allocate_handle(&newKey, keyId, - kSSS_KeyPart_Pair, curveType, MAX_ECC_BYTES, + keyPart, curveType, MAX_ECC_BYTES, kKeyObject_Mode_Persistent); } if (status == kStatus_SSS_Success) { @@ -569,8 +1949,38 @@ int se050_ecc_insert_private_key(int keyId, const byte* eccDer, return ret; } -int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, - word32 *outLen, struct ecc_key* key) +/** + * Insert ECC public key into SE050 at specified key ID. + * + * keyId SE050 key ID to place public key into + * eccDer DER encoded ECC public key + * eccDerSize Size of eccDer, bytes + * + * Return 0 on success, negative on error. + */ +int wc_se050_ecc_insert_public_key(word32 keyId, const byte* eccDer, + word32 eccDerSize) +{ + return se050_ecc_insert_key(keyId, eccDer, eccDerSize, ECC_PUBLICKEY); +} + +/** + * Insert ECC private key into SE050 at specified key ID. + * + * keyId SE050 key ID to place private key into + * eccDer DER encoded ECC private key + * eccDerSize Size of eccDer, bytes + * + * Return 0 on success, negative on error. + */ +int wc_se050_ecc_insert_private_key(word32 keyId, const byte* eccDer, + word32 eccDerSize) +{ + return se050_ecc_insert_key(keyId, eccDer, eccDerSize, ECC_PRIVATEKEY); +} + +int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, mp_int* r, mp_int* s, + byte* out, word32 *outLen, struct ecc_key* key) { int ret = 0; sss_status_t status; @@ -581,14 +1991,24 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, int keySize; int keySizeBits; int keyCreated = 0; - int keyId; + word32 keyId; sss_cipher_type_t curveType; + byte sigBuf[ECC_MAX_SIG_SIZE]; + size_t sigSz = sizeof(sigBuf); + word32 rLen = 0; + word32 sLen = 0; + #ifdef SE050_DEBUG - printf("se050_ecc_sign_hash_ex: key %p, in %p (%d), out %p (%d), keyId %d\n", - key, in, inLen, out, *outLen, key->keyId); + printf("se050_ecc_sign_hash_ex: key %p, in %p (%d), out %p (%d), " + "keyId %d\n", key, in, inLen, out, *outLen, key->keyId); #endif + if (in == NULL || r == NULL || s == NULL || out == NULL || + outLen == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + if (cfg_se050_i2c_pi == NULL) { return WC_HW_E; } @@ -600,8 +2020,14 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, } /* truncate if digest is larger than key size */ - if (inLen > (word32)keySize) + if (inLen > (word32)keySize) { inLen = (word32)keySize; + } + + /* For P-521, if inLen is 66, truncate down to 64 for SHA-512 */ + if ((keySize == 66) && (inLen == 66)) { + inLen = 64; + } algorithm = se050_map_hash_alg(inLen); if (algorithm == kAlgorithm_None) { @@ -626,7 +2052,7 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, /* this is run when a key was not generated and was instead passed in */ if (status == kStatus_SSS_Success) { keyId = key->keyId; - if (keyId <= 0) { + if (key->keyIdSet == 0) { byte derBuf[SE050_ECC_DER_MAX]; word32 derSz; @@ -642,9 +2068,13 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, keyId = se050_allocate_key(SE050_ECC_KEY); status = sss_key_object_allocate_handle(&newKey, keyId, kSSS_KeyPart_Pair, curveType, keySize, - kKeyObject_Mode_Transient); + kKeyObject_Mode_Persistent); } if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + keyCreated = 1; status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, derSz, keySizeBits, NULL, 0); @@ -652,36 +2082,53 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, } else { status = sss_key_object_get_handle(&newKey, keyId); - - /* mark that key was used for signing, don't free */ - key->flags |= WC_ECC_FLAG_DEC_SIGN; } } if (status == kStatus_SSS_Success) { + status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, &newKey, algorithm, kMode_SSS_Sign); if (status == kStatus_SSS_Success) { - byte sigBuf[ECC_MAX_SIG_SIZE]; - size_t sigSz = sizeof(sigBuf); + status = sss_asymmetric_sign_digest(&ctx_asymm, (uint8_t*)in, inLen, sigBuf, &sigSz); if (status == kStatus_SSS_Success) { + /* SE050 returns ASN.1 encoded signature */ - word32 rLen = keySize, sLen = keySize; + rLen = keySize; + sLen = keySize; + ret = DecodeECC_DSA_Sig_Bin(sigBuf, (word32)sigSz, out, &rLen, out+keySize, &sLen); + if (ret != 0) { status = kStatus_SSS_Fail; + } else { + /* In case rLen is smaller than keySize, move S up */ + XMEMCPY(out + rLen, out + keySize, sLen); } } } sss_asymmetric_context_free(&ctx_asymm); } + if (status == kStatus_SSS_Success) { + /* Load R and S into mp_int */ + ret = mp_read_unsigned_bin(r, out, rLen); + if (ret == MP_OKAY) { + ret = mp_read_unsigned_bin(s, out + rLen, sLen); + } + if (ret != MP_OKAY) { + status = kStatus_SSS_Fail; + } + ret = 0; + } + if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; ret = 0; } else { @@ -704,8 +2151,8 @@ int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, byte* out, return ret; } -int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, - word32 sigRSLen, struct ecc_key* key, int* res) +int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, mp_int* r, + mp_int* s, struct ecc_key* key, int* res) { int ret = 0; sss_status_t status; @@ -719,13 +2166,19 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, sss_cipher_type_t curveType; int keyCreated = 0; + byte rBuf[ECC_MAX_CRYPTO_HW_SIZE]; + byte sBuf[ECC_MAX_CRYPTO_HW_SIZE]; + byte sigBuf[ECC_MAX_SIG_SIZE]; + word32 rBufSz = (word32)sizeof(rBuf); + word32 sBufSz = (word32)sizeof(sBuf); + word32 sigSz = (word32)sizeof(sigBuf); + #ifdef SE050_DEBUG - printf("se050_ecc_verify_hash_ex: key %p, hash %p (%d), sig %p (%d)\n", - key, hash, hashLen, sigRS, sigRSLen); + printf("se050_ecc_verify_hash_ex: key %p, hash %p (%d)\n", + key, hash, hashLen); #endif *res = 0; - (void)sigRSLen; if (cfg_se050_i2c_pi == NULL) { return WC_HW_E; @@ -738,8 +2191,14 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, } /* truncate hash if larger than key size */ - if (hashLen > (word32)keySize) + if (hashLen > (word32)keySize) { hashLen = (word32)keySize; + } + + /* For P-521, if inLen is 66, truncate down to 64 for SHA-512 */ + if ((keySize == 66) && (hashLen == 66)) { + hashLen = 64; + } algorithm = se050_map_hash_alg(hashLen); if (algorithm == kAlgorithm_None) { @@ -765,7 +2224,7 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, /* this is run when a key was not generated and was instead passed in */ if (status == kStatus_SSS_Success) { keyId = key->keyId; - if (keyId <= 0) { + if (key->keyIdSet == 0) { byte derBuf[SE050_ECC_DER_MAX]; word32 derSz; @@ -781,9 +2240,13 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, keyId = se050_allocate_key(SE050_ECC_KEY); status = sss_key_object_allocate_handle(&newKey, keyId, kSSS_KeyPart_Public, curveType, keySize, - kKeyObject_Mode_Transient); + kKeyObject_Mode_Persistent); } if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &newKey); + keyCreated = 1; status = sss_key_store_set_key(&host_keystore, &newKey, derBuf, derSz, keySizeBits, NULL, 0); @@ -797,13 +2260,32 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, if (status == kStatus_SSS_Success) { status = sss_asymmetric_context_init(&ctx_asymm, cfg_se050_i2c_pi, &newKey, algorithm, kMode_SSS_Verify); + if (status == kStatus_SSS_Success) { /* SE050 expects ASN.1 encoded signature */ - byte sigBuf[ECC_MAX_SIG_SIZE]; - word32 sigSz = (word32)sizeof(sigBuf); - ret = StoreECC_DSA_Sig_Bin(sigBuf, &sigSz, - sigRS, keySize, - sigRS+keySize, keySize); + XMEMSET(rBuf, 0, sizeof(rBuf)); + XMEMSET(sBuf, 0, sizeof(sBuf)); + + rBufSz = mp_unsigned_bin_size(r); + sBufSz = mp_unsigned_bin_size(s); + + if (rBufSz > sizeof(rBuf) || sBufSz > sizeof(sBuf)) { + WOLFSSL_MSG("Internal R/S buffers too small for signature"); + ret = BUFFER_E; + } + + if (ret == 0) { + ret = mp_to_unsigned_bin(r, rBuf); + if (ret == MP_OKAY) { + ret = mp_to_unsigned_bin(s, sBuf); + } + } + + if (ret == 0) { + ret = StoreECC_DSA_Sig_Bin(sigBuf, &sigSz, rBuf, rBufSz, + sBuf, sBufSz); + } + if (ret == 0) { status = sss_asymmetric_verify_digest(&ctx_asymm, (uint8_t*)hash, hashLen, sigBuf, sigSz); @@ -812,12 +2294,12 @@ int se050_ecc_verify_hash_ex(const byte* hash, word32 hashLen, byte* sigRS, status = kStatus_SSS_Fail; } } - sss_asymmetric_context_free(&ctx_asymm); } if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; *res = 1; ret = 0; } @@ -854,7 +2336,7 @@ void se050_ecc_free_key(struct ecc_key* key) if (cfg_se050_i2c_pi == NULL) { return; } - if (key->keyId <= 0) { + if (key->keyIdSet == 0) { return; } @@ -873,16 +2355,121 @@ void se050_ecc_free_key(struct ecc_key* key) status = sss_key_object_get_handle(&keyObject, key->keyId); } if (status == kStatus_SSS_Success) { - if ((key->flags & WC_ECC_FLAG_DEC_SIGN) == 0) { - /* key was not used for signing, so release it */ - sss_key_store_erase_key(&host_keystore, &keyObject); - } sss_key_object_free(&keyObject); - key->keyId = -1; + key->keyId = 0; + key->keyIdSet = 0; } wolfSSL_CryptHwMutexUnLock(); } +/** + * Use specified SE050 key ID with this ecc_key struct. + * Should be called by wc_ecc_use_key_id() for using pre-populated + * SE050 keys. + * + * key Pointer to initialized ecc_key structure + * keyId SE050 key ID containing ECC key object + * + * Return 0 on success, negative on error. + */ +int se050_ecc_use_key_id(struct ecc_key* key, word32 keyId) +{ + int ret = 0; + sss_object_t keyObject; + sss_key_store_t host_keystore; + sss_status_t status = kStatus_SSS_Success; + uint8_t derBuf[SE050_ECC_DER_MAX]; + size_t derSz = sizeof(derBuf); + size_t derSzBits = 0; + word32 idx = 0; + +#ifdef SE050_DEBUG + printf("se050_ecc_use_key_id: key %p, keyId %d\n", key, keyId); +#endif + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (cfg_se050_i2c_pi == NULL) { + return WC_HW_E; + } + + if (wolfSSL_CryptHwMutexLock() != 0) { + return BAD_MUTEX_E; + } + + status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); + if (status == kStatus_SSS_Success) { + status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_ECC); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_init(&keyObject, &host_keystore); + } + if (status == kStatus_SSS_Success) { + status = sss_key_object_get_handle(&keyObject, keyId); + } + if (status == kStatus_SSS_Success) { + derSzBits = derSz * 8; + status = sss_key_store_get_key(&host_keystore, &keyObject, + derBuf, &derSz, &derSzBits); + (void)derSzBits; /* not used */ + } + if (status == kStatus_SSS_Success) { + ret = wc_EccPublicKeyDecode(derBuf, &idx, key, (word32)derSz); + if (ret != 0) { + status = kStatus_SSS_Fail; + } + } + if (status == kStatus_SSS_Success) { + key->keyId = keyId; + key->keyIdSet = 1; + ret = 0; + } + else if (ret == 0) { + ret = WC_HW_E; + } + + sss_key_object_free(&keyObject); + + wolfSSL_CryptHwMutexUnLock(); + +#ifdef SE050_DEBUG + printf("se050_ecc_use_key_id: ret %d\n", ret); +#endif + + return ret; +} + +/** + * Get SE050 key ID associated with this ecc_key struct. + * Should be called by wc_ecc_get_key_id() for the application to get + * what key ID wolfCrypt picked for this ecc_key struct when generating + * a key inside the SE050. + * + * key Pointer to initialized ecc_key structure + * keyId [OUT] SE050 key ID associated with this key structure + * + * Return 0 on success, negative on error. + */ +int se050_ecc_get_key_id(struct ecc_key* key, word32* keyId) +{ + int ret = 0; + + if (key == NULL || keyId == NULL) { + return BAD_FUNC_ARG; + } + + if (key->keyIdSet == 1) { + *keyId = key->keyId; + + } else { + WOLFSSL_MSG("SE050 key ID not set for ecc_key struct"); + ret = WC_HW_E; + } + + return ret; +} + int se050_ecc_create_key(struct ecc_key* key, int curve_id, int keySize) { int ret = 0; @@ -891,7 +2478,7 @@ int se050_ecc_create_key(struct ecc_key* key, int curve_id, int keySize) sss_key_store_t host_keystore; uint8_t derBuf[SE050_ECC_DER_MAX]; size_t derSz = sizeof(derBuf); - int keyId; + word32 keyId; int keySizeBits; sss_cipher_type_t curveType; int keyCreated = 0; @@ -923,11 +2510,16 @@ int se050_ecc_create_key(struct ecc_key* key, int curve_id, int keySize) } if (status == kStatus_SSS_Success) { keyId = se050_allocate_key(SE050_ECC_KEY); + /* Using Transient key type here does not work with SE050 */ status = sss_key_object_allocate_handle(&keyPair, keyId, kSSS_KeyPart_Pair, curveType, keySize, - kKeyObject_Mode_Transient); + kKeyObject_Mode_Persistent); } if (status == kStatus_SSS_Success) { + /* Try to delete existing key first. Ignore return since will fail + * if no key exists */ + sss_key_store_erase_key(&host_keystore, &keyPair); + keyCreated = 1; status = sss_key_store_generate_key(&host_keystore, &keyPair, keySizeBits, NULL); @@ -947,6 +2539,7 @@ int se050_ecc_create_key(struct ecc_key* key, int curve_id, int keySize) } if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; ret = 0; } else { @@ -979,7 +2572,7 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, sss_object_t ref_public_key; sss_object_t deriveKey; sss_derive_key_t ctx_derive_key; - int keyId; + word32 keyId; int keySize; int keySizeBits; sss_cipher_type_t curveType; @@ -994,12 +2587,14 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, if (cfg_se050_i2c_pi == NULL) { return WC_HW_E; } - if (private_key->keyId <= 0) { + if (private_key == NULL || public_key == NULL || + private_key->keyIdSet == 0) { return BAD_FUNC_ARG; } keySize = private_key->dp->size; - ret = se050_map_curve(private_key->dp->id, keySize, &keySizeBits, &curveType); + ret = se050_map_curve(private_key->dp->id, keySize, &keySizeBits, + &curveType); if (ret != 0) { return ret; } @@ -1016,14 +2611,15 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, status = sss_key_object_init(&ref_private_key, &host_keystore); } if (status == kStatus_SSS_Success) { - status = sss_key_object_get_handle(&ref_private_key, private_key->keyId); + status = sss_key_object_get_handle(&ref_private_key, + private_key->keyId); } if (status == kStatus_SSS_Success) { status = sss_key_object_init(&ref_public_key, &host_keystore); } if (status == kStatus_SSS_Success) { keyId = public_key->keyId; - if (keyId <= 0) { + if (public_key->keyIdSet == 0) { byte derBuf[SE050_ECC_DER_MAX]; word32 derSz; @@ -1040,12 +2636,15 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, keyId = se050_allocate_key(SE050_ECC_KEY); status = sss_key_object_allocate_handle(&ref_public_key, keyId, kSSS_KeyPart_Public, curveType, keySize, - kKeyObject_Mode_Transient); + kKeyObject_Mode_Persistent); } if (status == kStatus_SSS_Success) { - keyCreated = 1; + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &ref_public_key); status = sss_key_store_set_key(&host_keystore, &ref_public_key, derBuf, derSz, keySizeBits, NULL, 0); + keyCreated = 1; } } else { @@ -1056,8 +2655,7 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, status = sss_key_object_init(&deriveKey, &host_keystore); } if (status == kStatus_SSS_Success) { - int keyIdAes = se050_allocate_key(SE050_AES_KEY); - deriveKeyCreated = 1; + word32 keyIdAes = se050_allocate_key(SE050_AES_KEY); status = sss_key_object_allocate_handle(&deriveKey, keyIdAes, kSSS_KeyPart_Default, @@ -1070,12 +2668,16 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, &ref_private_key, kAlgorithm_SSS_ECDH, kMode_SSS_ComputeSharedSecret); if (status == kStatus_SSS_Success) { + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &deriveKey); status = sss_derive_key_dh(&ctx_derive_key, &ref_public_key, &deriveKey); } if (status == kStatus_SSS_Success) { size_t outlenSz = (size_t)*outlen; size_t outlenSzBits = outlenSz * 8; + deriveKeyCreated = 1; /* derived key export */ status = sss_key_store_get_key(&host_keystore, &deriveKey, out, &outlenSz, &outlenSzBits); @@ -1092,6 +2694,7 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, if (status == kStatus_SSS_Success) { public_key->keyId = keyId; + public_key->keyIdSet = 1; ret = 0; } else { @@ -1099,8 +2702,9 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, sss_key_store_erase_key(&host_keystore, &ref_public_key); sss_key_object_free(&ref_public_key); } - if (ret == 0) + if (ret == 0) { ret = WC_HW_E; + } } wolfSSL_CryptHwMutexUnLock(); @@ -1121,7 +2725,7 @@ int se050_ed25519_create_key(ed25519_key* key) sss_status_t status; sss_key_store_t host_keystore; sss_object_t newKey; - int keyId; + word32 keyId; int keySize = ED25519_KEY_SIZE; int keyCreated = 0; @@ -1158,6 +2762,7 @@ int se050_ed25519_create_key(ed25519_key* key) if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; ret = 0; } else { @@ -1171,7 +2776,7 @@ int se050_ed25519_create_key(ed25519_key* key) wolfSSL_CryptHwMutexUnLock(); #ifdef SE050_DEBUG - printf("se050_ed25519_create_key: ret %d, keyId %d\n", ret, key->keyId); + printf("se050_ed25519_create_key: ret %d, keyId %ld\n", ret, key->keyId); #endif return ret; @@ -1184,13 +2789,13 @@ void se050_ed25519_free_key(ed25519_key* key) sss_key_store_t host_keystore; #ifdef SE050_DEBUG - printf("se050_ed25519_free_key: %p, id %d\n", key, key->keyId); + printf("se050_ed25519_free_key: %p, id %ld\n", key, key->keyId); #endif if (cfg_se050_i2c_pi == NULL) { return; } - if (key->keyId <= 0) { + if (key->keyIdSet == 0) { return; } @@ -1210,12 +2815,9 @@ void se050_ed25519_free_key(ed25519_key* key) status = sss_key_object_get_handle(&newKey, key->keyId); } if (status == kStatus_SSS_Success) { - if ((key->flags & WC_ED25519_FLAG_DEC_SIGN) == 0) { - /* key was not used for signing, so release it */ - sss_key_store_erase_key(&host_keystore, &newKey); - } sss_key_object_free(&newKey); - key->keyId = -1; + key->keyId = 0; + key->keyIdSet = 0; } wolfSSL_CryptHwMutexUnLock(); } @@ -1230,11 +2832,11 @@ int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, sss_object_t newKey; int keySize = ED25519_KEY_SIZE; int keyCreated = 0; - int keyId; + word32 keyId; #ifdef SE050_DEBUG - printf("se050_ed25519_sign_msg: key %p, in %p (%d), out %p (%d), keyId %d\n", - key, in, inLen, out, *outLen, key->keyId); + printf("se050_ed25519_sign_msg: key %p, in %p (%d), out %p (%d), " + "keyId %ld\n", key, in, inLen, out, *outLen, key->keyId); #endif if (cfg_se050_i2c_pi == NULL) { @@ -1255,7 +2857,7 @@ int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, /* this is run when a key was not generated and was instead passed in */ if (status == kStatus_SSS_Success) { keyId = key->keyId; - if (keyId <= 0) { + if (key->keyIdSet == 0) { byte derBuf[SE050_ECC_DER_MAX]; word32 derSz; @@ -1281,9 +2883,6 @@ int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, } else { status = sss_key_object_get_handle(&newKey, keyId); - - /* mark that key was used for signing, don't free */ - key->flags |= WC_ED25519_FLAG_DEC_SIGN; } } if (status == kStatus_SSS_Success) { @@ -1291,8 +2890,9 @@ int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, &newKey, kAlgorithm_SSS_SHA512, kMode_SSS_Sign); if (status == kStatus_SSS_Success) { size_t outlenSz = (size_t)*outLen; - status = sss_se05x_asymmetric_sign((sss_se05x_asymmetric_t *)&ctx_asymm, - (uint8_t *)in, inLen, out, &outlenSz); + status = sss_se05x_asymmetric_sign( + (sss_se05x_asymmetric_t *)&ctx_asymm, + (uint8_t *)in, inLen, out, &outlenSz); *outLen = (word32)outlenSz; } @@ -1307,6 +2907,7 @@ int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, ret = WC_HW_E; } else { key->keyId = keyId; + key->keyIdSet = 1; } wolfSSL_CryptHwMutexUnLock(); @@ -1326,7 +2927,7 @@ int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen, sss_asymmetric_t ctx_asymm; sss_object_t newKey; sss_key_store_t host_keystore; - int keyId; + word32 keyId; int keySize = ED25519_KEY_SIZE; int keyCreated = 0; @@ -1345,18 +2946,20 @@ int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen, status = sss_key_store_context_init(&host_keystore, cfg_se050_i2c_pi); if (status == kStatus_SSS_Success) { - status = sss_key_store_allocate(&host_keystore, SE050_KEYSTOREID_ED25519); + status = sss_key_store_allocate(&host_keystore, + SE050_KEYSTOREID_ED25519); } if (status == kStatus_SSS_Success) { status = sss_key_object_init(&newKey, &host_keystore); } if (status == kStatus_SSS_Success) { keyId = key->keyId; - if (keyId <= 0) { + if (key->keyIdSet == 0) { byte derBuf[ED25519_PUB_KEY_SIZE + 12]; /* seq + algo + bitstring */ word32 derSz = 0; - ret = wc_Ed25519PublicKeyToDer(key, derBuf, (word32)sizeof(derBuf), 1); + ret = wc_Ed25519PublicKeyToDer(key, derBuf, + (word32)sizeof(derBuf), 1); if (ret >= 0) { derSz = ret; ret = 0; @@ -1394,6 +2997,7 @@ int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen, if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; *res = 1; ret = 0; } @@ -1428,7 +3032,7 @@ int se050_curve25519_create_key(curve25519_key* key, int keySize) sss_key_store_t host_keystore; uint8_t derBuf[SE050_ECC_DER_MAX]; size_t derSz = sizeof(derBuf); - int keyId; + word32 keyId; int keyCreated = 0; #ifdef SE050_DEBUG @@ -1486,6 +3090,7 @@ int se050_curve25519_create_key(curve25519_key* key, int keySize) if (status == kStatus_SSS_Success) { key->keyId = keyId; + key->keyIdSet = 1; ret = 0; } else { @@ -1498,7 +3103,7 @@ int se050_curve25519_create_key(curve25519_key* key, int keySize) wolfSSL_CryptHwMutexUnLock(); #ifdef SE050_DEBUG - printf("se050_curve25519_create_key: key %p, ret %d, keyId %d\n", + printf("se050_curve25519_create_key: key %p, ret %d, keyId %ld\n", key, ret, key->keyId); #endif @@ -1515,7 +3120,7 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, sss_object_t ref_public_key; sss_object_t deriveKey; sss_derive_key_t ctx_derive_key; - int keyId; + word32 keyId; int keySize = CURVE25519_KEYSIZE; int keyCreated = 0; int deriveKeyCreated = 0; @@ -1528,7 +3133,9 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, if (cfg_se050_i2c_pi == NULL) { return WC_HW_E; } - if (private_key->keyId <= 0) { + + if (private_key == NULL || public_key == NULL || + private_key->keyIdSet == 0) { return BAD_FUNC_ARG; } @@ -1545,14 +3152,15 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, status = sss_key_object_init(&ref_private_key, &host_keystore); } if (status == kStatus_SSS_Success) { - status = sss_key_object_get_handle(&ref_private_key, private_key->keyId); + status = sss_key_object_get_handle(&ref_private_key, + private_key->keyId); } if (status == kStatus_SSS_Success) { status = sss_key_object_init(&ref_public_key, &host_keystore); } if (status == kStatus_SSS_Success) { keyId = public_key->keyId; - if (keyId <= 0) { + if (public_key->keyIdSet == 0) { byte derBuf[CURVE25519_PUB_KEY_SIZE + 12]; /* seq + algo + bitstring */ word32 derSz; byte pubKey[CURVE25519_PUB_KEY_SIZE]; @@ -1591,7 +3199,7 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, status = sss_key_object_init(&deriveKey, &host_keystore); } if (status == kStatus_SSS_Success) { - int keyIdAes = se050_allocate_key(SE050_AES_KEY); + word32 keyIdAes = se050_allocate_key(SE050_AES_KEY); deriveKeyCreated = 1; status = sss_key_object_allocate_handle(&deriveKey, keyIdAes, @@ -1627,6 +3235,7 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, if (status == kStatus_SSS_Success) { public_key->keyId = keyId; + public_key->keyIdSet = 1; ret = 0; } else { @@ -1655,13 +3264,10 @@ void se050_curve25519_free_key(struct curve25519_key* key) sss_key_store_t host_keystore; #ifdef SE050_DEBUG - printf("se050_curve25519_free_key: %p, id %d\n", key, key->keyId); + printf("se050_curve25519_free_key: %p, id %ld\n", key, key->keyId); #endif - if (cfg_se050_i2c_pi == NULL) { - return; - } - if (key->keyId <= 0) { + if (cfg_se050_i2c_pi == NULL || key->keyIdSet == 0) { return; } @@ -1682,9 +3288,9 @@ void se050_curve25519_free_key(struct curve25519_key* key) status = sss_key_object_get_handle(&newKey, key->keyId); } if (status == kStatus_SSS_Success) { - sss_key_store_erase_key(&host_keystore, &newKey); sss_key_object_free(&newKey); - key->keyId = -1; + key->keyId = 0; + key->keyIdSet = 0; } wolfSSL_CryptHwMutexUnLock(); } diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index fdb6de0f4..81ab88167 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -2806,7 +2806,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } return 0; } -#elif defined(WOLFSSL_SE050) +#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_TRNG) #include int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz){ diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 568d8e8cc..00459e72f 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -55,6 +55,9 @@ RSA keys can be used to encrypt, decrypt, sign and verify data. #if defined(WOLFSSL_XILINX_CRYPT_VERSAL) #include #endif +#ifdef WOLFSSL_SE050 +#include +#endif #ifdef WOLFSSL_HAVE_SP_RSA #include #endif @@ -573,6 +576,43 @@ static int cc310_RSA_GenerateKeyPair(RsaKey* key, int size, long e) } #endif /* WOLFSSL_CRYPTOCELL */ +#ifdef WOLFSSL_SE050 +/* Use specified hardware key ID with RsaKey operations. Unlike devId, + * keyId is a word32 so can handle key IDs larger than an int. + * + * key initialized RsaKey struct + * keyId hardware key ID which stores RSA key + * flags optional flags, currently unused + * + * Return 0 on success, negative on error */ +int wc_RsaUseKeyId(RsaKey* key, word32 keyId, word32 flags) +{ + (void)flags; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + return se050_rsa_use_key_id(key, keyId); +} + +/* Get hardware key ID associated with this RsaKey structure. + * + * key initialized RsaKey struct + * keyId [OUT] output for key ID associated with this structure + * + * Returns 0 on success, negative on error. + */ +int wc_RsaGetKeyId(RsaKey* key, word32* keyId) +{ + if (key == NULL || keyId == NULL) { + return BAD_FUNC_ARG; + } + + return se050_rsa_get_key_id(key, keyId); +} +#endif /* WOLFSSL_SE050 */ + int wc_FreeRsaKey(RsaKey* key) { int ret = 0; @@ -3304,6 +3344,18 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, return cc310_RsaSSL_Sign(in, inLen, out, outLen, key, cc310_hashModeRSA(hash, 0)); } + #elif defined(WOLFSSL_SE050) + if (rsa_type == RSA_PUBLIC_ENCRYPT && pad_value == RSA_BLOCK_TYPE_2) { + return se050_rsa_public_encrypt(in, inLen, out, outLen, key, + rsa_type, pad_value, pad_type, hash, + mgf, label, labelSz, sz); + } + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + return se050_rsa_sign(in, inLen, out, outLen, key, rsa_type, + pad_value, pad_type, hash, mgf, label, + labelSz, sz); + } #endif /* WOLFSSL_CRYPTOCELL */ key->state = RSA_STATE_ENCRYPT_PAD; @@ -3427,6 +3479,26 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, return cc310_RsaSSL_Verify(in, inLen, out, key, cc310_hashModeRSA(hash, 0)); } + #elif defined(WOLFSSL_SE050) + if (rsa_type == RSA_PRIVATE_DECRYPT && pad_value == RSA_BLOCK_TYPE_2) { + ret = se050_rsa_private_decrypt(in, inLen, out, outLen, key, + rsa_type, pad_value, pad_type, hash, + mgf, label, labelSz); + if (outPtr != NULL) { + *outPtr = out; + } + return ret; + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + ret = se050_rsa_verify(in, inLen, out, outLen, key, rsa_type, + pad_value, pad_type, hash, mgf, label, + labelSz); + if (outPtr != NULL) { + *outPtr = out; + } + return ret; + } #endif /* WOLFSSL_CRYPTOCELL */ @@ -4625,6 +4697,7 @@ int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { #ifndef WC_NO_RNG +#if !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) #ifdef WOLFSSL_SMALL_STACK mp_int *p = NULL; mp_int *q = NULL; @@ -4637,15 +4710,36 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) mp_int tmp1_buf, *tmp1 = &tmp1_buf; mp_int tmp2_buf, *tmp2 = &tmp2_buf; mp_int tmp3_buf, *tmp3 = &tmp3_buf; -#endif - int err, i, failCount, primeSz, isPrime = 0; +#endif /* WOLFSSL_SMALL_STACK */ + int i, failCount, primeSz, isPrime = 0; byte* buf = NULL; +#endif /* !WOLFSSL_CRYPTOCELL && !WOLFSSL_SE050 */ + int err; if (key == NULL || rng == NULL) { err = BAD_FUNC_ARG; goto out; } + if (!RsaSizeCheck(size)) { + err = BAD_FUNC_ARG; + goto out; + } + + if (e < 3 || (e & 1) == 0) { + err = BAD_FUNC_ARG; + goto out; + } + +#if defined(WOLFSSL_CRYPTOCELL) + err = cc310_RSA_GenerateKeyPair(key, size, e); + goto out; +#elif defined(WOLFSSL_SE050) + err = se050_rsa_create_key(key, size, e); + goto out; +#else + /* software crypto */ + #ifdef WOLFSSL_SMALL_STACK p = (mp_int *)XMALLOC(sizeof *p, key->heap, DYNAMIC_TYPE_RSA); q = (mp_int *)XMALLOC(sizeof *q, key->heap, DYNAMIC_TYPE_RSA); @@ -4663,23 +4757,6 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) } #endif - if (!RsaSizeCheck(size)) { - err = BAD_FUNC_ARG; - goto out; - } - - if (e < 3 || (e & 1) == 0) { - err = BAD_FUNC_ARG; - goto out; - } - -#if defined(WOLFSSL_CRYPTOCELL) - - err = cc310_RSA_GenerateKeyPair(key, size, e); - goto out; - -#endif /* WOLFSSL_CRYPTOCELL */ - #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { err = wc_CryptoCb_MakeRsaKey(key, size, e, rng); @@ -4979,8 +5056,10 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) err = 0; #endif /* WOLF_CRYPTO_CB_ONLY_RSA */ +#endif /* WOLFSSL_CRYPTOCELL / SW only */ out: +#if !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) #ifdef WOLFSSL_SMALL_STACK if (p) XFREE(p, key->heap, DYNAMIC_TYPE_RSA); @@ -4998,7 +5077,8 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) mp_memzero_check(tmp1); mp_memzero_check(tmp2); mp_memzero_check(tmp3); -#endif +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* !WOLFSSL_CRYPTOCELL && !WOLFSSL_SE050 */ return err; diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index c592b0072..acddec474 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -930,6 +930,9 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) #ifdef WOLFSSL_PIC32MZ_HASH ret = wc_Pic32HashCopy(&src->cache, &dst->cache); #endif +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH) + ret = se050_hash_copy(&src->se050Ctx, &dst->se050Ctx); +#endif #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) dst->ctx.mode = src->ctx.mode; diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index e3b10afbb..7caa91caf 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -264,6 +264,10 @@ int wolfCrypt_Init(void) #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_INIT) ret = wc_se050_init(NULL); + if (ret != 0) { + WOLFSSL_MSG("SE050 init failed"); + return ret; + } #endif #ifdef WOLFSSL_ARMASM diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7492768da..7efa76302 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1546,7 +1546,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ { int ret; func_args args; -#ifdef WOLFSSL_ESPIDF +#if defined(WOLFSSL_ESPIDF) || defined(WOLFSSL_SE050) /* set dummy wallclock time. */ struct timeval utctime; struct timezone tz; @@ -2205,6 +2205,7 @@ WOLFSSL_TEST_SUBROUTINE int md5_test(void) ERROR_OUT(-1607 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; const char* large_digest = @@ -2229,6 +2230,7 @@ WOLFSSL_TEST_SUBROUTINE int md5_test(void) if (XMEMCMP(hash, large_digest, WC_MD5_DIGEST_SIZE) != 0) ERROR_OUT(-1610, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: @@ -2400,9 +2402,11 @@ WOLFSSL_TEST_SUBROUTINE int sha_test(void) ERROR_OUT(-1807 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; -#if defined(WOLFSSL_RENESAS_TSIP) || defined(WOLFSSL_RENESAS_SCEPROTECT) +#if defined(WOLFSSL_RENESAS_TSIP) || defined(WOLFSSL_RENESAS_SCEPROTECT) || \ + defined(HASH_SIZE_LIMIT) const char* large_digest = "\x1d\x6a\x5a\xf6\xe5\x7c\x86\xce\x7f\x7c\xaf\xd5\xdb\x08\xcd\x59" "\x15\x8c\x6d\xb6"; @@ -2414,7 +2418,8 @@ WOLFSSL_TEST_SUBROUTINE int sha_test(void) for (i = 0; i < (int)sizeof(large_input); i++) { large_input[i] = (byte)(i & 0xFF); } -#if defined(WOLFSSL_RENESAS_TSIP) || defined(WOLFSSL_RENESAS_SCEPROTECT) +#if defined(WOLFSSL_RENESAS_TSIP) || defined(WOLFSSL_RENESAS_SCEPROTECT) || \ + defined(HASH_SIZE_LIMIT) times = 20; #else times = 100; @@ -2434,6 +2439,7 @@ WOLFSSL_TEST_SUBROUTINE int sha_test(void) if (XMEMCMP(hash, large_digest, WC_SHA_DIGEST_SIZE) != 0) ERROR_OUT(-1810, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: @@ -2790,6 +2796,7 @@ WOLFSSL_TEST_SUBROUTINE int sha256_test(void) ERROR_OUT(-2307 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; #ifdef HASH_SIZE_LIMIT @@ -2824,6 +2831,7 @@ WOLFSSL_TEST_SUBROUTINE int sha256_test(void) if (XMEMCMP(hash, large_digest, WC_SHA256_DIGEST_SIZE) != 0) ERROR_OUT(-2310, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: @@ -2910,6 +2918,7 @@ WOLFSSL_TEST_SUBROUTINE int sha512_test(void) ERROR_OUT(-2407 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; #ifdef HASH_SIZE_LIMIT @@ -2957,6 +2966,7 @@ WOLFSSL_TEST_SUBROUTINE int sha512_test(void) } #endif } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: wc_Sha512Free(&sha); @@ -3040,6 +3050,7 @@ WOLFSSL_TEST_SUBROUTINE int sha384_test(void) ERROR_OUT(-2507 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; #ifdef HASH_SIZE_LIMIT @@ -3074,6 +3085,7 @@ WOLFSSL_TEST_SUBROUTINE int sha384_test(void) if (XMEMCMP(hash, large_digest, WC_SHA384_DIGEST_SIZE) != 0) ERROR_OUT(-2510, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: @@ -3141,6 +3153,7 @@ static int sha3_224_test(void) ERROR_OUT(-2605 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; const char* large_digest = @@ -3163,6 +3176,7 @@ static int sha3_224_test(void) if (XMEMCMP(hash, large_digest, WC_SHA3_224_DIGEST_SIZE) != 0) ERROR_OUT(-2608, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: wc_Sha3_224_Free(&sha); @@ -3242,6 +3256,7 @@ static int sha3_256_test(void) ERROR_OUT(-2705 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { for (i = 0; i < (int)sizeof(large_input); i++) { large_input[i] = (byte)(i & 0xFF); @@ -3259,6 +3274,7 @@ static int sha3_256_test(void) if (XMEMCMP(hash, large_digest, WC_SHA3_256_DIGEST_SIZE) != 0) ERROR_OUT(-2708, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ /* this is a software only variant of SHA3 not supported by external hardware devices */ #if defined(WOLFSSL_HASH_FLAGS) && !defined(WOLFSSL_ASYNC_CRYPT) @@ -3372,6 +3388,7 @@ static int sha3_384_test(void) #endif } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; const char* large_digest = @@ -3395,6 +3412,7 @@ static int sha3_384_test(void) if (XMEMCMP(hash, large_digest, WC_SHA3_384_DIGEST_SIZE) != 0) ERROR_OUT(-2808, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: wc_Sha3_384_Free(&sha); @@ -3468,6 +3486,7 @@ static int sha3_512_test(void) ERROR_OUT(-2905 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { byte large_input[1024]; const char* large_digest = @@ -3492,6 +3511,7 @@ static int sha3_512_test(void) if (XMEMCMP(hash, large_digest, WC_SHA3_512_DIGEST_SIZE) != 0) ERROR_OUT(-2908, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: wc_Sha3_512_Free(&sha); @@ -3680,6 +3700,7 @@ static int shake128_absorb_test(wc_Shake* sha) ERROR_OUT(-3103 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { for (i = 0; i < (int)sizeof(large_input); i++) { large_input[i] = (byte)(i & 0xFF); @@ -3703,6 +3724,7 @@ static int shake128_absorb_test(wc_Shake* sha) if (XMEMCMP(hash, large_digest, sizeof(hash)) != 0) ERROR_OUT(-3107, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: return ret; @@ -3828,6 +3850,7 @@ WOLFSSL_TEST_SUBROUTINE int shake128_test(void) ERROR_OUT(-3103 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { for (i = 0; i < (int)sizeof(large_input); i++) { large_input[i] = (byte)(i & 0xFF); @@ -3845,6 +3868,7 @@ WOLFSSL_TEST_SUBROUTINE int shake128_test(void) if (XMEMCMP(hash, large_digest, 114) != 0) ERROR_OUT(-3106, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ ret = shake128_absorb_test(&sha); @@ -3992,6 +4016,7 @@ static int shake256_absorb_test(wc_Shake* sha, byte *large_input_buf, ERROR_OUT(-3103 - i, exit); } +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { for (i = 0; i < (int)large_input_buf_size; i++) { large_input_buf[i] = (byte)(i & 0xFF); @@ -4015,6 +4040,7 @@ static int shake256_absorb_test(wc_Shake* sha, byte *large_input_buf, if (XMEMCMP(hash, large_digest, sizeof(hash)) != 0) ERROR_OUT(-3107, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ exit: return ret; @@ -4152,6 +4178,7 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) ERROR_OUT(-3107, exit); #endif +#ifndef NO_LARGE_HASH_TEST /* BEGIN LARGE HASH TEST */ { for (i = 0; i < SHAKE256_LARGE_INPUT_BUFSIZ; i++) { large_input[i] = (byte)(i & 0xFF); @@ -4169,6 +4196,7 @@ WOLFSSL_TEST_SUBROUTINE int shake256_test(void) if (XMEMCMP(hash, large_digest, 114) != 0) ERROR_OUT(-3106, exit); } /* END LARGE HASH TEST */ +#endif /* NO_LARGE_HASH_TEST */ ret = shake256_absorb_test(&sha, large_input, SHAKE256_LARGE_INPUT_BUFSIZ); exit: @@ -13882,8 +13910,8 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) if (ret != 0) #elif defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_RSA_VERIFY_ONLY) if (ret != SIG_TYPE_E) -#elif defined(WOLFSSL_CRYPTOCELL) - /* RNG is handled with the cryptocell */ +#elif defined(WOLFSSL_CRYPTOCELL) || defined(WOLFSSL_SE050) + /* RNG is handled by hardware */ if (ret != 0) #else if (ret != MISSING_RNG_E) @@ -14386,7 +14414,9 @@ static int rsa_pss_test(WC_RNG* rng, RsaKey* key) #ifdef RSA_PSS_TEST_WRONG_PARAMS int k, l; #endif +#ifndef WOLFSSL_SE050 int len; +#endif byte* plain; int mgf[] = { #ifndef NO_SHA @@ -14437,7 +14467,12 @@ static int rsa_pss_test(WC_RNG* rng, RsaKey* key) ERROR_OUT(-7730, exit_rsa_pss); digestSz = wc_HashGetDigestSize(hash[j]); +#ifdef WOLFSSL_SE050 + /* SE050 only supports MGF matched to same hash type */ + i = j; +#else for (i = 0; i < (int)(sizeof(mgf)/sizeof(*mgf)); i++) { +#endif outSz = RSA_TEST_BYTES; do { #if defined(WOLFSSL_ASYNC_CRYPT) @@ -14509,9 +14544,13 @@ static int rsa_pss_test(WC_RNG* rng, RsaKey* key) } } #endif - } +#ifndef WOLFSSL_SE050 + } /* end mgf for loop */ +#endif } +/* SE050 generates salts internally only of hash length */ +#ifndef WOLFSSL_SE050 /* Test that a salt length of zero works. */ digestSz = wc_HashGetDigestSize(hash[0]); outSz = RSA_TEST_BYTES; @@ -14699,6 +14738,7 @@ static int rsa_pss_test(WC_RNG* rng, RsaKey* key) ERROR_OUT(-7745, exit_rsa_pss); ret = 0; +#endif /* WOLFSSL_SE050 */ exit_rsa_pss: WC_FREE_VAR(sig, HEAP_HINT); WC_FREE_VAR(in, HEAP_HINT); @@ -15901,8 +15941,9 @@ static int rsa_oaep_padding_test(RsaKey* key, WC_RNG* rng) /* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ #if !defined(HAVE_CAVIUM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WOLFSSL_CRYPTOCELL) -/* label is unused in cryptocell so it won't detect decrypt error due to label */ + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) + /* label is unused in cryptocell and SE050 so it won't detect decrypt error + * due to label */ idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) @@ -15976,7 +16017,7 @@ static int rsa_oaep_padding_test(RsaKey* key, WC_RNG* rng) /* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ #if !defined(HAVE_CAVIUM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ - !defined(WOLFSSL_CRYPTOCELL) + !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) idx = (word32)ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 6727fcfb0..637e50644 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -202,7 +202,9 @@ struct Aes { #ifdef WOLFSSL_SE050 sss_symmetric_t aes_ctx; /* used as the function context */ int ctxInitDone; - int keyId; + word32 keyId; + byte keyIdSet; + byte useSWCrypt; /* Use SW crypt instead of SE050, before SCP03 auth */ #endif #ifdef GCM_TABLE /* key-based fast multiplication table. */ diff --git a/wolfssl/wolfcrypt/cmac.h b/wolfssl/wolfcrypt/cmac.h index f06029874..76979eb11 100644 --- a/wolfssl/wolfcrypt/cmac.h +++ b/wolfssl/wolfcrypt/cmac.h @@ -68,6 +68,9 @@ struct Cmac { word32 used; word32 len; #endif +#ifdef WOLFSSL_SE050 + byte useSWCrypt; /* Use SW crypt instead of SE050, before SCP03 auth */ +#endif }; diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index df535519a..d8053577a 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -91,7 +91,8 @@ struct curve25519_key { #endif #ifdef WOLFSSL_SE050 - int keyId; + word32 keyId; + byte keyIdSet; #endif /* bit fields */ diff --git a/wolfssl/wolfcrypt/des3.h b/wolfssl/wolfcrypt/des3.h index 5a878c1cb..451f08278 100644 --- a/wolfssl/wolfcrypt/des3.h +++ b/wolfssl/wolfcrypt/des3.h @@ -61,6 +61,11 @@ enum { #include #endif +#ifdef WOLFSSL_SE050 + /* SE050 SDK also defines DES_BLOCK_SIZE */ + #undef DES_BLOCK_SIZE +#endif + enum { DES_ENC_TYPE = WC_CIPHER_DES, /* cipher unique type */ DES3_ENC_TYPE = WC_CIPHER_DES3, /* cipher unique type */ diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 158a36f1f..1a080e6b7 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -177,8 +177,7 @@ enum { #endif ECC_MAX_CRYPTO_HW_SIZE = CRYPTOCELL_KEY_SIZE, #elif defined(WOLFSSL_SE050) - ECC_MAX_CRYPTO_HW_SIZE = 32, - ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = 64, + ECC_MAX_CRYPTO_HW_SIZE = 66, #elif defined(WOLFSSL_XILINX_CRYPT_VERSAL) ECC_MAX_CRYPTO_HW_SIZE = MAX_ECC_BYTES, #endif @@ -453,7 +452,8 @@ struct ecc_key { int partNum; /* partition number*/ #endif #ifdef WOLFSSL_SE050 - int keyId; + word32 keyId; + byte keyIdSet; #endif #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) int slot; /* Key Slot Number (-1 unknown) */ @@ -926,6 +926,13 @@ int sp_dsp_ecc_verify_256(remote_handle64 handle, const byte* hash, word32 hashL mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); #endif +#ifdef WOLFSSL_SE050 +WOLFSSL_API +int wc_ecc_use_key_id(ecc_key* key, word32 keyId, word32 flags); +WOLFSSL_API +int wc_ecc_get_key_id(ecc_key* key, word32* keyId); +#endif + #ifdef WC_ECC_NONBLOCK WOLFSSL_API int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx); #endif diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index fe1ac5a28..1d1f517af 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -93,8 +93,9 @@ struct ed25519_key { byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ #endif #ifdef WOLFSSL_SE050 - int keyId; + word32 keyId; word32 flags; + byte keyIdSet; #endif word16 privKeySet:1; word16 pubKeySet:1; diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index f61d29e06..62bcd1311 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -83,7 +83,6 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/nrf51.h \ wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ wolfssl/wolfcrypt/port/nxp/dcp_port.h \ - wolfssl/wolfcrypt/port/nxp/se050_port.h \ wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ wolfssl/wolfcrypt/port/xilinx/xil-versal-glue.h \ wolfssl/wolfcrypt/port/xilinx/xil-versal-trng.h \ @@ -192,3 +191,7 @@ endif if BUILD_PSA nobase_include_HEADERS+= wolfssl/wolfcrypt/port/psa/psa.h endif + +if BUILD_SE050 +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/nxp/se050_port.h +endif diff --git a/wolfssl/wolfcrypt/port/nxp/se050_port.h b/wolfssl/wolfcrypt/port/nxp/se050_port.h index f1c85b7d7..dc7b1beaf 100644 --- a/wolfssl/wolfcrypt/port/nxp/se050_port.h +++ b/wolfssl/wolfcrypt/port/nxp/se050_port.h @@ -33,6 +33,7 @@ #include "fsl_sss_se05x_types.h" #include "fsl_sss_se05x_apis.h" +#include "se05x_APDU.h" #if (SSS_HAVE_SSS > 1) #include "fsl_sss_api.h" @@ -60,16 +61,24 @@ #ifndef SE050_KEYSTOREID_ED25519 #define SE050_KEYSTOREID_ED25519 58 #endif -#ifndef SE050_KEYSTOREID_ECC -#define SE050_KEYSTOREID_ECC 60 -#endif #ifndef SE050_KEYSTOREID_CURVE25519 #define SE050_KEYSTOREID_CURVE25519 59 #endif +#ifndef SE050_KEYSTOREID_ECC +#define SE050_KEYSTOREID_ECC 60 +#endif +#ifndef SE050_KEYSTOREID_RSA +#define SE050_KEYSTOREID_RSA 61 +#endif +#ifndef SE050_KEYSTOREID_GENERIC +#define SE050_KEYSTOREID_GENERIC 62 +#endif + +/* old public API was renamed to add wc_ */ +#define se050_ecc_insert_private_key wc_se050_ecc_insert_private_key enum { - SSS_BLOCK_SIZE = 512, - + SSS_BLOCK_SIZE = 512, SSS_MAX_ECC_BITS = 521 }; @@ -77,17 +86,20 @@ enum SE050KeyType { SE050_ANY_KEY, SE050_AES_KEY, SE050_ECC_KEY, + SE050_RSA_KEY, SE050_ED25519_KEY, SE050_CURVE25519_KEY }; +#ifdef WOLFSSL_SE050_HASH typedef struct { void* heap; byte* msg; word32 used; word32 len; } SE050_HASH_Context; +#endif /* Public Functions */ WOLFSSL_API int wc_se050_set_config(sss_session_t *pSession, @@ -95,67 +107,122 @@ WOLFSSL_API int wc_se050_set_config(sss_session_t *pSession, #ifdef WOLFSSL_SE050_INIT WOLFSSL_API int wc_se050_init(const char* portName); #endif -WOLFSSL_API int se050_ecc_insert_private_key(int keyId, const byte* eccDer, - word32 eccDerSize); +WOLFSSL_API int wc_se050_erase_object(word32 keyId); + +WOLFSSL_API int wc_se050_ecc_insert_public_key(word32 keyId, + const byte* eccDer, word32 eccDerSize); +WOLFSSL_API int wc_se050_ecc_insert_private_key(word32 keyId, + const byte* eccDer, word32 eccDerSize); + +WOLFSSL_API int wc_se050_rsa_insert_public_key(word32 keyId, + const byte* rsaDer, word32 rsaDerSize); +WOLFSSL_API int wc_se050_rsa_insert_private_key(word32 keyId, + const byte* rsaDer, word32 rsaDerSize); + +WOLFSSL_API int wc_se050_insert_binary_object(word32 keyId, + const byte* object, word32 objectSz); +WOLFSSL_API int wc_se050_get_binary_object(word32 keyId, + byte* out, word32* outSz); /* Private Functions */ -WOLFSSL_LOCAL int se050_allocate_key(int keyType); +WOLFSSL_LOCAL word32 se050_allocate_key(int keyType); +#if !defined(WC_NO_RNG) && !defined(WOLFSSL_SE050_NO_TRNG) WOLFSSL_LOCAL int se050_get_random_number(uint32_t count, uint8_t* rand_out); +#endif +#ifdef WOLFSSL_SE050_HASH WOLFSSL_LOCAL int se050_hash_init(SE050_HASH_Context* se050Ctx, void* heap); WOLFSSL_LOCAL int se050_hash_update(SE050_HASH_Context* se050Ctx, const byte* data, word32 len); WOLFSSL_LOCAL int se050_hash_final(SE050_HASH_Context* se050Ctx, byte* hash, size_t digestLen, sss_algorithm_t algo); +WOLFSSL_LOCAL int se050_hash_copy(SE050_HASH_Context* src, + SE050_HASH_Context* dst); WOLFSSL_LOCAL void se050_hash_free(SE050_HASH_Context* se050Ctx); +#endif +#if defined(WOLFSSL_SE050_CRYPT) && !defined(NO_AES) struct Aes; +WOLFSSL_LOCAL int se050_aes_free_key_store_object(struct Aes* aes); WOLFSSL_LOCAL int se050_aes_set_key(struct Aes* aes, const byte* key, word32 len, const byte* iv, int dir); WOLFSSL_LOCAL int se050_aes_crypt(struct Aes* aes, const byte* in, byte* out, word32 sz, int dir, sss_algorithm_t algorithm); WOLFSSL_LOCAL void se050_aes_free(struct Aes* aes); +#endif - -struct ecc_key; struct WC_RNG; +#ifdef HAVE_ECC #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) struct sp_int; #define MATH_INT_T struct sp_int + typedef struct sp_int mp_int; #elif defined(USE_FAST_MATH) struct fp_int; #define MATH_INT_T struct fp_int + typedef struct fp_int mp_int; #else struct mp_int; #define MATH_INT_T struct mp_int #endif +struct ecc_key; +WOLFSSL_LOCAL int se050_ecc_use_key_id(struct ecc_key* key, word32 keyId); +WOLFSSL_LOCAL int se050_ecc_get_key_id(struct ecc_key* key, word32* keyId); WOLFSSL_LOCAL int se050_ecc_sign_hash_ex(const byte* in, word32 inLen, - byte* out, word32 *outLen, struct ecc_key* key); + mp_int* r, mp_int* s, byte* out, word32 *outLen, struct ecc_key* key); WOLFSSL_LOCAL int se050_ecc_verify_hash_ex(const byte* hash, word32 hashlen, - byte* sigRS, word32 sigRSLen, struct ecc_key* key, int* res); + mp_int* r, mp_int* s, struct ecc_key* key, int* res); -WOLFSSL_LOCAL int se050_ecc_create_key(struct ecc_key* key, int curve_id, int keySize); +WOLFSSL_LOCAL int se050_ecc_create_key(struct ecc_key* key, int curve_id, + int keySize); WOLFSSL_LOCAL int se050_ecc_shared_secret(struct ecc_key* private_key, struct ecc_key* public_key, byte* out, word32* outlen); WOLFSSL_LOCAL void se050_ecc_free_key(struct ecc_key* key); +#endif /* HAVE_ECC */ +#ifndef NO_RSA +struct RsaKey; +WOLFSSL_LOCAL int se050_rsa_use_key_id(struct RsaKey* key, word32 keyId); +WOLFSSL_LOCAL int se050_rsa_get_key_id(struct RsaKey* key, word32* keyId); +WOLFSSL_LOCAL int se050_rsa_create_key(struct RsaKey* key, int size, long e); +WOLFSSL_LOCAL void se050_rsa_free_key(struct RsaKey* key); +WOLFSSL_LOCAL int se050_rsa_sign(const byte* in, word32 inLen, byte* out, + word32 outLen, struct RsaKey* key, int rsa_type, byte pad_value, + int pad_type, enum wc_HashType hash, int mgf, byte* label, word32 labelSz, + int keySz); +WOLFSSL_LOCAL int se050_rsa_verify(const byte* in, word32 inLen, byte* out, + word32 outLen, struct RsaKey* key, int rsa_type, byte pad_value, + int pad_type, enum wc_HashType hash, int mgf, byte* label, word32 labelSz); +WOLFSSL_LOCAL int se050_rsa_public_encrypt(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key, int rsa_type, byte pad_value, + int pad_type, enum wc_HashType hash, int mgf, byte* label, + word32 labelSz, int keySz); +WOLFSSL_LOCAL int se050_rsa_private_decrypt(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key, int rsa_type, byte pad_value, + int pad_type, enum wc_HashType hash, int mgf, byte* label, word32 labelSz); +#endif +#ifdef HAVE_ED25519 struct ed25519_key; WOLFSSL_LOCAL int se050_ed25519_create_key(struct ed25519_key* key); WOLFSSL_LOCAL void se050_ed25519_free_key(struct ed25519_key* key); WOLFSSL_LOCAL int se050_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, struct ed25519_key* key); - WOLFSSL_LOCAL int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen, const byte* msg, word32 msgLen, struct ed25519_key* key, int* res); +#endif /* HAVE_ED25519 */ +#ifdef HAVE_CURVE25519 struct curve25519_key; struct ECPoint; -WOLFSSL_LOCAL int se050_curve25519_create_key(struct curve25519_key* key, int keySize); -WOLFSSL_LOCAL int se050_curve25519_shared_secret(struct curve25519_key* private_key, - struct curve25519_key* public_key, struct ECPoint* out); +WOLFSSL_LOCAL int se050_curve25519_create_key(struct curve25519_key* key, + int keySize); +WOLFSSL_LOCAL int se050_curve25519_shared_secret( + struct curve25519_key* private_key, struct curve25519_key* public_key, + struct ECPoint* out); WOLFSSL_LOCAL void se050_curve25519_free_key(struct curve25519_key* key); +#endif /* HAVE_CURVE25519 */ #endif /* _SE050_PORT_H_ */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 4e1daa36e..9de720249 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -206,6 +206,10 @@ struct RsaKey { #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif +#ifdef WOLFSSL_SE050 + word32 keyId; + byte keyIdSet; +#endif #ifdef WOLF_CRYPTO_CB int devId; #endif @@ -276,6 +280,10 @@ WOLFSSL_API int wc_CheckRsaKey(RsaKey* key); #ifdef WOLFSSL_XILINX_CRYPT WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); #endif /* WOLFSSL_XILINX_CRYPT */ +#ifdef WOLFSSL_SE050 +WOLFSSL_API int wc_RsaUseKeyId(RsaKey* key, word32 keyId, word32 flags); +WOLFSSL_API int wc_RsaGetKeyId(RsaKey* key, word32* keyId); +#endif /* WOLFSSL_SE050 */ WOLFSSL_API int wc_RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng); @@ -349,7 +357,7 @@ WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, word32 eSz, RsaKey* key); #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ - defined(WOLFSSL_KCAPI_RSA) + defined(WOLFSSL_KCAPI_RSA) || defined(WOLFSSL_SE050) WOLFSSL_API int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen); #endif