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