Merge pull request #4739 from rizlik/psa

support Platform Security Architecture (PSA) API
This commit is contained in:
David Garske
2022-02-07 10:40:21 -08:00
committed by GitHub
21 changed files with 1829 additions and 4 deletions

View File

@@ -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 "---"

View File

@@ -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

View File

@@ -18,6 +18,7 @@
<li>\ref Compression</li>
<li>\ref Error</li>
<li>\ref IoTSafe</li>
<li>\ref PSA</li>
<li>\ref Keys</li>
<li>\ref Logging</li>
<li>\ref Math</li>

View File

@@ -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);

View File

@@ -76,6 +76,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#include <wolfssl/wolfcrypt/cmac.h>
#endif
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES)
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#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;

View File

@@ -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

View File

@@ -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.

View File

@@ -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 <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_HAVE_PSA)
#include <psa/crypto.h>
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/types.h>
#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 */

View File

@@ -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 <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_HAVE_PSA)
#if !defined(WOLFSSL_PSA_NO_AES)
#if !defined(NO_AES)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifndef NO_INLINE
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#else
#include <wolfssl/wolfcrypt/misc.h>
#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 */

View File

@@ -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 <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
#if !defined(NO_SHA)
#include <wolfssl/wolfcrypt/sha.h>
#endif
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#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 */

View File

@@ -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 <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_HAVE_PSA)
#if defined(HAVE_PK_CALLBACKS)
#if !defined(WOLFSSL_PSA_NO_PKCBS)
#include <psa/crypto.h>
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/internal.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
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 */

View File

@@ -177,6 +177,10 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
#endif
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_RNG)
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#endif
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
static word32 intel_flags = 0;
static void wc_InitRng_IntelRD(void)

View File

@@ -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)

View File

@@ -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)

View File

@@ -112,6 +112,11 @@
#pragma warning(disable: 4996)
#endif
#if defined(WOLFSSL_HAVE_PSA)
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#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();

View File

@@ -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,

View File

@@ -96,6 +96,10 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
#include <wolfssl/wolfcrypt/random.h>
#endif
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES)
#include <psa/crypto.h>
#endif
#if defined(WOLFSSL_CRYPTOCELL)
#include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
#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

View File

@@ -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

View File

@@ -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 <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
/* 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 <psa/crypto.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/visibility.h>
#if !defined(WOLFSSL_PSA_NO_AES)
#if !defined(NO_AES)
#include <wolfssl/wolfcrypt/aes.h>
#endif
#endif /* WOLFSSL_PSA_NO_AES */
#if !defined(WOLFSSL_PSA_NO_PKCB)
#include <wolfssl/ssl.h>
#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 */

View File

@@ -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 <psa/crypto.h>
#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 */

View File

@@ -105,6 +105,12 @@
#include "wolfssl/wolfcrypt/port/kcapi/kcapi_hash.h"
#endif
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
#include <psa/crypto.h>
#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)];