Skip to content

Commit f99e718

Browse files
committed
Add AUTOSAR Classic Crypto Driver + Adaptive CryptoProvider
Adds a new port/ that exposes the wolfHSM client API as the standard AUTOSAR R22-11 Crypto interfaces, so wolfHSM can replace OEM / vendor HSM firmware in existing AUTOSAR Classic and Adaptive stacks with no SWC code changes. Layout port/autosar/classic/ AUTOSAR Classic Crypto Driver (C, R22-11) implements AUTOSAR_SWS_CryptoDriver; drops in below CryIf in any AUTOSAR Classic BSW. port/autosar/adaptive/ AUTOSAR Adaptive CryptoProvider (C++17). Lives in a wolfhsm::ara_crypto namespace so the port itself stays free of AUTOSAR- Consortium-licensed headers; integrators write a thin ara::crypto::cryp::CryptoProvider adapter that forwards each call. port/autosar/common/ algorithm + key-id mapping shared by both. port/autosar/docs/ integration guides, algorithm coverage matrix, and a note on the one in-port translation (client_workarounds.md). Classic — primitives wired through both sync and real async paths (Crypto_MainFunction drives wolfHSM Request/Response): - Hash: SHA-256 / 384 / 512 (single-call and START / UPDATE / FINISH streamed) - AES: ECB / CBC / CTR / GCM - MAC: AES-CMAC (gen + verify) - Signature: ECDSA P-256, Ed25519 (RFC 8032 pure), RSA-PKCS#1-v1.5 (sign + verify, plus tampered-sig negative paths) - Key agreement: ECDH (P-256) - KDF: HKDF, CMAC-KDF - Key management: KeyElementSet / Get / Copy, KeyCopy, KeySetValid, KeyGenerate (AES / ECC / Ed25519 / X25519 / RSA), KeyDerive, KeyExchangeCalcPubVal / CalcSecret - RNG: RandomGenerate Async dispatcher honours wolfHSM's "one Request in-flight per whClientContext" contract — Crypto_ProcessJob enqueues into WH_AUTOSAR_ASYNC_QUEUED; Crypto_MainFunction promotes the oldest queued slot to PENDING only when nothing else is in flight. Crypto_CancelJob handles the cancel-vs-completion race. Hash async chunks input across as many Sha*UpdateRequest cycles as needed. PENDING slots that exceed CRYPTO_ASYNC_TIMEOUT_TICKS are force- cleaned; resource cleanup goes through a single slotFreeWcResources path so wc_*Free runs exactly once on every terminal transition. Adaptive — WolfhsmCryptoProvider with nine context classes: - RandomGeneratorCtx, HashFunctionCtx - SymmetricBlockCipherCtx (AES ECB/CBC/CTR) - AuthCipherCtx (AES-GCM) - MessageAuthnCodeCtx (AES-CMAC) - SignerPrivateCtx / VerifierPublicCtx (ECDSA, Ed25519, RSA-PKCS1-v1.5; same isVerifyRejection translation as Classic) - KeyAgreementPrivateCtx (ECDH P-256) - KeyDerivationFunctionCtx (HKDF, CMAC-KDF) - KeyStorageProvider (Save / Load / Commit / Erase) Tests csm_smoke (Classic, C, per-category): - test_kat.c: NIST SHA / AES-CBC / ECDSA / Ed25519 / RSA-PKCS1v1.5 sign+verify+tampered-sig. - test_det.c: 10 parameter-check paths assert their (serviceId, errorId) tuples fire through Det_ReportError. - test_accounting.c: every test asserts wh_Autosar_DebugActiveSlotCount and ActiveHashStateCount return to zero, with a 2-second drain budget. - test_concurrency.c: 2 worker threads x 500 ms + a cancel thread; asserts submitted - cancelled == callbacks_delivered. - test_timeout.c: synthetic fake-pending injection + tick advance exercises the force-cleanup path deterministically. - test_cancel.c: accepts both cancel-vs-completion race outcomes via per-job callback tracking. ap_smoke (Adaptive, C++17): one end-to-end test per cluster against wh_posix_server. CI: new .github/workflows/build-and-test-autosar.yml builds the POSIX server, csm_smoke and ap_smoke, runs both suites under ASAN on/off. clang-format-check.yml passes on every new file in the diff. Sample smoke output (TCP against wh_posix_server): [basic] [kat] KAT hash: 5 vector(s) OK KAT aes-cbc: 2 vector(s) OK KAT ecdsa P-256: sign + good-sig verify + tampered-sig OK KAT ed25519: keygen + sign + verify + tampered-sig OK KAT rsa-pkcs1-v1.5 2048: keygen + sign + verify + tampered-sig OK [det] DET: 10 parameter-check paths fire correct (apiId, errorId) [accounting] accounting: leak-free across UPDATE/START misuse + 20-cycle async churn [cancel] cancel: queued / pending / unknown-job paths OK [timeout] timeout: force-cleanup after CRYPTO_ASYNC_TIMEOUT_TICKS fires E_NOT_OK callback [concurrency] concurrency: 32 async submitted, N cancelled, (32-N) callbacks delivered csm_smoke: all tests passed wolfHSM Adaptive Crypto Provider smoke (TCP) Random OK (32 bytes) Hash SHA-256("abc") matches NIST vector AES-CBC-128 NIST F.2.1 OK AES-GCM-128 roundtrip OK CMAC-AES generate + verify good + verify tampered OK ECDSA P-256 sign + verify-good + verify-bad OK ECDH P-256 shared secret OK (32 bytes) HKDF-SHA256 -> 32 bytes OK KeyStorage save / load roundtrip OK ap_smoke: all tests passed Scope notes - No vendor BSW headers vendored. Crypto.h, Crypto_GeneralTypes.h and the ara::crypto-shaped C++ headers are written from the public AUTOSAR SWS documents. Integrators supply Std_Types.h, Det.h, CryIf_Cbk.h and the vendor's Crypto_GeneralTypes.h from their BSW. The csm_smoke harness keeps a minimal fake_bsw/ directory for tool-free CI builds. - One client-side translation lives in Crypto_ProcessJob.c::isVerifyRejection — maps wolfCrypt-range negative return codes from wh_Client_EccVerify (currently surfaced when the signature is malformed-DER before math runs) into SWS-correct E_OK + verifyPtr=NOT_OK. The wolfHSM team has confirmed the underlying verify-handler contract is a real fix-up candidate; the port stays correct either way. See port/autosar/docs/client_workarounds.md. - AUTOSAR "conformant" labelling is reserved to AUTOSAR Partners. The port describes itself as "implements AUTOSAR R22-11 interfaces". Wording-only; no code impact. Out of scope - Reference CSM / CryIf inside the port (integrators use their BSW's). - AUTOSAR SHE wrapper (wolfhsm/wh_client_she.h already covers SHE). - PKCS#11 bridge. - ISO 26262 / ASIL qualification artefacts. - RSA-PSS / RSA-OAEP signature padding (separate follow-up). - ML-DSA / X25519 signature / agreement in Adaptive (waiting on keyId-shaped accessors). GPLv3 across all new files, copyright wolfSSL Inc., consistent with the rest of the repo. user_settings.h follows the existing convention of header-less user-overridable config. clang-format-15 clean across the whole port/autosar/ tree.
1 parent 7972967 commit f99e718

45 files changed

Lines changed: 9422 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Build and Test AUTOSAR Port
2+
3+
on:
4+
push:
5+
branches: [ 'master', 'main', 'release/**' ]
6+
pull_request:
7+
branches: [ '*' ]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
csm-smoke:
14+
strategy:
15+
matrix:
16+
asan: [ 'ASAN=0', 'ASAN=1' ]
17+
runs-on: ubuntu-latest
18+
# The job compiles wolfSSL + wolfcrypt from scratch three times (POSIX
19+
# server, csm_smoke, ap_smoke), each with ML-DSA/ML-KEM enabled, and the
20+
# ASAN=1 matrix variant adds substantial compile overhead. 5 minutes was
21+
# too tight on a 4-vCPU runner and both matrix jobs hit the wall.
22+
timeout-minutes: 15
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Checkout wolfssl
28+
uses: actions/checkout@v4
29+
with:
30+
repository: wolfssl/wolfssl
31+
path: wolfssl
32+
33+
- name: Build POSIX server
34+
run: |
35+
cd examples/posix/wh_posix_server
36+
${{ matrix.asan }} make -j WOLFSSL_DIR=../../../wolfssl
37+
38+
- name: Build csm_smoke
39+
run: |
40+
cd port/autosar/classic/examples/csm_smoke
41+
${{ matrix.asan }} make -j WOLFSSL_DIR=../../../../../wolfssl
42+
43+
- name: Build ap_smoke (Adaptive)
44+
run: |
45+
cd port/autosar/adaptive/examples/ap_smoke
46+
cmake -S . -B build -DWOLFHSM_DIR=../../../../.. -DWOLFSSL_DIR=../../../../../wolfssl
47+
cmake --build build --parallel
48+
49+
# Classic Crypto Driver smoke. Server is started/torn down per
50+
# smoke binary because the POSIX server's TCP transport tends to
51+
# close after the client disconnects.
52+
- name: Run csm_smoke (Classic)
53+
run: |
54+
cd examples/posix/wh_posix_server
55+
./Build/wh_posix_server.elf --type tcp &
56+
SRV=$!
57+
# Poll the listening port instead of sleeping a fixed second —
58+
# on a loaded GitHub runner the 1s wait can race.
59+
for i in $(seq 1 50); do
60+
(echo > /dev/tcp/127.0.0.1/23456) 2>/dev/null && break
61+
sleep 0.2
62+
done
63+
# Guard against a blocking-socket hang: the client should finish in
64+
# seconds, so cap it well under the job timeout and surface a clear
65+
# failure instead of silently eating the whole budget.
66+
( cd ../../../port/autosar/classic/examples/csm_smoke && timeout 120 ./Build/csm_smoke )
67+
rc=$?
68+
if [ $rc -eq 124 ]; then echo "csm_smoke timed out — likely a hang, not a slow build"; fi
69+
# Send TERM, then surface the server's exit status: a crash
70+
# mid-test (SIGSEGV / assert) must fail the CI job, not be
71+
# masked by the client's clean exit.
72+
kill -TERM $SRV 2>/dev/null || true
73+
wait $SRV
74+
srv_rc=$?
75+
# bash reports 143 (=128+15) for a clean SIGTERM exit; treat
76+
# that as success. Any other non-zero is a real server failure.
77+
if [ $srv_rc -ne 0 ] && [ $srv_rc -ne 143 ]; then
78+
echo "wh_posix_server exited with $srv_rc — failing CI"
79+
exit 1
80+
fi
81+
exit $rc
82+
83+
# Adaptive CryptoProvider smoke against a fresh server instance.
84+
- name: Run ap_smoke (Adaptive)
85+
run: |
86+
cd examples/posix/wh_posix_server
87+
./Build/wh_posix_server.elf --type tcp &
88+
SRV=$!
89+
for i in $(seq 1 50); do
90+
(echo > /dev/tcp/127.0.0.1/23456) 2>/dev/null && break
91+
sleep 0.2
92+
done
93+
( cd ../../../port/autosar/adaptive/examples/ap_smoke && timeout 120 ./build/ap_smoke )
94+
rc=$?
95+
if [ $rc -eq 124 ]; then echo "ap_smoke timed out — likely a hang, not a slow build"; fi
96+
kill -TERM $SRV 2>/dev/null || true
97+
wait $SRV
98+
srv_rc=$?
99+
if [ $srv_rc -ne 0 ] && [ $srv_rc -ne 143 ]; then
100+
echo "wh_posix_server exited with $srv_rc — failing CI"
101+
exit 1
102+
fi
103+
exit $rc

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ scan_out/*
2424

2525
# Test output
2626
test-suite.log
27+
port/autosar/adaptive/examples/*/build/
28+
29+
# Local wolfssl checkout for CI-style smoke builds
30+
/wolfssl/

port/autosar/README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# wolfHSM AUTOSAR Port
2+
3+
This port exposes the wolfHSM client API as standard AUTOSAR Crypto interfaces:
4+
5+
- **Classic Platform** (`classic/`) — implements `AUTOSAR_SWS_CryptoDriver`
6+
R22-11. Drop-in replacement for an OEM/vendor Crypto Driver, sits below
7+
CryIf in any AUTOSAR Classic BSW (MICROSAR / RTA-BSW / EB tresos).
8+
- **Adaptive Platform** (`adaptive/`) — implements an `ara::crypto`
9+
`CryptoProvider` per `AUTOSAR_SWS_Cryptography` R22-11. Registered via an
10+
AP Execution Manifest, plugs into any AP runtime supporting providers.
11+
12+
Both layers translate AUTOSAR-shaped calls into `wh_Client_*` calls against
13+
a wolfHSM server running on the secure core. Key material never leaves the
14+
server; only handles cross the boundary.
15+
16+
## Layout
17+
18+
```
19+
port/autosar/
20+
├── common/ algorithm and key-id mapping between AUTOSAR and wolfHSM
21+
├── classic/ AUTOSAR Classic Crypto Driver (C, R22-11)
22+
├── adaptive/ AUTOSAR Adaptive CryptoProvider (C++17, R22-11)
23+
└── docs/ integration notes and algorithm coverage table
24+
```
25+
26+
## Status
27+
28+
- **Classic** — hash (SHA-256 / 384 / 512), AES (ECB/CBC/CTR/GCM), CMAC,
29+
ECDSA P-256, Ed25519, RSA-PKCS#1-v1.5, ECDH P-256, HKDF, CMAC-KDF, RNG,
30+
key management. Sync and real-async dispatch through `Crypto_MainFunction`
31+
driving wolfHSM `*Request` / `*Response`.
32+
- **Adaptive**`WolfhsmCryptoProvider` with 9 context classes:
33+
`RandomGeneratorCtx`, `HashFunctionCtx`, `SymmetricBlockCipherCtx`,
34+
`AuthCipherCtx`, `MessageAuthnCodeCtx`, `SignerPrivateCtx` /
35+
`VerifierPublicCtx`, `KeyAgreementPrivateCtx`,
36+
`KeyDerivationFunctionCtx`, `KeyStorageProvider`.
37+
- **Tests**: `classic/examples/csm_smoke/` (per-category C harness, ~25
38+
tests) and `adaptive/examples/ap_smoke/` (per-cluster C++ harness, 9
39+
tests). Both run against `examples/posix/wh_posix_server` over TCP and
40+
are wired into `.github/workflows/build-and-test-autosar.yml`.
41+
42+
See `docs/algorithm_coverage.md` for the per-primitive matrix (sync /
43+
async / Adaptive coverage), and `docs/client_workarounds.md` for the one
44+
client-side translation kept while wolfHSM's verify-handler return
45+
contract evolves.
46+
47+
## Quickstart
48+
49+
```sh
50+
# Terminal 1 — run the wolfHSM POSIX server.
51+
cd examples/posix/wh_posix_server && make
52+
./Build/wh_posix_server.elf --type tcp
53+
54+
# Terminal 2 — build and run csm_smoke (Classic).
55+
cd port/autosar/classic/examples/csm_smoke && make
56+
./Build/csm_smoke
57+
58+
# Restart the server, then build and run ap_smoke (Adaptive).
59+
cd port/autosar/adaptive/examples/ap_smoke
60+
cmake -S . -B build && cmake --build build
61+
./build/ap_smoke
62+
```
63+
64+
Both binaries print one OK line per test category and `all tests passed`
65+
on success.
66+
67+
## Licensing
68+
69+
This port is GPLv3 like the rest of wolfHSM (`../../LICENSE`). Commercial
70+
integrators ship under wolfSSL's commercial license — same dual-license
71+
model as wolfSSL / wolfCrypt. The port contains no vendor-supplied BSW
72+
headers; `Crypto.h` and the `ara/crypto` headers are written from the
73+
public AUTOSAR SWS documents.
74+
75+
"AUTOSAR-conformant" labeling is restricted to AUTOSAR Partners. This port
76+
**implements** the AUTOSAR R22-11 interfaces; conformance certification is
77+
out of scope.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Build script for the wolfHSM AUTOSAR Adaptive CryptoProvider library.
2+
# Produces libwolfhsm_ara_crypto.{a,so} that an Adaptive integrator links
3+
# into their CryptoProvider adapter.
4+
5+
cmake_minimum_required(VERSION 3.13)
6+
project(wolfhsm_ara_crypto CXX)
7+
8+
set(CMAKE_CXX_STANDARD 17)
9+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
10+
set(CMAKE_CXX_EXTENSIONS OFF)
11+
12+
if(NOT DEFINED WOLFHSM_DIR)
13+
set(WOLFHSM_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
14+
endif()
15+
if(NOT DEFINED WOLFSSL_DIR)
16+
set(WOLFSSL_DIR ${WOLFHSM_DIR}/../wolfssl)
17+
endif()
18+
# Resolve to absolute paths so they don't get reinterpreted against this
19+
# target's source dir. This matters when a relative -DWOLFHSM_DIR is
20+
# passed for a standalone build; when inherited from a parent project the
21+
# values are already absolute and this is a no-op.
22+
get_filename_component(WOLFHSM_DIR "${WOLFHSM_DIR}" ABSOLUTE
23+
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
24+
get_filename_component(WOLFSSL_DIR "${WOLFSSL_DIR}" ABSOLUTE
25+
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
26+
27+
set(SRC src/crypto_provider.cpp)
28+
29+
add_library(wolfhsm_ara_crypto ${SRC})
30+
31+
target_include_directories(wolfhsm_ara_crypto PUBLIC
32+
include
33+
${WOLFHSM_DIR}
34+
${WOLFSSL_DIR}
35+
)
36+
# Integrators override WOLFHSM_CONFIG_DIR to point at their own
37+
# wolfhsm_cfg.h / user_settings.h. The default points at the shared
38+
# port/autosar config so the library builds out of the box for
39+
# verification.
40+
if(NOT DEFINED WOLFHSM_CONFIG_DIR)
41+
set(WOLFHSM_CONFIG_DIR ${CMAKE_CURRENT_LIST_DIR}/../common/config)
42+
endif()
43+
target_include_directories(wolfhsm_ara_crypto PRIVATE
44+
${WOLFHSM_CONFIG_DIR}
45+
${CMAKE_CURRENT_LIST_DIR}/../common/include
46+
)
47+
48+
target_compile_definitions(wolfhsm_ara_crypto PRIVATE
49+
WOLFHSM_CFG
50+
WOLFSSL_USER_SETTINGS
51+
)
52+
target_compile_options(wolfhsm_ara_crypto PRIVATE -Wall -Wextra -Werror)
53+
54+
# Integrators link this library into their ara::crypto::cryp::CryptoProvider
55+
# adapter. See docs/integration_adaptive.md for the bridging pattern.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Build the Adaptive CryptoProvider smoke binary.
2+
#
3+
# Usage (from port/autosar/adaptive/examples/ap_smoke/):
4+
# cmake -S . -B build -DWOLFHSM_DIR=../../../../.. -DWOLFSSL_DIR=/path/to/wolfssl
5+
# cmake --build build
6+
#
7+
# Run alongside examples/posix/wh_posix_server (TCP, default port 23456):
8+
# ./build/ap_smoke
9+
10+
cmake_minimum_required(VERSION 3.13)
11+
project(ap_smoke CXX C)
12+
13+
set(CMAKE_CXX_STANDARD 17)
14+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
15+
set(CMAKE_CXX_EXTENSIONS OFF)
16+
set(CMAKE_C_STANDARD 99)
17+
18+
if(NOT DEFINED WOLFHSM_DIR)
19+
set(WOLFHSM_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../..)
20+
endif()
21+
if(NOT DEFINED WOLFSSL_DIR)
22+
set(WOLFSSL_DIR ${WOLFHSM_DIR}/../wolfssl)
23+
endif()
24+
# Normalize to absolute paths anchored at this example's source dir. A
25+
# relative -DWOLFHSM_DIR is meant relative to where cmake was invoked
26+
# (here), but CMake resolves relative include dirs against each target's
27+
# own source dir — so the inherited value would point at the wrong place
28+
# inside the add_subdirectory()'d adaptive library. Resolving now makes
29+
# the paths unambiguous everywhere they're inherited.
30+
get_filename_component(WOLFHSM_DIR "${WOLFHSM_DIR}" ABSOLUTE
31+
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
32+
get_filename_component(WOLFSSL_DIR "${WOLFSSL_DIR}" ABSOLUTE
33+
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
34+
set(WOLFHSM_CONFIG_DIR ${WOLFHSM_DIR}/port/autosar/common/config)
35+
36+
# Pull in the Adaptive library.
37+
add_subdirectory(${WOLFHSM_DIR}/port/autosar/adaptive
38+
${CMAKE_BINARY_DIR}/wolfhsm_ara_crypto)
39+
40+
# Glob the wolfHSM client + wolfSSL sources we need at link time.
41+
file(GLOB WOLFHSM_SRC ${WOLFHSM_DIR}/src/*.c)
42+
file(GLOB WOLFHSM_POSIX ${WOLFHSM_DIR}/port/posix/*.c)
43+
file(GLOB WOLFCRYPT_SRC ${WOLFSSL_DIR}/wolfcrypt/src/*.c)
44+
file(GLOB WOLFSSL_SRC ${WOLFSSL_DIR}/src/*.c)
45+
46+
add_executable(ap_smoke
47+
ap_smoke.cpp
48+
${WOLFHSM_SRC}
49+
${WOLFHSM_POSIX}
50+
${WOLFCRYPT_SRC}
51+
${WOLFSSL_SRC}
52+
)
53+
54+
target_compile_definitions(ap_smoke PRIVATE
55+
_POSIX_C_SOURCE=200809L
56+
WOLFHSM_CFG
57+
WOLFSSL_USER_SETTINGS
58+
WC_USE_DEVID=0x5748534D
59+
)
60+
target_include_directories(ap_smoke PRIVATE
61+
${WOLFHSM_DIR}
62+
${WOLFSSL_DIR}
63+
${WOLFHSM_CONFIG_DIR}
64+
)
65+
target_link_libraries(ap_smoke PRIVATE wolfhsm_ara_crypto pthread m)

0 commit comments

Comments
 (0)