Skip to content

Add SHE (Secure Hardware Extension) support to wolfCrypt#10009

Open
night1rider wants to merge 11 commits intowolfSSL:masterfrom
night1rider:SHE-update
Open

Add SHE (Secure Hardware Extension) support to wolfCrypt#10009
night1rider wants to merge 11 commits intowolfSSL:masterfrom
night1rider:SHE-update

Conversation

@night1rider
Copy link
Copy Markdown
Contributor

@night1rider night1rider commented Mar 18, 2026

Implements software-only SHE CMD_LOAD_KEY message generation (M1/M2/M3)
and verification message computation (M4/M5) with optional crypto
callback support for hardware offload.

New files:

  • wolfssl/wolfcrypt/she.h: API declarations, constants, wc_SHE context
  • wolfcrypt/src/she.c: Miyaguchi-Preneel KDF, message generation,
    verification computation, and crypto callback integration
  • tests/api/test_she.c/h: API tests with 97% line / 100% function coverage

API:

  • wc_SHE_Init/Free, Init_Id, Init_Label (lifecycle)
  • wc_SHE_GenerateM1M2M3 (generate M1/M2/M3 to caller buffers, callback optional)
  • wc_SHE_GenerateM4M5 (generate M4/M5 to caller buffers, independent of
    M1/M2/M3, callback optional)
  • wc_SHE_ImportM1M2M3 (import external M1/M2/M3 into context)
  • wc_SHE_GetUID (callback required, fetches UID from hardware)
  • wc_SHE_GetCounter (callback required, reads monotonic counter from hardware)
  • wc_SHE_ExportKey (callback required, exports key slot as M1-M5 from hardware)
  • wc_SHE_SetKdfConstants (callback optional, WOLFSSL_SHE_EXTENDED only)
  • wc_SHE_SetM2Header (callback optional, WOLFSSL_SHE_EXTENDED only)
  • wc_SHE_SetM4Header (callback optional, WOLFSSL_SHE_EXTENDED only)
  • No key material stored in the context; all inputs passed at generation time

Crypto callback integration:

  • WC_ALGO_TYPE_SHE added to wc_AlgoType enum
  • Callback sub-types: WC_SHE_SET_UID, WC_SHE_GET_COUNTER,
    WC_SHE_GENERATE_M1M2M3, WC_SHE_GENERATE_M4M5, WC_SHE_EXPORT_KEY
  • Per-operation structs in wc_CryptoInfo union with full parameter passthrough
  • Dispatch functions in cryptocb.c
  • Optional features: NO_WC_SHE_GETUID, NO_WC_SHE_GETCOUNTER,
    NO_WC_SHE_EXPORTKEY, NO_WC_SHE_IMPORT_M123

Build system:

  • configure.ac: --enable-she=standard|extended
  • CMakeLists.txt: WOLFSSL_SHE standard|extended|no
  • src/include.am: she.c compilation
  • .github/workflows/os-check.yml: CI configs for standard, extended,
    and NO_* disable flag combinations

Ported from wolfHSM wh_she_crypto.c.

@night1rider night1rider self-assigned this Mar 18, 2026
@night1rider night1rider force-pushed the SHE-update branch 3 times, most recently from 39d4163 to 54b673a Compare March 22, 2026 02:07
@night1rider night1rider marked this pull request as ready for review March 23, 2026 15:38
Copy link
Copy Markdown
Contributor

@bigbrett bigbrett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely fantastic work @night1rider. A few issues to address but overall looks great.

@bigbrett bigbrett removed their assignment Mar 24, 2026
Copy link
Copy Markdown

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10009

Scan targets checked: wolfcrypt-bugs, wolfcrypt-src
Findings: 1

Low (1)

Missing NULL check on id parameter in wc_SHE_Init_Id

File: wolfcrypt/src/she.c:155-157
Function: wc_SHE_Init_Id
Category: NULL pointer dereference

The function wc_SHE_Init_Id validates she == NULL and checks that len is within bounds (0 to WC_SHE_MAX_ID_LEN), but does not check whether id is NULL before calling XMEMCPY(she->id, id, (size_t)len). If a caller passes id = NULL with len > 0, this results in a NULL pointer dereference. By contrast, the sibling function wc_SHE_Init_Label correctly validates label == NULL before use. The impact is limited because this requires caller misuse and would crash immediately (no memory corruption beyond the dereference), but it is inconsistent with the defensive validation pattern used throughout the rest of the SHE API.

if (len < 0 || len > WC_SHE_MAX_ID_LEN) {
        return BUFFER_E;
    }

    XMEMCPY(she->id, id, (size_t)len);

Recommendation: Add a NULL check for id when len > 0, consistent with the pattern in wc_SHE_Init_Label: if (id == NULL && len > 0) { return BAD_FUNC_ARG; } or simply if (id == NULL) { return BAD_FUNC_ARG; } before the length check.


This review was generated automatically by Fenrir. Findings are non-blocking.

night1rider added a commit to night1rider/wolfssl that referenced this pull request Mar 24, 2026
…_she.{c,h}, fix naming consistency, auto-enable CMAC/AES dependencies, add WC_SHE_SW_DEFAULT opt-inAddress PR wolfSSL#10009 review comments from bigbrett and Fenrir
night1rider added a commit to night1rider/wolfssl that referenced this pull request Mar 24, 2026
…_she.{c,h}, fix naming consistency, auto-enable CMAC/AES dependencies, add WC_SHE_SW_DEFAULT opt-inAddress PR wolfSSL#10009 review comments from bigbrett and Fenrir
@night1rider
Copy link
Copy Markdown
Contributor Author

Rebased off current master

bigbrett
bigbrett previously approved these changes Mar 25, 2026
@bigbrett bigbrett removed their assignment Mar 25, 2026
@night1rider night1rider added the Not For This Release Not for release 5.9.1 label Mar 27, 2026
@night1rider
Copy link
Copy Markdown
Contributor Author

Added wc_SHE_LoadKey, wc_SHE_LoadKey_Id, wc_SHE_LoadKey_Label and their verify counterparts.

These wrap Init, ImportM1M2M3, GenerateM4M5, and Free into a single call for hardware crypto callback usage. Verify variants compare returned M4/M5 against expected values using ConstantCompare.

All functions require a valid devId and can be compiled out with NO_WC_SHE_LOADKEY.

@night1rider
Copy link
Copy Markdown
Contributor Author

Jenkins retest this please

@dgarske dgarske removed the Not For This Release Not for release 5.9.1 label Apr 8, 2026
…LoadKey, wc_SHE_LoadKey_Id, wc_SHE_LoadKey_Label and their verify counterparts
@night1rider
Copy link
Copy Markdown
Contributor Author

Rebased to fix merge conflict

Copy link
Copy Markdown
Contributor

@dgarske dgarske left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skoll review

"Enable SHE key update support (standard|extended|no)"
"no" "standard;extended;no")

if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH-1: CMakeLists.txt missing required SHE dependency definitions

  • File: CMakeLists.txt:1649-1656
  • Function: N/A (build system)
  • Category: bug
  • Confidence: High

Description: The CMakeLists.txt SHE section only adds -DWOLFSSL_SHE but does not add -DWOLFSSL_CMAC or -DWOLFSSL_AES_DIRECT, nor does it force-enable the CMAC option. By contrast, configure.ac correctly adds all three flags and sets ENABLED_CMAC=yes and ENABLED_AESCBC=yes. A CMake build with -DWOLFSSL_SHE=standard (without separately enabling CMAC) will hit the #error "SHE requires CMAC" directive in wc_she.c.

Code:

if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
    if (NOT WOLFSSL_AES)
        message(FATAL_ERROR "Cannot use SHE without AES.")
    else()
        list(APPEND WOLFSSL_DEFINITIONS
            "-DWOLFSSL_SHE")
    endif()
endif()

Recommendation: Mirror the configure.ac behavior: force-enable CMAC (and thus AES_DIRECT) when SHE is enabled. For example:

Suggested change
if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
if (NOT WOLFSSL_AES)
message(FATAL_ERROR "Cannot use SHE without AES.")
else()
list(APPEND WOLFSSL_DEFINITIONS
"-DWOLFSSL_SHE")
# SHE requires CMAC and AES-DIRECT; force-enable them
override_cache(WOLFSSL_CMAC "yes")
endif()
endif()

#endif /* WOLFSSL_CMAC */

#ifdef WOLFSSL_SHE
int wc_CryptoCb_SheGetUid(wc_SHE* she, const byte* uid, word32 uidSz,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH-2: wc_CryptoCb_SheGetUid uid parameter is incorrectly const

  • File: wolfcrypt/src/cryptocb.c:2039, wolfssl/wolfcrypt/cryptocb.h:824, wolfssl/wolfcrypt/cryptocb.h:471
  • Function: wc_CryptoCb_SheGetUid
  • Category: bug
  • Confidence: High

Description: The uid parameter in wc_CryptoCb_SheGetUid is declared as const byte*, and the getUid.uid field in the wc_CryptoInfo.she.op union is also const byte*. However, the purpose of wc_SHE_GetUID (which calls this) is to fill the uid buffer — the header doc says "buffer to receive the 120-bit (15-byte) SHE UID". The software fallback confirms this by writing to it: XMEMCPY(uid, wc_She_DefaultUid, ...). A hardware callback implementation would need to cast away const to write the UID, which is undefined behavior in C.

Code:

// cryptocb.h:824
WOLFSSL_LOCAL int wc_CryptoCb_SheGetUid(wc_SHE* she, const byte* uid, ...);

// cryptocb.h:471 (inside wc_CryptoInfo)
struct {
    const byte* uid;   // <-- should be byte*
    word32      uidSz;
} getUid;

Recommendation: Change const byte* uid to byte* uid in:

  1. The wc_CryptoCb_SheGetUid function signature (declaration and definition)
  2. The getUid.uid field in wc_CryptoInfo


#endif /* WOLFSSL_SHE_EXTENDED */

/* -------------------------------------------------------------------------- */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM-3: Stale section comment before wc_SHE_ImportM1M2M3

  • File: wolfcrypt/src/wc_she.c:362-363
  • Function: N/A
  • Category: style
  • Confidence: High

Description: There's a stale section header comment /* GetUID */ immediately before the wc_SHE_ImportM1M2M3 function. It appears to be a copy-paste leftover from an earlier draft.

Code:

/* -------------------------------------------------------------------------- */
/* GetUID                                                                     */

#if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123)
/* -------------------------------------------------------------------------- */
/* Import M1/M2/M3                                                            */

Recommendation: Remove the stale /* GetUID */ comment block at lines 362-363 or replace with /* Import M1/M2/M3 */.

/* Requires a valid devId (not INVALID_DEVID) since the operation dispatches */
/* to a hardware crypto callback. */
/* -------------------------------------------------------------------------- */
int wc_SHE_LoadKey(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM-4: No test coverage for wc_SHE_LoadKey* and wc_SHE_LoadKey_Verify* functions

  • File: wolfcrypt/src/wc_she.c:814-975, tests/api/test_she.c, wolfcrypt/test/test.c
  • Function: wc_SHE_LoadKey, wc_SHE_LoadKey_Id, wc_SHE_LoadKey_Label, wc_SHE_LoadKey_Verify*
  • Category: test
  • Confidence: High

Description: The one-shot wc_SHE_LoadKey, wc_SHE_LoadKey_Id, wc_SHE_LoadKey_Label, wc_SHE_LoadKey_Verify, wc_SHE_LoadKey_Verify_Id, and wc_SHE_LoadKey_Verify_Label functions (9 public API functions total) have no test coverage in either tests/api/test_she.c or wolfcrypt/test/test.c. These are convenience wrappers around the tested primitives, but they contain their own parameter validation and internal orchestration logic (including the wc_SHE_LoadKey_Internal helper which calls GenerateM4M5 with NULL uid/newKey) that deserves coverage.

Recommendation: Add API tests for at least wc_SHE_LoadKey (basic + bad args) and wc_SHE_LoadKey_Verify (match + mismatch) using the crypto callback test infrastructure already established in test_wc_SHE_CryptoCb.

then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT"
ENABLED_CMAC=yes
ENABLED_AESCBC=yes
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MEDIUM-5: configure.ac SHE section sets ENABLED_AESCBC=yes too late to take effect

  • File: configure.ac:5963
  • Function: N/A (build system)
  • Category: bug
  • Confidence: Medium

Description: The SHE configure block sets ENABLED_AESCBC=yes (line 5963), but the AES-CBC disable check already ran at line 3287. If a user passes --disable-aescbc --enable-she=standard, the -DNO_AES_CBC flag is already added to AM_CFLAGS before the SHE block runs. Setting ENABLED_AESCBC=yes at that point doesn't remove the already-appended flag. The #error in wc_she.c will catch this at compile time, but it would be better to fail at configure time with a clear error message.

Code:

# Line 3287 (runs first):
if test "$ENABLED_AESCBC" = "no"
then
    AM_CFLAGS="$AM_CFLAGS -DNO_AES_CBC"  # Already added!
fi

# Line 5959 (runs later):
if test "x$ENABLED_SHE" = "xstandard" || ...
then
    ENABLED_AESCBC=yes  # Too late, -DNO_AES_CBC already in AM_CFLAGS
fi

Recommendation: Either add a check for NO_AES_CBC after the SHE block or, more robustly, move the ENABLED_AESCBC check to after all feature blocks that might override it (similar to how some flags are consolidated at the end of configure.ac). Alternatively, add an explicit check:

if test "x$ENABLED_SHE" != "xno" && test "$ENABLED_AESCBC" = "no"
then
    AC_MSG_ERROR([SHE requires AES-CBC. Remove --disable-aescbc or disable SHE.])
fi

return BAD_FUNC_ARG;
}

if (XSTRLEN(label) == 0 || XSTRLEN(label) > WC_SHE_MAX_LABEL_LEN) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOW-7: XSTRLEN(label) called twice in wc_SHE_LoadKey_Label validation

  • File: wolfcrypt/src/wc_she.c:947
  • Function: wc_SHE_LoadKey_Label
  • Category: style
  • Confidence: High

Description: XSTRLEN(label) is called twice in the same conditional expression — once for the == 0 check and once for the > WC_SHE_MAX_LABEL_LEN check. This redundancy walks the string twice.

Code:

if (XSTRLEN(label) == 0 || XSTRLEN(label) > WC_SHE_MAX_LABEL_LEN) {
    return BAD_FUNC_ARG;
}

Recommendation: Store the result in a local variable:

Suggested change
if (XSTRLEN(label) == 0 || XSTRLEN(label) > WC_SHE_MAX_LABEL_LEN) {
size_t len = XSTRLEN(label);
if (len == 0 || len > WC_SHE_MAX_LABEL_LEN) {
return BAD_FUNC_ARG;
}

… XSTRLEN double call, configure.ac AES-CBC guard, and add LoadKey/LoadKey_Verify test coverage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants