Skip to content

Commit a409d19

Browse files
committed
Extend the PolarFire SoC Athena port to SHA-2, AES, the RNG, ECC and RSA
1 parent 655c8ce commit a409d19

10 files changed

Lines changed: 5358 additions & 402 deletions

File tree

‎.github/workflows/mpfs-athena-compile.yml‎

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ name: "Microchip PolarFire SoC Athena port"
33
# Keeps the PolarFire SoC Athena F5200 crypto callback port compiling against
44
# the real Microchip CAL. The port is only built when --with-mpfs-athena names a
55
# CAL directory, so no other job compiles a line of it: without this guard a
6-
# rename in the CAL headers, or a refactor in aes.c, sha512.c or cryptocb.h,
7-
# would break it silently until someone next built for the board.
6+
# rename in the CAL headers, or a refactor in a wolfCrypt algorithm file or
7+
# cryptocb.h, would break it silently until someone next built for the board.
88
#
99
# Nothing is faked: the CAL ships in a public GitHub repository, headers and
1010
# archive both, so this compiles against the genuine vendor headers at a pinned
@@ -17,7 +17,7 @@ name: "Microchip PolarFire SoC Athena port"
1717
# by crossbuild-essential-riscv64, and a bare-metal toolchain would make this
1818
# job depend on how a libc happens to be packaged. None of that is what the job
1919
# is guarding: the breakage it catches is a CAL header rename, or a refactor in
20-
# aes.c, sha512.c or cryptocb.h, and the host compiler sees all of it. The
20+
# an algorithm file or cryptocb.h, and the host compiler sees all of it. The
2121
# target ABI is proven by building for the board, not here.
2222
#
2323
# Functional correctness is validated on an MPFS250TS Video Kit; see
@@ -74,13 +74,59 @@ jobs:
7474
extra: '-DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DWOLFSSL_AES_COUNTER'
7575
# The port advertises independent algorithm gates, so each has to
7676
# build on its own: an AES-only build has no WC_SHA384_DIGEST_SIZE,
77-
# and a SHA-only build compiles no cipher path.
77+
# and a SHA-only build compiles no cipher path. SHA-256 is on by
78+
# default, so the AES-only legs opt out of it.
7879
- leg: aesctr-only
79-
extra: '-DWOLFSSL_AES_COUNTER'
80+
extra: '-DWOLFSSL_AES_COUNTER -DWC_MPFS_ATHENA_NO_SHA256'
8081
- leg: sha384-only
8182
extra: '-DWOLFSSL_SHA512 -DWOLFSSL_SHA384'
83+
# The cipher case is shared by CTR and ECB, so each must build with
84+
# the other gate off.
85+
- leg: aesecb-only
86+
extra: '-DHAVE_AES_ECB -DWC_MPFS_ATHENA_NO_SHA256'
87+
# The XTS build the ECB path exists for, with a raised minimum so the
88+
# self-test takes its larger-buffer branch.
89+
- leg: aesxts
90+
extra: '-DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DWOLFSSL_AES_COUNTER -DHAVE_AES_ECB -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT -DWC_MPFS_ATHENA_AES_MIN_SZ=512'
8291
- leg: no-selftest
8392
extra: '-DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DWOLFSSL_AES_COUNTER -DWC_MPFS_ATHENA_NO_SELFTEST'
93+
# Every SHA-2 type, with the copy and free paths that allocate.
94+
- leg: sha2-all
95+
extra: '-DWOLFSSL_SHA224 -DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DCI_HEAP -DWOLFSSL_SMALL_STACK -DWOLFSSL_SMALL_STACK_CACHE -DWOLFSSL_HASH_KEEP -DWOLFSSL_HASH_FLAGS'
96+
# Every AES mode and CMAC, with a raised GCM minimum.
97+
- leg: aes-all
98+
extra: '-DHAVE_AES_CBC -DHAVE_AESGCM -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_KEYWRAP_PADDING -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT -DWOLFSSL_AES_COUNTER -DHAVE_AES_ECB -DWOLFSSL_AES_XTS -DWC_MPFS_ATHENA_GCM_MIN_SZ=64'
99+
- leg: rng-drbg
100+
extra: '-DWC_MPFS_ATHENA_RNG_DRBG'
101+
# The wolfBoot test application's shape: its own generator, no DRBG.
102+
- leg: custom-rng
103+
extra: '-DWC_NO_HASHDRBG -DCUSTOM_RAND_GENERATE_BLOCK=my_rng -DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DHAVE_AES_ECB'
104+
# Every RNG seeded from the engine, whatever its devId.
105+
- leg: custom-seed
106+
extra: '-DCUSTOM_RAND_GENERATE_SEED=wc_MpfsAthena_GenerateSeed -DWOLFSSL_SHA512 -DWOLFSSL_SHA384'
107+
# Every curve, and each ECC operation on its own, since the shared
108+
# helpers are gated on the ones that use them.
109+
- leg: ecc-all
110+
extra: '-DHAVE_ECC -DHAVE_ECC192 -DHAVE_ECC224 -DHAVE_ECC384 -DHAVE_ECC521 -DWOLFSSL_SHA512 -DWOLFSSL_SHA384'
111+
- leg: ecc-verify-only
112+
extra: '-DHAVE_ECC -DNO_ECC_SIGN -DNO_ECC_DHE'
113+
- leg: ecc-sign-only
114+
extra: '-DHAVE_ECC -DNO_ECC_VERIFY -DNO_ECC_DHE'
115+
- leg: ecc-dhe-only
116+
extra: '-DHAVE_ECC -DNO_ECC_SIGN -DNO_ECC_VERIFY'
117+
# Without ASN.1 the signature is r || s; wolfBoot's own
118+
# verify-only build is this shape.
119+
- leg: ecc-no-asn
120+
extra: '-DHAVE_ECC -DHAVE_ECC384 -DNO_ASN -DWOLFSSL_SHA512 -DWOLFSSL_SHA384'
121+
- leg: ecc-blind-set-k
122+
extra: '-DHAVE_ECC -DWOLFSSL_ECC_BLIND_K -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_DETERMINISTIC_K'
123+
- leg: rsa
124+
extra: '-DCI_RSA -DCI_HEAP -DWOLFSSL_SMALL_STACK -DWOLF_CRYPTO_CB_RSA_PAD'
125+
- leg: rsa-public-only
126+
extra: '-DCI_RSA -DWOLFSSL_RSA_PUBLIC_ONLY -DWC_MPFS_ATHENA_RSA_PUBLIC'
127+
# Every family kept in software.
128+
- leg: all-opted-out
129+
extra: '-DCI_RSA -DHAVE_ECC -DHAVE_AESGCM -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT -DHAVE_AES_KEYWRAP -DWOLFSSL_SHA512 -DWOLFSSL_SHA384 -DWC_MPFS_ATHENA_NO_SHA256 -DWC_MPFS_ATHENA_NO_SHA512 -DWC_MPFS_ATHENA_NO_CBC -DWC_MPFS_ATHENA_NO_GCM -DWC_MPFS_ATHENA_NO_KEYWRAP -DWC_MPFS_ATHENA_NO_CMAC -DWC_MPFS_ATHENA_NO_RNG -DWC_MPFS_ATHENA_NO_ECC -DWC_MPFS_ATHENA_NO_RSA'
84130
steps:
85131
- uses: actions/checkout@v4
86132
name: Checkout wolfSSL
@@ -118,12 +164,19 @@ jobs:
118164
#define SINGLE_THREADED
119165
#define NO_FILESYSTEM
120166
#define NO_WOLFSSL_DIR
121-
/* The first targets have no heap, so this is the static-pool leg. */
167+
/* The first targets have no heap, so this is the static-pool leg
168+
* unless a matrix leg asks for one. */
169+
#ifndef CI_HEAP
122170
#define WOLFSSL_NO_MALLOC
123171
#define NO_WOLFSSL_MEMORY
172+
#endif
124173
#define WC_NO_HARDEN
174+
#if !defined(HAVE_ECC) && !defined(CI_RSA)
125175
#define NO_BIG_INT
176+
#endif
177+
#ifndef CI_RSA
126178
#define NO_RSA
179+
#endif
127180
#define NO_DH
128181
#define NO_DSA
129182
#endif
@@ -136,6 +189,17 @@ jobs:
136189
wolfcrypt/src/port/microchip/mpfs_athena.c \
137190
-o "$GITHUB_WORKSPACE/mpfs_athena.o"
138191
192+
# The seed function is called from random.c, which has to see its
193+
# prototype.
194+
if [ "${{ matrix.leg }}" = "custom-seed" ]; then
195+
cc -c \
196+
-Wall -Wextra -Werror \
197+
-I. -I"$GITHUB_WORKSPACE/cfg" -I"$CAL" \
198+
-DWOLFSSL_USER_SETTINGS ${{ matrix.extra }} \
199+
wolfcrypt/src/random.c \
200+
-o "$GITHUB_WORKSPACE/random.o"
201+
fi
202+
139203
- name: Check every CAL symbol resolves in the archive
140204
run: |
141205
set -e
@@ -150,7 +214,7 @@ jobs:
150214
# cleanly here, so it has to be checked explicitly.
151215
missing=0
152216
for sym in $(nm --undefined-only "$OBJ" \
153-
| awk '{print $2}' | grep -E '^(CAL|aesf5200|shaf5200)'); do
217+
| awk '{print $2}' | grep -E '^(CAL|aesf5200|shaf5200|uiROMMods$)'); do
154218
if grep -qx "$sym" /tmp/cal_defined; then
155219
echo " ok $sym"
156220
else

‎configure.ac‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12573,13 +12573,13 @@ fi
1257312573

1257412574
if test "x$ENABLED_MPFS_ATHENA" = "xyes"
1257512575
then
12576-
# The port offloads what the ordinary wolfCrypt gates turn on, so without
12577-
# these it would compile to nothing.
12578-
if test "x$ENABLED_SHA384" = "xno"; then
12579-
AC_MSG_ERROR([--with-mpfs-athena needs SHA-384; drop --disable-sha384])
12580-
fi
12581-
if test "x$ENABLED_AESCTR" = "xno"; then
12582-
AC_MSG_ERROR([--with-mpfs-athena needs AES-CTR; add --enable-aesctr])
12576+
# AES-XTS reaches the engine only through the bulk ECB call that
12577+
# HAVE_AES_ECB compiles in; without it every XTS block is its own engine
12578+
# transaction, slower than software.
12579+
if test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESECB" = "xno"; then
12580+
ENABLED_AESECB=yes
12581+
AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_ECB"
12582+
AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AES_ECB"
1258312583
fi
1258412584
fi
1258512585

‎wolfcrypt/benchmark/benchmark.c‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5342,6 +5342,12 @@ int benchmark_free(void)
53425342
printf("%serror %d with wolfCrypt_Cleanup\n", err_prefix, ret);
53435343
}
53445344

5345+
#ifdef WOLFSSL_STATIC_MEMORY
5346+
/* The next benchmark_init() loads the pool again from its start, which
5347+
* would partition over this heap's structures if the hint were kept. */
5348+
HEAP_HINT = NULL;
5349+
#endif
5350+
53455351
return ret;
53465352
}
53475353

‎wolfcrypt/src/aes.c‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10010,6 +10010,9 @@ static void GMULT(byte *x, byte m[256][WC_AES_BLOCK_SIZE],
1001010010
XMEMCPY(x, Z + 1, WC_AES_BLOCK_SIZE);
1001110011
#endif
1001210012
#else
10013+
/* The 64-bit word path reads Z at odd offsets, so it needs unaligned loads
10014+
* just as the 32-bit one does. */
10015+
#ifndef WOLFSSL_USE_ALIGN
1001310016
byte* Z = ws->b;
1001410017
byte a;
1001510018
word64* pZ;
@@ -10036,6 +10039,24 @@ static void GMULT(byte *x, byte m[256][WC_AES_BLOCK_SIZE],
1003610039
pZ = (word64*)(Z + 1);
1003710040
pm = (word64*)(m[x[0]]);
1003810041
px[0] = pZ[0] ^ pm[0]; px[1] = pZ[1] ^ pm[1];
10042+
#else
10043+
byte* Z = ws->b;
10044+
byte a;
10045+
int i;
10046+
10047+
XMEMCPY(Z + 16, m[x[15]], WC_AES_BLOCK_SIZE);
10048+
a = Z[16 + 15];
10049+
Z[15] = R[a][0];
10050+
Z[16] ^= R[a][1];
10051+
for (i = 14; i > 0; i--) {
10052+
xorbuf(Z + i + 1, m[x[i]], WC_AES_BLOCK_SIZE);
10053+
a = Z[16 + i];
10054+
Z[i] = R[a][0];
10055+
Z[i+1] ^= R[a][1];
10056+
}
10057+
xorbuf(Z + 1, m[x[0]], WC_AES_BLOCK_SIZE);
10058+
XMEMCPY(x, Z + 1, WC_AES_BLOCK_SIZE);
10059+
#endif
1003910060
#endif
1004010061
}
1004110062
#endif

0 commit comments

Comments
 (0)