Skip to content

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

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

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

Conversation

@night1rider
Copy link
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
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.

WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
WOLFSSL_SERVER_EXAMPLE
WOLFSSL_SETTINGS_FILE
WOLFSSL_SH224
Copy link
Contributor

Choose a reason for hiding this comment

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

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a copy paste mistake I introduced, removed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if she.{c,h} is bound to cause some annoying conflicts in automotive codebases and vendor libs. Perhaps we could namespace it to wc_she.{c,h} just to get ahead of that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes sense since we already have files following this convention (wc_encrypt, wc_lms, wc_mlkem, wc_port, etc.) there's no issue doing it now. Names should be updated now

Comment on lines +238 to +242
/* Generate M1/M2/M3 for the SHE key update protocol and write to
* caller-provided buffers. Callback optional -- if a callback is
* registered it is tried first; if it returns CRYPTOCB_UNAVAILABLE
* the software path runs. This allows a secure element to generate
* M1/M2/M3 when it holds the auth key internally.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is a little confusing to mention the "Callback optional" field here, since the dispatch to cryptoCb is internal and not exposed in this module. For example, we don't say "Callback optional" in our AES API.

Same comment for other functions in this file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to mention usefulness of the callbacks somewhere, especially for generating M1/M2/M3 or M4/M5 when they need to access a secure element/hardware. This can be covered in the source comments and docs instead of the public header. I removed the callback language from all five API comments in wc_she.h.

Copy link
Contributor

Choose a reason for hiding this comment

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

make sure to update the out-of-tree doxygen with your lovely API comments too, so it renders in the website docs!

Copy link
Contributor Author

@night1rider night1rider Mar 24, 2026

Choose a reason for hiding this comment

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

I will link a PR shortly with the doc update in the main body of the pr description

* in - input data (e.g. BaseKey || KDF_Constant, 32 bytes)
* inSz - length of input in bytes (zero-padded to block boundary)
* out - output buffer for 16-byte compressed result */
WOLFSSL_TEST_VIS int wc_She_AesMp16(Aes* aes, const byte* in, word32 inSz,
Copy link
Contributor

Choose a reason for hiding this comment

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

All the other APIs use wc_SHE but this has wc_She. Unify for consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I overlooked this due to it being an internal function, updated the name.

return BAD_FUNC_ARG;
}

return wc_CryptoCb_SheSetUid(she, uid, uidSz, ctx);
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this be "get" UID based on calling function? Though the crypto callbacks do only have a set function. What is the intent here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was overlooked. Renamed wc_CryptoCb_SheSetUid to wc_CryptoCb_SheGetUid, WC_SHE_SET_UID to WC_SHE_GET_UID, and the union field setUid to getUid in cryptocb.h and cryptocb.c. The intent is to allow someone to use the same API after implementing the callback across different platforms. This is the same intent for GetCounter as well.

/* Returns CRYPTOCB_UNAVAILABLE if no callback. */
/* -------------------------------------------------------------------------- */
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETCOUNTER)
int wc_SHE_GetCounter(wc_SHE* she, word32* counter, const void* ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment here - I wonder if a default software impl with dumb global counter would be worthwhile just to enable testing? Could have a build macro enabling this to prevent inclusion in production builds maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in my previous comment regarding the "default global "wolfCrypt" UID".

#endif /* WOLFSSL_CMAC */

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

Choose a reason for hiding this comment

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

I'm confused, can you set the UID? Shouldn't this be "get" UID? Same comment is made in she.c.

Are we setting ID in local wolfCrypt struct or are we getting it from HW?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just overlooked this, addressed. We are getting the UID from hardware and some hardware supports a challenge to get the UID to prove that the hardware is real, hence the void context parameter. This is just an API to get the UID to then pass to the generate API calls. There is no setting the UID in the structure. The struct is now very basic and holds only M1/M2/M3 if they are imported and the import function is on, plus devId for callbacks, KDF constants, etc.

}
/* fall-through to software path */
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to reset ret=0 in fallback case for good measure

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, overlooked this.

int ret = wc_CryptoCb_Free(she->devId, WC_ALGO_TYPE_SHE,
0, 0, she);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

Ever a case where we want to ForceZero here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We already have a ForceZero on the fall-through path. The person who implements their callback should be allowed to control how free works. If they want our software cleanup, they can clean up what they want and then return CRYPTOCB_UNAVAILABLE to continue to the ForceZero. If they handle everything themselves, they return success and we skip it and the callback implementer assumes the responsibility.

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

@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
Copy link
Contributor Author

Rebased off current master

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.

3 participants