Skip to content
Merged
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
8 changes: 5 additions & 3 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ on:

jobs:
build:
name: ${{ matrix.os }} / debug=${{ matrix.debug }} / nuvoton=${{ matrix.nuvoton }}
name: ${{ matrix.os }} / debug=${{ matrix.debug }} / nuvoton=${{ matrix.nuvoton }} / dynamic-mem=${{ matrix.dynamic-mem }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-22.04]
debug: [yes, no]
nuvoton: [yes, no]
dynamic-mem: [yes, no]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -52,7 +53,8 @@ jobs:
run: |
./configure --with-wolfssl=$HOME/wolfssl-install \
${{ matrix.debug == 'yes' && '--enable-debug' || '' }} \
${{ matrix.nuvoton == 'yes' && '--enable-nuvoton' || '' }}
${{ matrix.nuvoton == 'yes' && '--enable-nuvoton' || '' }} \
${{ matrix.dynamic-mem == 'yes' && '--enable-dynamic-mem' || '' }}

- name: Build
run: make -j$(nproc)
Expand All @@ -66,7 +68,7 @@ jobs:
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-logs-${{ matrix.os }}-debug-${{ matrix.debug }}-nuvoton-${{ matrix.nuvoton }}
name: test-logs-${{ matrix.os }}-debug-${{ matrix.debug }}-nuvoton-${{ matrix.nuvoton }}-dynmem-${{ matrix.dynamic-mem }}
path: |
test/*.log
config.log
9 changes: 7 additions & 2 deletions .github/workflows/memory-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ on:

jobs:
valgrind:
name: Valgrind
name: Valgrind / dynamic-mem=${{ matrix.dynamic-mem }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dynamic-mem: [yes, no]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -42,7 +46,8 @@ jobs:
- name: Build with debug
run: |
./autogen.sh
./configure --with-wolfssl=$HOME/wolfssl-install --enable-debug
./configure --with-wolfssl=$HOME/wolfssl-install --enable-debug \
${{ matrix.dynamic-mem == 'yes' && '--enable-dynamic-mem' || '' }}
make -j$(nproc)
make -j$(nproc) check TESTS=

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ test/test_spdm
# pkg-config generated
wolfspdm.pc

# Auto-generated options header
wolfspdm/options.h

# Editor and IDE files
*~
*.swp
Expand Down
15 changes: 13 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,22 @@ endif
libwolfspdm_la_CPPFLAGS = -I$(srcdir)/wolfspdm -I$(srcdir)/src
libwolfspdm_la_LIBADD = -lwolfssl

# Generate options.h from config.h (propagate WOLFSPDM_ defines to consumers)
BUILT_SOURCES = wolfspdm/options.h
wolfspdm/options.h: config.h
@mkdir -p wolfspdm
@echo '/* wolfspdm/options.h — auto-generated from config.h, do not edit */' > $@
@echo '#ifndef WOLFSPDM_OPTIONS_H' >> $@
@echo '#define WOLFSPDM_OPTIONS_H' >> $@
@grep '^\#define WOLFSPDM_' config.h >> $@ || true
@echo '#endif /* WOLFSPDM_OPTIONS_H */' >> $@

# Public headers
nobase_include_HEADERS = \
wolfspdm/spdm.h \
wolfspdm/spdm_types.h \
wolfspdm/spdm_error.h
wolfspdm/spdm_error.h \
wolfspdm/options.h

# Nuvoton header (always installed, conditionally useful)
if BUILD_NUVOTON
Expand Down Expand Up @@ -53,4 +64,4 @@ EXTRA_DIST = \
LICENSE \
wolfspdm.pc.in

CLEANFILES = wolfspdm.pc
CLEANFILES = wolfspdm.pc wolfspdm/options.h
3 changes: 3 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
/* Enable debug output */
#undef WOLFSPDM_DEBUG

/* Enable dynamic memory allocation */
#undef WOLFSPDM_DYNAMIC_MEMORY

/* Enable Nuvoton TPM support */
#undef WOLFSPDM_NUVOTON

Expand Down
11 changes: 11 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ if test "x$enable_nuvoton" = "xyes"; then
fi
AM_CONDITIONAL([BUILD_NUVOTON], [test "x$enable_nuvoton" = "xyes"])

# Dynamic memory allocation (enables wolfSPDM_New/XMALLOC)
AC_ARG_ENABLE([dynamic-mem],
[AS_HELP_STRING([--enable-dynamic-mem], [Enable dynamic memory allocation (wolfSPDM_New)])],
[enable_dynamic_mem=$enableval],
[enable_dynamic_mem=no])

if test "x$enable_dynamic_mem" = "xyes"; then
AC_DEFINE([WOLFSPDM_DYNAMIC_MEMORY], [1], [Enable dynamic memory allocation])
fi

# Output files
AC_CONFIG_FILES([Makefile wolfspdm.pc])
AC_OUTPUT
Expand All @@ -74,5 +84,6 @@ echo "wolfSPDM configuration summary:"
echo " Version: $PACKAGE_VERSION"
echo " Debug: $enable_debug"
echo " Nuvoton: $enable_nuvoton"
echo " Dynamic mem: $enable_dynamic_mem"
echo " wolfSSL: ${WOLFSSL_DIR:-system}"
echo ""
83 changes: 42 additions & 41 deletions src/spdm_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,6 @@
* Context Management
* ========================================================================== */

WOLFSPDM_CTX* wolfSPDM_New(void)
{
WOLFSPDM_CTX* ctx;

ctx = (WOLFSPDM_CTX*)XMALLOC(sizeof(WOLFSPDM_CTX), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (ctx == NULL) {
return NULL;
}

XMEMSET(ctx, 0, sizeof(WOLFSPDM_CTX));
ctx->state = WOLFSPDM_STATE_INIT;

return ctx;
}

int wolfSPDM_Init(WOLFSPDM_CTX* ctx)
{
int rc;
Expand All @@ -52,9 +37,9 @@ int wolfSPDM_Init(WOLFSPDM_CTX* ctx)
return WOLFSPDM_E_INVALID_ARG;
}

if (ctx->initialized) {
return WOLFSPDM_E_ALREADY_INIT;
}
/* Clean slate — do NOT read any fields before this (could be garbage) */
XMEMSET(ctx, 0, sizeof(WOLFSPDM_CTX));
ctx->state = WOLFSPDM_STATE_INIT;

/* Initialize RNG */
rc = wc_InitRng(&ctx->rng);
Expand All @@ -70,43 +55,62 @@ int wolfSPDM_Init(WOLFSPDM_CTX* ctx)
ctx->reqSessionId = 0x0001;

ctx->initialized = 1;
ctx->state = WOLFSPDM_STATE_INIT;
/* isDynamic remains 0 — only wolfSPDM_New sets it */

return WOLFSPDM_SUCCESS;
}

#ifdef WOLFSPDM_DYNAMIC_MEMORY
WOLFSPDM_CTX* wolfSPDM_New(void)
{
WOLFSPDM_CTX* ctx;

ctx = (WOLFSPDM_CTX*)XMALLOC(sizeof(WOLFSPDM_CTX), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (ctx == NULL) {
return NULL;
}

if (wolfSPDM_Init(ctx) != WOLFSPDM_SUCCESS) {
XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return NULL;
}
ctx->isDynamic = 1; /* Tag AFTER Init so it isn't wiped */

return ctx;
}
#endif /* WOLFSPDM_DYNAMIC_MEMORY */

void wolfSPDM_Free(WOLFSPDM_CTX* ctx)
{
if (ctx == NULL) {
return;
}

#ifdef WOLFSPDM_DYNAMIC_MEMORY
{
int wasDynamic = ctx->isDynamic;
#endif

/* Free RNG */
if (ctx->rngInitialized) {
wc_FreeRng(&ctx->rng);
ctx->rngInitialized = 0;
}

/* Free ephemeral key */
if (ctx->ephemeralKeyInitialized) {
wc_ecc_free(&ctx->ephemeralKey);
ctx->ephemeralKeyInitialized = 0;
}

/* Zero out sensitive data */
XMEMSET(ctx->sharedSecret, 0, sizeof(ctx->sharedSecret));
XMEMSET(ctx->handshakeSecret, 0, sizeof(ctx->handshakeSecret));
XMEMSET(ctx->reqHsSecret, 0, sizeof(ctx->reqHsSecret));
XMEMSET(ctx->rspHsSecret, 0, sizeof(ctx->rspHsSecret));
XMEMSET(ctx->reqFinishedKey, 0, sizeof(ctx->reqFinishedKey));
XMEMSET(ctx->rspFinishedKey, 0, sizeof(ctx->rspFinishedKey));
XMEMSET(ctx->reqDataKey, 0, sizeof(ctx->reqDataKey));
XMEMSET(ctx->rspDataKey, 0, sizeof(ctx->rspDataKey));
XMEMSET(ctx->reqDataIv, 0, sizeof(ctx->reqDataIv));
XMEMSET(ctx->rspDataIv, 0, sizeof(ctx->rspDataIv));
XMEMSET(ctx->reqPrivKey, 0, sizeof(ctx->reqPrivKey));

XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}

/* Zero entire struct (covers all sensitive key material) */
wc_ForceZero(ctx, sizeof(WOLFSPDM_CTX));

#ifdef WOLFSPDM_DYNAMIC_MEMORY
if (wasDynamic) {
XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
#endif
Comment thread
aidangarske marked this conversation as resolved.
}

int wolfSPDM_GetCtxSize(void)
Expand All @@ -124,9 +128,6 @@ int wolfSPDM_InitStatic(WOLFSPDM_CTX* ctx, int size)
return WOLFSPDM_E_BUFFER_SMALL;
}

XMEMSET(ctx, 0, sizeof(WOLFSPDM_CTX));
ctx->state = WOLFSPDM_STATE_INIT;

return wolfSPDM_Init(ctx);
}

Expand Down Expand Up @@ -389,7 +390,7 @@ int wolfSPDM_Disconnect(WOLFSPDM_CTX* ctx)
{
int rc;
byte txBuf[8];
byte rxBuf[64];
byte rxBuf[16]; /* END_SESSION_ACK: 4 bytes */
word32 txSz, rxSz;

if (ctx == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion src/spdm_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ int wolfSPDM_SignHash(WOLFSPDM_CTX* ctx, const byte* hash, word32 hashSz,
ecc_key sigKey;
int rc;
int keyInit = 0;
byte derSig[128];
byte derSig[104]; /* P-384 DER sig max: 2 + (2+49) + (2+49) = 104 */
word32 derSigSz = sizeof(derSig);
word32 rLen, sLen;

Expand Down
2 changes: 2 additions & 0 deletions src/spdm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <wolfssl/wolfcrypt/hmac.h>
#include <wolfssl/wolfcrypt/kdf.h>
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/memory.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -75,6 +76,7 @@ struct WOLFSPDM_CTX {
/* Configuration flags */
int debug;
int initialized;
int isDynamic; /* Set by wolfSPDM_New(), checked by wolfSPDM_Free() */

/* Protocol mode (standard SPDM or Nuvoton) */
WOLFSPDM_MODE mode;
Expand Down
9 changes: 4 additions & 5 deletions src/spdm_secured.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx,
byte iv[WOLFSPDM_AEAD_IV_SIZE];
byte aad[16]; /* Up to 14 bytes for TCG format */
byte plainBuf[WOLFSPDM_MAX_MSG_SIZE + 16];
byte ciphertext[WOLFSPDM_MAX_MSG_SIZE + 16];
byte tag[WOLFSPDM_AEAD_TAG_SIZE];
word32 plainBufSz;
word16 recordLen;
Expand Down Expand Up @@ -259,13 +258,13 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx,
return WOLFSPDM_E_CRYPTO_FAIL;
}

rc = wc_AesGcmEncrypt(&aes, ciphertext, plainBuf, plainBufSz,
/* Encrypt directly into output buffer (enc + hdrSz) to avoid a copy */
rc = wc_AesGcmEncrypt(&aes, &enc[hdrSz], plainBuf, plainBufSz,
iv, WOLFSPDM_AEAD_IV_SIZE, tag, WOLFSPDM_AEAD_TAG_SIZE, aad, aadSz);
if (rc != 0) {
return WOLFSPDM_E_CRYPTO_FAIL;
}

XMEMCPY(&enc[hdrSz], ciphertext, plainBufSz);
XMEMCPY(&enc[hdrSz + plainBufSz], tag, WOLFSPDM_AEAD_TAG_SIZE);
*encSz = hdrSz + plainBufSz + WOLFSPDM_AEAD_TAG_SIZE;

Expand Down Expand Up @@ -495,8 +494,8 @@ int wolfSPDM_SecuredExchange(WOLFSPDM_CTX* ctx,
const byte* cmdPlain, word32 cmdSz,
byte* rspPlain, word32* rspSz)
{
byte encBuf[WOLFSPDM_MAX_MSG_SIZE + 64];
byte rxBuf[WOLFSPDM_MAX_MSG_SIZE + 64];
byte encBuf[WOLFSPDM_MAX_MSG_SIZE + 48];
byte rxBuf[WOLFSPDM_MAX_MSG_SIZE + 48];
word32 encSz = sizeof(encBuf);
word32 rxSz = sizeof(rxBuf);
int rc;
Expand Down
24 changes: 12 additions & 12 deletions src/spdm_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
int wolfSPDM_GetVersion(WOLFSPDM_CTX* ctx)
{
byte txBuf[8];
byte rxBuf[64];
byte rxBuf[32]; /* VERSION: 4 hdr + 2 count + up to 8 entries * 2 = 22 */
word32 txSz = sizeof(txBuf);
word32 rxSz = sizeof(rxBuf);
int rc;
Expand All @@ -49,8 +49,8 @@ int wolfSPDM_GetVersion(WOLFSPDM_CTX* ctx)

int wolfSPDM_GetCapabilities(WOLFSPDM_CTX* ctx)
{
byte txBuf[32];
byte rxBuf[64];
byte txBuf[24]; /* GET_CAPABILITIES: 20 bytes */
byte rxBuf[40]; /* CAPABILITIES: 20-36 bytes */
word32 txSz = sizeof(txBuf);
word32 rxSz = sizeof(rxBuf);
int rc;
Expand All @@ -74,8 +74,8 @@ int wolfSPDM_GetCapabilities(WOLFSPDM_CTX* ctx)

int wolfSPDM_NegotiateAlgorithms(WOLFSPDM_CTX* ctx)
{
byte txBuf[64];
byte rxBuf[128];
byte txBuf[52]; /* NEGOTIATE_ALGORITHMS: 48 bytes */
byte rxBuf[80]; /* ALGORITHMS: ~56 bytes with struct tables */
word32 txSz = sizeof(txBuf);
word32 rxSz = sizeof(rxBuf);
int rc;
Expand Down Expand Up @@ -122,7 +122,7 @@ int wolfSPDM_GetDigests(WOLFSPDM_CTX* ctx)
int wolfSPDM_GetCertificate(WOLFSPDM_CTX* ctx, int slotId)
{
byte txBuf[16];
byte rxBuf[2048];
byte rxBuf[1040]; /* 8 hdr + up to 1024 cert data per chunk */
word32 txSz;
word32 rxSz;
word16 offset = 0;
Expand Down Expand Up @@ -164,8 +164,8 @@ int wolfSPDM_GetCertificate(WOLFSPDM_CTX* ctx, int slotId)

int wolfSPDM_KeyExchange(WOLFSPDM_CTX* ctx)
{
byte txBuf[256];
byte rxBuf[512];
byte txBuf[192]; /* KEY_EXCHANGE: ~158 bytes */
byte rxBuf[384]; /* KEY_EXCHANGE_RSP: ~302 bytes */
word32 txSz = sizeof(txBuf);
word32 rxSz = sizeof(rxBuf);
int rc;
Expand All @@ -191,10 +191,10 @@ int wolfSPDM_KeyExchange(WOLFSPDM_CTX* ctx)

int wolfSPDM_Finish(WOLFSPDM_CTX* ctx)
{
byte finishBuf[160]; /* 148 bytes for mutual auth FINISH */
byte encBuf[512]; /* Encrypted: FINISH + padding + tag + headers */
byte rxBuf[256];
byte decBuf[128];
byte finishBuf[152]; /* 148 bytes max for mutual auth FINISH */
byte encBuf[256]; /* Encrypted: hdr(14) + padded(160) + tag(16) = 190 max */
byte rxBuf[128]; /* Encrypted FINISH_RSP: ~94 bytes max */
byte decBuf[64]; /* Decrypted FINISH_RSP: 4 hdr + 48 verify = 52 */
word32 finishSz = sizeof(finishBuf);
word32 encSz = sizeof(encBuf);
word32 rxSz = sizeof(rxBuf);
Expand Down
Loading
Loading