SDK สำหรับ TESAIoT Dev Kit
คู่มืออ้างอิง API และ Tutorial (ModusToolbox)
Loading...
Searching...
No Matches
การลงทะเบียนและการ publish ของ Protected Update

Functions

int publish_csr (uint8_t *csr, size_t csr_length, uint16_t target_oid, uint16_t trust_anchor_oid, uint32_t payload_version)
 publish CSR ที่สร้างไว้เสร็จแล้วเพื่อให้แพลตฟอร์มเซ็นให้; เป็น weak — ให้ตรวจ NULL ก่อน และเป็นตัวตั้ง ingest ให้พร้อมรับ
int tesaiot_publish_protected_update (const char *target_oid, const char *trust_anchor_oid, uint32_t payload_version, bool with_csr)
 ขอ Protected Update จากแพลตฟอร์ม (OID เป็น hex string); เป็น weak — ให้ตรวจ NULL ก่อน

Detailed Description

2 ฟังก์ชัน: ตัว publish ที่ตั้งรอบการทำงานให้พร้อมรับ — เป็นตัวสร้าง correlation id (กฎ 3 ข้อที่ย้อนกลับมาในทุกหัวข้อ กฎข้อ 3) ทั้ง 2 ตัวถูกใช้แบบ weak (symbol 6 ตัวที่ถูกใช้แบบ weak — ข้อกำหนดการตรวจ NULL) ให้ตรวจ NULL ของพอยน์เตอร์ก่อน

variant ที่ใช้ได้
mtb-mpy และ mtb-only

Function Documentation

◆ publish_csr()

int publish_csr ( uint8_t * csr,
size_t csr_length,
uint16_t target_oid,
uint16_t trust_anchor_oid,
uint32_t payload_version )

publish CSR ที่สร้างไว้เสร็จแล้วเพื่อให้แพลตฟอร์มเซ็นให้; เป็น weak — ให้ตรวจ NULL ก่อน และเป็นตัวตั้ง ingest ให้พร้อมรับ

Publish a CSR the caller has already built, for the platform to sign. target_oid is the slot the resulting certificate belongs in and trust_anchor_oid the anchor that will authorise writing it.

ข้อกำหนดการเรียกใช้
publish CSR ที่ผู้เรียกสร้างไว้เสร็จแล้ว — ภายใต้ touch hold คือ prov_make_csr_held() ในเส้นทางที่ส่งมอบจริง — เพื่อให้แพลตฟอร์มเซ็นให้ เป็น weak: ให้ตรวจ NULL ก่อนเรียก (symbol 6 ตัวที่ถูกใช้แบบ weak — ข้อกำหนดการตรวจ NULL) คืนค่า 0 เมื่อสำเร็จ ซึ่งหมายถึง queued และต้องมีเซสชันกับ broker ที่ยังใช้งานอยู่ บนสาย: topic device/<id>/commands/csr เป็นการ publish ตรงโดยข้ามคิวของ publisher ที่ QoS 0 (tesaiot_optiga_trust_m.c:1044-1049) ฟังก์ชันนี้ตั้ง ingest ให้พร้อมรับ — สร้าง correlation id (รหัสจับคู่คำขอกับคำตอบ) และล้างค่า g_protected_update_just_completed (tesaiot_optiga_trust_m.c:906-919) — ดังนั้นให้บันทึก snapshot ของ g_optiga_ingest_events ก่อน publish เพื่อแยกความสำเร็จของรอบตัวเองออกจากรอบก่อนหน้า OID ที่นี่เป็น uint16_t (0xE0E1, 0xE0E8) ต่างจาก hex string ที่ publisher ของ Protected Update รับ
variant ที่ใช้ได้
mtb-mpy และ mtb-only
extern int publish_csr(uint8_t *csr, size_t csr_length, uint16_t target_oid,
uint16_t trust_anchor_oid, uint32_t payload_version)
__attribute__((weak));
/* ...context: inside prov_run_locked() ... */
if (op != HSM_PROV_OP_PU) {
if (prov_manifest_anchor_held(s_prov.target_oid) != 0U) {
/* Say what is true. The manifest requirement is a metadata field,
* not a fuse: writing D0 back to E1 FC 07 clears it, which this
* firmware already does to key slots on every key generation, and
* which was measured on this board on 2026-08-08: D0 on 0xE0E1
* read 21 e0 e8 before the write and e1 fc 07 after. Calling it
* permanent would teach the operator something false about their
* own hardware. */
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_NONE,
"This slot takes signed manifests only. Use Protect, or "
"clear the requirement first. Nothing was changed.");
return;
}
if (publish_csr == NULL) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_NONE,
"CSR enrolment is not built into this firmware");
return;
}
if (!prov_make_csr_held(key_oid)) return;
}
char t[8], a[8];
(void)snprintf(t, sizeof(t), "%04X", s_prov.target_oid);
(void)snprintf(a, sizeof(a), "%04X", s_prov.anchor_oid);
/* Read the completion counter before publishing. Anything that finishes
* after this point is an answer to this request; anything that finished
* before it is not, no matter what a flag says. */
uint32_t events_before = g_optiga_ingest_events;
if (op == HSM_PROV_OP_PU) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Protected Update is not built into this firmware");
return;
}
prov_say(HSM_PROV_STATE_BUSY, HSM_PROV_STEP_PUBLISH,
"Asking the platform for a signed manifest");
events_before = g_optiga_ingest_events;
if (prov_publish_pu_held(t, a) != 0) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Could not publish the request - is the broker connected?");
return;
}
} else {
/* Plain enrolment publishes the CSR and the platform answers on
* commands/certificate, which the subscriber installs with an ordinary
* write. Once Protected Update has run against this object the chip
* refuses ordinary writes for good, so that path is simply gone - and
* saying so is more use than letting it fail inside the vendor library
* with a bare status code. */
prov_say(HSM_PROV_STATE_BUSY, HSM_PROV_STEP_PUBLISH,
"Sending the request to the platform");
events_before = g_optiga_ingest_events;
if (publish_csr((uint8_t *)s_prov.csr, strlen(s_prov.csr),
s_prov.target_oid, s_prov.anchor_oid, 1U) != 0) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Could not publish - is the broker connected?");
return;
}
}

◆ tesaiot_publish_protected_update()

int tesaiot_publish_protected_update ( const char * target_oid,
const char * trust_anchor_oid,
uint32_t payload_version,
bool with_csr )

ขอ Protected Update จากแพลตฟอร์ม (OID เป็น hex string); เป็น weak — ให้ตรวจ NULL ก่อน

Ask the platform for a Protected Update of target_oid, optionally enrolling a fresh key with a CSR in the same exchange. The OIDs are hex strings, e.g. "E0E1".

ข้อกำหนดการเรียกใช้
ขอ Protected Update ของ target_oid จากแพลตฟอร์ม โดยเลือกลงทะเบียนกุญแจใหม่พร้อม CSR ในการแลกเปลี่ยนครั้งเดียวกันได้ เป็น weak: ให้ตรวจ NULL ก่อน (symbol 6 ตัวที่ถูกใช้แบบ weak — ข้อกำหนดการตรวจ NULL) รับสี่อาร์กิวเมนต์ — มีไฟล์อ้างอิงที่ส่งมอบมาแต่ไม่มีผู้เรียก ซึ่งเรียกฟังก์ชันนี้ด้วยสามอาร์กิวเมนต์อันขัดกับ prototype นี้และคอมไพล์ไม่ผ่าน ไฟล์นั้นไม่ใช่เส้นทางที่ส่งมอบจริงและไม่ถูกอ้างถึง with_csr = true จะสร้างคู่กุญแจบนชิป (เป็นการทำลายของเดิมโดยจำเป็น) จึงต้องห่อการเรียกไว้ใน touch hold อย่างที่ prov_publish_pu_held() ทำ OID เป็น hex string"E0E1", "E0E8" จัดรูปด้วย snprintf("%04X") ที่ ipc_hsm_handler.c:2183-2184 ให้บันทึก snapshot ของ g_optiga_ingest_events ก่อน การเรียกนี้ตั้ง correlation id ให้พร้อมรับ และผู้เรียกต้องปลดสถานะนั้นในภายหลังผ่าน trustm_reset_state() ตัวฟังก์ชันจะปฏิเสธเมื่อ trust anchor ใน manifest ที่ชิปเก็บไว้ไม่ตรงกับที่ระบุมา (tesaiot_optiga_trust_m.c:1440-1449) ตัวอย่างที่คอมไพล์จริงตัวที่สอง — binding tesaiot.protected_update() ของ MicroPython ที่มีการประกาศแบบ weak และตัวกัน (guard) ค่า NULL แบบเดียวกัน — อยู่ที่ bento_libs/claw/common/mpy/modtesaiot.c:730-743 และ :760-762 (mtb-mpy เท่านั้น ไฟล์นั้นไม่อยู่ในแพ็กเกจ mtb-only)
variant ที่ใช้ได้
mtb-mpy และ mtb-only
static int prov_publish_pu_held(const char *target, const char *anchor)
{
int rc;
optiga_manager_touch_hold_reason("Generating a key and signing the request");
rc = tesaiot_publish_protected_update(target, anchor, 1U, true);
return rc;
}
/* ...context: inside prov_run_locked() ... */
if (op != HSM_PROV_OP_PU) {
if (prov_manifest_anchor_held(s_prov.target_oid) != 0U) {
/* Say what is true. The manifest requirement is a metadata field,
* not a fuse: writing D0 back to E1 FC 07 clears it, which this
* firmware already does to key slots on every key generation, and
* which was measured on this board on 2026-08-08: D0 on 0xE0E1
* read 21 e0 e8 before the write and e1 fc 07 after. Calling it
* permanent would teach the operator something false about their
* own hardware. */
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_NONE,
"This slot takes signed manifests only. Use Protect, or "
"clear the requirement first. Nothing was changed.");
return;
}
if (publish_csr == NULL) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_NONE,
"CSR enrolment is not built into this firmware");
return;
}
if (!prov_make_csr_held(key_oid)) return;
}
char t[8], a[8];
(void)snprintf(t, sizeof(t), "%04X", s_prov.target_oid);
(void)snprintf(a, sizeof(a), "%04X", s_prov.anchor_oid);
/* Read the completion counter before publishing. Anything that finishes
* after this point is an answer to this request; anything that finished
* before it is not, no matter what a flag says. */
uint32_t events_before = g_optiga_ingest_events;
if (op == HSM_PROV_OP_PU) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Protected Update is not built into this firmware");
return;
}
prov_say(HSM_PROV_STATE_BUSY, HSM_PROV_STEP_PUBLISH,
"Asking the platform for a signed manifest");
events_before = g_optiga_ingest_events;
if (prov_publish_pu_held(t, a) != 0) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Could not publish the request - is the broker connected?");
return;
}
} else {
/* Plain enrolment publishes the CSR and the platform answers on
* commands/certificate, which the subscriber installs with an ordinary
* write. Once Protected Update has run against this object the chip
* refuses ordinary writes for good, so that path is simply gone - and
* saying so is more use than letting it fail inside the vendor library
* with a bare status code. */
prov_say(HSM_PROV_STATE_BUSY, HSM_PROV_STEP_PUBLISH,
"Sending the request to the platform");
events_before = g_optiga_ingest_events;
if (publish_csr((uint8_t *)s_prov.csr, strlen(s_prov.csr),
s_prov.target_oid, s_prov.anchor_oid, 1U) != 0) {
prov_say(HSM_PROV_STATE_FAILED, HSM_PROV_STEP_PUBLISH,
"Could not publish - is the broker connected?");
return;
}
}