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 #include <stdint.h> 23 24 #ifdef __cplusplus 25 extern "C" 26 { 27 #endif 28 29 #define LIBCR51SIGN_SHA256_DIGEST_SIZE 32 30 #define LIBCR51SIGN_SHA512_DIGEST_SIZE 64 31 32 #define LIBCR51SIGN_MAX_REGION_COUNT 16 33 34 // Currently RSA4096 (in bytes). 35 #define LIBCR51SIGN_MAX_SIGNATURE_SIZE 512 36 37 // LINT.IfChange(image_mauv_max_size_def) 38 #define IMAGE_MAUV_DATA_MAX_SIZE (128) 39 // LINT.ThenChange() 40 41 // State of the image. 42 enum libcr51sign_validation_state 43 { 44 LIBCR51SIGN_IMAGE_UNSPECIFIED = 0, 45 // The image fails at least one descriptor or region check. 46 LIBCR51SIGN_IMAGE_INVALID = 1, 47 // The image passes all descriptor and region checks. Note that this does 48 // not mean that the image is valid for update. For example, the image may 49 // not pass MAUV checks. 50 LIBCR51SIGN_IMAGE_VALID = 2, 51 }; 52 53 // List of common error codes that can be returned 54 enum libcr51sign_validation_failure_reason 55 { 56 // All PayloadRegionState fields are valid & authenticated. 57 LIBCR51SIGN_SUCCESS = 0, 58 59 // Descriptor sanity check failed. None of the following 60 // PayloadRegionState fields are valid/populated. 61 LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1, 62 LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR = 2, 63 LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3, 64 65 // All fields are populated but may not be authentic. 66 LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4, 67 LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5, 68 LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED = 6, 69 LIBCR51SIGN_ERROR_UNTRUSTED_KEY = 7, 70 LIBCR51SIGN_ERROR_INVALID_SIGNATURE = 8, 71 LIBCR51SIGN_ERROR_INVALID_HASH = 9, 72 LIBCR51SIGN_ERROR_INVALID_HASH_TYPE = 10, 73 // Invalid argument 74 LIBCR51SIGN_ERROR_INVALID_ARGUMENT = 11, 75 LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC = 12, 76 LIBCR51SIGN_ERROR_INVALID_CONTEXT = 13, 77 LIBCR51SIGN_ERROR_INVALID_INTERFACE = 14, 78 LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME = 15, 79 // Invalid image region 80 LIBCR51SIGN_ERROR_INVALID_REGION_INPUT = 16, 81 LIBCR51SIGN_ERROR_INVALID_REGION_SIZE = 17, 82 LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA = 18, 83 LIBCR51SIGN_ERROR_RETRIEVING_STORED_IMAGE_MAUV_DATA = 19, 84 LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA = 20, 85 LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_DOES_NOT_ALLOW_UPDATE_TO_PAYLOAD = 21, 86 LIBCR51SIGN_ERROR_VALID_IMAGE_BUT_NEW_IMAGE_MAUV_DATA_NOT_STORED = 22, 87 LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_EXPECTS_PAYLOAD_IMAGE_MAUV = 23, 88 // Client did not find any stored MAUV in system 89 LIBCR51SIGN_NO_STORED_MAUV_FOUND = 24, 90 LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR_BLOBS = 25, 91 LIBCR51SIGN_ERROR_MAX = 26, 92 }; 93 94 struct libcr51sign_ctx 95 { 96 // Expectations needed to validate an image. Users must set these fields 97 // before calling libcr51sign_validate(). 98 uint32_t start_offset; // Absolute image start offset 99 uint32_t end_offset; // Absolute image end offset 100 enum image_family current_image_family; // Expected image family 101 enum image_type current_image_type; // Expected image type 102 int keyring_len; // keyring_len - number of keys in @a keyring 103 const void* keyring; // keyring - array of pointers to public keys 104 void* priv; // opaque context data (used for hash state) 105 106 // Data that is accessible if the image is valid after calling 107 // libcr51sign_validate(). 108 enum libcr51sign_validation_state validation_state; 109 size_t* valid_key; // valid_key - index of valid key 110 // Note: `descriptor` needs to be the last member of this struct due to the 111 // flexible array member in struct image_descriptor. 112 struct image_descriptor descriptor; // Cr51 image descriptor. 113 }; 114 115 struct libcr51sign_intf 116 { 117 // @func read read data from the image into a buffer 118 // 119 // @param[in] ctx - context struct 120 // @param[in] offset - bytes to seek into the image before reading 121 // @param[in] count - number of bytes to read 122 // @param[out] buf - pointer to buffer where result will be written 123 // 124 // @return nonzero on error, zero on success 125 126 int (*read)(const void*, uint32_t, uint32_t, uint8_t*); 127 128 // @func hash_init get ready to compute a hash 129 // 130 // @param[in] ctx - context struct 131 // @param[in] hash_type - type of hash function to use 132 // 133 // @return nonzero on error, zero on success 134 135 int (*hash_init)(const void*, enum hash_type); 136 137 // @func hash_update add data to the hash 138 // 139 // @param[in] ctx - context struct 140 // @param[in] buf - data to add to hash 141 // @param[in] count - number of bytes of data to add 142 // @param[in] hash_type - type of hash function to use 143 // 144 // @return nonzero on error, zero on success 145 146 int (*hash_update)(void*, const uint8_t*, size_t); 147 148 // Note this is a combination of an spi_nor_read() with spi_transaction() 149 // It is the responsibility of the caller to synchronize with other 150 // potential SPI clients / transactions. Collapsing the SPI stack results in 151 // a 2x throughput improvement (~20s -> ~10s to verify an Indus image with 152 // SHA256 HW acceleration). 153 // 154 // The caller is responsible for calling DCRYPTO_init()/HASH_final(). 155 156 int (*read_and_hash_update)(void* ctx, uint32_t offset, uint32_t size); 157 158 // @func hash_final finish hash calculation 159 // 160 // @param[in] ctx - context struct 161 // @param[out] hash - buffer to write hash to 162 // @param[in] hash_type - type of hash function to use 163 // 164 // @return nonzero on error, zero on success 165 166 int (*hash_final)(void*, uint8_t*); 167 168 // @func verify check that the signature is valid for given hashed data 169 // 170 // @param[in] ctx - context struct 171 // @param[in] scheme - type of signature, hash, etc. 172 // @param[in] sig - signature blob 173 // @param[in] sig_len - length of signature in bytes 174 // @param[in] data - pre-hashed data to verify 175 // @param[in] data_len - length of hashed data in bytes 176 // 177 // @return nonzero on error, zero on success 178 179 int (*verify_signature)(const void*, enum signature_scheme, const uint8_t*, 180 size_t, const uint8_t*, size_t); 181 182 // @func verify check that if the prod to dev downgrade/ hardware allowlist 183 // is allowed 184 // @return true: if allowed 185 // false: if not allowed 186 // BMC would return always false or pass a NULL pointer 187 // If NULL, treated as if the function always returns false. 188 189 bool (*prod_to_dev_downgrade_allowed)(); 190 191 // @func returns true if the current firmware is running in production mode. 192 // @return true: if in production mode 193 // false: if in any non-production mode 194 195 bool (*is_production_mode)(); 196 197 // @func returns true if the descriptor image size is valid. 198 bool (*image_size_valid)(size_t); 199 200 // @func Retrieve MAUV data currently stored in the system 201 // @param[in] ctx - context struct 202 // @param[out] current_image_mauv - Buffer to store the retrieved MAUV data 203 // @param[out] current_image_mauv_size - Number of bytes retrieved and 204 // stored 205 // in `current_image_mauv` 206 // @param[in] max_image_mauv_size - Maximum number of bytes to retrieve for 207 // MAUV data 208 // 209 // @return LIBCR51SIGN_SUCCESS: when MAUV is present in the system and 210 // retrieved successfully 211 // LIBCR51SIGN_NO_STORED_MAUV_FOUND: when MAUV is not present in the 212 // system (we are trusting the 213 // client here to return this 214 // value truthfully) 215 // other non-zero values: any other error scenario (like read 216 // failure, 217 // data corruption, etc.) 218 int (*retrieve_stored_image_mauv_data)(const void*, uint8_t* const, 219 uint32_t* const, const uint32_t); 220 221 // @func Store new MAUV data in the system 222 // @param[in] ctx - context struct 223 // @param[in] new_image_mauv - Buffer containing new MAUV data to be stored 224 // @param[in] new_image_mauv_size - Size of MAUV data in `new_image_mauv` 225 // buffer 226 // 227 // @return LIBCR51SIGN_SUCCESS: when new MAUV data is stored successfully. 228 // Non-zero value otherwise 229 int (*store_new_image_mauv_data)(const void*, const uint8_t* const, 230 const uint32_t); 231 232 // @func trust descriptor hash 233 // @param[in] ctx - context struct 234 // @param[in] descriptor_hash - Buffer containing descriptor hash 235 // @param[in] descriptor_hash_size - Size of descriptor hash 236 // 237 // @return true: if the external key is trusted 238 // false: if the external key is not trusted 239 bool (*trust_descriptor_hash)(const void*, const uint8_t*, size_t); 240 241 // @func Trust key in the signature structure 242 // @param[in] ctx - context struct 243 // @param[in] scheme - signature scheme 244 // @param[in] signature_structure - signature structure 245 // @param[in] signature_structure_size - Size of signature structure in 246 // bytes 247 // 248 // @return true: if the key in signature structure is trusted 249 // false: if the key in signature structure is not trusted 250 bool (*trust_key_in_signature_structure)( 251 void*, enum signature_scheme scheme, const void*, size_t); 252 253 // @func Verify RSA signature with modulus and exponent 254 // @param[in] ctx - context struct 255 // @param[in] sig_scheme - signature scheme 256 // @param[in] modulus - modulus of the RSA key, MSB (big-endian) 257 // @param[in] modulus_len - length of modulus in bytes 258 // @param[in] exponent - exponent of the RSA key 259 // @param[in] sig - signature blob 260 // @param[in] sig_len - length of signature in bytes 261 // @param[in] digest - digest to verify 262 // @param[in] digest_len - digest size 263 // 264 // @return true: if the signature is verified 265 // false: otherwise 266 bool (*verify_rsa_signature_with_modulus_and_exponent)( 267 const void* ctx, enum signature_scheme scheme, const uint8_t* modulus, 268 int modulus_len, uint32_t exponent, const uint8_t* sig, int sig_len, 269 const uint8_t* digest, int digest_len); 270 }; 271 272 struct libcr51sign_validated_regions 273 { 274 uint32_t region_count; 275 struct image_region image_regions[LIBCR51SIGN_MAX_REGION_COUNT]; 276 }; 277 278 // Check whether the signature on the image is valid. 279 // Validates the authenticity of an EEPROM image. Scans for & validates the 280 // signature on the image descriptor. If the descriptor validates, hashes the 281 // rest of the image to verify its integrity. 282 // 283 // @param[in] ctx - context which describes the image and holds opaque private 284 // data for the user of the library 285 // @param[in] intf - function pointers which interface to the current system 286 // and environment 287 // @param[out] image_regions - image_region pointer to an array for the output 288 // 289 // @return nonzero on error, zero on success 290 291 enum libcr51sign_validation_failure_reason libcr51sign_validate( 292 struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf, 293 struct libcr51sign_validated_regions* image_regions); 294 295 // Function to convert error code to string format 296 // @param[in] ec - error code 297 // @return error code in string format 298 299 const char* libcr51sign_errorcode_to_string( 300 enum libcr51sign_validation_failure_reason ec); 301 302 // Returns the hash_type for a given signature scheme 303 // @param[in] scheme - signature scheme 304 // @param[out] type - hash_type supported by given signature_scheme 305 // 306 // @return nonzero on error, zero on success 307 308 enum libcr51sign_validation_failure_reason get_hash_type_from_signature( 309 enum signature_scheme scheme, enum hash_type* type); 310 311 #ifdef __cplusplus 312 } // extern "C" 313 #endif 314 315 #endif // PLATFORMS_HAVEN_LIBCR51SIGN_LIBCR51SIGN_H_ 316