mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-08-04 01:34:11 +02:00
Merge pull request #10765 from night1rider/Xilinx-ASU-TRNG-Hashes-HMAC
Xilinx Versal Gen2 ASU port: TRNG, hashes, HMAC offload
This commit is contained in:
@@ -1047,6 +1047,8 @@ WOLFSSL_USE_FLASHMEM
|
||||
WOLFSSL_USE_FORCE_ZERO
|
||||
WOLFSSL_USE_OPTIONS_H
|
||||
WOLFSSL_VALIDATE_DH_KEYGEN
|
||||
WOLFSSL_VERSAL_GEN2_ASU
|
||||
WOLFSSL_VERSAL_GEN2_ASU_RTC
|
||||
WOLFSSL_WC_SLHDSA_RECURSIVE
|
||||
WOLFSSL_WC_XMSS_NO_SHA256
|
||||
WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME
|
||||
@@ -1074,6 +1076,7 @@ WOLF_CRYPTO_DEV
|
||||
WOLF_CRYPT_FIPS_H
|
||||
WOLF_NO_TRAILING_ENUM_COMMAS
|
||||
WindowsCE
|
||||
XASU_DISABLE_CACHE
|
||||
XGETPASSWD
|
||||
XMSS_CALL_PRF_KEYGEN
|
||||
XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_CORTEXA72_0_TIMESTAMP_CLK_FREQ
|
||||
|
||||
@@ -392,6 +392,23 @@ int wc_HmacCopy(Hmac* src, Hmac* dst) {
|
||||
|
||||
ret = HmacKeyCopyHash(src->macType, &src->hash, &dst->hash);
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY)
|
||||
/* The shallow copy above left dst sharing any per-context state a device
|
||||
* hung off devCtx; let the device give dst its own copy. The struct and the
|
||||
* hash context are already copied, so the callback only fixes up devCtx. */
|
||||
#ifndef WOLF_CRYPTO_CB_FIND
|
||||
if ((ret == 0) && (src->devId != INVALID_DEVID))
|
||||
#else
|
||||
if (ret == 0)
|
||||
#endif
|
||||
{
|
||||
int cbRet = wc_CryptoCb_Copy(src->devId, WC_ALGO_TYPE_HMAC,
|
||||
src->macType, (void*)src, (void*)dst);
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
ret = cbRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret != 0)
|
||||
XMEMSET(dst, 0, sizeof(*dst));
|
||||
return ret;
|
||||
@@ -1583,6 +1600,21 @@ void wc_HmacFree(Hmac* hmac)
|
||||
if (hmac == NULL)
|
||||
return;
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE)
|
||||
/* Let a device release any per-context state it hung off devCtx directly. If
|
||||
* a device handles it, devCtx is cleared and the finalize fallback below is
|
||||
* skipped; otherwise this is a no-op and the fallback still runs. */
|
||||
#ifndef WOLF_CRYPTO_CB_FIND
|
||||
if (hmac->devId != INVALID_DEVID && hmac->devCtx != NULL)
|
||||
#else
|
||||
if (hmac->devCtx != NULL)
|
||||
#endif
|
||||
{
|
||||
(void)wc_CryptoCb_Free(hmac->devId, WC_ALGO_TYPE_HMAC, hmac->macType, 0,
|
||||
(void*)hmac);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* handle cleanup case where final is not called */
|
||||
if (hmac->devId != INVALID_DEVID && hmac->devCtx != NULL) {
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/* asu_cryptocb.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU
|
||||
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_cryptocb.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/logging.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_rng.h>
|
||||
#endif
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_hash.h>
|
||||
#endif
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_hmac.h>
|
||||
#endif
|
||||
|
||||
#ifndef WOLF_CRYPTO_CB
|
||||
#error "WOLFSSL_VERSAL_GEN2_ASU requires WOLF_CRYPTO_CB"
|
||||
#endif
|
||||
|
||||
/* Route a context copy (WC_ALGO_TYPE_COPY) to the engine that owns the object,
|
||||
* keyed on the copy sub-algo. Each engine's single entry handles the copy.
|
||||
* Engines added later (cipher, pk) get a case here. */
|
||||
static int wc_AsuCopy(wc_CryptoInfo* info)
|
||||
{
|
||||
int ret = CRYPTOCB_UNAVAILABLE;
|
||||
|
||||
switch (info->copy.algo) {
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
case WC_ALGO_TYPE_HASH:
|
||||
ret = wc_AsuHash(info);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
case WC_ALGO_TYPE_HMAC:
|
||||
ret = wc_AsuHmac(info);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Route a context free (WC_ALGO_TYPE_FREE) to the engine that owns the object,
|
||||
* keyed on the free sub-algo, the same way as wc_AsuCopy. */
|
||||
static int wc_AsuFree(wc_CryptoInfo* info)
|
||||
{
|
||||
int ret = CRYPTOCB_UNAVAILABLE;
|
||||
|
||||
switch (info->free.algo) {
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
case WC_ALGO_TYPE_HASH:
|
||||
ret = wc_AsuHash(info);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
case WC_ALGO_TYPE_HMAC:
|
||||
ret = wc_AsuHmac(info);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Crypto callback dispatcher. Each engine handler runs the full operation
|
||||
* (looping over ASU transactions as needed) and returns the wolfCrypt result:
|
||||
* 0 when the ASU handled it, CRYPTOCB_UNAVAILABLE to fall back to software, or a
|
||||
* negative error. Engine cases are filled in per milestone: M1 hash and rng,
|
||||
* M2 aes, M3 public key. */
|
||||
static int wc_AsuCryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
|
||||
{
|
||||
int ret = CRYPTOCB_UNAVAILABLE;
|
||||
|
||||
(void)devId;
|
||||
(void)ctx;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (info->algo_type) {
|
||||
case WC_ALGO_TYPE_HASH: /* M1 asu_hash */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
ret = wc_AsuHash(info);
|
||||
#endif
|
||||
break;
|
||||
case WC_ALGO_TYPE_HMAC: /* M1 asu_hmac */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
ret = wc_AsuHmac(info);
|
||||
#endif
|
||||
break;
|
||||
case WC_ALGO_TYPE_SEED: /* M1 asu_rng */
|
||||
case WC_ALGO_TYPE_RNG: /* M1 asu_rng */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
ret = wc_AsuRng(info);
|
||||
#endif
|
||||
break;
|
||||
case WC_ALGO_TYPE_CIPHER: /* M2 asu_aes */
|
||||
break;
|
||||
case WC_ALGO_TYPE_CMAC: /* M2 asu_aes */
|
||||
break;
|
||||
case WC_ALGO_TYPE_PK: /* M3 asu_rsa and asu_ecc */
|
||||
break;
|
||||
case WC_ALGO_TYPE_COPY: /* context copy: route by sub-algo to its engine */
|
||||
ret = wc_AsuCopy(info);
|
||||
break;
|
||||
case WC_ALGO_TYPE_FREE: /* context free: route by sub-algo to its engine */
|
||||
ret = wc_AsuFree(info);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_AsuCryptoCb_RegisterDevice(int devId)
|
||||
{
|
||||
return wc_CryptoCb_RegisterDevice(devId, wc_AsuCryptoDevCb, NULL);
|
||||
}
|
||||
|
||||
void wc_AsuCryptoCb_UnRegisterDevice(int devId)
|
||||
{
|
||||
wc_CryptoCb_UnRegisterDevice(devId);
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU */
|
||||
@@ -0,0 +1,584 @@
|
||||
/* asu_hash.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* ASU hashing for the wolfSSL crypto callback: SHA2 256/384/512, SHA3
|
||||
* 256/384/512 and SHAKE256.
|
||||
*
|
||||
* Why the message is buffered instead of streamed to the hardware:
|
||||
* wolfSSL drives hashing as update()...update()...final(), and may have
|
||||
* several hash contexts in flight at the same time (interleaved). The ASU SHA
|
||||
* core supports START/UPDATE/FINISH streaming, but it keeps the running hash
|
||||
* state only inside the core and exposes no way to save and restore it:
|
||||
* XSha_Start always begins a fresh hash and the digest registers are read
|
||||
* only (read out at FINISH). The client library therefore allows only one
|
||||
* multi update stream in progress per priority channel. Because the hardware
|
||||
* cannot hold more than one partial hash, interleaved hardware streaming is
|
||||
* physically impossible.
|
||||
*
|
||||
* To support arbitrary interleaving correctly, each hash context's message is
|
||||
* accumulated in its own buffer hung off the wolfSSL hash devCtx (using the
|
||||
* wolfSSL _wc_Hash_Grow helper), and the digest is produced with a single
|
||||
* atomic ASU operation (START|UPDATE|FINISH) at final(). Several contexts can
|
||||
* be mid stream at once, each in its own buffer; the ASU only ever performs
|
||||
* one complete hash at a time (serialized by wc_AsuTransact).
|
||||
*
|
||||
* Because the state lives in devCtx, the copy and free crypto callbacks are
|
||||
* required: copy gives the destination context its own deep copy of the
|
||||
* buffer (a plain struct copy would share the pointer), and free releases the
|
||||
* buffer if a context is freed without being finalized.
|
||||
*
|
||||
* SHAKE256 is an extendable output function: the output length chosen at final()
|
||||
* is carried to this callback in the hash info outSz field (by wc_CryptoCb_Shake).
|
||||
* An output that fits the ASU response mailbox (WC_ASU_SHAKE_HW_MAX_BYTES) is
|
||||
* produced in one ASU SHAKE256 operation; a longer output cannot be returned by
|
||||
* the hardware (see that define) and is computed in software from the same
|
||||
* accumulated message. SHAKE128 has no ASU mode, so it is declined and runs in
|
||||
* software. Only the update()/final() hash style routes here; the
|
||||
* absorb()/squeezeBlocks() streaming XOF (used by ML-KEM and ML-DSA) is not on
|
||||
* the callback path and stays in software.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_hash.h>
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_util.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
#include <wolfssl/wolfcrypt/sha3.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#include "xasu_sha2.h"
|
||||
#include "xasu_sha3.h"
|
||||
#include "xasu_shainfo.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#ifndef WOLFSSL_HASH_KEEP
|
||||
#error "WOLFSSL_VERSAL_GEN2_ASU_HASH requires WOLFSSL_HASH_KEEP (_wc_Hash_Grow)"
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_SHA512_HASHTYPE
|
||||
#error "WOLFSSL_VERSAL_GEN2_ASU_HASH requires WOLFSSL_SHA512_HASHTYPE to tell \
|
||||
the SHA-512 family variants apart"
|
||||
#endif
|
||||
|
||||
/* Per hash context message accumulation, held in the wolfSSL hash devCtx. */
|
||||
typedef struct {
|
||||
byte* msg; /* accumulated message */
|
||||
word32 used; /* bytes accumulated */
|
||||
word32 len; /* buffer capacity */
|
||||
} AsuHashKeep;
|
||||
|
||||
/* One ASU hash request. */
|
||||
typedef struct {
|
||||
XAsu_ShaOperationCmd cmd;
|
||||
int isSha3;
|
||||
} AsuHashReq;
|
||||
|
||||
/* Release a kept message record. The message buffer holds the plaintext that
|
||||
* was hashed, so it is zeroized before being returned to the allocator. */
|
||||
static void wc_AsuHashKeepFree(AsuHashKeep* keep)
|
||||
{
|
||||
if (keep == NULL) {
|
||||
return;
|
||||
}
|
||||
if (keep->msg != NULL) {
|
||||
ForceZero(keep->msg, keep->len);
|
||||
XFREE(keep->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
XFREE(keep, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
||||
/* Submit thunk: queue one ASU hash operation. Called by wc_AsuTransact with the
|
||||
* submit lock held, so it only queues the request. */
|
||||
static int wc_AsuHashSubmit(XAsu_ClientParams* params, void* ctx)
|
||||
{
|
||||
AsuHashReq* req = (AsuHashReq*)ctx;
|
||||
|
||||
if (params == NULL || req == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
if (req->isSha3 != 0) {
|
||||
return XAsu_Sha3Operation(params, &req->cmd);
|
||||
}
|
||||
else {
|
||||
return XAsu_Sha2Operation(params, &req->cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the size of the hash context struct for the given hash type, or 0 for
|
||||
* an unsupported type. The copy callback needs this to duplicate the whole
|
||||
* context (see wc_AsuHashCopy). */
|
||||
static word32 wc_AsuHashCtxSize(int hashType)
|
||||
{
|
||||
switch (hashType) {
|
||||
case WC_HASH_TYPE_SHA256:
|
||||
return (word32)sizeof(wc_Sha256);
|
||||
case WC_HASH_TYPE_SHA384:
|
||||
return (word32)sizeof(wc_Sha384);
|
||||
case WC_HASH_TYPE_SHA512:
|
||||
return (word32)sizeof(wc_Sha512);
|
||||
case WC_HASH_TYPE_SHA3_256:
|
||||
case WC_HASH_TYPE_SHA3_384:
|
||||
case WC_HASH_TYPE_SHA3_512:
|
||||
case WC_HASH_TYPE_SHAKE256: /* wc_Shake is a wc_Sha3 */
|
||||
return (word32)sizeof(wc_Sha3);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the address of the devCtx field of the hash context for the given hash
|
||||
* type, or NULL for an unsupported type. */
|
||||
static void** wc_AsuHashDevCtx(void* hashCtx, int hashType)
|
||||
{
|
||||
if (hashCtx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (hashType) {
|
||||
case WC_HASH_TYPE_SHA256:
|
||||
return &((wc_Sha256*)hashCtx)->devCtx;
|
||||
case WC_HASH_TYPE_SHA384:
|
||||
return &((wc_Sha384*)hashCtx)->devCtx;
|
||||
case WC_HASH_TYPE_SHA512:
|
||||
return &((wc_Sha512*)hashCtx)->devCtx;
|
||||
case WC_HASH_TYPE_SHA3_256:
|
||||
case WC_HASH_TYPE_SHA3_384:
|
||||
case WC_HASH_TYPE_SHA3_512:
|
||||
case WC_HASH_TYPE_SHAKE256: /* wc_Shake is a wc_Sha3 */
|
||||
return &((wc_Sha3*)hashCtx)->devCtx;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve the hash info to the ASU type and mode, the digest length, and the
|
||||
* address of the context's devCtx field. Returns 0 if supported, otherwise
|
||||
* CRYPTOCB_UNAVAILABLE. */
|
||||
static int wc_AsuHashResolve(wc_CryptoInfo* info, void*** devCtx, u8* shaType,
|
||||
u8* shaMode, word32* hashLen)
|
||||
{
|
||||
if (info == NULL || devCtx == NULL || shaType == NULL ||
|
||||
shaMode == NULL || hashLen == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (info->hash.type) {
|
||||
case WC_HASH_TYPE_SHA256:
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha256, info->hash.type);
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_256;
|
||||
*hashLen = WC_SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA384:
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha384, info->hash.type);
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_384;
|
||||
*hashLen = WC_SHA384_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA512:
|
||||
/* SHA-512/224 and SHA-512/256 share the wc_Sha512 context and reach
|
||||
* this callback as plain SHA-512 on update() (the variant is only
|
||||
* known at final()). The ASU does only full SHA-512, and the
|
||||
* truncated variants use different initial values, so decline them
|
||||
* here and let wolfSSL run them entirely in software. */
|
||||
if (info->hash.sha512 != NULL &&
|
||||
(info->hash.sha512->hashType == WC_HASH_TYPE_SHA512_224 ||
|
||||
info->hash.sha512->hashType == WC_HASH_TYPE_SHA512_256)) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha512, info->hash.type);
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_512;
|
||||
*hashLen = WC_SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_256:
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha3, info->hash.type);
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_256;
|
||||
*hashLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_384:
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha3, info->hash.type);
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_384;
|
||||
*hashLen = WC_SHA3_384_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_512:
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha3, info->hash.type);
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_512;
|
||||
*hashLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHAKE256:
|
||||
/* SHAKE is an extendable output function: the digest length is the
|
||||
* caller's requested output, carried in outSz on the final call.
|
||||
* SHAKE128 is not a hardware mode, so it falls through to the
|
||||
* default and runs in software. */
|
||||
*devCtx = wc_AsuHashDevCtx(info->hash.sha3, info->hash.type);
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_SHAKE256;
|
||||
*hashLen = info->hash.outSz;
|
||||
break;
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_HASH_FLAGS
|
||||
/* Keccak-256 (legacy 0x01 padding) is selected with a hash flag on a SHA3
|
||||
* context. The ASU SHA3 core only does NIST SHA3 (0x06) padding, so decline
|
||||
* Keccak and let wolfSSL compute it in software. */
|
||||
if (*shaType == XASU_SHA3_TYPE && info->hash.sha3 != NULL &&
|
||||
(info->hash.sha3->flags & WC_HASH_SHA3_KECCAK256) != 0) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*devCtx == NULL) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Hash dataLen bytes from data in one atomic ASU operation, writing hashLen
|
||||
* bytes of digest. */
|
||||
static int wc_AsuHashOneShot(u8 shaType, u8 shaMode, const byte* data,
|
||||
word32 dataLen, byte* digest, word32 hashLen)
|
||||
{
|
||||
AsuHashReq req;
|
||||
word32 status;
|
||||
byte* outAddr = digest;
|
||||
word32 outLen = hashLen;
|
||||
byte xofTmp[XASU_SHAKE_256_MAX_HASH_LEN];
|
||||
|
||||
if (digest == NULL || (data == NULL && dataLen > 0)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* SHAKE256 is an extendable output function with a caller chosen length. The
|
||||
* ASU reads the result out of the digest registers a 32 bit word at a time,
|
||||
* so a length that is not a multiple of 4 would drop the final partial word.
|
||||
* Round the request up to a word boundary into a temporary buffer and copy
|
||||
* back exactly the bytes asked for. The ASU also caps a single SHAKE squeeze
|
||||
* at one rate block (XASU_SHAKE_256_MAX_HASH_LEN), which bounds the temp. */
|
||||
if ((shaMode == XASU_SHA_MODE_SHAKE256) && ((hashLen % 4u) != 0u) &&
|
||||
(hashLen <= XASU_SHAKE_256_MAX_HASH_LEN)) {
|
||||
outLen = (hashLen + 3u) & ~3u;
|
||||
outAddr = xofTmp;
|
||||
}
|
||||
|
||||
XMEMSET(&req, 0, sizeof(req));
|
||||
req.cmd.DataAddr = (u64)(UINTPTR)data;
|
||||
req.cmd.DataSize = dataLen;
|
||||
req.cmd.HashAddr = (u64)(UINTPTR)outAddr;
|
||||
req.cmd.HashBufSize = outLen;
|
||||
req.cmd.ShaMode = shaMode;
|
||||
req.cmd.IsLast = (u8)XASU_TRUE;
|
||||
if (dataLen > 0) {
|
||||
req.cmd.OperationFlags =
|
||||
(u8)(XASU_SHA_START | XASU_SHA_UPDATE | XASU_SHA_FINISH);
|
||||
}
|
||||
else {
|
||||
req.cmd.OperationFlags = (u8)(XASU_SHA_START | XASU_SHA_FINISH);
|
||||
}
|
||||
if (shaType == XASU_SHA3_TYPE) {
|
||||
req.isSha3 = 1;
|
||||
}
|
||||
else {
|
||||
req.isSha3 = 0;
|
||||
}
|
||||
|
||||
WC_ASU_PRINTF("[ASU] hash type=%d mode=%d dataLen=%u hashLen=%u\r\n",
|
||||
(int)shaType, (int)shaMode, (unsigned int)dataLen, (unsigned int)hashLen);
|
||||
|
||||
/* The ASU DMAs the input message from memory, so clean it out. The digest is
|
||||
* delivered back through the response path (a CPU copy), so it needs no
|
||||
* cache maintenance here. */
|
||||
if (dataLen > 0) {
|
||||
wc_AsuCacheFlush(data, dataLen);
|
||||
}
|
||||
|
||||
status = wc_AsuTransact(wc_AsuHashSubmit, &req, NULL);
|
||||
if (status != XST_SUCCESS) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
/* Copy back the exact byte count when a temp buffer was used for the SHAKE
|
||||
* word-alignment round up. */
|
||||
if (outAddr != digest) {
|
||||
XMEMCPY(digest, xofTmp, hashLen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The ASU returns a hash through a fixed response mailbox slot of 16 words (64
|
||||
* bytes), sized for the largest fixed digest (SHA-512). SHAKE256 is an
|
||||
* extendable output function, so a requested output up to this size fits in one
|
||||
* ASU operation and is offloaded; a longer output is computed in software
|
||||
* instead (see wc_AsuShakeSoftware).
|
||||
*
|
||||
* The hardware could in principle emit more by continuing the squeeze a rate
|
||||
* block at a time, but that path is closed to us: the XAsu_ShaOperationCmd
|
||||
* "next xof" continue-squeeze flag (ShakeReserved) is documented "NA for client,
|
||||
* ASUFW internal use", and the ASU server resets the squeeze after every finish.
|
||||
* So a client cannot chain blocks, and anything past one mailbox stays software. */
|
||||
#define WC_ASU_SHAKE_HW_MAX_BYTES 64
|
||||
|
||||
/* Compute SHAKE256 of the already accumulated message in software, for outputs
|
||||
* larger than the ASU can return. A private context with INVALID_DEVID keeps it
|
||||
* off the crypto callback (no recursion) so wolfSSL runs its own SHAKE. */
|
||||
static int wc_AsuShakeSoftware(const byte* data, word32 dataLen, byte* digest,
|
||||
word32 hashLen)
|
||||
{
|
||||
wc_Shake shake;
|
||||
int ret;
|
||||
|
||||
if (digest == NULL || (data == NULL && dataLen > 0)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wc_InitShake256(&shake, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dataLen > 0) {
|
||||
ret = wc_Shake256_Update(&shake, data, dataLen);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_Shake256_Final(&shake, digest, hashLen);
|
||||
}
|
||||
|
||||
wc_Shake256_Free(&shake);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* update() and final() handling for WC_ALGO_TYPE_HASH. Internal helper reached
|
||||
* through the wc_AsuHash dispatcher. */
|
||||
static int wc_AsuHashCompute(wc_CryptoInfo* info)
|
||||
{
|
||||
void** devCtxPtr = NULL;
|
||||
u8 shaType = 0;
|
||||
u8 shaMode = 0;
|
||||
word32 hashLen = 0;
|
||||
AsuHashKeep* keep;
|
||||
int ret;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wc_AsuHashResolve(info, &devCtxPtr, &shaType, &shaMode, &hashLen);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
keep = (AsuHashKeep*)(*devCtxPtr);
|
||||
|
||||
/* update(): accumulate the message with the wolfSSL grow helper. */
|
||||
if (info->hash.in != NULL) {
|
||||
if (keep == NULL) {
|
||||
keep = (AsuHashKeep*)XMALLOC(sizeof(AsuHashKeep), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (keep == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(keep, 0, sizeof(*keep));
|
||||
*devCtxPtr = keep;
|
||||
}
|
||||
|
||||
ret = _wc_Hash_Grow(&keep->msg, &keep->used, &keep->len,
|
||||
info->hash.in, (int)info->hash.inSz, NULL);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* final(): hash the whole accumulated message in one ASU operation, then
|
||||
* release the buffer. */
|
||||
if (info->hash.digest != NULL) {
|
||||
const byte* data = NULL;
|
||||
word32 dataLen = 0;
|
||||
|
||||
if (keep != NULL) {
|
||||
data = keep->msg;
|
||||
dataLen = keep->used;
|
||||
}
|
||||
|
||||
/* SHAKE256 output longer than the ASU response mailbox can carry is
|
||||
* produced in software from the same accumulated message; everything
|
||||
* else (the fixed hashes and short SHAKE) is one ASU operation. */
|
||||
if ((shaMode == XASU_SHA_MODE_SHAKE256) &&
|
||||
(hashLen > WC_ASU_SHAKE_HW_MAX_BYTES)) {
|
||||
ret = wc_AsuShakeSoftware(data, dataLen, info->hash.digest, hashLen);
|
||||
}
|
||||
else {
|
||||
ret = wc_AsuHashOneShot(shaType, shaMode, data, dataLen,
|
||||
info->hash.digest, hashLen);
|
||||
}
|
||||
|
||||
if (keep != NULL) {
|
||||
wc_AsuHashKeepFree(keep);
|
||||
*devCtxPtr = NULL;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_COPY handling for a hash context. Internal helper reached
|
||||
* through the wc_AsuHash dispatcher. */
|
||||
static int wc_AsuHashCopy(wc_CryptoInfo* info)
|
||||
{
|
||||
void** srcDevCtx;
|
||||
void** dstDevCtx;
|
||||
AsuHashKeep* srcKeep;
|
||||
AsuHashKeep* dstKeep;
|
||||
word32 ctxSize;
|
||||
int ret;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (info->copy.algo != WC_ALGO_TYPE_HASH) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
srcDevCtx = wc_AsuHashDevCtx(info->copy.src, info->copy.type);
|
||||
dstDevCtx = wc_AsuHashDevCtx(info->copy.dst, info->copy.type);
|
||||
ctxSize = wc_AsuHashCtxSize(info->copy.type);
|
||||
if (srcDevCtx == NULL || dstDevCtx == NULL || ctxSize == 0) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* wolfSSL calls this callback before its own struct copy and skips both that
|
||||
* copy and its own free of the destination when we return success, so the
|
||||
* callback owns the entire copy. Free any buffer the destination already
|
||||
* holds first (it is about to be overwritten), or it would leak. */
|
||||
wc_AsuHashKeepFree((AsuHashKeep*)(*dstDevCtx));
|
||||
|
||||
/* Duplicate the whole context struct, which carries devId (so the copy keeps
|
||||
* routing to this port) and the rest of the state. The struct copy leaves the
|
||||
* destination devCtx pointing at the source buffer, so then replace it with
|
||||
* the destination's own deep copy of the kept message. */
|
||||
XMEMCPY(info->copy.dst, info->copy.src, ctxSize);
|
||||
|
||||
srcKeep = (AsuHashKeep*)(*srcDevCtx);
|
||||
if (srcKeep == NULL) {
|
||||
*dstDevCtx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dstKeep = (AsuHashKeep*)XMALLOC(sizeof(AsuHashKeep), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (dstKeep == NULL) {
|
||||
*dstDevCtx = NULL;
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(dstKeep, 0, sizeof(*dstKeep));
|
||||
|
||||
if (srcKeep->used > 0) {
|
||||
ret = _wc_Hash_Grow(&dstKeep->msg, &dstKeep->used, &dstKeep->len,
|
||||
srcKeep->msg, (int)srcKeep->used, NULL);
|
||||
if (ret != 0) {
|
||||
wc_AsuHashKeepFree(dstKeep);
|
||||
*dstDevCtx = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
*dstDevCtx = dstKeep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_FREE handling for a hash context. Internal helper reached
|
||||
* through the wc_AsuHash dispatcher. */
|
||||
static int wc_AsuHashFree(wc_CryptoInfo* info)
|
||||
{
|
||||
void** devCtx;
|
||||
AsuHashKeep* keep;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (info->free.algo != WC_ALGO_TYPE_HASH) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
devCtx = wc_AsuHashDevCtx(info->free.obj, info->free.type);
|
||||
if (devCtx != NULL) {
|
||||
keep = (AsuHashKeep*)(*devCtx);
|
||||
if (keep != NULL) {
|
||||
wc_AsuHashKeepFree(keep);
|
||||
*devCtx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return unavailable so wolfSSL still runs its own ForceZero. devCtx is now
|
||||
* NULL, so there is no second free. */
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* Single entry point for the SHA2/SHA3 engine. The crypto callback dispatcher
|
||||
* routes every hash related operation here and this handler decides which one it
|
||||
* is: update/final (WC_ALGO_TYPE_HASH), context copy (WC_ALGO_TYPE_COPY), or
|
||||
* context free (WC_ALGO_TYPE_FREE). Keeping the whole lifecycle behind one entry
|
||||
* keeps it owned by this module. */
|
||||
int wc_AsuHash(wc_CryptoInfo* info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (info->algo_type) {
|
||||
case WC_ALGO_TYPE_HASH:
|
||||
return wc_AsuHashCompute(info);
|
||||
case WC_ALGO_TYPE_COPY:
|
||||
return wc_AsuHashCopy(info);
|
||||
case WC_ALGO_TYPE_FREE:
|
||||
return wc_AsuHashFree(info);
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HASH */
|
||||
@@ -0,0 +1,403 @@
|
||||
/* asu_hmac.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* ASU HMAC for the wolfSSL crypto callback: HMAC over SHA2 256/384/512 and SHA3
|
||||
* 256/384/512.
|
||||
*
|
||||
* The approach mirrors the SHA hash port (asu_hash.c): wolfSSL drives HMAC as
|
||||
* update()...update()...final() and may have several contexts in flight, but the
|
||||
* ASU keeps the running state only inside the core and cannot save and restore
|
||||
* it. So each context's message is accumulated in its own buffer hung off the
|
||||
* wolfSSL Hmac devCtx (with the wolfSSL _wc_Hash_Grow helper) and the whole HMAC
|
||||
* is produced in one atomic ASU operation at final(). The raw key is taken from
|
||||
* the context: wolfSSL records keyRaw and keyLen on the Hmac whenever the crypto
|
||||
* callback is enabled, and the ASU HMAC engine performs the key reduction
|
||||
* internally, so the unmodified user key is passed straight through.
|
||||
*
|
||||
* Lifecycle: unlike the hash contexts, wc_HmacCopy does not run through the copy
|
||||
* crypto callback and wc_HmacFree does not run through the free callback, so no
|
||||
* copy/free handlers are wired for HMAC. This is safe because the buffer is freed
|
||||
* in final() (the common path), wc_HmacFree finalizes any context that still owns
|
||||
* a buffer through this same callback (so an abandoned context is cleaned up),
|
||||
* and wolfSSL only copies an HMAC context right after the key is set, before any
|
||||
* update, when devCtx is still NULL (so the shallow struct copy shares nothing).
|
||||
*
|
||||
* HMAC output is always the underlying digest size (<= 64 bytes), so unlike SHAKE
|
||||
* it always fits the ASU response mailbox and is always offloaded for the
|
||||
* supported MAC types. HMAC over SHA-1, SHA-224 and the truncated SHA-512
|
||||
* variants has no ASU mode and is declined to software.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_hmac.h>
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_util.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
#include <wolfssl/wolfcrypt/sha3.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#include "xasu_hmac.h"
|
||||
#include "xasu_hmacinfo.h"
|
||||
#include "xasu_shainfo.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#ifndef WOLFSSL_HASH_KEEP
|
||||
#error "WOLFSSL_VERSAL_GEN2_ASU_HMAC requires WOLFSSL_HASH_KEEP (_wc_Hash_Grow)"
|
||||
#endif
|
||||
|
||||
/* Per HMAC context message accumulation, held in the wolfSSL Hmac devCtx. */
|
||||
typedef struct {
|
||||
byte* msg; /* accumulated message */
|
||||
word32 used; /* bytes accumulated */
|
||||
word32 len; /* buffer capacity */
|
||||
} AsuHmacKeep;
|
||||
|
||||
/* One ASU HMAC request. */
|
||||
typedef struct {
|
||||
XAsu_HmacParams params;
|
||||
} AsuHmacReq;
|
||||
|
||||
/* Release a kept message record. The message buffer holds plaintext that was
|
||||
* MAC'd, so it is zeroized before being returned to the allocator. */
|
||||
static void wc_AsuHmacKeepFree(AsuHmacKeep* keep)
|
||||
{
|
||||
if (keep == NULL) {
|
||||
return;
|
||||
}
|
||||
if (keep->msg != NULL) {
|
||||
ForceZero(keep->msg, keep->len);
|
||||
XFREE(keep->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
XFREE(keep, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
||||
/* Submit thunk: queue one ASU HMAC operation. Called by wc_AsuTransact with the
|
||||
* submit lock held, so it only queues the request. */
|
||||
static int wc_AsuHmacSubmit(XAsu_ClientParams* params, void* ctx)
|
||||
{
|
||||
AsuHmacReq* req = (AsuHmacReq*)ctx;
|
||||
|
||||
if (params == NULL || req == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XAsu_HmacCompute(params, &req->params);
|
||||
}
|
||||
|
||||
/* Resolve the wolfSSL MAC (hash) type to the ASU SHA type and mode and the HMAC
|
||||
* output length. Returns 0 if supported, otherwise CRYPTOCB_UNAVAILABLE. */
|
||||
static int wc_AsuHmacResolve(int macType, u8* shaType, u8* shaMode,
|
||||
word32* hmacLen)
|
||||
{
|
||||
if (shaType == NULL || shaMode == NULL || hmacLen == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (macType) {
|
||||
case WC_HASH_TYPE_SHA256:
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_256;
|
||||
*hmacLen = WC_SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA384:
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_384;
|
||||
*hmacLen = WC_SHA384_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA512:
|
||||
*shaType = XASU_SHA2_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_512;
|
||||
*hmacLen = WC_SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_256:
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_256;
|
||||
*hmacLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_384:
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_384;
|
||||
*hmacLen = WC_SHA3_384_DIGEST_SIZE;
|
||||
break;
|
||||
case WC_HASH_TYPE_SHA3_512:
|
||||
*shaType = XASU_SHA3_TYPE;
|
||||
*shaMode = XASU_SHA_MODE_512;
|
||||
*hmacLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
break;
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute HMAC over the whole message in one atomic ASU operation. */
|
||||
static int wc_AsuHmacOneShot(u8 shaType, u8 shaMode, const byte* key,
|
||||
word32 keyLen, const byte* msg, word32 msgLen, byte* mac, word32 macLen)
|
||||
{
|
||||
AsuHmacReq req;
|
||||
word32 status;
|
||||
|
||||
if (key == NULL || mac == NULL || (msg == NULL && msgLen > 0)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMSET(&req, 0, sizeof(req));
|
||||
req.params.ShaType = shaType;
|
||||
req.params.ShaMode = shaMode;
|
||||
req.params.IsLast = (u8)XASU_TRUE;
|
||||
req.params.KeyLen = keyLen;
|
||||
req.params.MsgLen = msgLen;
|
||||
req.params.HmacLen = macLen;
|
||||
req.params.KeyAddr = (u64)(UINTPTR)key;
|
||||
req.params.MsgBufferAddr = (u64)(UINTPTR)msg;
|
||||
req.params.HmacAddr = (u64)(UINTPTR)mac;
|
||||
if (msgLen > 0) {
|
||||
req.params.OperationFlags =
|
||||
(u8)(XASU_HMAC_INIT | XASU_HMAC_UPDATE | XASU_HMAC_FINAL);
|
||||
}
|
||||
else {
|
||||
req.params.OperationFlags = (u8)(XASU_HMAC_INIT | XASU_HMAC_FINAL);
|
||||
}
|
||||
|
||||
WC_ASU_PRINTF("[ASU] hmac type=%d mode=%d keyLen=%u msgLen=%u macLen=%u\r\n",
|
||||
(int)shaType, (int)shaMode, (unsigned int)keyLen, (unsigned int)msgLen,
|
||||
(unsigned int)macLen);
|
||||
|
||||
/* The ASU DMAs the key and message from memory, so clean them out. The MAC
|
||||
* is delivered back through the response path, so it needs no cache
|
||||
* maintenance here. */
|
||||
wc_AsuCacheFlush(key, keyLen);
|
||||
if (msgLen > 0) {
|
||||
wc_AsuCacheFlush(msg, msgLen);
|
||||
}
|
||||
|
||||
status = wc_AsuTransact(wc_AsuHmacSubmit, &req, NULL);
|
||||
if (status != XST_SUCCESS) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update() and final() handling for WC_ALGO_TYPE_HMAC. Internal helper reached
|
||||
* through the wc_AsuHmac dispatcher. */
|
||||
static int wc_AsuHmacCompute(wc_CryptoInfo* info)
|
||||
{
|
||||
Hmac* hmac;
|
||||
AsuHmacKeep* keep;
|
||||
u8 shaType = 0;
|
||||
u8 shaMode = 0;
|
||||
word32 hmacLen = 0;
|
||||
int ret;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
hmac = info->hmac.hmac;
|
||||
if (hmac == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wc_AsuHmacResolve(info->hmac.macType, &shaType, &shaMode, &hmacLen);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The ASU HMAC engine needs a non empty raw key; if wolfSSL did not retain
|
||||
* one, let it compute the HMAC in software. keyRaw and keyLen are fixed by
|
||||
* the preceding SetKey, so this decision is the same on every update and
|
||||
* final for a given context. */
|
||||
if ((hmac->keyRaw == NULL) || (hmac->keyLen == 0)) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
keep = (AsuHmacKeep*)hmac->devCtx;
|
||||
|
||||
/* update(): accumulate the message with the wolfSSL grow helper. */
|
||||
if (info->hmac.in != NULL) {
|
||||
if (keep == NULL) {
|
||||
keep = (AsuHmacKeep*)XMALLOC(sizeof(AsuHmacKeep), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (keep == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(keep, 0, sizeof(*keep));
|
||||
hmac->devCtx = keep;
|
||||
}
|
||||
|
||||
ret = _wc_Hash_Grow(&keep->msg, &keep->used, &keep->len,
|
||||
info->hmac.in, (int)info->hmac.inSz, NULL);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* final(): HMAC the whole accumulated message in one ASU operation, then
|
||||
* release the buffer. */
|
||||
if (info->hmac.digest != NULL) {
|
||||
const byte* msg = NULL;
|
||||
word32 msgLen = 0;
|
||||
|
||||
if (keep != NULL) {
|
||||
msg = keep->msg;
|
||||
msgLen = keep->used;
|
||||
}
|
||||
|
||||
ret = wc_AsuHmacOneShot(shaType, shaMode, hmac->keyRaw,
|
||||
(word32)hmac->keyLen, msg, msgLen, info->hmac.digest, hmacLen);
|
||||
|
||||
if (keep != NULL) {
|
||||
wc_AsuHmacKeepFree(keep);
|
||||
hmac->devCtx = NULL;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_COPY handling for an HMAC context. Unlike the hash copy callback,
|
||||
* wc_HmacCopy performs the struct copy itself (and deep copies the inner hash),
|
||||
* then calls this only to fix up the kept message: the shallow struct copy left
|
||||
* the destination sharing the source buffer pointer, so replace it with the
|
||||
* destination's own deep copy. Internal helper reached through wc_AsuHmac. */
|
||||
static int wc_AsuHmacCopy(wc_CryptoInfo* info)
|
||||
{
|
||||
Hmac* src;
|
||||
Hmac* dst;
|
||||
AsuHmacKeep* srcKeep;
|
||||
AsuHmacKeep* dstKeep;
|
||||
int ret;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (info->copy.algo != WC_ALGO_TYPE_HMAC) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
src = (Hmac*)info->copy.src;
|
||||
dst = (Hmac*)info->copy.dst;
|
||||
if (src == NULL || dst == NULL) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
srcKeep = (AsuHmacKeep*)src->devCtx;
|
||||
if (srcKeep == NULL) {
|
||||
dst->devCtx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dstKeep = (AsuHmacKeep*)XMALLOC(sizeof(AsuHmacKeep), NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (dstKeep == NULL) {
|
||||
dst->devCtx = NULL;
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(dstKeep, 0, sizeof(*dstKeep));
|
||||
|
||||
if (srcKeep->used > 0) {
|
||||
ret = _wc_Hash_Grow(&dstKeep->msg, &dstKeep->used, &dstKeep->len,
|
||||
srcKeep->msg, (int)srcKeep->used, NULL);
|
||||
if (ret != 0) {
|
||||
wc_AsuHmacKeepFree(dstKeep);
|
||||
dst->devCtx = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dst->devCtx = dstKeep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_FREE handling for an HMAC context: release the accumulated
|
||||
* message buffer so an abandoned context (updated but never finalized) is freed
|
||||
* without a stray ASU operation. Internal helper reached through wc_AsuHmac. */
|
||||
static int wc_AsuHmacFree(wc_CryptoInfo* info)
|
||||
{
|
||||
Hmac* hmac;
|
||||
AsuHmacKeep* keep;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (info->free.algo != WC_ALGO_TYPE_HMAC) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
hmac = (Hmac*)info->free.obj;
|
||||
if (hmac != NULL) {
|
||||
keep = (AsuHmacKeep*)hmac->devCtx;
|
||||
if (keep != NULL) {
|
||||
wc_AsuHmacKeepFree(keep);
|
||||
hmac->devCtx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return unavailable so wolfSSL still runs its own cleanup. devCtx is now
|
||||
* NULL, so there is no second free. */
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/* Single entry point for the HMAC engine. The crypto callback dispatcher routes
|
||||
* every HMAC related operation here and this handler decides which it is: update
|
||||
* and final (WC_ALGO_TYPE_HMAC), context copy (WC_ALGO_TYPE_COPY) or context
|
||||
* free (WC_ALGO_TYPE_FREE). */
|
||||
int wc_AsuHmac(wc_CryptoInfo* info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (info->algo_type) {
|
||||
case WC_ALGO_TYPE_HMAC:
|
||||
return wc_AsuHmacCompute(info);
|
||||
case WC_ALGO_TYPE_COPY:
|
||||
return wc_AsuHmacCopy(info);
|
||||
case WC_ALGO_TYPE_FREE:
|
||||
return wc_AsuHmacFree(info);
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HMAC */
|
||||
@@ -0,0 +1,133 @@
|
||||
/* asu_rng.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_rng.h>
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_util.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
|
||||
#include "xasu_trng.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
/* One TRNG read request, passed as the transaction context. */
|
||||
typedef struct {
|
||||
byte* buf;
|
||||
word32 len;
|
||||
} AsuTrngReq;
|
||||
|
||||
/* Submit thunk: queue one TRNG read of up to one strength block. Called by
|
||||
* wc_AsuTransact with the submit lock held, so it only queues the request. The
|
||||
* completion ISR copies the random bytes into buf, so no cache maintenance is
|
||||
* needed here. */
|
||||
static int wc_AsuTrngSubmit(XAsu_ClientParams* params, void* ctx)
|
||||
{
|
||||
AsuTrngReq* req = (AsuTrngReq*)ctx;
|
||||
|
||||
if (params == NULL || req == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XAsu_TrngGetRandomNum(params, req->buf, req->len);
|
||||
}
|
||||
|
||||
/* Fill out with len bytes from the ASU TRNG. The TRNG returns at most one
|
||||
* strength block (32 bytes) per call, so larger requests run over several
|
||||
* transactions, each its own ASU unique id. */
|
||||
static int wc_AsuTrngFill(byte* out, word32 len)
|
||||
{
|
||||
AsuTrngReq req;
|
||||
word32 chunk;
|
||||
|
||||
if (out == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
if (len < XASU_TRNG_RANDOM_NUM_IN_BYTES) {
|
||||
chunk = len;
|
||||
}
|
||||
else {
|
||||
chunk = XASU_TRNG_RANDOM_NUM_IN_BYTES;
|
||||
}
|
||||
|
||||
req.buf = out;
|
||||
req.len = chunk;
|
||||
|
||||
if (wc_AsuTransact(wc_AsuTrngSubmit, &req, NULL) != XST_SUCCESS) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
out += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_SEED: provide the ASU TRNG as a seed source for the DRBG.
|
||||
* Internal helper reached through the wc_AsuRng dispatcher. */
|
||||
static int wc_AsuRngSeed(wc_CryptoInfo* info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
return wc_AsuTrngFill(info->seed.seed, info->seed.sz);
|
||||
}
|
||||
|
||||
/* WC_ALGO_TYPE_RNG: serve random blocks straight from the ASU TRNG.
|
||||
* Internal helper reached through the wc_AsuRng dispatcher. */
|
||||
static int wc_AsuRngGenerate(wc_CryptoInfo* info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
return wc_AsuTrngFill(info->rng.out, info->rng.sz);
|
||||
}
|
||||
|
||||
/* Single entry point for the ASU TRNG. The crypto callback dispatcher routes
|
||||
* both random number requests here and this handler decides which it is: seed a
|
||||
* DRBG (WC_ALGO_TYPE_SEED) or serve random blocks (WC_ALGO_TYPE_RNG). */
|
||||
int wc_AsuRng(wc_CryptoInfo* info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch (info->algo_type) {
|
||||
case WC_ALGO_TYPE_SEED:
|
||||
return wc_AsuRngSeed(info);
|
||||
case WC_ALGO_TYPE_RNG:
|
||||
return wc_AsuRngGenerate(info);
|
||||
default:
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_TRNG */
|
||||
@@ -0,0 +1,220 @@
|
||||
/* asu_util.c
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU
|
||||
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_util.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/wc_port.h>
|
||||
|
||||
#include "xil_cache.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_RTC
|
||||
#include "xiltimer.h"
|
||||
#include "xrtcpsu.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
#ifndef COUNTS_PER_SECOND
|
||||
#define COUNTS_PER_SECOND XPAR_CPU_TIMESTAMP_CLK_FREQ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Shared response handler registered with every ASU request. The ASU client
|
||||
* passes the AsuWait record back through the callback reference. */
|
||||
static void wc_AsuResponseHandler(void* ref, u32 status)
|
||||
{
|
||||
AsuWait* wait = (AsuWait*)ref;
|
||||
|
||||
if (wait != NULL) {
|
||||
wait->Status = (word32)status;
|
||||
wait->Done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void wc_AsuWaitPrepare(AsuWait* wait, XAsu_ClientParams* params)
|
||||
{
|
||||
wait->Done = 0;
|
||||
wait->Status = (word32)XST_FAILURE;
|
||||
|
||||
params->Priority = XASU_PRIORITY_HIGH;
|
||||
params->SecureFlag = XASU_CMD_SECURE;
|
||||
params->CallBackFuncPtr = (XAsuClient_ResponseHandler)wc_AsuResponseHandler;
|
||||
params->CallBackRefPtr = (void*)wait;
|
||||
params->AdditionalStatus = (u32)XST_FAILURE;
|
||||
}
|
||||
|
||||
word32 wc_AsuWaitDone(AsuWait* wait)
|
||||
{
|
||||
while (wait->Done == 0) {
|
||||
/* busy wait for the single threaded baremetal client */
|
||||
}
|
||||
|
||||
return wait->Status;
|
||||
}
|
||||
|
||||
/* When WC_ASU_DISABLE_CACHE is set (mirrored from XASU_DISABLE_CACHE in
|
||||
* asu_settings.h) the data cache is off for the whole application, so buffer
|
||||
* maintenance is unnecessary and these become no ops. Otherwise the cache is on
|
||||
* and the port cleans inputs and invalidates outputs around each ASU access. */
|
||||
void wc_AsuCacheFlush(const void* addr, word32 len)
|
||||
{
|
||||
#ifdef WC_ASU_DISABLE_CACHE
|
||||
(void)addr;
|
||||
(void)len;
|
||||
#else
|
||||
Xil_DCacheFlushRange((INTPTR)addr, (INTPTR)len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wc_AsuCacheInvalidate(void* addr, word32 len)
|
||||
{
|
||||
#ifdef WC_ASU_DISABLE_CACHE
|
||||
(void)addr;
|
||||
(void)len;
|
||||
#else
|
||||
Xil_DCacheInvalidateRange((INTPTR)addr, (INTPTR)len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Transaction and concurrency (ticketing) */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* The ASU associates a unique id with each call and routes its completion back
|
||||
* to the request's own callback, so that id is the ticket: every transaction
|
||||
* gets its own AsuWait and several run concurrently. The only shared state that
|
||||
* needs guarding is the submit, since the client request allocation is not
|
||||
* thread safe. Locking uses the wolfSSL crypto hardware mutex (enabled for the
|
||||
* multi threaded build in asu_settings.h, a no op otherwise) and is held only
|
||||
* across the submit, never across the wait. */
|
||||
word32 wc_AsuTransact(AsuSubmitFn submit, void* ctx, word32* additionalStatus)
|
||||
{
|
||||
XAsu_ClientParams params;
|
||||
AsuWait wait;
|
||||
s32 status;
|
||||
|
||||
if (submit == NULL) {
|
||||
return (word32)XST_FAILURE;
|
||||
}
|
||||
|
||||
/* The prepared params carry this request's completion context, which the
|
||||
* ASU associates with the unique id it assigns. */
|
||||
wc_AsuWaitPrepare(&wait, ¶ms);
|
||||
|
||||
wolfSSL_CryptHwMutexLock();
|
||||
status = submit(¶ms, ctx);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
|
||||
if (status != XST_SUCCESS) {
|
||||
WC_ASU_PRINTF("[ASU] submit failed status=%d\r\n", (int)status);
|
||||
return (word32)status;
|
||||
}
|
||||
|
||||
/* Wait on our own completion outside the lock, so other callers submit and
|
||||
* run concurrently up to the ASU queue depth. */
|
||||
status = (s32)wc_AsuWaitDone(&wait);
|
||||
|
||||
WC_ASU_PRINTF("[ASU] op done status=%d\r\n", (int)status);
|
||||
|
||||
if (additionalStatus != NULL) {
|
||||
*additionalStatus = params.AdditionalStatus;
|
||||
}
|
||||
|
||||
return (word32)status;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_RTC
|
||||
|
||||
/* Timer and RTC. The benchmark time base is the Cortex A78 generic timer, which
|
||||
* is free running and needs no init. The system RTC is brought up by
|
||||
* wc_AsuTimerInit and read with wc_AsuRtcSeconds for wall clock timestamps. */
|
||||
|
||||
static XRtcPsu asuRtc;
|
||||
static int asuRtcReady = 0;
|
||||
|
||||
int wc_AsuTimerInit(void)
|
||||
{
|
||||
XRtcPsu_Config* cfg;
|
||||
|
||||
if (asuRtcReady) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_BASEADDR);
|
||||
if (cfg == NULL) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
if (XRtcPsu_CfgInitialize(&asuRtc, cfg, XPAR_XRTCPSU_0_BASEADDR)
|
||||
!= XST_SUCCESS) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
asuRtcReady = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
word64 wc_AsuTimerCount(void)
|
||||
{
|
||||
XTime now = 0;
|
||||
|
||||
XTime_GetTime(&now);
|
||||
|
||||
return (word64)now;
|
||||
}
|
||||
|
||||
double wc_AsuTimerSeconds(void)
|
||||
{
|
||||
return (double)wc_AsuTimerCount() / (double)COUNTS_PER_SECOND;
|
||||
}
|
||||
|
||||
word32 wc_AsuRtcSeconds(void)
|
||||
{
|
||||
if (!asuRtcReady && wc_AsuTimerInit() != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (word32)XRtcPsu_GetCurrentTime(&asuRtc);
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_USER_CURRTIME)
|
||||
|
||||
/* Benchmark time source. benchmark.c declares this extern when
|
||||
* WOLFSSL_USER_CURRTIME is set and calls it to time each operation. */
|
||||
double current_time(int reset)
|
||||
{
|
||||
(void)reset; /* the generic timer counter is free running */
|
||||
|
||||
return wc_AsuTimerSeconds();
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_USER_CURRTIME */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_RTC */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU */
|
||||
@@ -194,6 +194,10 @@ Threading/Mutex options:
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_VERSAL_GEN2_ASU)
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_cryptocb.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INTEL_QA_SYNC
|
||||
#include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
|
||||
#endif
|
||||
@@ -572,6 +576,16 @@ int wolfCrypt_Init(void)
|
||||
WOLFCRYPT_INIT_RAISE_BAD_STATE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Register the Versal Gen2 ASU device so wolfCrypt operations route to the
|
||||
* ASU hardware. The ASU client must already be initialized by the
|
||||
* application with XAsu_ClientInit. */
|
||||
#if defined(WOLFSSL_VERSAL_GEN2_ASU) && defined(WOLF_CRYPTO_CB)
|
||||
ret = wc_AsuCryptoCb_RegisterDevice(WOLFSSL_VERSAL_GEN2_ASU_DEVID);
|
||||
if (ret != 0) {
|
||||
WOLFCRYPT_INIT_RAISE_BAD_STATE();
|
||||
}
|
||||
#endif
|
||||
#if defined(MAX3266X_RTC)
|
||||
ret = wc_MXC_RTC_Init();
|
||||
if (ret != 0) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/* asu_cryptocb.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* wolfSSL crypto callback device for the Versal Gen2 ASU. Registering this
|
||||
* device routes wolfCrypt operations to the ASU hardware engines, with a
|
||||
* software fallback for anything the ASU does not handle. */
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_CRYPTOCB_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_CRYPTOCB_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU
|
||||
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Register the ASU device with the wolfSSL crypto callback framework. The ASU
|
||||
* client must already be initialized with XAsu_ClientInit. Pass the same devId
|
||||
* that WC_USE_DEVID is set to so wolfSSL routes operations to this device. */
|
||||
WOLFSSL_API int wc_AsuCryptoCb_RegisterDevice(int devId);
|
||||
|
||||
/* Remove the ASU device from the crypto callback framework. */
|
||||
WOLFSSL_API void wc_AsuCryptoCb_UnRegisterDevice(int devId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_CRYPTOCB_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/* asu_hash.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* ASU hashing for the wolfSSL crypto callback: SHA2 256/384/512 and SHA3
|
||||
* 256/384/512. The message is accumulated per hash context and hashed in a
|
||||
* single ASU operation at finalize. See asu_hash.c for why. */
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_HASH_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_HASH_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Single entry point for the SHA2/SHA3 engine. The crypto callback dispatcher
|
||||
* routes every hash related operation here and this handler decides which it is:
|
||||
* update and final (WC_ALGO_TYPE_HASH), context copy (WC_ALGO_TYPE_COPY), or
|
||||
* context release (WC_ALGO_TYPE_FREE). Supports SHA2 256/384/512 and SHA3
|
||||
* 256/384/512. Returns 0 on success, CRYPTOCB_UNAVAILABLE for an unsupported
|
||||
* operation or hash type (software fallback), or a negative error. */
|
||||
WOLFSSL_LOCAL int wc_AsuHash(wc_CryptoInfo* info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HASH */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HASH_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/* asu_hmac.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* ASU HMAC for the wolfSSL crypto callback: HMAC over SHA2 256/384/512 and SHA3
|
||||
* 256/384/512. The message is accumulated per HMAC context and the whole HMAC is
|
||||
* produced in a single ASU operation at finalize. See asu_hmac.c for why. */
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_HMAC_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_HMAC_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Single entry point for the HMAC engine. The crypto callback dispatcher routes
|
||||
* every HMAC related operation here and this handler decides which it is: update
|
||||
* and final (WC_ALGO_TYPE_HMAC), context copy (WC_ALGO_TYPE_COPY) or context
|
||||
* release (WC_ALGO_TYPE_FREE). The message is accumulated per context and the
|
||||
* HMAC is computed in one ASU operation at final using the raw key wolfSSL
|
||||
* keeps on the context. Supports HMAC over SHA2 256/384/512 and SHA3
|
||||
* 256/384/512. Returns 0 on success, CRYPTOCB_UNAVAILABLE for an unsupported
|
||||
* MAC type or key (software fallback), or a negative error. */
|
||||
WOLFSSL_LOCAL int wc_AsuHmac(wc_CryptoInfo* info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HMAC */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_HMAC_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/* asu_rng.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* ASU TRNG entropy for the wolfSSL crypto callback. Seeds the wolfCrypt Hash
|
||||
* DRBG from the ASU true random number generator. */
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_RNG_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_RNG_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Single entry point for the ASU TRNG. The crypto callback dispatcher routes
|
||||
* both random number operations here and this handler decides which it is: seed
|
||||
* a DRBG (WC_ALGO_TYPE_SEED, fills info->seed) or serve random blocks
|
||||
* (WC_ALGO_TYPE_RNG, fills info->rng). The ASU TRNG returns at most one strength
|
||||
* block (32 bytes) per call, so larger requests are filled over several ASU
|
||||
* transactions. Returns 0 on success, CRYPTOCB_UNAVAILABLE for an unsupported
|
||||
* operation, or a negative error. */
|
||||
WOLFSSL_LOCAL int wc_AsuRng(wc_CryptoInfo* info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_TRNG */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_RNG_H */
|
||||
@@ -0,0 +1,112 @@
|
||||
/* asu_settings.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* Compile time configuration for the Versal Gen2 ASU port. This header holds
|
||||
* only preprocessor macros and pulls in no BSP headers, so wolfSSL settings.h
|
||||
* can include it to select engines and map WC_USE_DEVID before the unmodified
|
||||
* wolfcrypt test and benchmark read it.
|
||||
*
|
||||
* Engine selection:
|
||||
* WOLFSSL_VERSAL_GEN2_ASU enables the port and must always be defined in
|
||||
* user_settings.h. With only that defined, every supported engine is
|
||||
* offloaded. To offload a subset, also define one or more of the engine
|
||||
* macros below, in which case only those are offloaded:
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_AES
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_CMAC
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_RSA
|
||||
* WOLFSSL_VERSAL_GEN2_ASU_ECC
|
||||
* An engine macro on its own does not enable the port.
|
||||
*/
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_SETTINGS_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_SETTINGS_H
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU
|
||||
|
||||
/* The port routes operations through the wolfSSL crypto callback framework. */
|
||||
#ifndef WOLF_CRYPTO_CB
|
||||
#define WOLF_CRYPTO_CB
|
||||
#endif
|
||||
|
||||
/* If the port is on but no specific engine was requested, enable the full
|
||||
* supported set. */
|
||||
#if !defined(WOLFSSL_VERSAL_GEN2_ASU_TRNG) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_HASH) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_HMAC) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_AES) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_CMAC) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_RSA) && \
|
||||
!defined(WOLFSSL_VERSAL_GEN2_ASU_ECC)
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_TRNG
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_HASH
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_HMAC
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_AES
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_CMAC
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_RSA
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_ECC
|
||||
#endif
|
||||
|
||||
/* Device id used to register and route to the ASU crypto callback. Override by
|
||||
* defining WOLFSSL_VERSAL_GEN2_ASU_DEVID (or WC_USE_DEVID) in user_settings.h
|
||||
* before settings.h. Any int other than INVALID_DEVID (-2) is valid; this is an
|
||||
* identifier, not an address or index. */
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_DEVID
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_DEVID 0x4153 /* 'AS' for ASU */
|
||||
#endif
|
||||
|
||||
/* Let the unmodified wolfcrypt test and benchmark route every operation through
|
||||
* this device by giving their devId the ASU value. */
|
||||
#ifndef WC_USE_DEVID
|
||||
#define WC_USE_DEVID WOLFSSL_VERSAL_GEN2_ASU_DEVID
|
||||
#endif
|
||||
|
||||
/* When the timer and RTC are turned on (WOLFSSL_VERSAL_GEN2_ASU_RTC in
|
||||
* user_settings.h), supply the benchmark current_time() hook from the port. */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_RTC
|
||||
#ifndef WOLFSSL_USER_CURRTIME
|
||||
#define WOLFSSL_USER_CURRTIME
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Mirror the application data cache switch into a port owned macro so the port
|
||||
* translation units do not depend on the application macro name. When
|
||||
* XASU_DISABLE_CACHE is set globally the data cache is off, so the port skips
|
||||
* buffer maintenance; otherwise it cleans inputs and invalidates outputs. */
|
||||
#ifdef XASU_DISABLE_CACHE
|
||||
#ifndef WC_ASU_DISABLE_CACHE
|
||||
#define WC_ASU_DISABLE_CACHE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Threading. The ticketing concurrency that lets several threads keep the ASU
|
||||
* queue busy is compiled out for a single threaded build, which instead uses
|
||||
* the wolfSSL crypto hardware mutex. Derived from SINGLE_THREADED. */
|
||||
#ifdef SINGLE_THREADED
|
||||
#undef WOLFSSL_VERSAL_GEN2_ASU_SINGLE_THREADED
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_SINGLE_THREADED
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_SETTINGS_H */
|
||||
@@ -0,0 +1,128 @@
|
||||
/* asu_util.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 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 3 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
|
||||
*/
|
||||
|
||||
/* Shared helpers for the Versal Gen2 ASU port: the asynchronous request to
|
||||
* synchronous completion bridge and cache maintenance for ASU buffers. */
|
||||
|
||||
#ifndef WOLFSSL_VERSAL_GEN2_ASU_UTIL_H
|
||||
#define WOLFSSL_VERSAL_GEN2_ASU_UTIL_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU
|
||||
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#include "xasu_client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Debug print to confirm operations are going through the ASU port. Enable by
|
||||
* defining WOLFSSL_VERSAL_GEN2_ASU_DEBUG in user_settings.h. Prints over the
|
||||
* standalone console (xil_printf); compiles out otherwise. */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_DEBUG
|
||||
#include "xil_printf.h"
|
||||
#define WC_ASU_PRINTF(...) xil_printf(__VA_ARGS__)
|
||||
#else
|
||||
#define WC_ASU_PRINTF(...) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Completion record for one asynchronous ASU request. The ASU client invokes
|
||||
* the shared response handler from its mailbox path, which fills this record;
|
||||
* the submitting code then spins until Done is set. */
|
||||
typedef struct AsuWait {
|
||||
volatile byte Done; /* set when the response handler has run */
|
||||
volatile word32 Status; /* server status captured by the handler */
|
||||
} AsuWait;
|
||||
|
||||
/* Initialize Wait and point ClientParams at the shared response handler. The
|
||||
* request is configured as high priority and secure by default. */
|
||||
WOLFSSL_LOCAL void wc_AsuWaitPrepare(AsuWait* wait, XAsu_ClientParams* params);
|
||||
|
||||
/* Block until the request bound to Wait completes and return the server
|
||||
* status. Single threaded baremetal client, so a busy wait is correct. */
|
||||
WOLFSSL_LOCAL word32 wc_AsuWaitDone(AsuWait* wait);
|
||||
|
||||
/* Clean a buffer out to memory so the ASU sees the latest CPU writes. */
|
||||
WOLFSSL_LOCAL void wc_AsuCacheFlush(const void* addr, word32 len);
|
||||
|
||||
/* Invalidate a buffer so the CPU reads what the ASU wrote to memory. */
|
||||
WOLFSSL_LOCAL void wc_AsuCacheInvalidate(void* addr, word32 len);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Transaction and concurrency (ticketing) */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Submit function for one ASU transaction. The implementation fills its
|
||||
* request from ctx and calls the matching XAsu_* client API with the prepared
|
||||
* ClientParams, returning the client submission status (XST_SUCCESS when the
|
||||
* request was queued). It is called with the submit lock held, so it must only
|
||||
* queue the request, never wait. */
|
||||
typedef int (*AsuSubmitFn)(XAsu_ClientParams* params, void* ctx);
|
||||
|
||||
/* Run one ASU transaction and return the server status (XST_SUCCESS on success,
|
||||
* otherwise a failure status). If additionalStatus is not NULL it receives the
|
||||
* server AdditionalStatus field, used by operations like AES GCM tag checks.
|
||||
*
|
||||
* With WOLFSSL_VERSAL_GEN2_ASU_SINGLE_THREADED this is submit then wait under
|
||||
* the wolfSSL crypto hardware mutex. Otherwise it takes a FIFO ticket, submits
|
||||
* under the short submit lock so the non thread safe client allocation is
|
||||
* serialized, hands the turn to the next waiter, then waits on its own
|
||||
* completion outside the lock, so up to the ASU queue depth of requests run
|
||||
* concurrently across threads. */
|
||||
WOLFSSL_LOCAL word32 wc_AsuTransact(AsuSubmitFn submit, void* ctx,
|
||||
word32* additionalStatus);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Timer and RTC (optional, for benchmarking) */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* The entire timer and RTC facility is gated by WOLFSSL_VERSAL_GEN2_ASU_RTC,
|
||||
* turned on in user_settings.h, so it compiles out completely for a build that
|
||||
* does not benchmark. When enabled it provides the benchmark current_time()
|
||||
* hook from the Cortex A78 generic timer and an optional system RTC wall clock
|
||||
* read. */
|
||||
#ifdef WOLFSSL_VERSAL_GEN2_ASU_RTC
|
||||
|
||||
/* Bring up the time source. Returns 0 on success. */
|
||||
WOLFSSL_LOCAL int wc_AsuTimerInit(void);
|
||||
|
||||
/* Raw monotonic count from the generic timer. */
|
||||
WOLFSSL_LOCAL word64 wc_AsuTimerCount(void);
|
||||
|
||||
/* Monotonic time in seconds from the generic timer. This is what the benchmark
|
||||
* current_time() hook reports. */
|
||||
WOLFSSL_LOCAL double wc_AsuTimerSeconds(void);
|
||||
|
||||
/* Wall clock time in seconds from the system RTC. One second resolution, so it
|
||||
* is for timestamps, not per operation timing. */
|
||||
WOLFSSL_LOCAL word32 wc_AsuRtcSeconds(void);
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_RTC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU */
|
||||
|
||||
#endif /* WOLFSSL_VERSAL_GEN2_ASU_UTIL_H */
|
||||
@@ -389,6 +389,13 @@
|
||||
#define __aarch64__ 1
|
||||
#endif
|
||||
|
||||
/* Versal Gen2 ASU port: enable the crypto callback and map WC_USE_DEVID before
|
||||
* the rest of settings.h and before the unmodified test and benchmark read it.
|
||||
* This header is macro only and pulls in no BSP dependencies. */
|
||||
#if defined(WOLFSSL_VERSAL_GEN2_ASU)
|
||||
#include <wolfssl/wolfcrypt/port/xilinx/versal_gen2_asu/asu_settings.h>
|
||||
#endif
|
||||
|
||||
/* Forward propagation of the legacy parent gate to the canonical name
|
||||
* (HAVE_DILITHIUM -> WOLFSSL_HAVE_MLDSA). Always active: required so that
|
||||
* a user_settings.h or build flag using only the legacy spelling still
|
||||
|
||||
Reference in New Issue
Block a user