SDK สำหรับ TESAIoT Dev Kit
คู่มืออ้างอิง API และ Tutorial (ModusToolbox)
Loading...
Searching...
No Matches

Functions

bool optiga_manager_init (callback_handler_t callback, void *context)
 นำ OPTIGA stack ขึ้นทำงาน (idempotent — เรียกซ้ำแล้วได้ผลเดิม) เรียกได้เฉพาะใน task context — คืน false หากชิปไม่ตอบ
optiga_util_t * optiga_manager_acquire (void)
 instance ของ optiga_util ที่ใช้ร่วมกัน; เป็น NULL จนกว่า optiga_manager_init() จะทำงานแล้ว
void optiga_manager_release (void)
 ปล่อย instance ที่ acquire มา — เพียงครั้งเดียวต่อหนึ่งการ acquire ที่ไม่ใช่ NULL ในทุกเส้นทางออก
bool optiga_manager_lock (void)
 จับ mutex ของ manager; คืน false เมื่อไม่เคย initialise — เป็นการทดสอบ "manager ขึ้นแล้วหรือยัง" ที่แท้จริง
void optiga_manager_unlock (void)
 unlock หนึ่งครั้งต่อ lock ที่สำเร็จหนึ่งครั้ง รวมทุกเส้นทางออกก่อนกำหนด; ให้ปล่อย touch hold ก่อน
bool optiga_chip_enter (void)
 เปิดเซสชันกับชิป (re-entrant ต่อหนึ่ง task); ค่า false เป็นความล้มเหลวเด็ดขาดของการเรียกครั้งนี้ — และไม่ใช่การตรวจสอบว่า init แล้วหรือยัง
void optiga_chip_exit (void)
 exit หนึ่งครั้งต่อ enter ที่สำเร็จหนึ่งครั้ง; ห้ามเรียกหลังจาก enter ที่ล้มเหลว

Detailed Description

7 ฟังก์ชัน — ความเป็นเจ้าของ instance เดียวของ OPTIGA ชิปตัวนี้เป็นอุปกรณ์เครื่องเดียวหลังบัส I2C เส้นเดียว ใช้ร่วมกันระหว่างเส้นทาง MQTT/TLS หน้าจอการจัดเตรียม (provisioning) ของ HSM และโมดูล optiga ของ MicroPython ทุกอย่างที่แตะชิปตัวนี้ต้องผ่านที่นี่ สามใน 7 ตัวเป็น alias ของกันและกันภายใน archive — optiga_manager_release(), optiga_manager_unlock() และ optiga_chip_exit() ต่างลดค่าตัวนับความลึกแบบ re-entrant ตัวเดียวกัน — จึงเป็นเหตุผลที่กฎการจับคู่ในแต่ละรายการเข้มงวด

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

Function Documentation

◆ optiga_manager_init()

bool optiga_manager_init ( callback_handler_t callback,
void * context )

นำ OPTIGA stack ขึ้นทำงาน (idempotent — เรียกซ้ำแล้วได้ผลเดิม) เรียกได้เฉพาะใน task context — คืน false หากชิปไม่ตอบ

Bring up the OPTIGA stack. Returns false if the chip did not answer.

ข้อกำหนดการเรียกใช้
นำ OPTIGA stack ขึ้นทำงาน คืน false หากชิปไม่ตอบ เรียกได้เฉพาะใน task context — หากเรียกจาก main() ก่อน vTaskStartScheduler() จะไปถึง xTimerCreate() ภายใน critical section ที่ยังไม่มี scheduler (ipc_hsm_handler.c:1357-1364) เป็น idempotent (คืน true หาก initialise ไปแล้ว) และภายในจัดลำดับให้ทำงานทีละครั้ง ผู้เรียกเป็นฝ่ายจัดหา optiga_util_callback ซึ่งเป็น extern ที่ผู้ใช้ไลบรารีต้องนิยามเอง (สิ่งที่ผู้ใช้ไลบรารีต้องจัดหาให้) optiga_trust_open_application() เป็นขั้นตอนแยกต่างหาก: init อย่างเดียวไม่เปิด application และ prov_open_held() ที่ส่งมอบมาทำทั้งสองอย่างภายใต้ touch hold เดียว การข้าม init ทำให้ TLS CertificateVerify ล้มเหลวทุกครั้ง (mqtt_mtls_setup.c:184-201) — ตอนนี้ขั้นตอนตั้งค่า mTLS จึงเรียก init ก่อน และปล่อย touch hold ของตัวเองใน branch ที่ล้มเหลว
variant ที่ใช้ได้
mtb-mpy และ mtb-only
static bool prov_open_held(void)
{
bool ok;
optiga_manager_touch_hold_reason("Opening the secure element");
return ok;
}
/* ...context: inside mqtt_mtls_setup() ... */
printf("[mTLS] optiga_manager_init failed — signing would be impossible\n");
return false;
}

◆ optiga_manager_acquire()

optiga_util_t * optiga_manager_acquire ( void )

instance ของ optiga_util ที่ใช้ร่วมกัน; เป็น NULL จนกว่า optiga_manager_init() จะทำงานแล้ว

The shared optiga_util instance, or NULL before init.

ข้อกำหนดการเรียกใช้
instance ของ optiga_util ที่ใช้ร่วมกัน คืนค่า NULL จนกว่า optiga_manager_init() จะทำงานแล้ว (ipc_hsm_handler.c:1442-1445) เมื่อได้ NULL ห้ามเรียก optiga_manager_release() — ภายในตัวฟังก์ชันได้ออกจาก gate (ด่านกั้น) ไปแล้ว (tesaiot_optiga_manager.c:266-269) เมื่อไม่ใช่ NULL ต้องมี release() เพียงครั้งเดียวต่อหนึ่งเส้นทางออก รวมถึงเส้นทางที่เกิดข้อผิดพลาด OPTIGA host library ทำงานแบบอะซิงโครนัส: ให้ตั้ง optiga_lib_status = OPTIGA_LIB_BUSY ก่อนเรียก แล้ววนถาม (polling) ค่านั้นหลังจากนั้น ผู้เรียกทุกรายอยู่ฝั่งเทมเพลต (optiga_trust_helpers.c ×14, tesaiot_pu_ingest.c ×4) ส่วน acquire เองห่อ optiga_chip_enter() ไว้
variant ที่ใช้ได้
mtb-mpy และ mtb-only
/* ...context: inside the certificate read helper ... */
// Acquire OPTIGA instance (thread-safe)
optiga_util_t *me_util = optiga_manager_acquire();
if (!me_util) {
printf("%s ERROR: OPTIGA instance not available\n", LABEL_SUBSCRIBER);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}
// Perform async read
optiga_lib_status = OPTIGA_LIB_BUSY;
optiga_lib_status_t status = optiga_util_read_data(me_util, oid, 0, cert_der, &cert_len);
if (OPTIGA_LIB_SUCCESS != status) {
printf("%s ERROR: OPTIGA read failed (0x%04X)\n", LABEL_SUBSCRIBER, status);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}
// Wait for read completion (max 2 seconds)
TickType_t start = xTaskGetTickCount();
TickType_t timeout = pdMS_TO_TICKS(2000);
while (optiga_lib_status == OPTIGA_LIB_BUSY && (xTaskGetTickCount() - start) < timeout) {
vTaskDelay(pdMS_TO_TICKS(100));
}
if (optiga_lib_status != OPTIGA_LIB_SUCCESS) {
printf("%s ERROR: OPTIGA read timeout/failed (0x%04X)\n", LABEL_SUBSCRIBER, optiga_lib_status);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}

◆ optiga_manager_release()

void optiga_manager_release ( void )

ปล่อย instance ที่ acquire มา — เพียงครั้งเดียวต่อหนึ่งการ acquire ที่ไม่ใช่ NULL ในทุกเส้นทางออก

Release the instance taken with optiga_manager_acquire().

ข้อกำหนดการเรียกใช้
ปล่อย instance ที่รับมาด้วย optiga_manager_acquire() เพียงครั้งเดียวต่อหนึ่งการ acquire ที่ไม่ใช่ NULL ในทุกเส้นทางออกรวมถึงกรณีข้อผิดพลาด — ฟังก์ชันที่ยกมาด้านล่างมีเส้นทางออกสามทาง (tesaiot_pu_ingest.c:242, :256, :261) และแต่ละทางปล่อยครบ ฟังก์ชันนี้เป็น alias ของ optiga_chip_exit() และลดค่าตัวนับความลึกแบบ re-entrant ตัวเดียวกัน การปล่อยเกินมาหนึ่งครั้งจึงทำให้ผู้เรียกที่อยู่สูงขึ้นไปใน stack เสียสมดุล
variant ที่ใช้ได้
mtb-mpy และ mtb-only
/* ...context: inside the certificate read helper ... */
// Acquire OPTIGA instance (thread-safe)
optiga_util_t *me_util = optiga_manager_acquire();
if (!me_util) {
printf("%s ERROR: OPTIGA instance not available\n", LABEL_SUBSCRIBER);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}
// Perform async read
optiga_lib_status = OPTIGA_LIB_BUSY;
optiga_lib_status_t status = optiga_util_read_data(me_util, oid, 0, cert_der, &cert_len);
if (OPTIGA_LIB_SUCCESS != status) {
printf("%s ERROR: OPTIGA read failed (0x%04X)\n", LABEL_SUBSCRIBER, status);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}
// Wait for read completion (max 2 seconds)
TickType_t start = xTaskGetTickCount();
TickType_t timeout = pdMS_TO_TICKS(2000);
while (optiga_lib_status == OPTIGA_LIB_BUSY && (xTaskGetTickCount() - start) < timeout) {
vTaskDelay(pdMS_TO_TICKS(100));
}
if (optiga_lib_status != OPTIGA_LIB_SUCCESS) {
printf("%s ERROR: OPTIGA read timeout/failed (0x%04X)\n", LABEL_SUBSCRIBER, optiga_lib_status);
vPortFree(cert_der);
return CY_RSLT_TYPE_ERROR;
}

◆ optiga_manager_lock()

bool optiga_manager_lock ( void )

จับ mutex ของ manager; คืน false เมื่อไม่เคย initialise — เป็นการทดสอบ "manager ขึ้นแล้วหรือยัง" ที่แท้จริง

Take and release the manager mutex. Task context only.

ข้อกำหนดการเรียกใช้
จับ mutex ของ manager เรียกได้เฉพาะใน task context คืนค่า false เมื่อ manager ไม่เคยถูก initialise (tesaiot_optiga_manager.c:342-348) — สิ่งนี้ ไม่ใช่ optiga_chip_enter() คือการทดสอบ "manager ขึ้นแล้วหรือยัง" ที่ถูกต้อง ลำดับภายในหนึ่ง transaction: lock → touch_hold → work → touch_release → unlock ห้ามเปิด OPTIGA application ขณะที่ยังถือ lock อยู่optiga_trust_helpers.c:4628-4636 แสดงลำดับที่ต้องใช้ คือ optiga_trust_open_application() ก่อน แล้ว optiga_manager_lock() ตามหลัง เมื่อได้ค่า false กลับมา ให้คืนค่าข้อผิดพลาด ห้ามทำงานต่อ และห้าม unlock
variant ที่ใช้ได้
mtb-mpy และ mtb-only
/* ...context: inside trustm_ecdsa_sign() ... */
/* Lock OPTIGA mutex for thread-safe access */
printf("optiga_manager_lock failed\n");
return OPTIGA_LIB_BUSY;
}
/* Keep CM55 touch off SCB5 for the whole transaction — the secure element
* and the touch controller share the bus, and the TLS handshake signs after
* the mTLS setup has already resumed touch polling. */
/* ...context: inside trustm_ecdsa_sign(), the single exit path ... */

◆ optiga_manager_unlock()

void optiga_manager_unlock ( void )

unlock หนึ่งครั้งต่อ lock ที่สำเร็จหนึ่งครั้ง รวมทุกเส้นทางออกก่อนกำหนด; ให้ปล่อย touch hold ก่อน

ข้อกำหนดการเรียกใช้
unlock หนึ่งครั้งต่อ lock ที่สำเร็จหนึ่งครั้ง รวมถึงทุกเส้นทางออกก่อนกำหนด (branch !crypt ในตัวอย่างมาตรฐานด้านล่าง) เมื่อมีการจับ touch hold ไว้ด้วย ให้ปล่อย hold ก่อน unlock (optiga_trust_helpers.c:1721-1722) เป็น alias ของ optiga_chip_exit() ตัวอย่างที่คอมไพล์จริงคือคู่ release/unlock ที่แสดงไว้ใต้ optiga_manager_lock() ส่วนรูปแบบ lock/unlock ที่ชัดที่สุดใน tree ถูกยกมาต่อจากนี้ — เป็นโค้ดอ้างอิงที่ส่งมอบมา แต่ proj_cm33_ns ไม่ได้คอมไพล์ (tesaiot_crypto.c ไม่อยู่ในรายการ SOURCES ใด ๆ ให้ยกไปใช้เป็นสำนวนโค้ดเท่านั้น)
variant ที่ใช้ได้
mtb-mpy และ mtb-only
/* shipped reference, not compiled by proj_cm33_ns */
/* ...context: inside the TRNG random_generate helper ... */
if (!optiga_manager_is_initialized()) {
return TESAIOT_ERROR_NOT_INITIALIZED;
}
return TESAIOT_ERROR_TIMEOUT;
}
volatile optiga_lib_status_t optiga_status = OPTIGA_LIB_BUSY;
optiga_crypt_t *crypt = optiga_manager_create_crypt(crypto_callback,
(void *)&optiga_status);
if (!crypt) {
return TESAIOT_ERROR_OPTIGA;
}
optiga_lib_status_t result = optiga_crypt_random(crypt,
OPTIGA_RNG_TYPE_TRNG,
buffer,
length);
int rc = TESAIOT_ERROR_OPTIGA;
if (result == OPTIGA_LIB_SUCCESS) {
rc = crypto_wait_for_completion(&optiga_status);
}
optiga_crypt_destroy(crypt);

◆ optiga_chip_enter()

bool optiga_chip_enter ( void )

เปิดเซสชันกับชิป (re-entrant ต่อหนึ่ง task); ค่า false เป็นความล้มเหลวเด็ดขาดของการเรียกครั้งนี้ — และไม่ใช่การตรวจสอบว่า init แล้วหรือยัง

Open and close a chip session around a burst of operations.

ข้อกำหนดการเรียกใช้
เปิดเซสชันกับชิปครอบชุดปฏิบัติการที่ทำต่อเนื่องกัน เป็น re-entrant ต่อหนึ่ง FreeRTOS task — การซ้อนกันทำได้โดยไม่มีต้นทุน ฟังก์ชันที่ถูกเรียกซึ่ง enter ซ้ำจึงไม่ deadlock กับผู้เรียกของตัวเอง ค่า false ที่คืนมาหมายความว่า task อื่นกำลังถือชิปอยู่ ซึ่งเป็นความล้มเหลวเด็ดขาดของการเรียกครั้งนี้ — ให้คืนค่าข้อผิดพลาด ห้ามทำงานต่อ touch hold ถูกจับไว้ภายใน gate และปล่อยก่อน optiga_chip_exit() ไม่ใช่การตรวจสอบว่า init แล้วหรือยัง: ฟังก์ชันนี้คืนค่า true โดยเจตนาเมื่อ manager ไม่เคยถูก initialise (tesaiot_optiga_manager.c:157-169) ให้ใช้ optiga_manager_lock() สำหรับการตรวจนั้น การเข้าใจสลับกันคือสาเหตุที่มีบันทึกไว้ของข้อบกพร่องประเภทเข้าถึงโดยไม่ผ่าน gate หลายรายการ เส้นทางการลงทะเบียน (enrolment) ทั้งสองเส้นไม่เคยเรียกฟังก์ชันนี้โดยตรง — แต่ไปถึงมันผ่าน lock/unlock และ acquire/release ซึ่งห่อมันไว้ (tesaiot_optiga_manager.c:340-365)
variant ที่ใช้ได้
mtb-mpy และ mtb-only
int optiga_verify_cert_key_pair(uint16_t cert_oid, uint16_t key_oid)
{
int rc;
/* Two tasks call this: the MQTT subscriber after installing a certificate,
* and the provisioning task when its wait ends. They share cert_pem - a 2 KB
* static - and the library's single global status. The gate is re-entrant, so
* the certificate read and the signature inside still take it, without
* deadlocking on this one. */
return -5; /* the chip is busy elsewhere; a verdict now would be a guess */
}
optiga_manager_touch_hold_reason("Checking certificate against its key");
rc = verify_cert_key_pair_locked(cert_oid, key_oid);
return rc;
}

◆ optiga_chip_exit()

void optiga_chip_exit ( void )

exit หนึ่งครั้งต่อ enter ที่สำเร็จหนึ่งครั้ง; ห้ามเรียกหลังจาก enter ที่ล้มเหลว

ข้อกำหนดการเรียกใช้
exit หนึ่งครั้งต่อ enter ที่สำเร็จหนึ่งครั้ง ห้ามเรียกหลังจาก enter ที่ล้มเหลว — รูปแบบ deferred close ด้านล่างคืนค่าออกก่อนกำหนดที่ branch ของ enter ที่ล้มเหลวโดยไม่ exit และเลื่อนการ close ไปให้ครั้งที่สมดุลถัดไป ("closing under another task's transaction is worse than deferring the close") ความเป็นเจ้าของถูกตรวจแยกตาม task ภายในตัวฟังก์ชัน
variant ที่ใช้ได้
mtb-mpy และ mtb-only
{
/* Closing under another task's transaction is worse than deferring the
* close: the reference stays, and the next balanced close will do it. */
optiga_lib_print_message("close deferred: the chip is busy elsewhere",
OPTIGA_UTIL_SERVICE, OPTIGA_UTIL_SERVICE_COLOR);
return;
}
optiga_trust_close_application_gated();
}