1 /*
2  * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 #include <stdint.h>
14 #include <stdbool.h>
15 
16 #define ETS_DS_MAX_BITS 3072
17 
18 #define ETS_DS_IV_LEN 16
19 
20 /* Length of parameter 'C' stored in flash (not including IV)
21 
22    Comprises encrypted Y, M, rinv, md (32), mprime (4), length (4), padding (8)
23 
24    Note that if ETS_DS_MAX_BITS<4096, 'C' needs to be split up when writing to hardware
25 */
26 #define ETS_DS_C_LEN ((ETS_DS_MAX_BITS * 3 / 8) + 32 + 8 + 8)
27 
28 /* Encrypted ETS data. Recommended to store in flash in this format.
29  */
30 typedef struct {
31     /* RSA LENGTH register parameters
32      * (number of words in RSA key & operands, minus one).
33      *
34      *
35      * This value must match the length field encrypted and stored in 'c',
36      * or invalid results will be returned. (The DS peripheral will
37      * always use the value in 'c', not this value, so an attacker can't
38      * alter the DS peripheral results this way, it will just truncate or
39      * extend the message and the resulting signature in software.)
40      */
41     unsigned rsa_length;
42 
43     /* IV value used to encrypt 'c' */
44     uint8_t iv[ETS_DS_IV_LEN];
45 
46     /* Encrypted Digital Signature parameters. Result of AES-CBC encryption
47        of plaintext values. Includes an encrypted message digest.
48     */
49     uint8_t c[ETS_DS_C_LEN];
50 } ets_ds_data_t;
51 
52 typedef enum {
53     ETS_DS_OK,
54     ETS_DS_INVALID_PARAM,   /* Supplied parameters are invalid */
55     ETS_DS_INVALID_KEY,     /* HMAC peripheral failed to supply key */
56     ETS_DS_INVALID_PADDING, /* 'c' decrypted with invalid padding */
57     ETS_DS_INVALID_DIGEST,  /* 'c' decrypted with invalid digest */
58 } ets_ds_result_t;
59 
60 void ets_ds_enable(void);
61 
62 void ets_ds_disable(void);
63 
64 
65 /*
66  * @brief Start signing a message (or padded message digest) using the Digital Signature peripheral
67  *
68  * - @param message Pointer to message (or padded digest) containing the message to sign. Should be
69  *   (data->rsa_length + 1)*4 bytes long.  @param data Pointer to DS data. Can be a pointer to data
70  *   in flash.
71  *
72  * Caller must have already called ets_ds_enable() and ets_hmac_calculate_downstream() before calling
73  * this function, and is responsible for calling ets_ds_finish_sign() and then
74  * ets_hmac_invalidate_downstream() afterwards.
75  *
76  * @return ETS_DS_OK if signature is in progress, ETS_DS_INVALID_PARAM if param is invalid,
77  * EST_DS_INVALID_KEY if key or HMAC peripheral is configured incorrectly.
78  */
79 ets_ds_result_t ets_ds_start_sign(const void *message, const ets_ds_data_t *data);
80 
81 
82 /*
83  * @brief Returns true if the DS peripheral is busy following a call to ets_ds_start_sign()
84  *
85  * A result of false indicates that a call to ets_ds_finish_sign() will not block.
86  *
87  * Only valid if ets_ds_enable() has been called.
88  */
89 bool ets_ds_is_busy(void);
90 
91 
92 /* @brief Finish signing a message using the Digital Signature peripheral
93  *
94  * Must be called after ets_ds_start_sign(). Can use ets_ds_busy() to wait until
95  * peripheral is no longer busy.
96  *
97  * - @param signature Pointer to buffer to contain the signature. Should be
98  *   (data->rsa_length + 1)*4 bytes long.
99  * - @param data Should match the 'data' parameter passed to ets_ds_start_sign()
100  *
101  * @param ETS_DS_OK if signing succeeded, ETS_DS_INVALID_PARAM if param is invalid,
102  * ETS_DS_INVALID_DIGEST or ETS_DS_INVALID_PADDING if there is a problem with the
103  * encrypted data digest or padding bytes (in case of ETS_DS_INVALID_PADDING, a
104  * digest is produced anyhow.)
105  */
106 ets_ds_result_t ets_ds_finish_sign(void *signature, const ets_ds_data_t *data);
107 
108 
109 /* Plaintext parameters used by Digital Signature.
110 
111    Not used for signing with DS peripheral, but can be encrypted
112    in-device by calling ets_ds_encrypt_params()
113 */
114 typedef struct {
115     uint32_t Y[ETS_DS_MAX_BITS / 32];
116     uint32_t M[ETS_DS_MAX_BITS / 32];
117     uint32_t Rb[ETS_DS_MAX_BITS / 32];
118     uint32_t M_prime;
119     uint32_t length;
120 } ets_ds_p_data_t;
121 
122 typedef enum {
123     ETS_DS_KEY_HMAC, /* The HMAC key (as stored in efuse) */
124     ETS_DS_KEY_AES,  /* The AES key (as derived from HMAC key by HMAC peripheral in downstream mode) */
125 } ets_ds_key_t;
126 
127 /* @brief Encrypt DS parameters suitable for storing and later use with DS peripheral
128  *
129  * @param data Output buffer to store encrypted data, suitable for later use generating signatures.
130  * @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
131  * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process is done and 'data' is stored.
132  * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the corresponding HMAC key will be stored to efuse and then permanently erased.
133  * @param key_type Type of key stored in 'key' (either the AES-256 DS key, or an HMAC DS key from which the AES DS key is derived using HMAC peripheral)
134  *
135  * @return ETS_DS_INVALID_PARAM if any parameter is invalid, or ETS_DS_OK if 'data' is successfully generated from the input parameters.
136  */
137 ets_ds_result_t ets_ds_encrypt_params(ets_ds_data_t *data, const void *iv, const ets_ds_p_data_t *p_data, const void *key, ets_ds_key_t key_type);
138 
139 
140 #ifdef __cplusplus
141 }
142 #endif
143