diff --git a/components/esp_driver_bitscrambler/include/driver/bitscrambler.h b/components/esp_driver_bitscrambler/include/driver/bitscrambler.h index 00b4841981e..72dfaaf8d45 100644 --- a/components/esp_driver_bitscrambler/include/driver/bitscrambler.h +++ b/components/esp_driver_bitscrambler/include/driver/bitscrambler.h @@ -73,6 +73,11 @@ void bitscrambler_free(bitscrambler_handle_t handle); /** * @brief Load a BitScrambler binary program into BitScrambler memory * + * @note The program blob is expected to come from a trusted BitScrambler assembler + * output. This API validates the header fields against hardware limits, but it + * does not take an explicit blob length and therefore cannot verify that an + * arbitrary caller-supplied buffer is complete. + * * @param handle BitScrambler handle * @param program Binary program to load * diff --git a/components/esp_driver_bitscrambler/src/bitscrambler.c b/components/esp_driver_bitscrambler/src/bitscrambler.c index e5ede7cdb5c..c4433673fe9 100644 --- a/components/esp_driver_bitscrambler/src/bitscrambler.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler.c @@ -30,8 +30,7 @@ static const char *TAG = "bitscrambler"; #define BITSCRAMBLER_BINARY_VER 1 //max version we're compatible with #define BITSCRAMBLER_HW_REV 0 -// LUT index register is 11 bits wide, so the LUT address space is 2048 bytes. -#define BITSCRAMBLER_LUT_MAX_BYTES (1U << 11) +#define BITSCRAMBLER_MAX_LUT_WORDS (BITSCRAMBLER_LL_LUT_MAX_BYTES / sizeof(uint32_t)) // After a reset, it can take a few cycles for the BitScrambler to actually be // reset. We check this many times for this; if it takes longer the hardware @@ -58,6 +57,9 @@ typedef struct { } bitscrambler_program_hdr_t; #define INST_LEN_WORDS BITSCRAMBLER_LL_INST_LEN_WORDS +#define BITSCRAMBLER_V1_HDR_LEN_WORDS (sizeof(bitscrambler_program_hdr_t) / sizeof(uint32_t)) + +_Static_assert(sizeof(bitscrambler_program_hdr_t) % sizeof(uint32_t) == 0, "bitscrambler program header must be word aligned"); // For now, hardware only has one TX and on RX unit. Need to make this more flexible if we get // non-specific and/or more channels. @@ -193,7 +195,7 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra //Parse the program header. There are two versions, V0 is generated by the C assembler while //v1 is generated by the Python assembler. - int inst_len_bytes = INST_LEN_WORDS * sizeof(uint32_t); //note this is different for v1 and v0 + size_t inst_len_bytes = INST_LEN_WORDS * sizeof(uint32_t); //note this is different for v1 and v0 memcpy(&hdr, program_bin, sizeof(bitscrambler_program_hdr_t)); if (hdr.version != BITSCRAMBLER_BINARY_VER) { ESP_LOGE(TAG, "Bitscrambler binary version %d not supported!", hdr.version); @@ -203,12 +205,29 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra ESP_LOGE(TAG, "Bitscrambler hardware rev %d not supported!", hdr.hw_rev); return ESP_ERR_INVALID_ARG; } + if (hdr.hdr_len != BITSCRAMBLER_V1_HDR_LEN_WORDS) { + ESP_LOGE(TAG, "Bitscrambler header length %d not supported!", hdr.hdr_len); + return ESP_ERR_INVALID_ARG; + } + if (hdr.inst_ct > BITSCRAMBLER_LL_MAX_INST) { + ESP_LOGE(TAG, "Bitscrambler instruction count %d exceeds hardware limit!", hdr.inst_ct); + return ESP_ERR_INVALID_ARG; + } + if (hdr.lut_word_ct > BITSCRAMBLER_MAX_LUT_WORDS) { + ESP_LOGE(TAG, "Bitscrambler LUT size %d words exceeds hardware limit!", hdr.lut_word_ct); + return ESP_ERR_INVALID_ARG; + } + if (hdr.lut_width > BITSCRAMBLER_LUT_WIDTH_32BIT) { + ESP_LOGE(TAG, "Bitscrambler LUT width %d not supported!", hdr.lut_width); + return ESP_ERR_INVALID_ARG; + } bitscrambler_ll_set_state(bs->hw, bs->cfg.dir, BITSCRAMBLER_SET_STATE_HALT); //Load the program const uint8_t *p = (const uint8_t*)program_bin; - p += hdr.hdr_len * sizeof(uint32_t); //skip header + size_t header_size_bytes = hdr.hdr_len * sizeof(uint32_t); + p += header_size_bytes; //skip header uint32_t instr[INST_LEN_WORDS]; for (int inst = 0; inst < hdr.inst_ct; inst++) { //v0 doesn't have the words 32-bit aligned, so memcpy to work around that @@ -222,9 +241,10 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra ESP_LOGD(TAG, "Loaded %d instructions", hdr.inst_ct); //Load the LUT. bitscrambler_ll_set_lut_width(bs->hw, bs->cfg.dir, BITSCRAMBLER_LUT_WIDTH_32BIT); - uint32_t *lut = (uint32_t*)p; for (int w = 0; w < hdr.lut_word_ct; w++) { - bitscrambler_ll_lutmem_write(bs->hw, bs->cfg.dir, w, lut[w]); + uint32_t lut_word; + memcpy(&lut_word, p + (w * sizeof(lut_word)), sizeof(lut_word)); + bitscrambler_ll_lutmem_write(bs->hw, bs->cfg.dir, w, lut_word); } //Set options from header @@ -249,7 +269,7 @@ esp_err_t bitscrambler_load_lut(bitscrambler_handle_t handle, void *lut, size_t if (!handle || !lut) { return ESP_ERR_INVALID_ARG; } - if (size_bytes > BITSCRAMBLER_LUT_MAX_BYTES) { + if (size_bytes > BITSCRAMBLER_LL_LUT_MAX_BYTES) { return ESP_ERR_INVALID_SIZE; } const uint8_t *lut_bytes = (const uint8_t *)lut; diff --git a/components/hal/esp32c5/include/hal/bitscrambler_ll.h b/components/hal/esp32c5/include/hal/bitscrambler_ll.h index 7c8706a776d..e9c1b6347e5 100644 --- a/components/hal/esp32c5/include/hal/bitscrambler_ll.h +++ b/components/hal/esp32c5/include/hal/bitscrambler_ll.h @@ -23,6 +23,9 @@ extern "C" { #define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL) #define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW +// LUT index register is 11 bits wide, so the LUT address space is 2048 bytes. +#define BITSCRAMBLER_LL_LUT_MAX_BYTES (1U << 11) +#define BITSCRAMBLER_LL_MAX_INST 8 /** * @brief Select peripheral BitScrambler is attached to diff --git a/components/hal/esp32p4/include/hal/bitscrambler_ll.h b/components/hal/esp32p4/include/hal/bitscrambler_ll.h index ae0cd2fb998..0ec0298d850 100644 --- a/components/hal/esp32p4/include/hal/bitscrambler_ll.h +++ b/components/hal/esp32p4/include/hal/bitscrambler_ll.h @@ -23,6 +23,9 @@ extern "C" { #define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL) #define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW +// LUT index register is 11 bits wide, so the LUT address space is 2048 bytes. +#define BITSCRAMBLER_LL_LUT_MAX_BYTES (1U << 11) +#define BITSCRAMBLER_LL_MAX_INST 8 /** * @brief Select peripheral BitScrambler is attached to