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