From f3acda6b4c2317d4f6c6a472f90fae674ba1f65e Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 18 Aug 2026 10:29:26 -0700 Subject: [PATCH] Add a Linux user space backend for the CAAM port --- configure.ac | 9 + wolfcrypt/src/include.am | 12 + wolfcrypt/src/port/caam/README.md | 91 +++++- wolfcrypt/src/port/caam/caam_driver.c | 13 +- wolfcrypt/src/port/caam/caam_error.c | 3 +- wolfcrypt/src/port/caam/caam_linux.c | 298 +++++++++++++++++ wolfcrypt/src/port/caam/wolfcaam_linux.c | 319 +++++++++++++++++++ wolfssl/wolfcrypt/include.am | 2 + wolfssl/wolfcrypt/port/caam/caam_driver.h | 46 ++- wolfssl/wolfcrypt/port/caam/caam_linux.h | 102 ++++++ wolfssl/wolfcrypt/port/caam/wolfcaam.h | 8 +- wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h | 61 ++++ wolfssl/wolfcrypt/settings.h | 16 + 13 files changed, 967 insertions(+), 13 deletions(-) create mode 100644 wolfcrypt/src/port/caam/caam_linux.c create mode 100644 wolfcrypt/src/port/caam/wolfcaam_linux.c create mode 100644 wolfssl/wolfcrypt/port/caam/caam_linux.h create mode 100644 wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h diff --git a/configure.ac b/configure.ac index 3b997f801ba..4ff51bd089a 100644 --- a/configure.ac +++ b/configure.ac @@ -4717,6 +4717,14 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IMX6UL_CAAM" ;; + linux) + # Drive a job ring from Linux user space. Needs a reserved + # physical DMA pool (boot with mem=) and the in-tree caam driver + # unbound; see wolfcrypt/src/port/caam/README.md. + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CAAM_LINUX -DWOLFSSL_CAAM_NO_SM" + ENABLED_CAAM_LINUX="yes" + ;; + seco) SECO_DIR=$trylibsecodir AM_CPPFLAGS="$AM_CPPFLAGS -I$SECO_DIR/include" @@ -13417,6 +13425,7 @@ AM_CONDITIONAL([BUILD_RC2],[test "x$ENABLED_RC2" = "xyes"]) AM_CONDITIONAL([BUILD_CUDA],[test "x$ENABLED_CUDA" = "xyes"]) AM_CONDITIONAL([BUILD_CAAM],[test "x$ENABLED_CAAM" != "xno"]) AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM_QNX" = "xyes"]) +AM_CONDITIONAL([BUILD_CAAM_LINUX],[test "x$ENABLED_CAAM_LINUX" = "xyes"]) AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"]) AM_CONDITIONAL([BUILD_IOTSAFE_HWRNG],[test "x$ENABLED_IOTSAFE_HWRNG" = "xyes"]) AM_CONDITIONAL([BUILD_VAULTIC],[test "x$ENABLED_VAULTIC" = "xyes"]) diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index f0e7ca3c717..92c80d434ad 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -99,6 +99,8 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/caam/caam_driver.c \ wolfcrypt/src/port/caam/caam_error.c \ wolfcrypt/src/port/caam/caam_qnx.c \ + wolfcrypt/src/port/caam/caam_linux.c \ + wolfcrypt/src/port/caam/wolfcaam_linux.c \ wolfcrypt/src/port/caam/caam_integrity.c \ wolfcrypt/src/port/caam/caam_sha.c \ wolfcrypt/src/port/caam/caam_doc.pdf \ @@ -243,6 +245,16 @@ endif EXTRA_DIST += wolfcrypt/src/port/sealsq/README.md +if BUILD_CAAM_LINUX +# The driver core is built out of tree for QNX (a resource manager) and into +# the kernel for INTEGRITY. On Linux it runs in process, so it is built into +# the library along with its port layer and request dispatch. +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/caam_driver.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/caam_error.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/caam_linux.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_linux.c +endif + if BUILD_CAAM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_init.c src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/caam/wolfcaam_qnx.c diff --git a/wolfcrypt/src/port/caam/README.md b/wolfcrypt/src/port/caam/README.md index eef8b8cde2f..da921041ead 100644 --- a/wolfcrypt/src/port/caam/README.md +++ b/wolfcrypt/src/port/caam/README.md @@ -1 +1,90 @@ -See caam_doc.pdf for documentation about building and using. +# wolfSSL CAAM Port + +See `caam_doc.pdf` for documentation about building and using the driver on +i.MX under INTEGRITY, and `IDE/QNX/README.md` for the QNX build. + +## Linux user space (`--enable-caam=linux`) + +Runs the same driver core (`caam_driver.c`) from a Linux user space process, +developed against the SEC on a QorIQ T1040. QNX reaches the hardware through a +resource manager; here the driver runs in the calling process and a request is +a direct call. + + ./configure --host=powerpc-linux-gnu CC=powerpc-linux-gnu-gcc \ + --enable-caam=linux + make + +Accelerated: **AES-CBC, AES-CTR, AES-ECB** and the **TRNG**. Everything else +returns `CRYPTOCB_UNAVAILABLE` and runs in software, so an unsupported +operation is a performance question, not a correctness one. Hashing has no +descriptors in this driver (as on QNX), there is no i.MX style secure memory +block on this part so blobs and black keys are out, and public key is not +dispatched yet even though the driver carries the descriptors. + +### The engine has to be yours + +The in-tree `caam` driver claims all four job rings at boot and, on a part with +more than 4 GB of DDR, sets `MCFGR[PS]` for 64-bit descriptor pointers. +`MCFGR` is global to the block, so sharing it is not an option: this driver +writes 32-bit pointer words. Take the whole engine, then put it back in 32-bit +mode: + + for j in ffe301000.jr ffe302000.jr ffe303000.jr ffe304000.jr; do + echo $j > /sys/bus/platform/drivers/caam_jr/unbind; done + echo ffe300000.crypto > /sys/bus/platform/drivers/caam/unbind + +Unbinding leaves that driver's interrupt handler registered, and the first job +to complete would otherwise raise an IRQ it services against freed state and +panic the kernel. `CAAM_SET_JOBRING_ADDR()` masks the ring interrupt when it +claims the ring; the driver polls anyway. + +### Reserved DMA memory + +The engine cannot use ordinary user pages: they are not physically contiguous, +and on a 36-bit part they sit above what a 32-bit descriptor pointer can +address (measured on a T1040: virtual `0x100b4f10` -> physical +`0x1_EF9C2F10`). Boot Linux with `mem=` so it stops managing the top of DDR, +and the port carves engine buffers out of that reserved range instead: + + setenv othbootargs 'ramdisk_size=1000000 mem=2048M' + +That leaves physical `[2 GB, 4 GB)` unmanaged, contiguous, and below the +32-bit limit. It also makes `CONFIG_STRICT_DEVMEM` allow the mapping, since +the range is no longer reported as System RAM. + +Note CCSR is at the full physical address under Linux (`0xF_FE000000` on a +T1040), not the 32-bit view bare metal sees. + +| Macro | Default | Meaning | +|---|---|---| +| `CAAM_LINUX_CCSR_PHYS` | `0xFFE000000ULL` | Physical base of the CCSR window | +| `CAAM_LINUX_SEC_OFFSET` | `0x300000` | SEC block within CCSR | +| `CAAM_LINUX_JR_OFFSET` | `0x1000` | Which job ring to claim | +| `CAAM_LINUX_POOL_PHYS` | `0x80000000ULL` | Base of the reserved DMA pool | +| `CAAM_LINUX_POOL_SZ` | 256 KB | Size of that pool | +| `CAAM_LINUX_AES_MAX` | 16 KB | Largest AES request taken; bigger goes to software | + +### Performance: read this before enabling it + +On a T1040 at 1.4 GHz the engine is **slower than software AES**, measured +with the same binary over the same buffers: + +| Buffer | Software | CAAM | Ratio | +|---:|---:|---:|---:| +| 512 B | 42.69 MiB/s | 21.61 MiB/s | 0.51x | +| 1 KB | 44.61 MiB/s | 24.88 MiB/s | 0.56x | +| 4 KB | 45.67 MiB/s | 27.09 MiB/s | 0.59x | +| 8 KB | 46.30 MiB/s | 27.50 MiB/s | 0.59x | +| 16 KB | 46.31 MiB/s | 27.75 MiB/s | 0.60x | + +Hardware throughput is flat at roughly 28 MiB/s because the per-job cost +dominates: two `memcpy`s to stage operands in and results out of the pool, a +descriptor build, and a polled completion. Software rises with buffer size and +the e5500's AES is quick. The gap does narrow with key size, since the engine +barely notices AES-256 while software slows down. + +So the reason to enable this is not throughput. It is access to the TRNG as a +real entropy source, and having the crypto happen somewhere other than the +core. Closing the gap means removing the bounce buffers (letting callers +allocate from the pool directly), raising the transfer size toward the SEC's +64 KB per-descriptor limit, and completing on an interrupt rather than a poll. diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index dd5e2749718..7721f51a803 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -24,7 +24,8 @@ #endif #if (defined(__INTEGRITY) || defined(INTEGRITY)) || \ - (defined(__QNX__) || defined(__QNXNTO__)) + (defined(__QNX__) || defined(__QNXNTO__)) || \ + defined(WOLFSSL_CAAM_LINUX) #if defined(__QNX__) || defined(__QNXNTO__) #include @@ -240,6 +241,7 @@ static Error caamFreePage(unsigned int page) } /* free the partition and dealloc */ +#ifndef WOLFSSL_CAAM_NO_SM Error caamFreePart(unsigned int part) { unsigned int status; @@ -263,9 +265,11 @@ Error caamFreePart(unsigned int part) WOLFSSL_MSG("free'd partition"); return Success; } +#endif /* !WOLFSSL_CAAM_NO_SM */ /* find all partitions we own and free them */ +#ifndef WOLFSSL_CAAM_NO_SM static Error caamFreeAllPart() { unsigned int SMPO; @@ -281,11 +285,13 @@ static Error caamFreeAllPart() return 0; } +#endif /* !WOLFSSL_CAAM_NO_SM */ /* search through the partitions to find an unused one * returns negative value on failure, on success returns 0 or greater */ +#ifndef WOLFSSL_CAAM_NO_SM int caamFindUnusedPartition() { unsigned int SMPO; @@ -302,6 +308,7 @@ int caamFindUnusedPartition() return ret; } +#endif /* !WOLFSSL_CAAM_NO_SM */ /* flag contains how the partition is set i.e CSP flag and read/write access @@ -366,6 +373,7 @@ static Error caamCreatePartition(unsigned int* page, unsigned int par, /* return a partitions physical address on success, returns 0 on fail */ +#ifndef WOLFSSL_CAAM_NO_SM CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag) { int err; @@ -382,6 +390,7 @@ CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag) return (CAAM_ADDRESS)(CAAM_PAGE + (part << 12)); } +#endif /* !WOLFSSL_CAAM_NO_SM */ /* Gets the status of a job. Returns CAAM_WAITING if no output jobs ready to be @@ -1977,7 +1986,9 @@ int InitCAAM(void) int CleanupCAAM() { +#ifndef WOLFSSL_CAAM_NO_SM caamFreeAllPart(); +#endif CAAM_UNSET_JOBRING_ADDR(caam.ring.BaseAddr, caam.ring.JobIn, caam.ring.VirtualIn); CAAM_FREE_MUTEX(&caam.ring.jr_lock); diff --git a/wolfcrypt/src/port/caam/caam_error.c b/wolfcrypt/src/port/caam/caam_error.c index c8a6151d2e3..9b3cc17759d 100644 --- a/wolfcrypt/src/port/caam/caam_error.c +++ b/wolfcrypt/src/port/caam/caam_error.c @@ -24,7 +24,8 @@ #endif #if (defined(__INTEGRITY) || defined(INTEGRITY)) || \ - (defined(__QNX__) || defined(__QNXNTO__)) + (defined(__QNX__) || defined(__QNXNTO__)) || \ + defined(WOLFSSL_CAAM_LINUX) #include #include diff --git a/wolfcrypt/src/port/caam/caam_linux.c b/wolfcrypt/src/port/caam/caam_linux.c new file mode 100644 index 00000000000..2d0533e5e55 --- /dev/null +++ b/wolfcrypt/src/port/caam/caam_linux.c @@ -0,0 +1,298 @@ +/* caam_linux.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 + */ + +/* + * Port layer letting the CAAM driver core run in Linux user space, developed + * against the SEC on a QorIQ T1040. It implements the seam declared at the + * bottom of caam_driver.h, the same one caam_qnx.c implements for QNX. + * + * Two things differ from QNX and shape the design. + * + * Memory: QNX hands out physically contiguous pages with + * mmap(MAP_PHYS | MAP_ANON) and translates them with mem_offset64(). Linux + * user space has neither, and on a part with more than 4 GB of DDR ordinary + * pages sit above what a 32-bit descriptor pointer can reach. So nothing is + * allocated from the heap: boot with mem= to leave a range of physical memory + * unmanaged and carve engine buffers out of that. Translation is then a + * subtraction and contiguity is free. + * + * Ownership: the in-tree caam driver claims all four job rings at boot and + * configures the block globally, so it has to be unbound first, both the + * rings and the parent. That leaves its interrupt handler registered, and the + * first job to complete would raise an IRQ it services against freed state, + * so this port masks the ring interrupt when it claims the ring. The driver + * polls anyway. See README.md for the full sequence. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#undef WC_NO_HARDEN +#define WC_NO_HARDEN /* silence warning, it is irrelevant here */ +#include + +#if defined(WOLFSSL_CAAM_LINUX) + +#include +#include +#include +#include + +#include + +/* job ring configuration register, bit 0 masks the ring interrupt */ +#define CAAM_LINUX_JRCFGR_LS 0x0054 +#define CAAM_LINUX_JRCFGR_IMSK 0x00000001 + +static int caamMemFd = -1; /* /dev/mem, held open while mapped */ +static void* caamSecMap = NULL; /* the SEC register block */ + +static unsigned char* caamPoolVirt = NULL; +static CAAM_ADDRESS caamPoolPhys = 0; +static unsigned int caamPoolUsed = 0; + +/* Map a physical range through /dev/mem, opening it on first use. */ +static void* caamMapPhys(unsigned long long phys, unsigned int len) +{ + void* map; + + if (caamMemFd < 0) { + caamMemFd = open(CAAM_LINUX_MEM_DEV, O_RDWR | O_SYNC); + if (caamMemFd < 0) { + WOLFSSL_MSG("caam: could not open /dev/mem"); + return NULL; + } + } + + map = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, caamMemFd, + (off_t)phys); + if (map == MAP_FAILED) { + WOLFSSL_MSG("caam: could not map physical range"); + return NULL; + } + + return map; +} + +/* Offset of an address within the pool, or -1 if it is not a pool address. + * Linux must have been told not to manage the range (mem= on the kernel + * command line), which also makes CONFIG_STRICT_DEVMEM allow the mapping: + * the range is no longer reported as System RAM. */ +static long caamPoolOffset(const void* v, int sz) +{ + const unsigned char* p = (const unsigned char*)v; + + if (caamPoolVirt == NULL || p < caamPoolVirt || sz < 0 || + (p + sz) > (caamPoolVirt + CAAM_LINUX_POOL_SZ)) { + return -1; + } + + return (long)(p - caamPoolVirt); +} + +/* Hand out a cache line aligned block. Nothing is returned to the pool: the + * driver takes a small, bounded set of buffers and holds them for the life of + * the process, so a bump allocator cannot fragment. Callers that would + * otherwise allocate per operation keep their own scratch instead. */ +static unsigned char* caamPoolAlloc(int sz, CAAM_ADDRESS* physOut) +{ + unsigned int need; + unsigned char* out; + + if (sz <= 0) { + return NULL; + } + + if (caamPoolVirt == NULL) { + caamPoolVirt = (unsigned char*)caamMapPhys(CAAM_LINUX_POOL_PHYS, + CAAM_LINUX_POOL_SZ); + if (caamPoolVirt == NULL) { + return NULL; + } + caamPoolPhys = (CAAM_ADDRESS)CAAM_LINUX_POOL_PHYS; + caamPoolUsed = 0; + memset(caamPoolVirt, 0, CAAM_LINUX_POOL_SZ); + } + + need = ((unsigned int)sz + 63u) & ~63u; + if (caamPoolUsed + need > (unsigned int)CAAM_LINUX_POOL_SZ) { + WOLFSSL_MSG("caam: reserved DMA pool exhausted"); + return NULL; + } + + out = caamPoolVirt + caamPoolUsed; + if (physOut != NULL) { + *physOut = caamPoolPhys + caamPoolUsed; + } + caamPoolUsed += need; + + return out; +} + + +/* The mapping is uncached and both the host and the SEC are big endian here, + * so a plain volatile access is enough. */ +unsigned int CAAM_READ(CAAM_ADDRESS reg) +{ + return *(volatile unsigned int*)reg; +} + +void CAAM_WRITE(CAAM_ADDRESS reg, unsigned int in) +{ + *(volatile unsigned int*)reg = in; +} + + +int CAAM_SET_BASEADDR(CAAM_ADDRESS* baseAddr) +{ + if (baseAddr == NULL) { + return -1; + } + + caamSecMap = caamMapPhys(CAAM_LINUX_CCSR_PHYS + CAAM_LINUX_SEC_OFFSET, + CAAM_LINUX_SEC_SIZE); + if (caamSecMap == NULL) { + return -1; + } + *baseAddr = (CAAM_ADDRESS)caamSecMap; + + return 0; +} + +void CAAM_UNSET_BASEADDR(CAAM_ADDRESS baseAddr) +{ + (void)baseAddr; + + if (caamSecMap != NULL) { + munmap(caamSecMap, CAAM_LINUX_SEC_SIZE); + caamSecMap = NULL; + } + if (caamMemFd >= 0) { + close(caamMemFd); + caamMemFd = -1; + } +} + +/* The job ring registers are inside the block CAAM_SET_BASEADDR already + * mapped, so this only offsets into it. The ring itself comes from the pool. */ +int CAAM_SET_JOBRING_ADDR(CAAM_ADDRESS* base, CAAM_ADDRESS* ringInPhy, + void** ringInVir) +{ + unsigned char* ring; + CAAM_ADDRESS phys = 0; + + if (base == NULL || ringInPhy == NULL || ringInVir == NULL || + caamSecMap == NULL) { + return -1; + } + + *base = (CAAM_ADDRESS)caamSecMap + CAAM_LINUX_JR_OFFSET; + + /* Mask this ring's interrupt: the kernel driver leaves its handler + * installed after an unbind, and a completion interrupt would then be + * serviced against memory it has already freed. */ + CAAM_WRITE(*base + CAAM_LINUX_JRCFGR_LS, + CAAM_READ(*base + CAAM_LINUX_JRCFGR_LS) | CAAM_LINUX_JRCFGR_IMSK); + + ring = caamPoolAlloc(1024, &phys); + if (ring == NULL) { + return -1; + } + + *ringInPhy = phys; + *ringInVir = ring; + + return 0; +} + +void CAAM_UNSET_JOBRING_ADDR(CAAM_ADDRESS base, CAAM_ADDRESS ringInPhy, + void* ringInVir) +{ + /* The ring came from the pool and the register window is part of the + * block mapping, so there is nothing to give back. */ + (void)base; + (void)ringInPhy; + (void)ringInVir; +} + + +CAAM_ADDRESS CAAM_ADR_TO_PHYSICAL(void* in, int inSz) +{ + long off = caamPoolOffset(in, inSz); + + if (off < 0) { + WOLFSSL_MSG("caam: address is not in the reserved DMA pool"); + return 0; + } + + return caamPoolPhys + (CAAM_ADDRESS)off; +} + +CAAM_ADDRESS CAAM_ADR_TO_VIRTUAL(CAAM_ADDRESS in, int length) +{ + (void)length; + + if (caamPoolVirt == NULL || in < caamPoolPhys || + in >= (caamPoolPhys + CAAM_LINUX_POOL_SZ)) { + WOLFSSL_MSG("caam: physical address is outside the reserved pool"); + return 0; + } + + return (CAAM_ADDRESS)(caamPoolVirt + (in - caamPoolPhys)); +} + +/* Take a caller buffer and give back one the engine can reach. */ +void* CAAM_ADR_MAP(CAAM_ADDRESS in, int inSz, unsigned char copy) +{ + unsigned char* out = caamPoolAlloc(inSz, NULL); + + if (out != NULL && copy && in != 0) { + memcpy(out, (void*)in, inSz); + } + + return out; +} + +void CAAM_ADR_UNMAP(void* vaddr, CAAM_ADDRESS out, int outSz, + unsigned char copy) +{ + if (copy && vaddr != NULL && out != 0 && outSz > 0) { + memcpy((void*)out, vaddr, outSz); + } + + /* pool blocks are not individually freed; see caamPoolAlloc() */ +} + +/* The pool is mapped uncached, so there is no cache to push or drop. The + * barrier stops descriptor writes being reordered past the register write + * that rings the doorbell. */ +int CAAM_ADR_SYNC(void* vaddr, int sz) +{ + (void)vaddr; + (void)sz; + + __asm__ __volatile__("sync" ::: "memory"); + + return 0; +} + +#endif /* WOLFSSL_CAAM_LINUX */ diff --git a/wolfcrypt/src/port/caam/wolfcaam_linux.c b/wolfcrypt/src/port/caam/wolfcaam_linux.c new file mode 100644 index 00000000000..af11f94064d --- /dev/null +++ b/wolfcrypt/src/port/caam/wolfcaam_linux.c @@ -0,0 +1,319 @@ +/* wolfcaam_linux.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 + */ + +/* + * Request dispatch for the Linux port. QNX sends each request to a separate + * resource manager over devctl; here the driver runs in the calling process, + * so a request is a direct call. + * + * The work this layer does is moving data. Caller buffers come from + * wolfCrypt's heap, which the engine cannot reach, so every operand is staged + * in the reserved DMA pool and results are copied back. + * + * The staging buffers are shared, so a request holds a mutex from the moment + * it starts staging until the results are copied out. The driver's own + * jr_lock only covers the ring submission window, which is too narrow: two + * threads could otherwise interleave their staging and each receive the + * other's ciphertext. + * + * Note the return convention: wc_caamAddAndWait() tests against Success, + * which is 1, and Failure is 0. This layer must not use the usual "zero means + * success". + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_CAAM) && defined(WOLFSSL_CAAM_LINUX) + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* Largest AES request taken by the engine. Anything bigger goes back as + * CRYPTOCB_UNAVAILABLE for software to handle. */ +#ifndef CAAM_LINUX_AES_MAX + #define CAAM_LINUX_AES_MAX (16 * 1024) +#endif +#define CAAM_LINUX_KEY_MAX 32 +#define CAAM_LINUX_IV_MAX 16 + +/* Bound on a single entropy request. WC_CAAM_MAX_ENTROPY is what + * wc_GenerateSeed() asks for at a time. */ +#define CAAM_LINUX_ENT_MAX 64 + +static int caamInitDone = 0; +static int caamLockInit = 0; +static wolfSSL_Mutex caamLock; + +/* Staged once and reused: the pool is a bump allocator with no free, so a + * fresh mapping per operation would exhaust it within a few hundred calls. */ +static unsigned char* caamKeyBuf = NULL; +static unsigned char* caamIvBuf = NULL; +static unsigned char* caamInBuf = NULL; +static unsigned char* caamOutBuf = NULL; +static unsigned char* caamEntBuf = NULL; + +int wc_CAAMInitInterface(void) +{ + int ret = 0; + + if (!caamLockInit) { + if (wc_InitMutex(&caamLock) != 0) { + WOLFSSL_MSG("caam: could not create the request mutex"); + return WC_HW_E; + } + caamLockInit = 1; + } + + if (wc_LockMutex(&caamLock) != 0) { + return WC_HW_E; + } + if (!caamInitDone) { + if (InitCAAM() == 0) { + caamInitDone = 1; + } + else { + WOLFSSL_MSG("caam: could not initialize the driver"); + ret = WC_HW_E; + } + } + wc_UnLockMutex(&caamLock); + + return ret; +} + +void wc_CAAMFreeInterface(void) +{ + if (caamInitDone) { + CleanupCAAM(); + caamInitDone = 0; + } + + /* Leave nothing behind in the shared pool, then drop the pointers so a + * later init cannot reuse them. */ + if (caamKeyBuf != NULL) { + ForceZero(caamKeyBuf, CAAM_LINUX_KEY_MAX + CAAM_LINUX_IV_MAX + + CAAM_LINUX_ENT_MAX + (2 * CAAM_LINUX_AES_MAX)); + } + caamKeyBuf = NULL; + caamIvBuf = NULL; + caamInBuf = NULL; + caamOutBuf = NULL; + caamEntBuf = NULL; + + if (caamLockInit) { + wc_FreeMutex(&caamLock); + caamLockInit = 0; + } +} + +/* One pool block, split into the pieces a request needs. Taking it in a + * single allocation means a failure cannot strand partially used pool. */ +static int caamLinuxScratch(void) +{ + unsigned char* p; + int need = CAAM_LINUX_KEY_MAX + CAAM_LINUX_IV_MAX + CAAM_LINUX_ENT_MAX + + (2 * CAAM_LINUX_AES_MAX); + + if (caamOutBuf != NULL) { + return 0; + } + + p = (unsigned char*)CAAM_ADR_MAP(0, need, 0); + if (p == NULL) { + WOLFSSL_MSG("caam: could not reserve scratch in the DMA pool"); + return -1; + } + + caamKeyBuf = p; p += CAAM_LINUX_KEY_MAX; + caamIvBuf = p; p += CAAM_LINUX_IV_MAX; + caamEntBuf = p; p += CAAM_LINUX_ENT_MAX; + caamInBuf = p; p += CAAM_LINUX_AES_MAX; + caamOutBuf = p; + + return 0; +} + +/* Entropy is staged like everything else. caamEntropy() reads the TRNG + * registers with the CPU on era < 9 parts, where a heap pointer would have + * worked, but on era >= 9 it builds a descriptor and the engine DMAs the + * result - and an address outside the pool translates to physical 0. */ +static int caamLinuxEntropy(CAAM_BUFFER* buf, int sz) +{ + int ret; + + if (sz < 1 || buf == NULL || buf[0].Length <= 0 || + buf[0].Length > CAAM_LINUX_ENT_MAX) { + return Failure; + } + if (caamLinuxScratch() != 0) { + return Failure; + } + + /* Pass the driver's status straight back: wc_caamAddAndWait() turns + * CAAM_WAITING into RAN_BLOCK_E and wc_GenerateSeed() retries with a + * delay, so do not spin here. */ + ret = caamEntropy(caamEntBuf, buf[0].Length); + if (ret == Success) { + XMEMCPY((void*)buf[0].TheAddress, caamEntBuf, buf[0].Length); + } + ForceZero(caamEntBuf, CAAM_LINUX_ENT_MAX); + + return ret; +} + +/* AES-CBC/CTR/ECB. ECB has no IV, so it passes three buffers where CBC and + * CTR pass four plus a slot for the updated IV. caamAes() walks its list the + * same way, so both lists are built to the same shape. */ +static int caamLinuxAes(int type, unsigned int args[4], CAAM_BUFFER* buf, + int sz) +{ + DESCSTRUCT desc; + CAAM_BUFFER dma[4]; + int ivIdx, inIdx, outIdx, ivSz = 0; + int ret = Failure; + + if (buf == NULL) { + return Failure; + } + + ivIdx = (type == CAAM_AESCBC || type == CAAM_AESCTR) ? 1 : 0; + inIdx = ivIdx + 1; + outIdx = ivIdx + 2; + if (sz < (outIdx + 1)) { + return Failure; + } + + /* Lengths come from the caller as signed ints and end up as a memcpy + * size, so reject anything not in range rather than only too large. */ + if (buf[0].Length <= 0 || buf[inIdx].Length <= 0 || + buf[outIdx].Length <= 0 || (ivIdx && buf[1].Length <= 0)) { + return Failure; + } + if (buf[0].Length > CAAM_LINUX_KEY_MAX || + buf[inIdx].Length > CAAM_LINUX_AES_MAX || + buf[outIdx].Length > CAAM_LINUX_AES_MAX || + (ivIdx && buf[1].Length > CAAM_LINUX_IV_MAX)) { + return CRYPTOCB_UNAVAILABLE; + } + if (caamLinuxScratch() != 0) { + return Failure; + } + + XMEMCPY(caamKeyBuf, (void*)buf[0].TheAddress, buf[0].Length); + XMEMCPY(caamInBuf, (void*)buf[inIdx].TheAddress, buf[inIdx].Length); + dma[0].BufferType = DataBuffer; + dma[0].TheAddress = (CAAM_ADDRESS)caamKeyBuf; + dma[0].Length = buf[0].Length; + + if (ivIdx) { + ivSz = buf[1].Length; + XMEMCPY(caamIvBuf, (void*)buf[1].TheAddress, ivSz); + dma[1].BufferType = DataBuffer; + dma[1].TheAddress = (CAAM_ADDRESS)caamIvBuf; + dma[1].Length = ivSz; + } + + dma[inIdx].BufferType = DataBuffer; + dma[inIdx].TheAddress = (CAAM_ADDRESS)caamInBuf; + dma[inIdx].Length = buf[inIdx].Length; + + dma[outIdx].BufferType = DataBuffer | LastBuffer; + dma[outIdx].TheAddress = (CAAM_ADDRESS)caamOutBuf; + dma[outIdx].Length = buf[outIdx].Length; + + caamDescInit(&desc, type, args, dma, outIdx + 1); + if (caamAes(&desc, dma, args) == Success) { + XMEMCPY((void*)buf[outIdx].TheAddress, caamOutBuf, buf[outIdx].Length); + + /* hand back the updated IV so chaining continues correctly */ + if (ivSz > 0 && sz > (outIdx + 1) && buf[outIdx + 1].TheAddress != 0) { + XMEMCPY((void*)buf[outIdx + 1].TheAddress, caamIvBuf, ivSz); + } + ret = Success; + } + else { + WOLFSSL_MSG("caam: AES job did not complete"); + } + + /* Clear the key material on every request: it is the secret, and it is + * only 48 bytes. The data buffers are cleared at teardown instead - + * wiping up to 2 x CAAM_LINUX_AES_MAX per call costs about a fifth of + * the throughput, and the next request overwrites them before the engine + * reads them anyway. */ + ForceZero(caamKeyBuf, CAAM_LINUX_KEY_MAX); + ForceZero(caamIvBuf, CAAM_LINUX_IV_MAX); + + return ret; +} + +int SynchronousSendRequest(int type, unsigned int args[4], CAAM_BUFFER* buf, + int sz) +{ + int ret; + + if (wc_CAAMInitInterface() != 0) { + return Failure; + } + + switch (type) { + case CAAM_ENTROPY: + case CAAM_AESCBC: + case CAAM_AESCTR: + case CAAM_AESECB: + break; + default: + /* Anything else goes to software rather than pretending to run. */ + WOLFSSL_MSG("caam: request type not handled by the Linux port"); + return CRYPTOCB_UNAVAILABLE; + } + + /* Held across staging, submission and copy back, since the staging + * buffers are shared by every caller. */ + if (wc_LockMutex(&caamLock) != 0) { + return Failure; + } + + if (type == CAAM_ENTROPY) { + ret = caamLinuxEntropy(buf, sz); + } + else { + ret = caamLinuxAes(type, args, buf, sz); + } + + wc_UnLockMutex(&caamLock); + + return ret; +} + +#endif /* WOLFSSL_CAAM && WOLFSSL_CAAM_LINUX */ diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 6deb44ebc91..bd3ae2350fa 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -108,6 +108,7 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/caam/caam_driver.h \ wolfssl/wolfcrypt/port/caam/caam_error.h \ wolfssl/wolfcrypt/port/caam/caam_qnx.h \ + wolfssl/wolfcrypt/port/caam/caam_linux.h \ wolfssl/wolfcrypt/port/silabs/silabs_aes.h \ wolfssl/wolfcrypt/port/silabs/silabs_ecc.h \ wolfssl/wolfcrypt/port/silabs/silabs_hash.h \ @@ -218,6 +219,7 @@ nobase_include_HEADERS+= wolfssl/wolfcrypt/port/caam/wolfcaam.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_cmac.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_aes.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_qnx.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_seco.h \ wolfssl/wolfcrypt/port/caam/wolfcaam_fsl_nxp.h endif diff --git a/wolfssl/wolfcrypt/port/caam/caam_driver.h b/wolfssl/wolfcrypt/port/caam/caam_driver.h index 87d135fb60f..517d70b4c4a 100644 --- a/wolfssl/wolfcrypt/port/caam/caam_driver.h +++ b/wolfssl/wolfcrypt/port/caam/caam_driver.h @@ -27,9 +27,21 @@ #include "caam_qnx.h" #endif +#if defined(WOLFSSL_CAAM_LINUX) + int InitCAAM(void); + int CleanupCAAM(void); + #include "caam_linux.h" +#endif + #ifndef CAAM_BASE -#if (defined(__INTEGRITY) || defined(INTEGRITY)) +#if defined(WOLFSSL_CAAM_LINUX) + /* The Linux port maps the block itself, by physical address, in + * caam_linux.c. These only satisfy references elsewhere in the header; + * secure memory is not used (WOLFSSL_CAAM_NO_SM). */ + #define CAAM_BASE 0 + #define CAAM_PAGE 0 +#elif (defined(__INTEGRITY) || defined(INTEGRITY)) #define CAAM_BASE 0xf2100000 #define CAAM_PAGE 0xf0100000 #elif defined(__aarch64__) @@ -49,13 +61,26 @@ #endif /* !CAAM_BASE */ -#ifdef WOLFSSL_CAAM_PRINT - #include - #define WOLFSSL_MSG(in) printf("%s\n", (in)) - void DEBUG_PRINT_ARRAY(void* a, int aSz, char* str); -#else - #define WOLFSSL_MSG(in) do {} while (0) - #define DEBUG_PRINT_ARRAY(a,aSz,str) do {} while (0) +/* The driver is built standalone for QNX and INTEGRITY, with no wolfSSL + * logging available, so it supplies its own. Guarded because a build that + * compiles the driver into the library has already defined the real ones from + * logging.h, and silently replacing them there would compile out every + * diagnostic in the shim layer. */ +#ifndef WOLFSSL_MSG + #ifdef WOLFSSL_CAAM_PRINT + #include + #define WOLFSSL_MSG(in) printf("%s\n", (in)) + void DEBUG_PRINT_ARRAY(void* a, int aSz, char* str); + #else + #define WOLFSSL_MSG(in) do {} while (0) + #endif +#endif +#ifndef DEBUG_PRINT_ARRAY + #ifdef WOLFSSL_CAAM_PRINT + void DEBUG_PRINT_ARRAY(void* a, int aSz, char* str); + #else + #define DEBUG_PRINT_ARRAY(a,aSz,str) do {} while (0) + #endif #endif #define CAAM_PAGE_MAX 6 @@ -380,9 +405,14 @@ int caamAead(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4]); int caamAesCmac(DESCSTRUCT *desc, int sz, unsigned int args[4]); int caamBlob(DESCSTRUCT *desc); +#ifndef WOLFSSL_CAAM_NO_SM +/* Secure memory. Not every part has the block, and the shim layer declares + * its own wrappers of the same names, so keep these out of a build with + * secure memory turned off. */ CAAM_ADDRESS caamGetPartition(unsigned int part, int partSz, unsigned int flag); int caamFreePart(unsigned int part); int caamFindUnusedPartition(void); +#endif diff --git a/wolfssl/wolfcrypt/port/caam/caam_linux.h b/wolfssl/wolfcrypt/port/caam/caam_linux.h new file mode 100644 index 00000000000..db5c275a412 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/caam_linux.h @@ -0,0 +1,102 @@ +/* caam_linux.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 + */ + +/* Types and macros the CAAM driver core expects from its environment, for a + * Linux userspace host. Mirrors caam_qnx.h; see caam_linux.c for the port + * layer itself. */ + +#ifndef CAAM_LINUX_H +#define CAAM_LINUX_H + +#include +#include +#include +#include + +#define CAAM_MUTEX pthread_mutex_t +#define CAAM_INIT_MUTEX(x) pthread_mutex_init((x), NULL) +#define CAAM_FREE_MUTEX(x) pthread_mutex_destroy((x)) +#define CAAM_LOCK_MUTEX(x) pthread_mutex_lock((x)) +#define CAAM_UNLOCK_MUTEX(x) pthread_mutex_unlock((x)) + +#define Error int +#define Value int +#define Boolean int +#define CAAM_ADDRESS uintptr_t +#define Success 1 +#define Failure 0 +#define INTERRUPT_Panic() do {} while (0) +#define MemoryMapMayNotBeEmpty -1 +#define CAAM_WAITING -2 +#define NoActivityReady -1 +#define MemoryOperationNotPerformed -1 +#define CAAM_ARGS_E -3 + +#ifndef WOLFSSL_CAAM_BUFFER +#define WOLFSSL_CAAM_BUFFER + typedef struct CAAM_BUFFER { + int BufferType; + CAAM_ADDRESS TheAddress; + int Length; + } CAAM_BUFFER; +#endif + +/* Physical base of the CCSR window and the SEC block inside it. These parts + * have a 36-bit physical address space, so the value does not fit the 32-bit + * CAAM_ADDRESS the driver uses for virtual addresses; it is only ever used as + * an mmap offset inside caam_linux.c. */ +#ifndef CAAM_LINUX_CCSR_PHYS + #define CAAM_LINUX_CCSR_PHYS 0xFFE000000ULL +#endif +#ifndef CAAM_LINUX_SEC_OFFSET + #define CAAM_LINUX_SEC_OFFSET 0x300000ULL +#endif +#ifndef CAAM_LINUX_SEC_SIZE + #define CAAM_LINUX_SEC_SIZE 0x10000 +#endif + +/* Which job ring to claim, as an offset from the SEC base. Ring N sits at + * (N + 1) * 0x1000. */ +#ifndef CAAM_LINUX_JR_OFFSET + #define CAAM_LINUX_JR_OFFSET 0x1000 +#endif + +/* Reserved physical DMA pool. + * + * The engine cannot use ordinary user pages: they are not physically + * contiguous and, on a part with more than 4 GB, sit above what a 32-bit + * descriptor pointer can reach. Boot Linux with mem= so it stops managing the + * top of DDR and carve engine buffers out of that reserved range instead. */ +#ifndef CAAM_LINUX_POOL_PHYS + #define CAAM_LINUX_POOL_PHYS 0x80000000ULL +#endif +#ifndef CAAM_LINUX_POOL_SZ + #define CAAM_LINUX_POOL_SZ (256 * 1024) +#endif + +#ifndef CAAM_LINUX_MEM_DEV + #define CAAM_LINUX_MEM_DEV "/dev/mem" +#endif + +/* Yield to other threads while polling for job completion. */ +#define CAAM_CPU_CHILL() sched_yield() + +#endif /* CAAM_LINUX_H */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h index d033054249b..b38b104dc0a 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -32,11 +32,13 @@ #include #elif defined(WOLFSSL_IMXRT1170_CAAM) #include +#elif defined(WOLFSSL_CAAM_LINUX) + #include #endif #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_SECO_CAAM) || \ - defined(WOLFSSL_IMXRT1170_CAAM) + defined(WOLFSSL_IMXRT1170_CAAM) || defined(WOLFSSL_CAAM_LINUX) /* unique devId for CAAM use on crypto callbacks */ @@ -69,8 +71,10 @@ WOLFSSL_LOCAL int wc_caamAddAndWait(CAAM_BUFFER* buf, int sz, word32 arg[4], word32 type); WOLFSSL_LOCAL int caamFindUnusedPartition(void); +#ifndef WOLFSSL_CAAM_NO_SM WOLFSSL_LOCAL CAAM_ADDRESS caamGetPartition(int part, int sz); WOLFSSL_LOCAL int caamFreePart(int partNum); +#endif WOLFSSL_LOCAL int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* in, int inSz); WOLFSSL_LOCAL int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz); @@ -97,7 +101,7 @@ WOLFSSL_API int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, #define WC_CAAM_MAX_ENTROPY 44 #if !defined(WOLFSSL_QNX_CAAM) && !defined(WOLFSSL_SECO_CAAM) && \ - !defined(WOLFSSL_IMXRT1170_CAAM) + !defined(WOLFSSL_IMXRT1170_CAAM) && !defined(WOLFSSL_CAAM_LINUX) WOLFSSL_API int wc_caamSetResource(IODevice ioDev); #ifndef WC_CAAM_READ #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h b/wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h new file mode 100644 index 00000000000..5ccd74bc7b4 --- /dev/null +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam_linux.h @@ -0,0 +1,61 @@ +/* wolfcaam_linux.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 + */ + +#ifndef WOLFCAAM_LINUX_H +#define WOLFCAAM_LINUX_H + +#if defined(WOLFSSL_CAAM_LINUX) + +#include + +/* caam_linux.h, pulled in by caam_driver.h, already supplies CAAM_ADDRESS, + * CAAM_BUFFER, Error/Value/Boolean and the status values. What is left is + * what the shim layer itself refers to. */ +#define DataBuffer 0 +#define LastBuffer 0 +#define ResourceNotAvailable -3 + +/* unique devId for CAAM use on crypto callbacks */ +#ifndef WOLFSSL_CAAM_DEVID + #define WOLFSSL_CAAM_DEVID 7 +#endif + +#include +#include +#include +#include +#include + +/* Unlike QNX, which reaches a resource manager over devctl, the Linux port + * drives the engine from inside the calling process, so a request is a plain + * function call. */ +WOLFSSL_LOCAL int SynchronousSendRequest(int type, unsigned int args[4], + CAAM_BUFFER *buf, int sz); +WOLFSSL_LOCAL int wc_CAAMInitInterface(void); +WOLFSSL_LOCAL void wc_CAAMFreeInterface(void); + +#define CAAM_SEND_REQUEST(type, sz, arg, buf) \ + SynchronousSendRequest((type), (arg), (buf), (sz)) +#define CAAM_INIT_INTERFACE wc_CAAMInitInterface +#define CAAM_FREE_INTERFACE wc_CAAMFreeInterface + +#endif /* WOLFSSL_CAAM_LINUX */ +#endif /* WOLFCAAM_LINUX_H */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 2bfbb4ddef4..b7e8f630873 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -3202,6 +3202,22 @@ #endif /* OS specific support so far */ +#ifdef WOLFSSL_CAAM_LINUX + #undef WOLFSSL_CAAM + #define WOLFSSL_CAAM + /* The driver core carries no hash descriptors, so hashing stays in + * software, the same as QNX. */ + #undef WOLFSSL_NO_CAAM_HASH + #define WOLFSSL_NO_CAAM_HASH + /* No i.MX style secure memory block, so no blobs or black keys. */ + #undef WOLFSSL_NO_CAAM_BLOB + #define WOLFSSL_NO_CAAM_BLOB + /* Public key is not dispatched by this port yet, so leave ECC in + * software rather than half offloading it. */ + #undef WOLFSSL_NO_CAAM_ECC + #define WOLFSSL_NO_CAAM_ECC +#endif + #ifdef WOLFSSL_QNX_CAAM /* shim layer for QNX hashing not yet implemented */ #define WOLFSSL_NO_CAAM_HASH