diff --git a/configure.ac b/configure.ac index 3d493eab9..eca24b329 100644 --- a/configure.ac +++ b/configure.ac @@ -1173,6 +1173,82 @@ AC_ARG_ENABLE([smime], [ ENABLED_SMIME=no ] ) +# Platform Security Architecture (PSA) +AC_ARG_ENABLE([psa], +[AS_HELP_STRING([--enable-psa],[use Platform Security Architecture (PSA) interface (default: disabled)])], +[ ENABLED_PSA=$enableval ], +[ ENABLED_PSA=no ] +) + +AC_ARG_WITH([psa-include], + [AS_HELP_STRING([--with-psa-include=PATH], + [PATH to directory with PSA header files])], + [PSA_INCLUDE=$withval], + [PSA_INCLUDE=""]) + +AC_ARG_WITH([psa-lib], + [AS_HELP_STRING([--with-psa-lib=PATH],[PATH to directory with the PSA library])], + [PSA_LIB=$withval], + [PSA_LIB=""]) + +AC_ARG_WITH([psa-lib-name], + [AS_HELP_STRING([--with-psa-lib-name=NAME],[NAME of PSA library])], + [PSA_LIB_NAME=$withval], + [PSA_LIB_NAME=""]) + +AC_ARG_ENABLE([psa-lib-static], + [AS_HELP_STRING([--enable-psa-lib-static],[Link PSA as static library (default: disable)])], + [ ENABLED_PSA_STATIC=$enableval ], + [ ENABLED_PSA_STATIC=no ] +) + +if test "x$ENABLED_PSA" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_PSA" +fi + +if test "x$ENABLED_PSA" != "xyes" && \ + (test "x$PSA_LIB"! = "x" || test "x$PSA_INCLUDE" != "x" || test "x$PSA_LIB_NAME" != "x" ) +then + AC_MSG_ERROR([to use PSA you need to enable it with --enable-psa]) +fi + +if test -n "$PSA_LIB" +then + AC_MSG_CHECKING([for $PSA_LIB]) + if ! test -d "$PSA_LIB" + then + AC_MSG_ERROR([PSA lib dir $PSA_LIB not found.]) + fi + AC_MSG_RESULT([yes]) + AM_LDFLAGS="$AM_LDFLAGS -L$PSA_LIB" +fi + +if test -n "$PSA_LIB_NAME" +then + if test "x$ENABLED_PSA_STATIC" = "xyes" + then + LIB_STATIC_ADD="$LIB_STATIC_ADD $PSA_LIB/$PSA_LIB_NAME" + else + LIB_ADD="$LIB_ADD -l$PSA_LIB_NAME" + fi +fi + +if test -n "$PSA_INCLUDE" +then + AC_MSG_CHECKING([for $PSA_INCLUDE]) + if ! test -d "$PSA_INCLUDE" + then + AC_MSG_ERROR([psa include dir $PSA_INCLUDE not found.]) + fi + AC_MSG_RESULT([yes]) + AM_CFLAGS="$AM_CFLAGS -I$PSA_INCLUDE" +fi + +AC_SUBST([PSA_LIB]) +AC_SUBST([PSA_LIB_NAME]) +AC_SUBST([PSA_INCLUDE]) + # OPENSSL Compatibility ALL AC_ARG_ENABLE([opensslall], [AS_HELP_STRING([--enable-opensslall],[Enable all OpenSSL API, size++ (default: disabled)])], @@ -7512,6 +7588,7 @@ AM_CONDITIONAL([BUILD_KDF],[test "x$ENABLED_KDF" = "xyes"]) AM_CONDITIONAL([BUILD_HMAC],[test "x$ENABLED_HMAC" = "xyes"]) AM_CONDITIONAL([BUILD_ERROR_STRINGS],[test "x$ENABLED_ERROR_STRINGS" = "xyes"]) AM_CONDITIONAL([BUILD_DO178],[test "x$ENABLED_DO178" = "xyes"]) +AM_CONDITIONAL([BUILD_PSA],[test "x$ENABLED_PSA" = "xyes"]) if test "$ENABLED_REPRODUCIBLE_BUILD" != "yes" && (test "$ax_enable_debug" = "yes" || @@ -7911,6 +7988,7 @@ echo " * i.MX6 CAAM: $ENABLED_CAAM" echo " * IoT-Safe: $ENABLED_IOTSAFE" echo " * IoT-Safe HWRNG: $ENABLED_IOTSAFE_HWRNG" echo " * NXP SE050: $ENABLED_SE050" +echo " * PSA: $ENABLED_PSA" echo "" echo "---" diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index 1bc719dad..e7102a52c 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -226,7 +226,7 @@ If compiled in, the module supports IoT-Safe random number generator as source of entropy for wolfCrypt. - + \defgroup PSA Platform Security Architecture (PSA) API \defgroup Keys Key and Cert Conversion \defgroup Logging Logging \defgroup Math Math API diff --git a/doc/dox_comments/header_files/doxygen_pages.h b/doc/dox_comments/header_files/doxygen_pages.h index 700171d07..39065f819 100644 --- a/doc/dox_comments/header_files/doxygen_pages.h +++ b/doc/dox_comments/header_files/doxygen_pages.h @@ -18,6 +18,7 @@
  • \ref Compression
  • \ref Error
  • \ref IoTSafe
  • +
  • \ref PSA
  • \ref Keys
  • \ref Logging
  • \ref Math
  • diff --git a/doc/dox_comments/header_files/psa.h b/doc/dox_comments/header_files/psa.h new file mode 100644 index 000000000..4259bfa00 --- /dev/null +++ b/doc/dox_comments/header_files/psa.h @@ -0,0 +1,96 @@ +/*! + \ingroup PSA + \brief This function enables PSA support on the given context. + + \param ctx pointer to the WOLFSSL_CTX object on which the PSA support must be enabled + \return WOLFSSL_SUCCESS on success + \return BAD_FUNC_ARG if ctx == NULL + + _Example_ + \code + WOLFSSL_CTX *ctx; + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!ctx) + return NULL; + ret = wolfSSL_CTX_psa_enable(ctx); + if (ret != WOLFSSL_SUCCESS) + printf("can't enable PSA on ctx"); + + \endcode + + \sa wolfSSL_set_psa_ctx +*/ +WOLFSSL_API int wolfSSL_CTX_psa_enable(WOLFSSL_CTX *ctx); + +/*! + \ingroup PSA + + \brief This function setup the PSA context for the given SSL session + + \param ssl pointer to the WOLFSSL where the ctx will be enabled + \param ctx pointer to a struct psa_ssl_ctx (must be unique for a ssl session) + + \return WOLFSSL_SUCCESS on success + \return BAD_FUNC_ARG if ssl or ctx are NULL + + This function setup the PSA context for the TLS callbacks to the given SSL + session. At the end of the session, the resources used by the context + should be freed using wolfSSL_free_psa_ctx(). + + _Example_ + \code + // Create new ssl session + WOLFSSL *ssl; + struct psa_ssl_ctx psa_ctx = { 0 }; + ssl = wolfSSL_new(ctx); + if (!ssl) + return NULL; + // setup PSA context + ret = wolfSSL_set_psa_ctx(ssl, ctx); + \endcode + + \sa wolfSSL_psa_set_private_key_id + \sa wolfSSL_psa_free_psa_ctx +*/ +WOLFSSL_API int wolfSSL_set_psa_ctx(WOLFSSL *ssl, struct psa_ssl_ctx *ctx); + +/*! + \ingroup PSA + \brief This function releases the resources used by a PSA context + + \param ctx pointer to a struct psa_ssl_ctx + + \sa wolfSSL_set_psa_ctx +*/ +WOLFSSL_API void wolfSSL_free_psa_ctx(struct psa_ssl_ctx *ctx); + +/*! + \ingroup PSA + \brief This function set the private key used by an SSL session + + \param ctx pointer to a struct psa_ssl_ctx + \param id PSA id of the key to be used as private key + + _Example_ + \code + // Create new ssl session + WOLFSSL *ssl; + struct psa_ssl_ctx psa_ctx = { 0 }; + psa_key_id_t key_id; + + // key provisioning already done + get_private_key_id(&key_id); + + ssl = wolfSSL_new(ctx); + if (!ssl) + return NULL; + + wolfSSL_psa_set_private_key_id(&psa_ctx, key_id); + wolfSSL_set_psa_ctx(ssl, ctx); + \endcode + + \sa wolfSSL_set_psa_ctx +*/ + +WOLFSSL_API int wolfSSL_psa_set_private_key_id(struct psa_ssl_ctx *ctx, + psa_key_id_t id); diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 58404292c..7c9aacf09 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -76,6 +76,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + #include +#endif + /* fips wrapper calls, user can call direct */ #if defined(HAVE_FIPS) && \ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) @@ -1063,6 +1067,8 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits defined(WOLFSSL_AES_CFB) || defined(HAVE_AES_ECB) #define NEED_AES_TABLES #endif +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) +/* implemented in wolfcrypt/src/port/psa/psa_aes.c */ #else /* using wolfCrypt software implementation */ @@ -2905,6 +2911,11 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( if (keylen > sizeof(aes->key)) { return BAD_FUNC_ARG; } +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + return wc_psa_aes_set_key(aes, userKey, keylen, (uint8_t*)iv, + ((psa_algorithm_t)0), dir); +#endif + rk = aes->key; XMEMCPY(rk, userKey, keylen); #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \ @@ -3910,6 +3921,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #elif defined(WOLFSSL_SILABS_SE_ACCEL) /* implemented in wolfcrypt/src/port/silabs/silabs_hash.c */ +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + /* implemented in wolfcrypt/src/port/psa/psa_aes.c */ + #else /* Software AES - CBC Encrypt */ @@ -4341,6 +4355,8 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* use aes ecnryption plus sw implementation */ #define NEED_AES_CTR_SOFT + #elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + /* implemented in wolfcrypt/src/port/psa/psa_aes.c */ #else /* Use software based AES counter */ @@ -10436,6 +10452,10 @@ int wc_AesInit(Aes* aes, void* heap, int devId) aes->ctrSet = 0; #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + ret = wc_psa_aes_init(aes); +#endif + return ret; } @@ -10534,6 +10554,10 @@ void wc_AesFree(Aes* aes) se050_aes_free(aes); #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + wc_psa_aes_free(aes); +#endif + } @@ -10544,6 +10568,10 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize) if (aes == NULL || keySize == NULL) { return BAD_FUNC_ARG; } + +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + return wc_psa_aes_get_key_size(aes, keySize); +#endif #if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) *keySize = aes->ctx.key.keySize; return ret; diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 5324cf370..593374121 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -184,3 +184,11 @@ endif if BUILD_SE050 src_libwolfssl_la_SOURCES += wolfcrypt/src/port/nxp/se050_port.c endif + +if BUILD_PSA +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/psa/psa.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/psa/psa_hash.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/psa/psa_aes.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/psa/psa_pkcbs.c +endif +EXTRA_DIST += wolfcrypt/src/port/psa/README.md diff --git a/wolfcrypt/src/port/psa/README.md b/wolfcrypt/src/port/psa/README.md new file mode 100644 index 000000000..59bf89bc8 --- /dev/null +++ b/wolfcrypt/src/port/psa/README.md @@ -0,0 +1,115 @@ +wolfSSL using Platform Security Architecture (PSA) +================================================= + +## Overview + +wolfSSL can be configured to use a PSA library for the following operations: +* hashes: SHA-1, SHA-224, SAH-256 +* AES: AES-ECB, AES-CBC, AES-CTR, AES-GCM, AES-CCM +* ECDH PK callbacks (P-256) +* ECDSA PK callbacks (P-256) +* RNG + +Client certificates are not supported. + +## Build +### Basic configuration + +To enable PSA support in wolfSSL you need to provide the name of the library +that implements the PSA interface using `--with-psa-lib-name=LIBNAME`. You may +also provide the path to the library headers (with `--with-psa-include`) and to +to the PSA library itself (with `--with-psa-lib`). As an example, to use mbedtls +PSA implementation you may use: + +``` +./configure --enable-psa --with-psa-include=/dir/to/mbedtls/include --with-psa-lib=/dir/to/mbedtls/library --with-psa-lib-name=mbedcrypto +``` + +### Customize build + +You can switch off some of the algorithms supported using the following defines: + + * `WOLFSSL_PSA_NO_RNG`: disable PSA random generator support + * `WOLFSSL_PSA_NO_HASH`: disable PSA hashing support + * `WOLFSSL_PSA_NO_AES`: disable PSA AES support + * `WOLFSSL_PSA_NO_PKCBS`: disable PK callbacks support + +## Supporting non-thread safe PSA implementation + +If the PSA implementation used is not thread-safe, you can serialize all calls +to the PSA library using the define `WOLFSSL_PSA_GLOBAL_LOCK`. + +## Using PSA PK callbacks + +To use Public Key PSA callbacks you need to enable them using the function: + +`wolfSSL_CTX_psa_enable(WOLFSSL_CTX *ctx)` + +Context information regarding a single SSL session is stored inside a `struct +psa_ssl_ctx`. The user needs to define and setup a `struct psa_ssl_ctx`, then +to attach it to an ssl session with `wolfSSL_set_psa_ctx(WOLFSSL *ssl, struct +psa_ssl_ctx *ctx)`. When the session is over, the application should free the +psa context with `wolfSSL_free_psa_ctx(struct psa_ssl_ctx *ctx)`. + +Example: +``` + struct psa_ssl_ctx psa_ctx = { 0 }; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int ret + + /* WOLFSSL_CTX initialization here */ + + ret = wolfSSL_CTX_psa_enable(ctx); + if (ret != WOLFSSL_SUCCESS) + printf("can't enable PSA on ctx"); + + ssl = wolfSSL_new(ctx); + ret = wolfSSL_set_psa_ctx(ssl, &psa_ctx); + if (ret != WOLFSSL_SUCCESS) + printf("can't enable PSA on ctx"); + + /* SSL communication */ + + wolfSSL_free_psa_ctx(&psa_ctx); + SSL_free(ssl); ssl = NULL; + SSL_CTX_free(ctx); ctx = NULL; +``` + +### Setup server side private key + +On the server side, the private key of the server should be loaded inside the +PSA engine storage. To use the key inside the ssl session you have to invoke +`wolfSSL_psa_set_private_key_id(struct psa_ssl_ctx *ctx, psa_key_id_t id);`. The +key needs to have `PSA_KEY_USAGE_SIGN_HASH` usage flag set. Example: + +``` + psa_key_attributes_t key_attr = { 0 }; + struct psa_ssl_ctx psa_ctx = { 0 }; + psa_key_type_t key_type; + psa_key_id_t key_id; + psa_status_t status; + + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); + + psa_set_key_type(&key_attr, key_type); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY); + + status = psa_import_key(&key_attr, ecc_key_256, + sizeof(ecc_key_256), &key_id); + + if (status != PSA_SUCCESS) { + fprintf(stderr, + "ERROR: provisioning of private key failed: [%d] \n", status); + exit(-1); + } + + wolfSSL_psa_set_private_key_id(&psa_ctx, key_id); +} + +``` + +## Additional note + - AES-GCM, AES-CTR, AES-CCM are not implemented directly. The software + implementation uses the AES-ECB PSA one to implement them. diff --git a/wolfcrypt/src/port/psa/psa.c b/wolfcrypt/src/port/psa/psa.c new file mode 100644 index 000000000..a019d3a5d --- /dev/null +++ b/wolfcrypt/src/port/psa/psa.c @@ -0,0 +1,95 @@ +/* psa.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_HAVE_PSA) + +#include + +#include + +#include +#include + +#if defined(WOLFSSL_PSA_GLOBAL_LOCK) +static wolfSSL_Mutex psa_global_mutex; + +void PSA_LOCK() +{ + /* ideally we should propagate the return error here. Leaving out for code + simplicity for now. */ + wc_LockMutex(&psa_global_mutex); +} + +void PSA_UNLOCK() +{ + wc_UnLockMutex(&psa_global_mutex); +} + +#endif + + +int wc_psa_init() +{ + psa_status_t s; + +#if defined(WOLFSSL_PSA_GLOBAL_LOCK) + wc_InitMutex(&psa_global_mutex); +#endif + + PSA_LOCK(); + s = psa_crypto_init(); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + return 0; +} + +#if !defined(WOLFSSL_PSA_NO_RNG) +/** + * wc_psa_get_random() - generate @size random bytes in @out + * @out: output buffer + * @size: number of random bytes to generate + * + * return: 0 on success + */ +int wc_psa_get_random(unsigned char *out, word32 sz) +{ + psa_status_t s; + + PSA_LOCK(); + s = psa_generate_random((uint8_t*)out, sz); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + return 0; +} +#endif + +#endif /* WOLFSSL_HAVE_PSA */ diff --git a/wolfcrypt/src/port/psa/psa_aes.c b/wolfcrypt/src/port/psa/psa_aes.c new file mode 100644 index 000000000..e69ea9969 --- /dev/null +++ b/wolfcrypt/src/port/psa/psa_aes.c @@ -0,0 +1,351 @@ +/* psa_aes.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_HAVE_PSA) +#if !defined(WOLFSSL_PSA_NO_AES) +#if !defined(NO_AES) + +#include +#include +#include + +#ifndef NO_INLINE +#define WOLFSSL_MISC_INCLUDED +#include +#else +#include +#endif + +static int wc_psa_aes_import_key(Aes *aes, const uint8_t *key, + size_t key_length, psa_algorithm_t alg, + int dir) +{ + psa_key_attributes_t key_attr; + psa_key_id_t id; + psa_status_t s; + + XMEMSET(&key_attr, 0, sizeof(key_attr)); + aes->key_id = 0; + aes->ctx_initialized = 0; + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); + psa_set_key_usage_flags(&key_attr, + dir == AES_ENCRYPTION ? PSA_KEY_USAGE_ENCRYPT : + dir == AES_DECRYPTION ? PSA_KEY_USAGE_DECRYPT : 0); + psa_set_key_algorithm(&key_attr, alg); + + PSA_LOCK(); + s = psa_import_key(&key_attr, key, key_length, &id); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + aes->key_id = id; + aes->key_need_importing = 0; + + return 0; +} + +/** + * wc_psa_aes_init() - init @aes PSA resources + * @aes: Aes object + */ +int wc_psa_aes_init(Aes *aes) +{ + aes->key_id = 0; + aes->ctx_initialized = 0; + aes->key_need_importing = 0; + XMEMSET(&aes->psa_ctx, 0, sizeof(aes->psa_ctx)); + return 0; +} + +/** + * wc_psa_aes_get_key_size() - get the size of the key in @aes + * @aes: Aes object + * @keySize: where to store the size of the key + * + * returns: 0 on success + */ +int wc_psa_aes_get_key_size(Aes *aes, word32 *keySize) +{ + psa_key_attributes_t attr; + psa_status_t s; + + if (aes->key_need_importing == 1) { + *keySize = aes->keylen; + return 0; + } + + if (aes->key_id == PSA_KEY_ID_NULL) + return BAD_FUNC_ARG; + + PSA_LOCK(); + s = psa_get_key_attributes(aes->key_id, &attr); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + *keySize = (word32)(psa_get_key_bits(&attr) / 8); + PSA_LOCK(); + psa_reset_key_attributes(&attr); + PSA_UNLOCK(); + return 0; +} + +/** + * wc_psa_aes_set_key() - set key / iv to object *aes + * @aes: object to set the key into + * @key: key to import + * @key_length: size of the key in bytes + * @iv: IV (can be null) + * @alg: algorithm (mode) to use with this key (can be 0) + * @dir: direction to use with this key + * + * + * NOTE: if we don't know for teh mode or the direction (@alg == 0) the key + * import operation will be delayed until the first wc_psa_aes_encrypt_decrypt() + * invocation. In this case the key is temporary stored inside the AES + * object. Indeed PSA requires that the mode of operation is already known when + * importing a new key. + * + * returns: 0 on success, WC_HW_E on PSA error +*/ +int wc_psa_aes_set_key(Aes *aes, const uint8_t *key, size_t key_length, + uint8_t *iv, psa_algorithm_t alg, int dir) +{ + psa_status_t s; + int ret; + + /* the object was already used for other encryption. Reset the context */ + if (aes->ctx_initialized) { + PSA_LOCK(); + s = psa_cipher_abort(&aes->psa_ctx); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + aes->ctx_initialized =0; + } + + /* a key was already imported, destroy it first */ + if (aes->key_id != PSA_KEY_ID_NULL) { + PSA_LOCK(); + psa_destroy_key(aes->key_id); + PSA_UNLOCK(); + + aes->key_id = PSA_KEY_ID_NULL; + } + + /* we have been invoked from a generic wcSetKey. We don't know the mode that + will be used, so we can't import the key in PSA yet. Let's copy the key + inside the object, we will import it when we'll know the cipher mode */ + if (alg == PSA_ALG_NONE) { + XMEMCPY(aes->key, key, key_length); + aes->key_need_importing = 1; + } else { + PSA_LOCK(); + ret = wc_psa_aes_import_key(aes, key, key_length, alg, dir); + PSA_UNLOCK(); + if (ret != 0) + return ret; + } + + return wc_AesSetIV(aes, iv); +} + +/** + * wc_psa_aes_encrypt_decrypt() - do an encrypt/decrypt step + * @aes: Aes object + * @input: input data + * @output: where to store the result of the operation + * @length: size of the input data + * @alg: algorithm (mode) to use in the operation + * @direction: either @AES_ENCRYPT or @AES_DECRYPT + * + * returns: + * 0 on success + * BAD_FUNC_ARG for bad argument + * WC_HW_E for PSA error + */ +int wc_psa_aes_encrypt_decrypt(Aes *aes, const uint8_t *input, + uint8_t *output, size_t length, + psa_algorithm_t alg, int direction) +{ + size_t output_length; + psa_status_t s; + int r; + + if (aes == NULL || input == NULL || output == NULL) + return BAD_FUNC_ARG; + + /* This is the first time we invoke encrypt/decrypt */ + if (aes->ctx_initialized == 0) { + + /* import the key */ + if (aes->key_need_importing == 1) { + r = wc_psa_aes_import_key(aes, (uint8_t*)aes->key, aes->keylen, + alg, direction); + if (r != 0) + return r; + + ForceZero(aes->key, aes->keylen); + aes->key_need_importing = 0; + aes->keylen = 0; + } + + if (direction == AES_ENCRYPTION) { + PSA_LOCK(); + s = psa_cipher_encrypt_setup(&aes->psa_ctx, aes->key_id, alg); + PSA_UNLOCK(); + } else { + PSA_LOCK(); + s = psa_cipher_decrypt_setup(&aes->psa_ctx, aes->key_id, alg); + PSA_UNLOCK(); + } + + if (s != PSA_SUCCESS) + goto err; + + aes->ctx_initialized = 1; + + /* ECB doesn't use IV */ + if (alg != PSA_ALG_ECB_NO_PADDING) { + + /* wc_SetIV stores the IV in reg */ + PSA_LOCK(); + s = psa_cipher_set_iv(&aes->psa_ctx, + (uint8_t*)aes->reg, AES_IV_SIZE); + PSA_UNLOCK(); + + if (s != PSA_SUCCESS) + goto err; + } + + } + + PSA_LOCK(); + s = psa_cipher_update(&aes->psa_ctx, input, + length, output, length, &output_length); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + goto err; + + if (output_length != length) + goto err; + + return 0; + + err: + wc_psa_aes_free(aes); + return WC_HW_E; + } + +/** + * wc_psa_aes_free() - PSA cipher cleanup + * @aes: the Aes object to cleanup + */ +int wc_psa_aes_free(Aes *aes) +{ + if (aes->key_id != PSA_KEY_ID_NULL) { + PSA_LOCK(); + psa_destroy_key(aes->key_id); + PSA_UNLOCK(); + aes->key_id = PSA_KEY_ID_NULL; + } + + if (aes->ctx_initialized == 1) { + PSA_LOCK(); + psa_cipher_abort(&aes->psa_ctx); + PSA_UNLOCK(); + aes->ctx_initialized = 0; + } + + aes->ctx_initialized = 0; + aes->key_need_importing = 0; + + return 0; +} + +int wc_AesEncrypt(Aes *aes, const byte *inBlock, byte *outBlock) +{ + return wc_psa_aes_encrypt_decrypt(aes, inBlock, outBlock, + AES_BLOCK_SIZE, PSA_ALG_ECB_NO_PADDING, + AES_ENCRYPTION); +} + +#if defined(HAVE_AES_DECRYPT) +int wc_AesDecrypt(Aes *aes, const byte *inBlock, byte *outBlock) +{ + return wc_psa_aes_encrypt_decrypt(aes, inBlock, outBlock, + AES_BLOCK_SIZE, PSA_ALG_ECB_NO_PADDING, + AES_DECRYPTION); +} +#endif + +#if defined(WOLFSSL_AES_COUNTER) + +int wc_AesCtrEncrypt(Aes *aes, byte *out, const byte *in, word32 sz) +{ + return wc_psa_aes_encrypt_decrypt(aes, in, out, sz, PSA_ALG_CTR, + AES_ENCRYPTION); +} +#endif + +#if defined (HAVE_AES_CBC) +int wc_AesCbcEncrypt(Aes *aes, byte *out, const byte *in, word32 sz) +{ + + if (sz % AES_BLOCK_SIZE != 0) +#if defined (WOLFSSL_AES_CBC_LENGTH_CHECKS) + return BAD_LENGTH_E; +#else + return BAD_FUNC_ARG; +#endif + + return wc_psa_aes_encrypt_decrypt(aes, in, out, sz, + PSA_ALG_CBC_NO_PADDING, + AES_ENCRYPTION); +} + +int wc_AesCbcDecrypt(Aes *aes, byte *out, const byte *in, word32 sz) +{ + + if (sz % AES_BLOCK_SIZE != 0) +#if defined (WOLFSSL_AES_CBC_LENGTH_CHECKS) + return BAD_LENGTH_E; +#else + return BAD_FUNC_ARG; +#endif + + return wc_psa_aes_encrypt_decrypt(aes, in, out, sz, + PSA_ALG_CBC_NO_PADDING, + AES_DECRYPTION); +} +#endif /* HAVE_AES_CBC */ + +#endif /* ! NO_AES */ +#endif /* ! WOLFSSL_PSA_NO_AES */ +#endif /* WOLFSSL_HAVE_PSA */ diff --git a/wolfcrypt/src/port/psa/psa_hash.c b/wolfcrypt/src/port/psa/psa_hash.c new file mode 100644 index 000000000..9d3e678ea --- /dev/null +++ b/wolfcrypt/src/port/psa/psa_hash.c @@ -0,0 +1,305 @@ +/* psa_hash.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + +#if !defined(NO_SHA) +#include +#endif + +#if !defined(NO_SHA256) +#include +#endif + +#include +#include + +#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA224) +static int wc_psa_hash_init_and_setup(psa_hash_operation_t *ctx, + psa_algorithm_t alg) +{ + psa_status_t s; + + if (ctx == NULL) + return BAD_FUNC_ARG; + + XMEMSET(ctx, 0, sizeof(*ctx)); + + PSA_LOCK(); + s = psa_hash_setup(ctx, alg); + PSA_UNLOCK(); + + if (s != PSA_SUCCESS) { + PSA_LOCK(); + psa_hash_abort(ctx); + PSA_UNLOCK(); + return WC_HW_E; + } + + return 0; +} + +static int wc_psa_hash_update(psa_hash_operation_t *ctx, const uint8_t *input, + size_t input_length) +{ + psa_status_t s; + + if (ctx == NULL || (input == NULL && input_length > 0)) + return BAD_FUNC_ARG; + + PSA_LOCK(); + s = psa_hash_update(ctx, input, input_length); + PSA_UNLOCK(); + + if (s != PSA_SUCCESS) { + PSA_LOCK(); + psa_hash_abort(ctx); + PSA_UNLOCK(); + return WC_HW_E; + } + + return 0; +} + +static int wc_psa_hash_finish_setup(psa_hash_operation_t *ctx, + uint8_t *output, psa_algorithm_t alg) +{ + size_t hash_length; + psa_status_t s; + + if (ctx == NULL || output == NULL) + return BAD_FUNC_ARG; + + PSA_LOCK(); + s = psa_hash_finish(ctx, output, PSA_HASH_LENGTH(alg), &hash_length); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) { + PSA_LOCK(); + psa_hash_abort(ctx); + PSA_UNLOCK(); + return WC_HW_E; + } + + PSA_LOCK(); + s = psa_hash_setup(ctx, alg); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) { + PSA_LOCK(); + psa_hash_abort(ctx); + PSA_UNLOCK(); + return WC_HW_E; + } + + return 0; +} + +static int wc_psa_hash_clone(const psa_hash_operation_t *src, + psa_hash_operation_t *dst) +{ + psa_status_t s; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + PSA_LOCK(); + psa_hash_abort(dst); + PSA_UNLOCK(); + + PSA_LOCK(); + s = psa_hash_clone(src, dst); + PSA_UNLOCK(); + + if (s != PSA_SUCCESS) + return WC_HW_E; + + return 0; +} + +static int wc_psa_hash_abort(psa_hash_operation_t *ctx) +{ + psa_status_t s; + + if (ctx == NULL) + return BAD_FUNC_ARG; + + PSA_LOCK(); + s = psa_hash_abort(ctx); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) + return WC_HW_E; + + return 0; +} + +static int wc_psa_get_hash(psa_hash_operation_t *ctx, + uint8_t *out, psa_algorithm_t alg) +{ + psa_hash_operation_t tmp; + size_t hash_length; + psa_status_t s; + + (void)hash_length; + + if (ctx == NULL || out == NULL) + return BAD_FUNC_ARG; + + XMEMSET(&tmp, 0, sizeof(tmp)); + PSA_LOCK(); + s = psa_hash_clone(ctx, &tmp); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) { + psa_hash_abort(&tmp); + return WC_HW_E; + } + + PSA_LOCK(); + s = psa_hash_finish(&tmp, out, PSA_HASH_LENGTH(alg), &hash_length); + PSA_UNLOCK(); + if (s != PSA_SUCCESS) { + PSA_LOCK(); + psa_hash_abort(&tmp); + PSA_UNLOCK(); + return WC_HW_E; + } + + return 0; +} +#endif /* !defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA224)*/ + +#if !defined(NO_SHA) + +int wc_InitSha_ex(wc_Sha *sha, void *heap, int devId) +{ + (void)heap; + (void)devId; + + return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_1); +} + +int wc_ShaUpdate(wc_Sha *sha, const byte *in, word32 size) +{ + return wc_psa_hash_update(&sha->psa_ctx, in, size); +} + +int wc_ShaFinal(wc_Sha *sha, byte *out) +{ + return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_1); +} + +int wc_ShaGetHash(wc_Sha *sha, byte *out) +{ + + return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_1); +} + +int wc_ShaCopy(wc_Sha *src, wc_Sha *dst) +{ + return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx); +} + +void wc_ShaFree(wc_Sha *sha) +{ + wc_psa_hash_abort(&sha->psa_ctx); +} +#endif /* !NO_SHA */ + +#if !defined(NO_SHA256) + +int wc_InitSha256_ex(wc_Sha256 *sha, void *heap, int devId) +{ + (void)heap; + (void)devId; + + return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_256); +} + +int wc_Sha256Update(wc_Sha256 *sha, const byte *in, word32 size) +{ + return wc_psa_hash_update(&sha->psa_ctx, in, size); +} + +int wc_Sha256Final(wc_Sha256 *sha, byte *out) +{ + return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_256); +} + +int wc_Sha256GetHash(wc_Sha256 *sha, byte *out) +{ + return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_256); +} + +int wc_Sha256Copy(wc_Sha256 *src, wc_Sha256 *dst) +{ + return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx); +} + +void wc_Sha256Free(wc_Sha256 *sha) +{ + wc_psa_hash_abort(&sha->psa_ctx); +} + +#endif /* !NO_SHA256 */ + +#if defined(WOLFSSL_SHA224) + +int wc_InitSha224_ex(wc_Sha224 *sha, void *heap, int devId) +{ + (void)heap; + (void)devId; + + return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_224); +} + +int wc_Sha224Update(wc_Sha224 *sha, const byte *in, word32 size) +{ + return wc_psa_hash_update(&sha->psa_ctx, in, size); +} + +int wc_Sha224Final(wc_Sha224 *sha, byte *out) +{ + return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_224); +} + +int wc_Sha224GetHash(wc_Sha224 *sha, byte *out) +{ + return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_224); +} + +int wc_Sha224Copy(wc_Sha224 *src, wc_Sha224 *dst) +{ + return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx); +} + +void wc_Sha224Free(wc_Sha224 *sha) +{ + wc_psa_hash_abort(&sha->psa_ctx); +} + +#endif /* WOLFSSL_SHA224 */ + +#endif /* WOLFSSL_HAVE_PSA && !WOLFSSL_PSA_NO_HASH */ diff --git a/wolfcrypt/src/port/psa/psa_pkcbs.c b/wolfcrypt/src/port/psa/psa_pkcbs.c new file mode 100644 index 000000000..12a69a667 --- /dev/null +++ b/wolfcrypt/src/port/psa/psa_pkcbs.c @@ -0,0 +1,546 @@ +/* psa_pkcbs.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_HAVE_PSA) +#if defined(HAVE_PK_CALLBACKS) +#if !defined(WOLFSSL_PSA_NO_PKCBS) + +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_ECC + +#include + +static int psa_ecc_get_curve_info_from_curve_id(int ecc_curve, + psa_ecc_family_t *family, + size_t *key_size) +{ + if (ecc_curve != ECC_SECP256R1) + return NOT_COMPILED_IN; + + *family = PSA_ECC_FAMILY_SECP_R1; + if (key_size != NULL) + *key_size = 32; + + return 0; +} + +/** + * psa_ecc_export_to_wc_key() - export psa @key_id into ecc_key @key + * @key: already initialized ecc_key to export the key into [out] + * @key_id: key to export [in] + * @key_size: size fo the key [in] + * @curve_id: wc id of the curve [in] + * + * returns 0 on success + */ +static int psa_ecc_export_to_wc_key(struct ecc_key *key, + psa_key_id_t key_id, + int curve_id) +{ + uint8_t raw[(MAX_ECC_BYTES * 2) + 1]; + psa_status_t status; + size_t length; + int ret; + + PSA_LOCK(); + status = psa_export_public_key(key_id, + raw, sizeof(raw), &length); + PSA_UNLOCK(); + + if (status != PSA_SUCCESS) { + WOLFSSL_MSG("PSA: export key error"); + return WC_HW_E; + } + + ret = wc_ecc_import_x963_ex(raw, (word32)length, key, curve_id); + if (ret != 0) { + WOLFSSL_MSG("PSA: import key error"); + return WC_HW_E; + } + + return 0; +} + +static int psa_ecc_keygen(int ecc_curve, unsigned key_size, + psa_key_id_t *key_id) +{ + psa_key_attributes_t key_attr = { 0 }; + size_t ecc_curve_key_size; + psa_ecc_family_t family; + psa_status_t status; + int ret; + + ret = psa_ecc_get_curve_info_from_curve_id(ecc_curve, &family, + &ecc_curve_key_size); + if (ret != 0) + return ret; + + if (key_size != 0 && key_size != ecc_curve_key_size) + return BAD_FUNC_ARG; + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(family)); + psa_set_key_bits(&key_attr, ecc_curve_key_size * 8); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE); + + PSA_LOCK(); + status = psa_generate_key(&key_attr, key_id); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) + return WC_HW_E; + + return 0; +} + +static int psa_ecc_keygen_cb(WOLFSSL* ssl, struct ecc_key* key, + unsigned int key_size, int ecc_curve, void* ctx) +{ + struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx *)ctx; + psa_key_id_t psa_key_id; + int ret; + + (void)ssl; + + WOLFSSL_ENTER("psa_ecc_keygen_cb"); + + if (psa_ctx == NULL) + return BAD_FUNC_ARG; + + ret = psa_ecc_keygen(ecc_curve, key_size, &psa_key_id); + if (ret != 0) + return WC_HW_E; + + ret = psa_ecc_export_to_wc_key(key, psa_key_id, ecc_curve); + if (ret != 0) { + PSA_LOCK(); + psa_destroy_key(psa_key_id); + PSA_UNLOCK(); + return WC_HW_E; + } + + psa_ctx->dh_key = psa_key_id; + + return 0; +} + +static int psa_ecc_shared_secret_tls12_client(struct ecc_key* other_key, + unsigned char* pubKeyDer, + word32* pubKeySz, + unsigned char* out, + word32* output_size) +{ + uint8_t raw[(MAX_ECC_BYTES * 2) + 1]; + psa_status_t status; + word32 raw_length; + psa_key_id_t key; + size_t length; + int ret; + + ret = psa_ecc_keygen(other_key->dp->id, 0, &key); + if (ret != 0) + return ret; + + PSA_LOCK(); + status = psa_export_public_key(key, pubKeyDer, *pubKeySz, &length); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) { + ret = WC_HW_E; + goto exit; + } + + *pubKeySz = (word32)length; + + raw_length = (word32)sizeof(raw); + ret = wc_ecc_export_x963_ex(other_key, raw, &raw_length, 0); + if (ret != 0) + goto exit; + + PSA_LOCK(); + status = psa_raw_key_agreement(PSA_ALG_ECDH, key, + raw, raw_length, + out, *output_size, + &length); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) { + ret = WC_HW_E; + goto exit; + } + + *output_size = (word32)length; + ret = 0; + + exit: + PSA_LOCK(); + psa_destroy_key(key); + PSA_UNLOCK(); + + return ret; +} + +static int psa_ecc_shared_secret_cb(WOLFSSL* ssl, struct ecc_key* other_key, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* output_size, + int side, void* ctx) +{ + struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx *)ctx; + size_t output_length; + psa_status_t status; + + if (psa_ctx == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_ENTER("psa_ecc_shared_secret_cb"); + + /* client before tls13 must create the key and export it in pubkeyDer. The + server key is stored in other_key */ + if (side == WOLFSSL_CLIENT_END && + wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { + return psa_ecc_shared_secret_tls12_client(other_key, + pubKeyDer, pubKeySz, + out, output_size); + } + + PSA_LOCK(); + status = psa_raw_key_agreement(PSA_ALG_ECDH, + psa_ctx->dh_key, + pubKeyDer, + *pubKeySz, + out, *output_size, + &output_length); + PSA_UNLOCK(); + + if (status != PSA_SUCCESS) { + WOLFSSL_MSG("PSA: error raw_key_agreement"); + return WC_HW_E; + } + + *output_size = (word32)output_length; + + PSA_LOCK(); + psa_destroy_key(psa_ctx->dh_key); + PSA_UNLOCK(); + + psa_ctx->dh_key = PSA_KEY_ID_NULL; + + return 0; +} + +static int psa_ecc_sign_cb(WOLFSSL* ssl, const unsigned char* input, + unsigned int input_length, + unsigned char* signature, word32* signature_size, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx*)ctx; + uint8_t rs[MAX_ECC_BYTES * 2]; + psa_status_t status; + size_t rs_length; + word32 point_len; + int ret; + + (void)ssl; + (void)keyDer; + (void)keySz; + + WOLFSSL_ENTER("psa_ecc_sign_cb"); + + if (psa_ctx == NULL) + return BAD_FUNC_ARG; + + status = psa_sign_hash(psa_ctx->private_key, + PSA_ALG_ECDSA_ANY, input, + input_length, rs, sizeof(rs), + &rs_length); + if (status != PSA_SUCCESS) + return WC_HW_E; + + point_len = (word32)(rs_length / 2); + ret = wc_ecc_rs_raw_to_sig(rs, point_len, rs + point_len, point_len, + signature, signature_size); + if (ret != 0) + return -1; + + return 0; +} + +static int psa_ecc_decode_public_key(const uint8_t *key, word32 key_length, + psa_key_id_t *key_id) +{ + uint8_t raw_key[(MAX_ECC_BYTES * 2) + 1]; + psa_key_attributes_t attr = { 0 }; + word32 raw_key_length, idx; + psa_ecc_family_t ecc_curve; + size_t ecc_curve_size; + psa_status_t status; + ecc_key tmp_key; + int ret; + + ret = wc_ecc_init(&tmp_key); + if (ret != 0 ) + return ret; + + idx = 0; + ret = wc_EccPublicKeyDecode(key, &idx, &tmp_key, key_length); + if (ret != 0 ) + goto exit; + + raw_key_length = (word32)sizeof(raw_key); + ret = wc_ecc_export_x963_ex(&tmp_key, raw_key, &raw_key_length, 0); + if (ret != 0 ) + goto exit; + + ret = psa_ecc_get_curve_info_from_curve_id(tmp_key.dp->id, + &ecc_curve, &ecc_curve_size); + if (ret != 0 ) + goto exit; + + psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(ecc_curve)); + psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_bits(&attr, ecc_curve_size * 8); + psa_set_key_algorithm(&attr, PSA_ALG_ECDSA_ANY); + + PSA_LOCK(); + status = psa_import_key(&attr, raw_key, raw_key_length, key_id); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) { + WOLFSSL_MSG("psa_ecc_decode_public_key: can't import the key"); + ret = WC_HW_E; + goto exit; + } + + ret = 0; + +exit: + wc_ecc_free(&tmp_key); + return ret; +} + +static int psa_ecc_verify_cb(WOLFSSL* ssl, const byte* sig, word32 sig_length, + const byte* hash, word32 hash_length, + const byte* key, word32 key_length, + int* result, void* ctx) +{ + uint8_t raw_signature[MAX_ECC_BYTES * 2], *s; + psa_key_id_t tmp_key; + word32 r_len, s_len; + psa_status_t status; + int ret; + + (void)ssl; + (void)ctx; + WOLFSSL_ENTER("psa_ecc_verify_cb"); + + ret = psa_ecc_decode_public_key(key, key_length, &tmp_key); + if (ret != 0) + return ret; + + r_len = s_len = MAX_ECC_BYTES; + s = raw_signature + r_len; + ret = wc_ecc_sig_to_rs(sig, sig_length, raw_signature, &r_len, + s, &s_len); + if (ret != 0) + goto exit; + + /* coalescence of r and s in the buffer */ + XMEMCPY(raw_signature + r_len, s, s_len); + + PSA_LOCK(); + status = psa_verify_hash(tmp_key, PSA_ALG_ECDSA_ANY, hash, + hash_length, raw_signature, r_len + s_len); + PSA_UNLOCK(); + + if (status == PSA_SUCCESS) { + *result = 1; + } else { + *result = 0; + + if (status != PSA_ERROR_INVALID_SIGNATURE) { + WOLFSSL_MSG("psa_ecc_verify_cb: can't verify hash"); + ret = WC_HW_E; + } + + /* returns 0 for invalid signature as well */ + } + + exit: + PSA_LOCK(); + psa_destroy_key(tmp_key); + PSA_UNLOCK(); + + return ret; +} +#endif /* HAVE_ECC */ + +#ifdef HAVE_HKDF +static int psa_hkdf_extract_cb(byte* prk, const byte* salt, + word32 salt_length, byte* ikm, + word32 ikm_length, int digest, + void* ctx) +{ + psa_key_attributes_t attr = { 0 }; + psa_algorithm_t hash; + psa_key_id_t tmp_key; + psa_status_t status; + size_t digest_len; + + (void)ctx; + + WOLFSSL_ENTER("psa hkdf cb"); + + if (salt_length != 0 && salt == NULL) + return BAD_FUNC_ARG; + + switch (digest) { +#ifndef NO_SHA256 + case WC_SHA256: + digest_len = WC_SHA256_DIGEST_SIZE; + hash = PSA_ALG_SHA_256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case WC_SHA384: + digest_len = WC_SHA384_DIGEST_SIZE; + hash = PSA_ALG_SHA_384; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC); + psa_set_key_algorithm(&attr, PSA_ALG_HMAC(hash)); + psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE); + + /* salt not provided, use zeroed digest len string. Use temporarily the prk + buffer as we are sure is big enough */ + if (salt == NULL) { + XMEMSET(prk, 0, digest_len); + salt = prk; + salt_length = (word32)digest_len; + } + + /* When length is 0 then use zeroed data of digest length. */ + if (ikm_length == 0) { + ikm_length = (word32)digest_len; + XMEMSET(ikm, 0, digest_len); + } + + PSA_LOCK(); + status = psa_import_key(&attr, salt, salt_length, &tmp_key); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) { + WOLFSSL_MSG("psa_hkdf_cb: failed to import tmp key"); + return WC_HW_E; + } + + PSA_LOCK(); + status = psa_mac_compute(tmp_key, PSA_ALG_HMAC(hash), + ikm, ikm_length, prk, digest_len, + &digest_len); + PSA_UNLOCK(); + if (status != PSA_SUCCESS) { + WOLFSSL_MSG("psa_hkdf_cb: failed to compute hashed mac"); + PSA_LOCK(); + psa_destroy_key(tmp_key); + PSA_UNLOCK(); + return WC_HW_E; + } + + PSA_LOCK(); + psa_destroy_key(tmp_key); + PSA_UNLOCK(); + + return 0; +} +#endif /* HAVE_HKDF */ + +int wolfSSL_psa_set_private_key_id(struct psa_ssl_ctx *ctx, psa_key_id_t id) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + if (id == PSA_KEY_ID_NULL) + return BAD_FUNC_ARG; + + ctx->private_key = id; + + return WOLFSSL_SUCCESS; +} + +void wolfSSL_free_psa_ctx(struct psa_ssl_ctx *ctx) +{ + if (ctx->dh_key != PSA_KEY_ID_NULL) { + PSA_LOCK(); + psa_destroy_key(ctx->dh_key); + PSA_UNLOCK(); + ctx->dh_key = PSA_KEY_ID_NULL; + } +} + +int wolfSSL_set_psa_ctx(WOLFSSL *ssl, struct psa_ssl_ctx *ctx) +{ + if (ctx == NULL || ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_ECC + wolfSSL_SetEccSignCtx(ssl, ctx); + wolfSSL_SetEccKeyGenCtx(ssl, ctx); + wolfSSL_SetEccSharedSecretCtx(ssl, ctx); + wolfSSL_SetEccVerifyCtx(ssl, ctx); +#endif +#ifdef HAVE_HKDF + wolfSSL_SetHKDFExtractCtx(ssl, ctx); +#endif + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_psa_enable(WOLFSSL_CTX *ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_ECC + wolfSSL_CTX_SetEccSignCb(ctx, psa_ecc_sign_cb); + wolfSSL_CTX_SetEccKeyGenCb(ctx, psa_ecc_keygen_cb); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, psa_ecc_shared_secret_cb); + wolfSSL_CTX_SetEccVerifyCb(ctx, psa_ecc_verify_cb); +#endif +#ifdef HAVE_HKDF + wolfSSL_CTX_SetHKDFExtractCb(ctx, psa_hkdf_extract_cb); +#endif + return WOLFSSL_SUCCESS; +} + +#endif /* !WOLFSSL_PSA_NO_PKCBS */ +#endif /* HAVE_PK_CALLBACKS */ +#endif /* WOLFSSL_HAVE_PSA */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 35ee476bf..330308160 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -177,6 +177,10 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) #include #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_RNG) +#include +#endif + #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) static word32 intel_flags = 0; static void wc_InitRng_IntelRD(void) diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 9df07ef14..bc38ae4f6 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -370,6 +370,8 @@ return ret; } +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) +/* implemented in wolfcrypt/src/port/psa/psa_hash.c */ #else /* Software implementation */ #define USE_SHA_SOFTWARE_IMPL @@ -832,6 +834,8 @@ int wc_InitSha(wc_Sha* sha) return wc_InitSha_ex(sha, NULL, INVALID_DEVID); } +#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) + void wc_ShaFree(wc_Sha* sha) { if (sha == NULL) @@ -859,6 +863,7 @@ void wc_ShaFree(wc_Sha* sha) #endif } +#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ #endif /* !WOLFSSL_TI_HASH */ #endif /* HAVE_FIPS */ @@ -866,6 +871,8 @@ void wc_ShaFree(wc_Sha* sha) #if !defined(WOLFSSL_RENESAS_TSIP_CRYPT) || \ defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) + +#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) int wc_ShaGetHash(wc_Sha* sha, byte* hash) { int ret; @@ -929,7 +936,7 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) } #endif /* defined(WOLFSSL_RENESAS_TSIP_CRYPT) ... */ #endif /* !WOLFSSL_TI_HASH && !WOLFSSL_IMXRT_DCP */ - +#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ #ifdef WOLFSSL_HASH_FLAGS int wc_ShaSetFlags(wc_Sha* sha, word32 flags) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 6f9ea6191..45dcb433f 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -185,7 +185,8 @@ where 0 <= L < 2^64. (!defined(WOLFSSL_RENESAS_TSIP_CRYPT) || defined(NO_WOLFSSL_RENESAS_TSIP_HASH)) && \ !defined(WOLFSSL_PSOC6_CRYPTO) && !defined(WOLFSSL_IMXRT_DCP) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \ !defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_SE050_HASH) && \ - (!defined(WOLFSSL_RENESAS_SCEPROTECT) || defined(NO_WOLFSSL_RENESAS_SCEPROTECT_HASH)) + (!defined(WOLFSSL_RENESAS_SCEPROTECT) || defined(NO_WOLFSSL_RENESAS_SCEPROTECT_HASH)) && \ + (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) @@ -765,6 +766,9 @@ static int InitSha256(wc_Sha256* sha256) #elif defined(WOLFSSL_KCAPI_HASH) /* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */ +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ + #else #define NEED_SOFT_SHA256 @@ -1459,6 +1463,9 @@ static int InitSha256(wc_Sha256* sha256) #elif defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_NO_KCAPI_SHA224) /* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */ +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ + #else #define NEED_SOFT_SHA224 @@ -1582,6 +1589,9 @@ static int InitSha256(wc_Sha256* sha256) return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); } +#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ + void wc_Sha224Free(wc_Sha224* sha224) { if (sha224 == NULL) @@ -1606,6 +1616,7 @@ static int InitSha256(wc_Sha256* sha256) #endif } #endif /* WOLFSSL_SHA224 */ +#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ int wc_InitSha256(wc_Sha256* sha256) @@ -1613,6 +1624,9 @@ int wc_InitSha256(wc_Sha256* sha256) return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); } +#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ + void wc_Sha256Free(wc_Sha256* sha256) { if (sha256 == NULL) @@ -1664,6 +1678,7 @@ void wc_Sha256Free(wc_Sha256* sha256) #endif } +#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ #endif /* !WOLFSSL_TI_HASH */ #endif /* HAVE_FIPS */ @@ -1673,6 +1688,8 @@ void wc_Sha256Free(wc_Sha256* sha256) #if defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_NO_KCAPI_SHA224) /* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */ +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ #else @@ -1762,6 +1779,9 @@ void wc_Sha256Free(wc_Sha256* sha256) #elif defined(WOLFSSL_KCAPI_HASH) /* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */ +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + /* implemented in wolfcrypt/src/port/psa/psa_hash.c */ + #else int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 695ea7e2f..bd3a27d0c 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -112,6 +112,11 @@ #pragma warning(disable: 4996) #endif +#if defined(WOLFSSL_HAVE_PSA) + #include +#endif + + /* prevent multiple mutex initializations */ static volatile int initRefCount = 0; @@ -270,6 +275,11 @@ int wolfCrypt_Init(void) } #endif + #if defined(WOLFSSL_HAVE_PSA) + if ((ret = wc_psa_init()) != 0) + return ret; + #endif + #ifdef HAVE_ECC #ifdef FP_ECC wc_ecc_fp_init(); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 56818857b..e9de88aff 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7702,11 +7702,14 @@ static int aes_key_size_test(void) ERROR_OUT(-5307, out); /* CryptoCell handles rounds internally */ #if !defined(HAVE_FIPS) && !defined(WOLFSSL_CRYPTOCELL) + /* PSA don't use aes->rounds */ +#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_AES) /* Force invalid rounds */ aes->rounds = 16; ret = wc_AesGetKeySize(aes, &keySize); if (ret != BAD_FUNC_ARG) ERROR_OUT(-5308, out); +#endif #endif ret = wc_AesSetKey(aes, key16, sizeof(key16), iv, AES_ENCRYPTION); @@ -7909,7 +7912,6 @@ static int aes_xts_128_test(void) ERROR_OUT(-5410, out); if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) ERROR_OUT(-5411, out); - wc_AesXtsFree(aes); /* fail case with decrypting using wrong key */ XMEMSET(buf, 0, sizeof(buf)); @@ -7922,6 +7924,8 @@ static int aes_xts_128_test(void) if (XMEMCMP(p2, buf, sizeof(p2)) == 0) /* fail case with wrong key */ ERROR_OUT(-5413, out); + wc_AesXtsFree(aes); + /* set correct key and retest */ XMEMSET(buf, 0, sizeof(buf)); if (wc_AesXtsSetKey(aes, k2, sizeof(k2), AES_DECRYPTION, diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 18f2cd0b8..921b3219c 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -96,6 +96,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) +#include +#endif + #if defined(WOLFSSL_CRYPTOCELL) #include #endif @@ -270,6 +274,12 @@ struct Aes { #endif #if defined(WOLFSSL_SILABS_SE_ACCEL) silabs_aes_t ctx; +#endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + psa_key_id_t key_id; + psa_cipher_operation_t psa_ctx; + int ctx_initialized; + int key_need_importing; #endif void* heap; /* memory hint to use */ #ifdef WOLFSSL_AESGCM_STREAM diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index d39d435cb..9bf1d9a8d 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -171,3 +171,7 @@ endif if BUILD_IOTSAFE nobase_include_HEADERS+= wolfssl/wolfcrypt/port/iotsafe/iotsafe.h endif + +if BUILD_PSA +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/psa/psa.h +endif diff --git a/wolfssl/wolfcrypt/port/psa/psa.h b/wolfssl/wolfcrypt/port/psa/psa.h new file mode 100644 index 000000000..e4683b28b --- /dev/null +++ b/wolfssl/wolfcrypt/port/psa/psa.h @@ -0,0 +1,127 @@ +/* psa.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/** + * Platform Security Architecture (PSA) header + * + * If WOLFSSL_HAVE_PSA is defined, wolfSSL can use the cryptographic primitives + * exported by a PSA Crypto API. + * + * Defines: + * + * WOLFSSL_HAVE_PSA: Global switch to enable PSA + * WOLFSSL_PSA_NO_RNG: disable PSA random generator support + * WOLFSSL_PSA_NO_HASH: disable PSA hashing support + * WOLFSSL_PSA_NO_AES: disable PSA AES support + * WOLFSSL_PSA_GLOBAL_LOCK: serialize the access to the underlying PSA lib + * WOLFSSL_PSA_NO_PKCBS: disable PK callbacks support + */ + +#ifndef WOLFSSL_PSA_H +#define WOLFSSL_PSA_H + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* PSA implementation takes over the Sha struct and Sha functions implementation + completely. Devoiding the struct of the DevId field and hooks to make + crypto_cb work. */ +#if !defined(WOLFSSL_PSA_NO_HASH) && defined(WOLF_CRYPTO_CB) +#error "WOLFSSL PSA is not supported with WOLF_CRYPTO_CB" +#endif + +#if defined(WOLFSSL_HAVE_PSA) + +#include +#include +#include + +#if !defined(WOLFSSL_PSA_NO_AES) +#if !defined(NO_AES) +#include +#endif +#endif /* WOLFSSL_PSA_NO_AES */ + +#if !defined(WOLFSSL_PSA_NO_PKCB) +#include +#endif + +#if defined(WOLFSSL_PSA_GLOBAL_LOCK) +void PSA_LOCK(void); +void PSA_UNLOCK(void); +#else +#define PSA_LOCK() +#define PSA_UNLOCK() +#endif + +int wc_psa_init(void); + +#if !defined(WOLFSSL_PSA_NO_RNG) + +WOLFSSL_API int wc_psa_get_random(unsigned char *out, word32 sz); +#ifndef HAVE_HASHDRBG +#define CUSTOM_RAND_GENERATE_BLOCK wc_psa_get_random +#else +#define CUSTOM_RAND_GENERATE_SEED wc_psa_get_random +#endif + +#endif /* WOLFSSL_HAVE_PSA_RNG */ + +#if !defined(WOLFSSL_PSA_NO_AES) && !defined(NO_AES) + +int wc_psa_aes_init(Aes *aes); +int wc_psa_aes_free(Aes *aes); +int wc_psa_aes_get_key_size(Aes *aes, word32 *keySize); +int wc_psa_aes_set_key(Aes *aes, const uint8_t *key, + size_t key_length, uint8_t *iv, + psa_algorithm_t alg, int dir); + +WOLFSSL_API int wc_psa_aes_encrypt_decrypt(Aes *aes, const uint8_t *input, + uint8_t *output, size_t length, + psa_algorithm_t alg, int direction); + +WOLFSSL_API int wc_AesEncrypt(Aes *aes, const byte *inBlock, byte *outBlock); + +#if defined(HAVE_AES_DECRYPT) +WOLFSSL_API int wc_AesDecrypt(Aes *aes, const byte *inBlock, byte *outBlock); +#endif + +#endif + +#if defined(HAVE_PK_CALLBACKS) && !defined(WOLFSSL_PSA_NO_PKCB) + +struct psa_ssl_ctx { + psa_key_id_t private_key; + psa_key_id_t dh_key; +}; + +WOLFSSL_API int wolfSSL_CTX_psa_enable(WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_set_psa_ctx(WOLFSSL *ssl, struct psa_ssl_ctx *ctx); +WOLFSSL_API void wolfSSL_free_psa_ctx(struct psa_ssl_ctx *ctx); +WOLFSSL_API int wolfSSL_psa_set_private_key_id(struct psa_ssl_ctx *ctx, + psa_key_id_t id); +#endif + +#endif /* WOLFSSL_HAVE_PSA */ +#endif /* WOLFSSL_PSA_H */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 1f3de3b09..ad93830cd 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -114,6 +114,12 @@ enum { #include "wolfssl/wolfcrypt/port/nxp/se050_port.h" #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) +#include +#undef WOLFSSL_NO_HASH_RAW +#define WOLFSSL_NO_HASH_RAW +#endif + /* Sha digest */ struct wc_Sha { #ifdef FREESCALE_LTC_SHA @@ -127,6 +133,8 @@ struct wc_Sha { #elif defined(WOLFSSL_IMXRT_DCP) dcp_handle_t handle; dcp_hash_ctx_t ctx; +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + psa_hash_operation_t psa_ctx; #else word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 1f5030604..56a9ae859 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -105,6 +105,12 @@ #include "wolfssl/wolfcrypt/port/kcapi/kcapi_hash.h" #endif +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) +#include +#undef WOLFSSL_NO_HASH_RAW +#define WOLFSSL_NO_HASH_RAW +#endif + #if defined(_MSC_VER) #define SHA256_NOINLINE __declspec(noinline) #elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__) @@ -168,6 +174,8 @@ struct wc_Sha256 { cy_stc_crypto_sha_state_t hash_state; cy_en_crypto_sha_mode_t sha_mode; cy_stc_crypto_v2_sha256_buffers_t sha_buffers; +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) + psa_hash_operation_t psa_ctx; #else /* alignment on digest and buffer speeds up ARMv8 crypto operations */ ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];