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

Functions

void bento_devmode_init (void)
 เป็น idempotent สร้าง secret ขนาด 32 ไบต์ใน RAM จุดเข้าสาธารณะของ devmode ทุกจุดเรียกฟังก์ชันนี้เอง
void bento_devmode_nonce_issue (uint8_t nonce_out[BENTO_DEVMODE_NONCE_LEN])
 เติม nonce ใหม่ขนาด 16 ไบต์ ทับตัวที่ค้างอยู่ทิ้ง และเริ่มนับนาฬิกา TTL
bool bento_devmode_unlock (const char *hmac_hex, size_t hmac_hex_len)
 ตรวจสอบ HMAC เทียบกับ nonce ที่ค้างอยู่ และทำให้ nonce ใช้ไม่ได้อีกทุกครั้งที่ถูกเรียก (ใช้ได้ครั้งเดียว)
void bento_devmode_lock (void)
 ล้าง flag ปลดล็อก
bool bento_devmode_is_unlocked (void)
 บอกว่า verb ที่มีสิทธิ์พิเศษ (bento.exec) ได้รับอนุญาตอยู่ในขณะนั้นหรือไม่
size_t bento_devmode_secret_hex (char *out, size_t out_sz)
 secret ในรูป hex 64 อักขระ + NUL หรือคืน 0 เมื่อบัฟเฟอร์เล็กเกินไป ห้ามพิมพ์ค่านี้ลง UART
void bento_devmode_emit_provision (void)
 ส่ง event provision หนึ่งครั้งต่อการบูตหนึ่งรอบ ตอนเปลี่ยนสถานะเป็น CONNECTED การส่งที่ล้มเหลวจะลองใหม่
size_t bento_devmode_secret_fp_hex (char *out, size_t out_sz)
 4 ไบต์แรกของ SHA-256(secret) ในรูป hex 8 อักขระ + NUL — พิมพ์ออกได้อย่างปลอดภัย

Detailed Description

8 ฟังก์ชัน: การปลดล็อกโหมดสำหรับผู้พัฒนา ในกลุ่ม bento_devmode_* คอมไพล์เฉพาะเมื่อ ENABLE_PAGE_BENTO_BUDDY=1 (ค่าตั้งต้นคือ 0, proj_cm33_ns/Makefile:64, :305) ให้ build ใหม่หลังจาก make getlibs — ดู Flag gate (อ่านก่อน)

การประกาศ: bento_devmode.h ส่วนการนำไปสร้างจริงถูกเก็บไว้ใน libbento_secure.a secret ที่ใช้ร่วมกันนั้น อยู่ใน RAM เท่านั้นและถูกสร้างใหม่ทุกครั้งที่บูต (การคงค่าไว้ใน slot 0xE120 ของ OPTIGA ถูกเลื่อนออกไป) — ฝั่ง desktop ต้องจัดเตรียมใหม่หลังการบูตใหม่ทุกครั้ง TTL ของ nonce คือ BENTO_DEVMODE_NONCE_TTL_MS (60000) และมี challenge ค้างได้ครั้งละหนึ่งรายการ

สิ่งที่ challenge/response นี้ปกป้องได้ และสิ่งที่ปกป้องไม่ได้ การจัดเตรียมค่าเริ่มต้นนั้นทำโดยส่ง secret ออกไปในรูป plaintext ให้ peer ตัวแรกที่เชื่อมต่อสำเร็จ (Devmode ที่ bento_devmode_emit_provision) ผ่าน TX ที่ไม่ได้ตั้งบิต GATTDB_PERM_AUTH_* และตัว secret มาจาก xorshift32 ที่มีเอนโทรปีต่ำกว่า 32 บิต ขั้นตอน HMAC เองถูกต้อง แต่ผลลัพธ์รวมคือ gate ที่กัน peer ซึ่งมาทีหลังได้เท่านั้น จึงเป็นเครื่องกีดขวาง ไม่ใช่ขอบเขตการบังคับใช้สิทธิ์

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

Function Documentation

◆ bento_devmode_init()

void bento_devmode_init ( void )

เป็น idempotent สร้าง secret ขนาด 32 ไบต์ใน RAM จุดเข้าสาธารณะของ devmode ทุกจุดเรียกฟังก์ชันนี้เอง

ข้อกำหนดการเรียกใช้
เป็น idempotent (เรียกซ้ำแล้วผลเหมือนเดิม) โดยมี flag ภายในที่บอกว่า secret พร้อมแล้วเป็นตัวกัน ไม่จำเป็นต้องมีผู้เรียกจากภายนอก — จุดเข้าสาธารณะของ devmode ทุกจุดเรียกฟังก์ชันนี้เอง (bento_devmode_nonce_issue(), bento_devmode_secret_hex(), bento_devmode_secret_fp_hex(), bento_devmode_emit_provision()) ไม่มีการจับ lock ตั้งค่าตั้งต้นให้ PRNG แล้วเติม secret ขนาด 32 ไบต์ call site ในเทมเพลต: 0 (ใน archive: 4)

คุณภาพของ secret PRNG ที่ใช้คือ xorshift32 ซึ่ง seed จาก tick ของ FreeRTOS, แอดเดรสบน stack และค่าคงที่หนึ่งค่า เอนโทรปีจึงต่ำกว่า 32 บิต และไม่แข็งแรงพอในเชิงการเข้ารหัส ไม่ได้ใช้ RNG ของ OPTIGA การย้ายไปใช้ค่าจากชิปเป็นงานที่ยังไม่ได้ทำ

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

◆ bento_devmode_nonce_issue()

void bento_devmode_nonce_issue ( uint8_t nonce_out[BENTO_DEVMODE_NONCE_LEN])

เติม nonce ใหม่ขนาด 16 ไบต์ ทับตัวที่ค้างอยู่ทิ้ง และเริ่มนับนาฬิกา TTL

ข้อกำหนดการเรียกใช้
เติม nonce ใหม่ขนาด 16 ไบต์ ทับตัวที่ค้างอยู่ทิ้ง แล้วเริ่มนับนาฬิกา TTL เรียก init ให้ตัวเอง call site ในเทมเพลต: 0; ถูกเรียกภายใน archive เท่านั้น (จาก handler ของ verb bento.devmode.nonce)

ผลด้านความปลอดภัยที่ต้องระบุให้ตรง ฟังก์ชันนี้ส่ง secret ออกไปในรูป plaintext ให้ peer ตัวแรกที่เชื่อมต่อสำเร็จหลังการบูต และ characteristic TX ไม่ได้ตั้งบิต GATTDB_PERM_AUTH_* (ดู ข้อมูล GATT) ดังนั้น peer ที่ยังไม่ได้จับคู่ก็รับค่านี้ได้ ขั้นตอน HMAC-SHA256 เองถูกต้อง แต่การครอบครองกุญแจไม่ได้ถูกจำกัดไว้กับเครื่องเดสก์ท็อปที่ได้รับอนุญาต gate นี้จึงกัน peer ที่มาทีหลังได้เท่านั้น ให้ถือเป็นเครื่องกีดขวาง ไม่ใช่ขอบเขตการบังคับใช้สิทธิ์

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

◆ bento_devmode_unlock()

bool bento_devmode_unlock ( const char * hmac_hex,
size_t hmac_hex_len )

ตรวจสอบ HMAC เทียบกับ nonce ที่ค้างอยู่ และทำให้ nonce ใช้ไม่ได้อีกทุกครั้งที่ถูกเรียก (ใช้ได้ครั้งเดียว)

ข้อกำหนดการเรียกใช้
ตรวจสอบสตริง hex ของ HMAC-SHA256 เทียบกับ nonce ที่ค้างอยู่และกับ secret คืน true เมื่อค่าตรงกัน และ TTL ยังไม่หมดอายุ ซึ่งจะตั้ง flag ปลดล็อกด้วย ทำให้ nonce ใช้ไม่ได้อีกทุกครั้งที่ถูกเรียก (ใช้ได้ครั้งเดียว เป็นการป้องกันการเล่นซ้ำ) call site ในเทมเพลต: 0; ถูกเรียกภายใน archive เท่านั้น (จาก handler ของ verb bento.devmode.unlock ซึ่งส่งสตริง hex ตรงมาจาก token ของ JSON โดยไม่ได้ปิดท้ายด้วย NUL)
variant ที่ใช้ได้
mtb-mpy และ mtb-only

◆ bento_devmode_lock()

void bento_devmode_lock ( void )

ล้าง flag ปลดล็อก

ข้อกำหนดการเรียกใช้
ล้าง flag ปลดล็อก call site ในเทมเพลต: 0; ถูกเรียกภายใน archive เท่านั้น (จาก handler ของ verb bento.devmode.lock)
variant ที่ใช้ได้
mtb-mpy และ mtb-only

◆ bento_devmode_is_unlocked()

bool bento_devmode_is_unlocked ( void )

บอกว่า verb ที่มีสิทธิ์พิเศษ (bento.exec) ได้รับอนุญาตอยู่ในขณะนั้นหรือไม่

ข้อกำหนดการเรียกใช้
บอกว่า verb ที่มีสิทธิ์พิเศษ (bento.exec) ได้รับอนุญาตอยู่ในขณะนั้นหรือไม่ call site ในเทมเพลต: 0; ถูกเรียกภายใน archive เท่านั้น (จาก handler ของ verb bento.exec เพื่อตรวจ gate และจากส่วนที่สร้าง JSON สถานะ)
variant ที่ใช้ได้
mtb-mpy และ mtb-only

◆ bento_devmode_secret_hex()

size_t bento_devmode_secret_hex ( char * out,
size_t out_sz )

secret ในรูป hex 64 อักขระ + NUL หรือคืน 0 เมื่อบัฟเฟอร์เล็กเกินไป ห้ามพิมพ์ค่านี้ลง UART

ข้อกำหนดการเรียกใช้
เขียน secret ในรูป hex 64 อักขระ + NUL คืนค่าความยาวที่เขียนได้ หรือคืน 0 เมื่อบัฟเฟอร์เล็กเกินไป — ต้องตรวจค่า 0 ผู้เรียก ห้ามพิมพ์ค่านี้ลง UART call site ในเทมเพลต: 0; ถูกเรียกภายใน archive โดย bento_devmode_emit_provision()
variant ที่ใช้ได้
mtb-mpy และ mtb-only

◆ bento_devmode_emit_provision()

void bento_devmode_emit_provision ( void )

ส่ง event provision หนึ่งครั้งต่อการบูตหนึ่งรอบ ตอนเปลี่ยนสถานะเป็น CONNECTED การส่งที่ล้มเหลวจะลองใหม่

ข้อกำหนดการเรียกใช้
ส่ง {"evt":"bento.devmode.provision","secret":"<64 hex>"} ออกทาง NUS หนึ่งครั้งต่อการบูตหนึ่งรอบ (มี flag แบบ static บอกว่าส่งไปแล้ว การส่งที่ล้มเหลวจะปล่อย flag นั้นไว้โดยไม่ตั้งค่า การเปลี่ยนสถานะเป็น CONNECTED ครั้งถัดไปจึงลองใหม่) ต่อไว้กับการเปลี่ยนสถานะเป็น CONNECTED ในส่วนการนำไปสร้างจริงของโมดูล ble_nus คู่กับ bento_fw_emit_boot_complete() หากไม่มีการส่งนี้ bento.devmode.unlock ทุกครั้งจะตอบ not_permitted call site ในเทมเพลต: 0; ถูกเรียกภายใน archive เท่านั้น (จาก callback สถานะของ link ในจังหวะที่เปลี่ยนเป็น CONNECTED)
variant ที่ใช้ได้
mtb-mpy และ mtb-only

◆ bento_devmode_secret_fp_hex()

size_t bento_devmode_secret_fp_hex ( char * out,
size_t out_sz )

4 ไบต์แรกของ SHA-256(secret) ในรูป hex 8 อักขระ + NUL — พิมพ์ออกได้อย่างปลอดภัย

ข้อกำหนดการเรียกใช้
4 ไบต์แรกของ SHA-256(secret) ในรูป hex 8 อักขระ + NUL — พิมพ์ออกได้อย่างปลอดภัย ทำให้ฝั่ง desktop กับเฟิร์มแวร์ยืนยันได้ว่าถือ secret ตัวเดียวกัน โดยไม่ทำให้ค่านั้นรั่วไหล คืนค่าความยาวที่เขียนได้ คืน 0 เมื่อบัฟเฟอร์เล็กเกินไป call site ในเทมเพลต: 0 (ใน archive: 3 — หนึ่งครั้งใน bento_devmode_emit_provision() และสองครั้งใน handler ของ verb bento.devmode.unlock)
variant ที่ใช้ได้
mtb-mpy และ mtb-only