Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"])
Expand Down
12 changes: 12 additions & 0 deletions wolfcrypt/src/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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
Expand Down
91 changes: 90 additions & 1 deletion wolfcrypt/src/port/caam/README.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 12 additions & 1 deletion wolfcrypt/src/port/caam/caam_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <sys/mman.h>
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion wolfcrypt/src/port/caam/caam_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
#endif

#if (defined(__INTEGRITY) || defined(INTEGRITY)) || \
(defined(__QNX__) || defined(__QNXNTO__))
(defined(__QNX__) || defined(__QNXNTO__)) || \
defined(WOLFSSL_CAAM_LINUX)

#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#include <wolfssl/wolfcrypt/port/caam/caam_error.h>
Expand Down
Loading
Loading