diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index bd942c0..fd9611e 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -2,9 +2,9 @@ name: Build and Test on: push: - branches: [ main, master, develop ] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [ main, master, develop ] + branches: [ '*' ] jobs: build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index eec6bf3..8076041 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,9 +2,9 @@ name: CodeQL Security on: push: - branches: [ main, master, develop ] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [ main, master, develop ] + branches: [ '*' ] schedule: - cron: '0 6 * * 1' diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000..9a00668 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,46 @@ +# Codespell test + +name: Codespell test + +# START OF COMMON SECTION +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-22.04 + timeout-minutes: 5 + steps: + - name: Checkout wolfSPDM + uses: actions/checkout@v4 + + - name: Create exclude file if needed + run: | + if [ ! -f .codespellexcludelines ]; then + touch .codespellexcludelines + fi + + - name: Run codespell + uses: codespell-project/actions-codespell@v2.1 + with: + check_filenames: true + check_hidden: true + ignore_words_list: adin,aNULL,cLen,dout,haveA,inOut,inout,parm,parms,ser,siz,te,Te + exclude_file: '.codespellexcludelines' + skip: '*.der,*.pem,.git,*.txt' + + - name: Print errors + if: ${{ failure() }} + run: | + if [ -f test-suite.log ] ; then + cat test-suite.log + fi diff --git a/.github/workflows/compiler-warnings.yml b/.github/workflows/compiler-warnings.yml index 6c3fe5f..f10fa09 100644 --- a/.github/workflows/compiler-warnings.yml +++ b/.github/workflows/compiler-warnings.yml @@ -2,9 +2,9 @@ name: Compiler Warnings on: push: - branches: [ main, master, develop ] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [ main, master, develop ] + branches: [ '*' ] jobs: gcc-strict: @@ -42,9 +42,8 @@ jobs: - name: Build with strict warnings run: | ./autogen.sh - ./configure --with-wolfssl=$HOME/wolfssl-install --enable-nuvoton \ - CFLAGS="-Wall -Wextra -Wpedantic -Werror -Wconversion -Wshadow" - make -j$(nproc) + ./configure --with-wolfssl=$HOME/wolfssl-install --enable-nuvoton + make -j$(nproc) CFLAGS="-Wall -Wextra -Wpedantic -Werror -Wconversion -Wshadow" clang: name: Clang Build @@ -81,9 +80,8 @@ jobs: - name: Build with clang run: | ./autogen.sh - CC=clang ./configure --with-wolfssl=$HOME/wolfssl-install --enable-nuvoton \ - CFLAGS="-Wall -Wextra -Werror" - make -j$(nproc) + CC=clang ./configure --with-wolfssl=$HOME/wolfssl-install --enable-nuvoton + make -j$(nproc) CFLAGS="-Wall -Wextra -Werror" - name: Run unit tests run: make check diff --git a/.github/workflows/memory-check.yml b/.github/workflows/memory-check.yml index 017e7c0..bc8510a 100644 --- a/.github/workflows/memory-check.yml +++ b/.github/workflows/memory-check.yml @@ -2,9 +2,9 @@ name: Memory Check on: push: - branches: [ main, master, develop ] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [ main, master, develop ] + branches: [ '*' ] jobs: valgrind: @@ -44,6 +44,7 @@ jobs: ./autogen.sh ./configure --with-wolfssl=$HOME/wolfssl-install --enable-debug make -j$(nproc) + make -j$(nproc) check TESTS= - name: Run valgrind run: | diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index fb2958e..44390a3 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -2,9 +2,9 @@ name: Static Analysis on: push: - branches: [ main, master, develop ] + branches: [ 'master', 'main', 'release/**' ] pull_request: - branches: [ main, master, develop ] + branches: [ '*' ] jobs: cppcheck: @@ -45,6 +45,8 @@ jobs: cppcheck --enable=warning,style,performance,portability \ --error-exitcode=1 \ --suppress=missingIncludeSystem \ + --suppress=constParameterPointer \ + --suppress=knownConditionTrueFalse \ --inline-suppr \ -I wolfspdm -I src -I $HOME/wolfssl-install/include \ src/ test/ diff --git a/src/spdm_context.c b/src/spdm_context.c index ae23c6f..ce1c4c2 100644 --- a/src/spdm_context.c +++ b/src/spdm_context.c @@ -267,6 +267,7 @@ byte wolfSPDM_GetVersion_Negotiated(WOLFSPDM_CTX* ctx) return ctx->spdmVersion; } +#ifdef WOLFSPDM_NUVOTON word32 wolfSPDM_GetConnectionHandle(WOLFSPDM_CTX* ctx) { if (ctx == NULL) { @@ -282,6 +283,7 @@ word16 wolfSPDM_GetFipsIndicator(WOLFSPDM_CTX* ctx) } return ctx->fipsIndicator; } +#endif /* ========================================================================== * Session Establishment - Connect (Full Handshake) diff --git a/src/spdm_kdf.c b/src/spdm_kdf.c index d4797f5..0960422 100644 --- a/src/spdm_kdf.c +++ b/src/spdm_kdf.c @@ -71,25 +71,13 @@ int wolfSPDM_HkdfExpandLabel(byte spdmVersion, const byte* secret, word32 secret infoLen += SPDM_BIN_CONCAT_PREFIX_LEN; XMEMCPY(info + infoLen, label, XSTRLEN(label)); - infoLen += XSTRLEN(label); + infoLen += (word32)XSTRLEN(label); if (context != NULL && contextSz > 0) { XMEMCPY(info + infoLen, context, contextSz); infoLen += contextSz; } - /* Debug: print HKDF info parameter */ - { - word32 i; - printf("[wolfSPDM] HKDF Label: \"%s\" outSz=%u\n", label, outSz); - printf("[wolfSPDM] HKDF info (%u bytes): ", infoLen); - for (i = 0; i < infoLen && i < 32; i++) { - printf("%02x ", info[i]); - } - if (infoLen > 32) printf("..."); - printf("\n"); - } - rc = wc_HKDF_Expand(WC_SHA384, secret, secretSz, info, infoLen, out, outSz); return (rc == 0) ? WOLFSPDM_SUCCESS : WOLFSPDM_E_CRYPTO_FAIL; diff --git a/src/spdm_msg.c b/src/spdm_msg.c index 0af97e8..94b8254 100644 --- a/src/spdm_msg.c +++ b/src/spdm_msg.c @@ -486,7 +486,8 @@ int wolfSPDM_ParseCapabilities(WOLFSPDM_CTX* ctx, const byte* buf, word32 bufSz) return WOLFSPDM_E_CAPS_MISMATCH; } - ctx->rspCaps = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24); + ctx->rspCaps = (word32)buf[8] | ((word32)buf[9] << 8) | + ((word32)buf[10] << 16) | ((word32)buf[11] << 24); ctx->state = WOLFSPDM_STATE_CAPS; wolfSPDM_DebugPrint(ctx, "Responder caps: 0x%08x\n", ctx->rspCaps); @@ -545,8 +546,8 @@ int wolfSPDM_ParseCertificate(WOLFSPDM_CTX* ctx, const byte* buf, word32 bufSz, return WOLFSPDM_E_CERT_FAIL; } - *portionLen = buf[4] | (buf[5] << 8); - *remainderLen = buf[6] | (buf[7] << 8); + *portionLen = (word16)(buf[4] | (buf[5] << 8)); + *remainderLen = (word16)(buf[6] | (buf[7] << 8)); /* Add certificate chain data (starting at offset 8) */ if (*portionLen > 0 && bufSz >= (word32)(8 + *portionLen)) { @@ -590,8 +591,8 @@ int wolfSPDM_ParseKeyExchangeRsp(WOLFSPDM_CTX* ctx, const byte* buf, word32 bufS return WOLFSPDM_E_KEY_EXCHANGE; } - ctx->rspSessionId = buf[4] | (buf[5] << 8); - ctx->sessionId = ctx->reqSessionId | (ctx->rspSessionId << 16); + ctx->rspSessionId = (word16)(buf[4] | (buf[5] << 8)); + ctx->sessionId = (word32)ctx->reqSessionId | ((word32)ctx->rspSessionId << 16); wolfSPDM_DebugPrint(ctx, "RspSessionID: 0x%04x, SessionID: 0x%08x\n", ctx->rspSessionId, ctx->sessionId); @@ -601,7 +602,7 @@ int wolfSPDM_ParseKeyExchangeRsp(WOLFSPDM_CTX* ctx, const byte* buf, word32 bufS XMEMCPY(peerPubKeyY, &buf[88], WOLFSPDM_ECC_KEY_SIZE); /* OpaqueLen at offset 136 */ - opaqueLen = buf[136] | (buf[137] << 8); + opaqueLen = (word16)(buf[136] | (buf[137] << 8)); sigOffset = 138 + opaqueLen; keRspPartialLen = sigOffset; diff --git a/src/spdm_nuvoton.c b/src/spdm_nuvoton.c index 8a0d39c..b2d5428 100644 --- a/src/spdm_nuvoton.c +++ b/src/spdm_nuvoton.c @@ -349,7 +349,6 @@ int wolfSPDM_ParseTcgSecuredMessage( #define SPDM_VERSION_1_3 0x13 #define SPDM_VENDOR_DEFINED_REQUEST 0xFE #define SPDM_VENDOR_DEFINED_RESPONSE 0x7E -#define SPDM_ERROR 0x7F int wolfSPDM_BuildVendorDefined( const char* vdCode, diff --git a/src/spdm_secured.c b/src/spdm_secured.c index 79bdd76..f67a90c 100644 --- a/src/spdm_secured.c +++ b/src/spdm_secured.c @@ -67,9 +67,9 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx, * IV XOR: Rightmost 8 bytes (bytes 4-11) with 8-byte sequence number */ word16 appDataLen = (word16)plainSz; - word16 unpadded = 2 + appDataLen; /* AppDataLength + SPDM msg */ - word16 padLen = (16 - (unpadded % 16)) % 16; /* Pad to 16-byte boundary */ - word16 encPayloadSz = unpadded + padLen; + word16 unpadded = (word16)(2 + appDataLen); /* AppDataLength + SPDM msg */ + word16 padLen = (word16)((16 - (unpadded % 16)) % 16); /* Pad to 16-byte boundary */ + word16 encPayloadSz = (word16)(unpadded + padLen); plainBufSz = encPayloadSz; /* Length field = ciphertext + MAC (per Nuvoton spec page 25: Length=160=144+16) */ @@ -127,8 +127,8 @@ int wolfSPDM_EncryptInternal(WOLFSPDM_CTX* ctx, * Header: SessionID(4 LE) + SeqNum(2 LE) + Length(2 LE) = 8 bytes * AAD = Header */ - word16 appDataLen = 1 + plainSz; - word16 encDataLen = 2 + appDataLen; + word16 appDataLen = (word16)(1 + plainSz); + word16 encDataLen = (word16)(2 + appDataLen); plainBufSz = encDataLen; recordLen = (word16)(encDataLen + WOLFSPDM_AEAD_TAG_SIZE); @@ -280,12 +280,13 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, } /* Parse header: SessionID(4) + SeqNum(8) + Length(2) */ - rspSessionId = enc[0] | (enc[1] << 8) | (enc[2] << 16) | (enc[3] << 24); + rspSessionId = (word32)enc[0] | ((word32)enc[1] << 8) | + ((word32)enc[2] << 16) | ((word32)enc[3] << 24); rspSeqNum64 = (word64)enc[4] | ((word64)enc[5] << 8) | ((word64)enc[6] << 16) | ((word64)enc[7] << 24) | ((word64)enc[8] << 32) | ((word64)enc[9] << 40) | ((word64)enc[10] << 48) | ((word64)enc[11] << 56); - rspLen = enc[12] | (enc[13] << 8); + rspLen = (word16)(enc[12] | (enc[13] << 8)); rspSeqNum = (word16)(rspSeqNum64 & 0xFFFF); /* For debug output */ if (rspSessionId != ctx->sessionId) { @@ -299,7 +300,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, return WOLFSPDM_E_BUFFER_SMALL; } - cipherLen = rspLen - WOLFSPDM_AEAD_TAG_SIZE; + cipherLen = (word16)(rspLen - WOLFSPDM_AEAD_TAG_SIZE); ciphertext = enc + hdrSz; tag = enc + hdrSz + cipherLen; @@ -335,7 +336,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, } /* Parse decrypted: AppDataLen (2 LE) || SPDM message || RandomData */ - appDataLen = decrypted[0] | (decrypted[1] << 8); + appDataLen = (word16)(decrypted[0] | (decrypted[1] << 8)); wolfSPDM_DebugPrint(ctx, "Decrypted appDataLen: %u\n", appDataLen); wolfSPDM_DebugHex(ctx, "Decrypted data (first 32)", decrypted, @@ -365,9 +366,10 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, } /* Parse header */ - rspSessionId = enc[0] | (enc[1] << 8) | (enc[2] << 16) | (enc[3] << 24); - rspSeqNum = enc[4] | (enc[5] << 8); - rspLen = enc[6] | (enc[7] << 8); + rspSessionId = (word32)enc[0] | ((word32)enc[1] << 8) | + ((word32)enc[2] << 16) | ((word32)enc[3] << 24); + rspSeqNum = (word16)(enc[4] | (enc[5] << 8)); + rspLen = (word16)(enc[6] | (enc[7] << 8)); if (rspSessionId != ctx->sessionId) { wolfSPDM_DebugPrint(ctx, "Session ID mismatch: 0x%08x != 0x%08x\n", @@ -379,7 +381,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, return WOLFSPDM_E_BUFFER_SMALL; } - cipherLen = rspLen - WOLFSPDM_AEAD_TAG_SIZE; + cipherLen = (word16)(rspLen - WOLFSPDM_AEAD_TAG_SIZE); ciphertext = enc + hdrSz; tag = enc + hdrSz + cipherLen; @@ -403,7 +405,7 @@ int wolfSPDM_DecryptInternal(WOLFSPDM_CTX* ctx, } /* Parse decrypted: AppDataLen (2) || MCTP (1) || SPDM msg */ - appDataLen = decrypted[0] | (decrypted[1] << 8); + appDataLen = (word16)(decrypted[0] | (decrypted[1] << 8)); if (appDataLen < 1 || cipherLen < (word32)(2 + appDataLen)) { return WOLFSPDM_E_BUFFER_SMALL; diff --git a/test/unit_test.c b/test/unit_test.c index 5991976..5faf852 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -27,6 +27,15 @@ static int g_testsFailed = 0; return 0; \ } while(0) +/* Dummy I/O callback for testing */ +static int dummy_io_cb(WOLFSPDM_CTX* ctx, const byte* txBuf, word32 txSz, + byte* rxBuf, word32* rxSz, void* userCtx) +{ + (void)ctx; (void)txBuf; (void)txSz; + (void)rxBuf; (void)rxSz; (void)userCtx; + return -1; +} + /* ========================================================================== */ /* Context Tests */ /* ========================================================================== */ @@ -109,9 +118,9 @@ static int test_context_set_io(void) wolfSPDM_Init(ctx); /* Dummy callback for testing */ - rc = wolfSPDM_SetIO(ctx, (WOLFSPDM_IO_CB)0x12345678, &dummy); + rc = wolfSPDM_SetIO(ctx, dummy_io_cb, &dummy); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "SetIO failed"); - TEST_ASSERT(ctx->ioCb == (WOLFSPDM_IO_CB)0x12345678, "IO callback not set"); + TEST_ASSERT(ctx->ioCb == dummy_io_cb, "IO callback not set"); TEST_ASSERT(ctx->ioUserCtx == &dummy, "User context not set"); /* NULL callback should fail */ @@ -363,85 +372,115 @@ static int test_build_get_version(void) static int test_build_get_capabilities(void) { + WOLFSPDM_CTX* ctx; byte buf[32]; word32 bufSz = sizeof(buf); int rc; printf("test_build_get_capabilities...\n"); - rc = wolfSPDM_BuildGetCapabilities(buf, &bufSz, WOLFSPDM_DEFAULT_REQ_CAPS); + ctx = wolfSPDM_New(); + wolfSPDM_Init(ctx); + ctx->spdmVersion = SPDM_VERSION_12; + + rc = wolfSPDM_BuildGetCapabilities(ctx, buf, &bufSz); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "BuildGetCapabilities failed"); TEST_ASSERT(bufSz == 20, "GET_CAPABILITIES should be 20 bytes"); TEST_ASSERT(buf[0] == SPDM_VERSION_12, "Version should be 0x12"); TEST_ASSERT(buf[1] == SPDM_GET_CAPABILITIES, "Code should be 0xE1"); + wolfSPDM_Free(ctx); TEST_PASS(); } static int test_build_negotiate_algorithms(void) { + WOLFSPDM_CTX* ctx; byte buf[64]; word32 bufSz = sizeof(buf); int rc; printf("test_build_negotiate_algorithms...\n"); - rc = wolfSPDM_BuildNegotiateAlgorithms(buf, &bufSz); + ctx = wolfSPDM_New(); + wolfSPDM_Init(ctx); + ctx->spdmVersion = SPDM_VERSION_12; + + rc = wolfSPDM_BuildNegotiateAlgorithms(ctx, buf, &bufSz); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "BuildNegotiateAlgorithms failed"); TEST_ASSERT(bufSz == 48, "NEGOTIATE_ALGORITHMS should be 48 bytes"); TEST_ASSERT(buf[0] == SPDM_VERSION_12, "Version should be 0x12"); TEST_ASSERT(buf[1] == SPDM_NEGOTIATE_ALGORITHMS, "Code should be 0xE3"); + wolfSPDM_Free(ctx); TEST_PASS(); } static int test_build_get_digests(void) { + WOLFSPDM_CTX* ctx; byte buf[16]; word32 bufSz = sizeof(buf); int rc; printf("test_build_get_digests...\n"); - rc = wolfSPDM_BuildGetDigests(buf, &bufSz); + ctx = wolfSPDM_New(); + wolfSPDM_Init(ctx); + ctx->spdmVersion = SPDM_VERSION_12; + + rc = wolfSPDM_BuildGetDigests(ctx, buf, &bufSz); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "BuildGetDigests failed"); TEST_ASSERT(bufSz == 4, "GET_DIGESTS should be 4 bytes"); TEST_ASSERT(buf[1] == SPDM_GET_DIGESTS, "Code should be 0x81"); + wolfSPDM_Free(ctx); TEST_PASS(); } static int test_build_get_certificate(void) { + WOLFSPDM_CTX* ctx; byte buf[16]; word32 bufSz = sizeof(buf); int rc; printf("test_build_get_certificate...\n"); - rc = wolfSPDM_BuildGetCertificate(buf, &bufSz, 0, 0, 1024); + ctx = wolfSPDM_New(); + wolfSPDM_Init(ctx); + ctx->spdmVersion = SPDM_VERSION_12; + + rc = wolfSPDM_BuildGetCertificate(ctx, buf, &bufSz, 0, 0, 1024); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "BuildGetCertificate failed"); TEST_ASSERT(bufSz == 8, "GET_CERTIFICATE should be 8 bytes"); TEST_ASSERT(buf[1] == SPDM_GET_CERTIFICATE, "Code should be 0x82"); TEST_ASSERT(buf[2] == 0x00, "SlotID should be 0"); TEST_ASSERT(buf[6] == 0x00 && buf[7] == 0x04, "Length should be 1024"); + wolfSPDM_Free(ctx); TEST_PASS(); } static int test_build_end_session(void) { + WOLFSPDM_CTX* ctx; byte buf[16]; word32 bufSz = sizeof(buf); int rc; printf("test_build_end_session...\n"); - rc = wolfSPDM_BuildEndSession(buf, &bufSz); + ctx = wolfSPDM_New(); + wolfSPDM_Init(ctx); + ctx->spdmVersion = SPDM_VERSION_12; + + rc = wolfSPDM_BuildEndSession(ctx, buf, &bufSz); TEST_ASSERT(rc == WOLFSPDM_SUCCESS, "BuildEndSession failed"); TEST_ASSERT(bufSz == 4, "END_SESSION should be 4 bytes"); TEST_ASSERT(buf[1] == SPDM_END_SESSION, "Code should be 0xEA"); + wolfSPDM_Free(ctx); TEST_PASS(); } diff --git a/wolfspdm/spdm.h b/wolfspdm/spdm.h index aed2330..4639ba0 100644 --- a/wolfspdm/spdm.h +++ b/wolfspdm/spdm.h @@ -389,6 +389,7 @@ word32 wolfSPDM_GetSessionId(WOLFSPDM_CTX* ctx); */ byte wolfSPDM_GetVersion_Negotiated(WOLFSPDM_CTX* ctx); +#ifdef WOLFSPDM_NUVOTON /** * Get the connection handle (Nuvoton TCG binding). * @@ -404,6 +405,7 @@ word32 wolfSPDM_GetConnectionHandle(WOLFSPDM_CTX* ctx); * @return FIPS indicator value. */ word16 wolfSPDM_GetFipsIndicator(WOLFSPDM_CTX* ctx); +#endif /* ========================================================================== * Debug/Utility