1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef PLATFORMS_HAVEN_LIBCR51SIGN_LIBCR51SIGN_H_
17 #define PLATFORMS_HAVEN_LIBCR51SIGN_LIBCR51SIGN_H_
18 
19 #include <libcr51sign/cr51_image_descriptor.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 
23 #ifdef __cplusplus
24 extern "C"
25 {
26 #endif
27 
28 #define LIBCR51SIGN_SHA256_DIGEST_SIZE 32
29 #define LIBCR51SIGN_SHA512_DIGEST_SIZE 64
30 
31 #define LIBCR51SIGN_MAX_REGION_COUNT 16
32 
33 // Currently RSA4096 (in bytes).
34 #define LIBCR51SIGN_MAX_SIGNATURE_SIZE 512
35 
36 #define IMAGE_MAUV_DATA_MAX_SIZE (128)
37 
38 // List of common error codes that can be returned
39 enum libcr51sign_validation_failure_reason
40 {
41     // All PayloadRegionState fields are valid & authenticated.
42     LIBCR51SIGN_SUCCESS = 0,
43 
44     // Descriptor sanity check failed. None of the following
45     // PayloadRegionState fields are valid/populated.
46     LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
47     LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR = 2,
48     LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
49 
50     // All fields are populated but may not be authentic.
51     LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
52     LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
53     LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED = 6,
54     LIBCR51SIGN_ERROR_UNTRUSTED_KEY = 7,
55     LIBCR51SIGN_ERROR_INVALID_SIGNATURE = 8,
56     LIBCR51SIGN_ERROR_INVALID_HASH = 9,
57     LIBCR51SIGN_ERROR_INVALID_HASH_TYPE = 10,
58     // Invalid argument
59     LIBCR51SIGN_ERROR_INVALID_ARGUMENT = 11,
60     LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC = 12,
61     LIBCR51SIGN_ERROR_INVALID_CONTEXT = 13,
62     LIBCR51SIGN_ERROR_INVALID_INTERFACE = 14,
63     LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME = 15,
64     // Invalid image region
65     LIBCR51SIGN_ERROR_INVALID_REGION_INPUT = 16,
66     LIBCR51SIGN_ERROR_INVALID_REGION_SIZE = 17,
67     LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA = 18,
68     LIBCR51SIGN_ERROR_RETRIEVING_STORED_IMAGE_MAUV_DATA = 19,
69     LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA = 20,
70     LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_DOES_NOT_ALLOW_UPDATE_TO_PAYLOAD = 21,
71     LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED = 22,
72     LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_EXPECTS_PAYLOAD_IMAGE_MAUV = 23,
73     // Client did not find any stored MAUV in system
74     LIBCR51SIGN_NO_STORED_MAUV_FOUND = 24,
75     LIBCR51SIGN_ERROR_MAX = 25,
76 };
77 
78 struct libcr51sign_ctx
79 {
80     // Absolute image start offset
81     uint32_t start_offset;
82     // Absolute image end offset
83     uint32_t end_offset;
84     size_t block_size;
85     enum image_family current_image_family;
86     enum image_type current_image_type;
87     // keyring_len - number of keys in @a keyring
88     int keyring_len;
89     // valid_key - index of valid key on success
90     size_t* valid_key;
91     // keyring - array of pointers to public keys
92     const void* keyring;
93     void* priv;
94     struct image_descriptor descriptor;
95 };
96 
97 struct libcr51sign_intf
98 {
99     // @func read read data from the image into a buffer
100     //
101     // @param[in] ctx - context struct
102     // @param[in] offset - bytes to seek into the image before reading
103     // @param[in] count - number of bytes to read
104     // @param[out] buf - pointer to buffer where result will be written
105     //
106     // @return nonzero on error, zero on success
107 
108     int (*read)(const void*, uint32_t, uint32_t, uint8_t*);
109 
110     // @func hash_init get ready to compute a hash
111     //
112     // @param[in] ctx - context struct
113     // @param[in] hash_type - type of hash function to use
114     //
115     // @return nonzero on error, zero on success
116 
117     int (*hash_init)(const void*, enum hash_type);
118 
119     // @func hash_update add data to the hash
120     //
121     // @param[in] ctx - context struct
122     // @param[in] buf - data to add to hash
123     // @param[in] count - number of bytes of data to add
124     // @param[in] hash_type - type of hash function to use
125     //
126     // @return nonzero on error, zero on success
127 
128     int (*hash_update)(void*, const uint8_t*, size_t);
129 
130     // Note this is a combination of an spi_nor_read() with spi_transaction()
131     // It is the responsibility of the caller to synchronize with other
132     // potential SPI clients / transactions. Collapsing the SPI stack results in
133     // a 2x throughput improvement (~20s -> ~10s to verify an Indus image with
134     // SHA256 HW acceleration).
135     //
136     // The caller is responsible for calling DCRYPTO_init()/HASH_final().
137 
138     int (*read_and_hash_update)(void* ctx, uint32_t offset, uint32_t size);
139 
140     // @func hash_final finish hash calculation
141     //
142     // @param[in] ctx - context struct
143     // @param[out] hash - buffer to write hash to
144     // @param[in] hash_type - type of hash function to use
145     //
146     // @return nonzero on error, zero on success
147 
148     int (*hash_final)(void*, uint8_t*);
149 
150     // @func verify check that the signature is valid for given hashed data
151     //
152     // @param[in] ctx - context struct
153     // @param[in] scheme - type of signature, hash, etc.
154     // @param[in] sig - signature blob
155     // @param[in] sig_len - length of signature in bytes
156     // @param[in] data - pre-hashed data to verify
157     // @param[in] data_len - length of hashed data in bytes
158     //
159     // @return nonzero on error, zero on success
160 
161     int (*verify_signature)(const void*, enum signature_scheme, const uint8_t*,
162                             size_t, const uint8_t*, size_t);
163 
164     // @func verify check that if the prod to dev downgrade/ hardware allowlist
165     // is allowed
166     // @return  true: if allowed
167     //          false: if not allowed
168     // BMC would return always false or pass a NULL pointer
169     // If NULL, treated as if the function always returns false.
170 
171     bool (*prod_to_dev_downgrade_allowed)();
172 
173     // @func returns true if the current firmware is running in production mode.
174     // @return true: if in production mode
175     //         false: if in any non-production mode
176 
177     bool (*is_production_mode)();
178 
179     // @func returns true if the descriptor image size is valid.
180     bool (*image_size_valid)(size_t);
181 
182     // @func Retrieve MAUV data currently stored in the system
183     // @param[in]  ctx - context struct
184     // @param[out] current_image_mauv - Buffer to store the retrieved MAUV data
185     // @param[out] current_image_mauv_size - Number of bytes retrieved and
186     // stored
187     //                                       in `current_image_mauv`
188     // @param[in]  max_image_mauv_size - Maximum number of bytes to retrieve for
189     //                                   MAUV data
190     //
191     // @return LIBCR51SIGN_SUCCESS: when MAUV is present in the system and
192     //                              retrieved successfully
193     //         LIBCR51SIGN_NO_STORED_MAUV_FOUND: when MAUV is not present in the
194     //                                           system (we are trusting the
195     //                                           client here to return this
196     //                                           value truthfully)
197     //         other non-zero values: any other error scenario (like read
198     //         failure,
199     //                                data corruption, etc.)
200     int (*retrieve_stored_image_mauv_data)(const void*, uint8_t* const,
201                                            uint32_t* const, const uint32_t);
202 
203     // @func Store new MAUV data in the system
204     // @param[in]  ctx - context struct
205     // @param[in]  new_image_mauv - Buffer containing new MAUV data to be stored
206     // @param[in]  new_image_mauv_size - Size of MAUV data in `new_image_mauv`
207     //                                   buffer
208     //
209     // @return LIBCR51SIGN_SUCCESS: when new MAUV data is stored successfully.
210     //                              Non-zero value otherwise
211     int (*store_new_image_mauv_data)(const void*, const uint8_t* const,
212                                      const uint32_t);
213 };
214 
215 struct libcr51sign_validated_regions
216 {
217     uint32_t region_count;
218     struct image_region image_regions[LIBCR51SIGN_MAX_REGION_COUNT];
219 };
220 
221 // Check whether the signature on the image is valid.
222 // Validates the authenticity of an EEPROM image. Scans for & validates the
223 // signature on the image descriptor. If the descriptor validates, hashes the
224 // rest of the image to verify its integrity.
225 //
226 // @param[in] ctx - context which describes the image and holds opaque private
227 //                  data for the user of the library
228 // @param[in] intf - function pointers which interface to the current system
229 //                   and environment
230 // @param[out] image_regions - image_region pointer to an array for the output
231 //
232 // @return nonzero on error, zero on success
233 
234 enum libcr51sign_validation_failure_reason
235     libcr51sign_validate(const struct libcr51sign_ctx* ctx,
236                          struct libcr51sign_intf* intf,
237                          struct libcr51sign_validated_regions* image_regions);
238 
239 // Function to convert error code to string format
240 // @param[in] ec - error code
241 // @return error code in string format
242 
243 const char* libcr51sign_errorcode_to_string(
244     enum libcr51sign_validation_failure_reason ec);
245 
246 // Returns the hash_type for a given signature scheme
247 // @param[in] scheme - signature scheme
248 // @param[out] type - hash_type supported by given signature_scheme
249 //
250 // @return nonzero on error, zero on success
251 
252 enum libcr51sign_validation_failure_reason
253     get_hash_type_from_signature(enum signature_scheme scheme,
254                                  enum hash_type* type);
255 
256 #ifdef __cplusplus
257 } //  extern "C"
258 #endif
259 
260 #endif // PLATFORMS_HAVEN_LIBCR51SIGN_LIBCR51SIGN_H_
261