mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
psa: support AES
This commit is contained in:
@ -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;
|
||||
|
@ -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
|
||||
|
324
wolfcrypt/src/port/psa/psa_aes.c
Normal file
324
wolfcrypt/src/port/psa/psa_aes.c
Normal 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 */
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user