Doc: S2 HMAC documentation
This commit is contained in:
parent
017f07cda7
commit
2da7e65646
7 changed files with 146 additions and 2 deletions
|
@ -44,12 +44,12 @@ typedef enum {
|
||||||
*
|
*
|
||||||
* @note Uses the HMAC peripheral in "upstream" mode.
|
* @note Uses the HMAC peripheral in "upstream" mode.
|
||||||
*
|
*
|
||||||
* @param key_id Determines which of the 7 key blocks in the efuses should be used for the HMAC calcuation.
|
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
|
||||||
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
|
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
|
||||||
* @param message the message for which to calculate the HMAC
|
* @param message the message for which to calculate the HMAC
|
||||||
* @param message_len message length
|
* @param message_len message length
|
||||||
* return ESP_ERR_INVALID_STATE if unsuccessful
|
* return ESP_ERR_INVALID_STATE if unsuccessful
|
||||||
* @param [out] hmac the hmac result
|
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be 32 bytes long
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* * ESP_OK, if the calculation was successful,
|
* * ESP_OK, if the calculation was successful,
|
||||||
|
|
|
@ -110,6 +110,7 @@ INPUT = \
|
||||||
$(IDF_PATH)/components/driver/include/driver/adc_common.h \
|
$(IDF_PATH)/components/driver/include/driver/adc_common.h \
|
||||||
$(IDF_PATH)/components/driver/include/driver/uart.h \
|
$(IDF_PATH)/components/driver/include/driver/uart.h \
|
||||||
$(IDF_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \
|
$(IDF_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \
|
||||||
|
$(IDF_PATH)/components/esp32s2/include/esp_hmac.h \
|
||||||
$(IDF_PATH)/components/soc/include/hal/rmt_types.h \
|
$(IDF_PATH)/components/soc/include/hal/rmt_types.h \
|
||||||
$(IDF_PATH)/components/soc/include/hal/spi_types.h \
|
$(IDF_PATH)/components/soc/include/hal/spi_types.h \
|
||||||
$(IDF_PATH)/components/soc/include/hal/pcnt_types.h \
|
$(IDF_PATH)/components/soc/include/hal/pcnt_types.h \
|
||||||
|
|
|
@ -160,6 +160,7 @@ def update_exclude_patterns(tags):
|
||||||
for e in ['esp32s2.rst',
|
for e in ['esp32s2.rst',
|
||||||
'hw-reference/esp32s2/**',
|
'hw-reference/esp32s2/**',
|
||||||
'api-guides/ulps2_instruction_set.rst',
|
'api-guides/ulps2_instruction_set.rst',
|
||||||
|
'api-reference/peripherals/hmac.rst',
|
||||||
'api-reference/peripherals/temp_sensor.rst']:
|
'api-reference/peripherals/temp_sensor.rst']:
|
||||||
exclude_patterns.append(e)
|
exclude_patterns.append(e)
|
||||||
|
|
||||||
|
|
138
docs/en/api-reference/peripherals/hmac.rst
Normal file
138
docs/en/api-reference/peripherals/hmac.rst
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
HMAC
|
||||||
|
====
|
||||||
|
|
||||||
|
The HMAC (Hash-based Message Authentication Code) module provides hardware acceleration for SHA256-HMAC generation using a key burned into an eFuse block.
|
||||||
|
HMACs work with pre-shared secret keys and provide authenticity and integrity to a message.
|
||||||
|
|
||||||
|
Look into the `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_ (PDF) for more detailed information about the application workflow and the HMAC calculation process.
|
||||||
|
|
||||||
|
Generalized Application Scheme
|
||||||
|
------------------------------
|
||||||
|
Let there be two parties, A and B. They want to verify the authenticity and integrity of messages sent between each other.
|
||||||
|
Before they can start sending messages, they need to exchange the secret key via a secure channel.
|
||||||
|
To verify A's messages, B can do the following:
|
||||||
|
|
||||||
|
- A calculates the HMAC of the message it wants to send.
|
||||||
|
- A sends the message and the HMAC to B.
|
||||||
|
- B calculates HMAC of the received message itself.
|
||||||
|
- B checks wether the received and calculated HMACs match.
|
||||||
|
If they do match, the message is authentic.
|
||||||
|
|
||||||
|
However, the HMAC itself isn't bound to this use case.
|
||||||
|
It can also be used for challenge-response protocols supporting HMAC or as a key input for further security modules (see below), etc.
|
||||||
|
|
||||||
|
HMAC on the {IDF_TARGET_NAME}
|
||||||
|
-----------------------------
|
||||||
|
On the {IDF_TARGET_NAME}, the HMAC module works with a secret key burnt into the eFuses.
|
||||||
|
This eFuse key can be made completely inaccessible for any resources outside the cryptographic modules, thus avoiding key leakage.
|
||||||
|
|
||||||
|
Furthermore, the {IDF_TARGET_NAME} has three different application scenarios for its HMAC module:
|
||||||
|
|
||||||
|
#. HMAC is generated for software use
|
||||||
|
#. HMAC is used as a key for the Digital Signature (DS) module
|
||||||
|
#. HMAC is used for enabling the soft-disabled JTAG interface
|
||||||
|
|
||||||
|
The first mode is also called *Upstream* mode, while the last two modes are also called *Downstream* modes.
|
||||||
|
|
||||||
|
eFuse Keys for HMAC
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
Six physical eFuse blocks can be used as keys for the HMAC module: block 4 up to block 9.
|
||||||
|
The enum :cpp:enum:`hmac_key_id_t` in the API maps them to `HMAC_KEY0 ... HMAC_KEY5`.
|
||||||
|
Each key has a corresponding eFuse parameter *key purpose* determining for which of the three HMAC application scenarios (see below) the key may be used:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 15 70
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Key Purpose
|
||||||
|
- Application Scenario
|
||||||
|
* - 8
|
||||||
|
- HMAC generated for software use
|
||||||
|
* - 7
|
||||||
|
- HMAC used as a key for the Digital Signature (DS) module
|
||||||
|
* - 6
|
||||||
|
- HMAC used for enabling the soft-disabled JTAG interface
|
||||||
|
* - 5
|
||||||
|
- HMAC both as a key for the DS module and for enabling JTAG
|
||||||
|
|
||||||
|
This is to prevent the usage of a key for a different function than originally intended.
|
||||||
|
|
||||||
|
To calculate an HMAC, the software has to provide the ID of the key block containing the secret key as well as the *key purpose* (see chapter *eFuse Controller* in the `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_).
|
||||||
|
Before the HMAC key calculation, the HMAC module looks up the purpose of the provided key block.
|
||||||
|
The calculation only proceeds if the provided key purpose matches the purpose stored in the eFuses of the key block provided by the ID.
|
||||||
|
|
||||||
|
HMAC Generation for Software
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Key Purpose value: 8
|
||||||
|
|
||||||
|
In this case, the HMAC is given out to the software (e.g. to authenticate a message).
|
||||||
|
|
||||||
|
The API to calculate the HMAC is :cpp:func:`esp_hmac_calculate`.
|
||||||
|
Only the message, message length and the eFuse key block ID have to be provided to that function.
|
||||||
|
The rest, like setting the key purpose, is done automatically.
|
||||||
|
|
||||||
|
HMAC for Digital Signature
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Key Purpose values: 7, 5
|
||||||
|
|
||||||
|
The HMAC can be used as a key derivation function to decrypt private key parameters which are used by the Digital Signature module.
|
||||||
|
A standard message is used by the hardware in that case.
|
||||||
|
The user only needs to provide the eFuse key block and purpose on the HMAC side (additional parameters are required for the Digital Signature component in that case).
|
||||||
|
Neither the key nor the actual HMAC are ever exposed to outside the HMAC module and DS component.
|
||||||
|
The calculation of the HMAC and its hand-over to the DS component happen internally.
|
||||||
|
|
||||||
|
For more details, check the chapter *Digital Signature* in the `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||||
|
|
||||||
|
HMAC for Enabling JTAG
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Key Purpose values: 6, 5
|
||||||
|
|
||||||
|
The third application is using the HMAC as a key to enable JTAG if it was soft-disabled before.
|
||||||
|
This functionality is currently not implemented.
|
||||||
|
|
||||||
|
Application Outline
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Following code is an outline of how to set an eFuse key and then use it to calculate an HMAC for software usage.
|
||||||
|
We use `ets_efuse_write_key` to set physical key block 4 in the eFuse for the HMAC module together with its purpose.
|
||||||
|
`ETS_EFUSE_KEY_PURPOSE_HMAC_UP` (8) means that this key can only be used for HMAC generation for software usage:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#include "esp32s2/rom/efuse.h"
|
||||||
|
|
||||||
|
const uint8_t key_data[32] = { ... };
|
||||||
|
|
||||||
|
int ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY4,
|
||||||
|
ETS_EFUSE_KEY_PURPOSE_HMAC_UP,
|
||||||
|
key_data, sizeof(key_data));
|
||||||
|
|
||||||
|
if (ets_status == ESP_OK) {
|
||||||
|
// written key
|
||||||
|
} else {
|
||||||
|
// writing key failed, maybe written already
|
||||||
|
}
|
||||||
|
|
||||||
|
Now we can use the saved key to calculate an HMAC for software usage.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#include "esp_hmac.h"
|
||||||
|
|
||||||
|
uint8_t hmac[32];
|
||||||
|
|
||||||
|
const char *message = "Hello, HMAC!";
|
||||||
|
const size_t msg_len = 12;
|
||||||
|
|
||||||
|
esp_err_t result = esp_hmac_calculate(HMAC_KEY4, message, msg_len, hmac);
|
||||||
|
|
||||||
|
if (result == ESP_OK) {
|
||||||
|
// HMAC written to hmac now
|
||||||
|
} else {
|
||||||
|
// failure calculating HMAC
|
||||||
|
}
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include-build-file:: inc/esp_hmac.inc
|
|
@ -11,6 +11,7 @@ Peripherals API
|
||||||
CAN <can>
|
CAN <can>
|
||||||
DAC <dac>
|
DAC <dac>
|
||||||
GPIO (including RTC low power I/O) <gpio>
|
GPIO (including RTC low power I/O) <gpio>
|
||||||
|
:esp32s2: HMAC <hmac>
|
||||||
I2C <i2c>
|
I2C <i2c>
|
||||||
I2S <i2s>
|
I2S <i2s>
|
||||||
LED Control <ledc>
|
LED Control <ledc>
|
||||||
|
|
2
docs/zh_CN/api-reference/peripherals/hmac.rst
Normal file
2
docs/zh_CN/api-reference/peripherals/hmac.rst
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.. include:: ../../../en/api-reference/peripherals/hmac.rst
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
CAN <can>
|
CAN <can>
|
||||||
DAC <dac>
|
DAC <dac>
|
||||||
GPIO (including RTC low power I/O) <gpio>
|
GPIO (including RTC low power I/O) <gpio>
|
||||||
|
:esp32s2: HMAC <hmac>
|
||||||
I2C <i2c>
|
I2C <i2c>
|
||||||
I2S <i2s>
|
I2S <i2s>
|
||||||
LED Control <ledc>
|
LED Control <ledc>
|
||||||
|
|
Loading…
Reference in a new issue