psa: support AES

This commit is contained in:
Marco Oliverio
2021-12-22 17:41:01 +01:00
parent 9ccfc81f26
commit a7165907da
6 changed files with 393 additions and 0 deletions

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

@ -188,4 +188,5 @@ 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
endif

View File

@ -0,0 +1,324 @@
/* 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);
s = psa_import_key(&key_attr, key, key_length, &id);
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;
s = psa_get_key_attributes(aes->key_id, &attr);
if (s != PSA_SUCCESS)
return WC_HW_E;
*keySize = (word32)(psa_get_key_bits(&attr) / 8);
psa_reset_key_attributes(&attr);
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) {
s = psa_cipher_abort(&aes->psa_ctx);
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_destroy_key(aes->key_id);
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 {
ret = wc_psa_aes_import_key(aes, key, key_length, alg, dir);
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) {
s = psa_cipher_encrypt_setup(&aes->psa_ctx, aes->key_id, alg);
} else {
s = psa_cipher_decrypt_setup(&aes->psa_ctx, aes->key_id, alg);
}
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 */
s = psa_cipher_set_iv(&aes->psa_ctx,
(uint8_t*)aes->reg, AES_IV_SIZE);
if (s != PSA_SUCCESS)
goto err;
}
}
s = psa_cipher_update(&aes->psa_ctx, input,
length, output, length, &output_length);
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_destroy_key(aes->key_id);
aes->key_id = PSA_KEY_ID_NULL;
}
if (aes->ctx_initialized == 1) {
psa_cipher_abort(&aes->psa_ctx);
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

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

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

@ -30,6 +30,7 @@
* 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
*/
#ifndef WOLFSSL_PSA_H
@ -47,6 +48,11 @@
#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 */
int wc_psa_init(void);
@ -59,7 +65,28 @@ WOLFSSL_API int wc_psa_get_random(unsigned char *out, word32 sz);
#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
#endif /* WOLFSSL_HAVE_PSA */
#endif /* WOLFSSL_PSA_H */