1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * SPDX-License-Identifier: MIT 5 */ 6 7 #if !defined(AVB_INSIDE_LIBAVB_H) && !defined(AVB_COMPILATION) 8 #error "Never include this file directly, include libavb.h instead." 9 #endif 10 11 #ifndef AVB_OPS_H_ 12 #define AVB_OPS_H_ 13 14 #include "avb_sysdeps.h" 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 /* Well-known names of named persistent values. */ 21 #define AVB_NPV_PERSISTENT_DIGEST_PREFIX "avb.persistent_digest." 22 23 /* Return codes used for I/O operations. 24 * 25 * AVB_IO_RESULT_OK is returned if the requested operation was 26 * successful. 27 * 28 * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk 29 * or other subsystem) encountered an I/O error. 30 * 31 * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory. 32 * 33 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested 34 * partition does not exist. 35 * 36 * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the 37 * range of bytes requested to be read or written is outside the range 38 * of the partition. 39 * 40 * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE is returned if a named persistent value 41 * does not exist. 42 * 43 * AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE is returned if a named persistent 44 * value size is not supported or does not match the expected size. 45 * 46 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned if a buffer is too small 47 * for the requested operation. 48 */ 49 typedef enum { 50 AVB_IO_RESULT_OK, 51 AVB_IO_RESULT_ERROR_OOM, 52 AVB_IO_RESULT_ERROR_IO, 53 AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, 54 AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION, 55 AVB_IO_RESULT_ERROR_NO_SUCH_VALUE, 56 AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE, 57 AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, 58 } AvbIOResult; 59 60 struct AvbOps; 61 typedef struct AvbOps AvbOps; 62 63 /* Forward-declaration of operations in libavb_ab. */ 64 struct AvbABOps; 65 66 /* Forward-declaration of operations in libavb_atx. */ 67 struct AvbAtxOps; 68 69 /* High-level operations/functions/methods that are platform 70 * dependent. 71 * 72 * Operations may be added in the future so when implementing it 73 * always make sure to zero out sizeof(AvbOps) bytes of the struct to 74 * ensure that unimplemented operations are set to NULL. 75 */ 76 struct AvbOps { 77 /* This pointer can be used by the application/bootloader using 78 * libavb and is typically used in each operation to get a pointer 79 * to platform-specific resources. It cannot be used by libraries. 80 */ 81 void* user_data; 82 83 /* If libavb_ab is used, this should point to the 84 * AvbABOps. Otherwise it must be set to NULL. 85 */ 86 struct AvbABOps* ab_ops; 87 88 /* If libavb_atx is used, this should point to the 89 * AvbAtxOps. Otherwise it must be set to NULL. 90 */ 91 struct AvbAtxOps* atx_ops; 92 93 /* Reads |num_bytes| from offset |offset| from partition with name 94 * |partition| (NUL-terminated UTF-8 string). If |offset| is 95 * negative, its absolute value should be interpreted as the number 96 * of bytes from the end of the partition. 97 * 98 * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if 99 * there is no partition with the given name, 100 * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested 101 * |offset| is outside the partition, and AVB_IO_RESULT_ERROR_IO if 102 * there was an I/O error from the underlying I/O subsystem. If the 103 * operation succeeds as requested AVB_IO_RESULT_OK is returned and 104 * the data is available in |buffer|. 105 * 106 * The only time partial I/O may occur is if reading beyond the end 107 * of the partition. In this case the value returned in 108 * |out_num_read| may be smaller than |num_bytes|. 109 */ 110 AvbIOResult (*read_from_partition)(AvbOps* ops, 111 const char* partition, 112 int64_t offset, 113 size_t num_bytes, 114 void* buffer, 115 size_t* out_num_read); 116 117 /* Gets the starting pointer of a partition that is pre-loaded in memory, and 118 * save it to |out_pointer|. The preloaded partition is expected to be 119 * |num_bytes|, where the actual preloaded byte count is returned in 120 * |out_num_bytes_preloaded|. |out_num_bytes_preloaded| must be no larger than 121 * |num_bytes|. 122 * 123 * This provides an alternative way to access a partition that is preloaded 124 * into memory without a full memory copy. When this function pointer is not 125 * set (has value NULL), or when the |out_pointer| is set to NULL as a result, 126 * |read_from_partition| will be used as the fallback. This function is mainly 127 * used for accessing the entire partition content to calculate its hash. 128 * 129 * Preloaded partition data must outlive the lifespan of the 130 * |AvbSlotVerifyData| structure that |avb_slot_verify| outputs. 131 */ 132 AvbIOResult (*get_preloaded_partition)(AvbOps* ops, 133 const char* partition, 134 size_t num_bytes, 135 uint8_t** out_pointer, 136 size_t* out_num_bytes_preloaded); 137 138 /* Writes |num_bytes| from |bffer| at offset |offset| to partition 139 * with name |partition| (NUL-terminated UTF-8 string). If |offset| 140 * is negative, its absolute value should be interpreted as the 141 * number of bytes from the end of the partition. 142 * 143 * This function returns AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION if 144 * there is no partition with the given name, 145 * AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION if the requested 146 * byterange goes outside the partition, and AVB_IO_RESULT_ERROR_IO 147 * if there was an I/O error from the underlying I/O subsystem. If 148 * the operation succeeds as requested AVB_IO_RESULT_OK is 149 * returned. 150 * 151 * This function never does any partial I/O, it either transfers all 152 * of the requested bytes or returns an error. 153 */ 154 AvbIOResult (*write_to_partition)(AvbOps* ops, 155 const char* partition, 156 int64_t offset, 157 size_t num_bytes, 158 const void* buffer); 159 160 /* Checks if the given public key used to sign the 'vbmeta' 161 * partition is trusted. Boot loaders typically compare this with 162 * embedded key material generated with 'avbtool 163 * extract_public_key'. 164 * 165 * The public key is in the array pointed to by |public_key_data| 166 * and is of |public_key_length| bytes. 167 * 168 * If there is no public key metadata (set with the avbtool option 169 * --public_key_metadata) then |public_key_metadata| will be set to 170 * NULL. Otherwise this field points to the data which is 171 * |public_key_metadata_length| bytes long. 172 * 173 * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set - 174 * true if trusted or false if untrusted. 175 */ 176 AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops, 177 const uint8_t* public_key_data, 178 size_t public_key_length, 179 const uint8_t* public_key_metadata, 180 size_t public_key_metadata_length, 181 bool* out_is_trusted); 182 183 /* Gets the rollback index corresponding to the location given by 184 * |rollback_index_location|. The value is returned in 185 * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback 186 * index was retrieved, otherwise an error code. 187 * 188 * A device may have a limited amount of rollback index locations (say, 189 * one or four) so may error out if |rollback_index_location| exceeds 190 * this number. 191 */ 192 AvbIOResult (*read_rollback_index)(AvbOps* ops, 193 size_t rollback_index_location, 194 uint64_t* out_rollback_index); 195 196 /* Sets the rollback index corresponding to the location given by 197 * |rollback_index_location| to |rollback_index|. Returns 198 * AVB_IO_RESULT_OK if the rollback index was set, otherwise an 199 * error code. 200 * 201 * A device may have a limited amount of rollback index locations (say, 202 * one or four) so may error out if |rollback_index_location| exceeds 203 * this number. 204 */ 205 AvbIOResult (*write_rollback_index)(AvbOps* ops, 206 size_t rollback_index_location, 207 uint64_t rollback_index); 208 209 /* Gets whether the device is unlocked. The value is returned in 210 * |out_is_unlocked| (true if unlocked, false otherwise). Returns 211 * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error 212 * code. 213 */ 214 AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked); 215 216 /* Gets the unique partition GUID for a partition with name in 217 * |partition| (NUL-terminated UTF-8 string). The GUID is copied as 218 * a string into |guid_buf| of size |guid_buf_size| and will be NUL 219 * terminated. The string must be lower-case and properly 220 * hyphenated. For example: 221 * 222 * 527c1c6d-6361-4593-8842-3c78fcd39219 223 * 224 * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 225 */ 226 AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops, 227 const char* partition, 228 char* guid_buf, 229 size_t guid_buf_size); 230 231 /* Gets the size of a partition with the name in |partition| 232 * (NUL-terminated UTF-8 string). Returns the value in 233 * |out_size_num_bytes|. 234 * 235 * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 236 */ 237 AvbIOResult (*get_size_of_partition)(AvbOps* ops, 238 const char* partition, 239 uint64_t* out_size_num_bytes); 240 241 /* Reads a persistent value corresponding to the given |name|. The value is 242 * returned in |out_buffer| which must point to |buffer_size| bytes. On 243 * success |out_num_bytes_read| contains the number of bytes read into 244 * |out_buffer|. If AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE is returned, 245 * |out_num_bytes_read| contains the number of bytes that would have been read 246 * which can be used to allocate a buffer. 247 * 248 * The |buffer_size| may be zero and the |out_buffer| may be NULL, but if 249 * |out_buffer| is NULL then |buffer_size| *must* be zero. 250 * 251 * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 252 * 253 * If the value does not exist, is not supported, or is not populated, returns 254 * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If |buffer_size| is smaller than the 255 * size of the stored value, returns AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE. 256 * 257 * This operation is currently only used to support persistent digests. If a 258 * device does not use persistent digests this function pointer can be set to 259 * NULL. 260 */ 261 AvbIOResult (*read_persistent_value)(AvbOps* ops, 262 const char* name, 263 size_t buffer_size, 264 uint8_t* out_buffer, 265 size_t* out_num_bytes_read); 266 267 /* Writes a persistent value corresponding to the given |name|. The value is 268 * supplied in |value| which must point to |value_size| bytes. Any existing 269 * value with the same name is overwritten. If |value_size| is zero, future 270 * calls to |read_persistent_value| will return 271 * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. 272 * 273 * Returns AVB_IO_RESULT_OK on success, otherwise an error code. 274 * 275 * If the value |name| is not supported, returns 276 * AVB_IO_RESULT_ERROR_NO_SUCH_VALUE. If the |value_size| is not supported, 277 * returns AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE. 278 * 279 * This operation is currently only used to support persistent digests. If a 280 * device does not use persistent digests this function pointer can be set to 281 * NULL. 282 */ 283 AvbIOResult (*write_persistent_value)(AvbOps* ops, 284 const char* name, 285 size_t value_size, 286 const uint8_t* value); 287 }; 288 289 #ifdef __cplusplus 290 } 291 #endif 292 293 #endif /* AVB_OPS_H_ */ 294