SDK User API & Code Examples
Who this is for: Developers writing code against the SDK, the REST API, or the Cloud SDK.
What you'll learn: The canonical device authentication flow in C, plus reference examples for the REST API and the Python Cloud SDK.
Event handling model
The Device starts a backend listener in a background thread and runs the interactive menu on the main thread in parallel, serialized by a mutex (g_sdk_mutex) so the SDK is never called concurrently. On startup the device prints [READY] Listening for TrustBridge triggers sandgrain/v1/{tid}/cmd/run_auth. The BE/FE publishes {"mode":1|2|3} to that topic to trigger the matching flow (modes 1/2/3 map to the same fault-injection profiles as menu options 1/2/3). After a backend-triggered run, the device re-prints the menu prompt so manual use continues.
Device SDK (C): the canonical authentication flow
#include "sdk_sgr_user_api.h"
int main(void) {
if (SGR_SDK_Initialize() != SGR_SDK_OK) return 1;
/* Phase 1 + 2 mutual authentication via the Gateway */
sgr_sdk_status_t st = SGR_SDK_Authenticate_Via_GW();
if (st != SGR_SDK_OK) { /* handle AUTH_FAILED / COMM_ERROR */ return 1; }
/* Optional: verify firmware, then authorize installation */
uint8_t fw_rw[16];
if (SGR_SDK_Verification_FW(fw_data, fw_size, fw_rw) == SGR_SDK_OK)
SGR_SDK_Installation(); /* uses fw_rw from the verification step */
return 0;
}
TrustBridge REST API: authenticate, then bulk-import
# 1) Log in and capture the JWT
TOKEN=$(curl -s http://localhost:3000/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"TrustAdmin","password":"TrustAdmin"}' \
| jq -r '.data.access_token')
# 2) Bulk-import devices from a JSON manifest
curl -s http://localhost:3000/api/devices/bulk-import \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data-binary @devices.json
Cloud SDK (Python): a challenge / response against CyberRock
from sandgrain_cloud_sdk import CloudSDK, CloudSDKConfig
import aiohttp
async def authenticate(tid, rw, creds):
async with aiohttp.ClientSession() as session:
sdk = CloudSDK(
cfg=CloudSDKConfig(base_url="https://device-api.sandbox.sandgrain.io"),
session=session, creds=creds)
cw = await sdk.request_cw(tid=tid) # challenge word
# ... the device computes RW on its crypto chip ...
await sdk.reply_rw(tid, cw.cw, rw, cw.transactionId)
return await sdk.wait_auth_ok(tid, cw.transactionId)
Worked scenarios (the PoC menu)
- Basic: Mutual authentication (Option 1): both CW and RW transmitted without corruption; the Gateway verifies with zero bit difference and the Server returns
AUT_OK. - Intermediate: Fault injection (Option 2): controlled bit corruptions are injected; the Gateway detects them, builds candidates, triggers Error Management, and resolves to
AUT_OKonce a candidate matches. - Advanced: Error Management stress (Option 3): heavier corruption forces the Gateway to test multiple candidates before finding the exact match.
- Production: Firmware verification then installation: the device hashes the firmware (SHA-256), obtains the expected RW from the chip, saves
RW_verify, and uses it for the installation exchange. A tampered image yieldsFW_NOK, and installation is denied.
Related articles: Developer Guide & Best Practices · REST API Reference · The Authentication Flow & Error Management · SDK API Reference