1*b13c0e40SEric Biggers /* SPDX-License-Identifier: MIT */ 2*b13c0e40SEric Biggers /* 3*b13c0e40SEric Biggers * libfsverity API 4*b13c0e40SEric Biggers * 5*b13c0e40SEric Biggers * Copyright 2018 Google LLC 6*b13c0e40SEric Biggers * Copyright (C) 2020 Facebook 7*b13c0e40SEric Biggers * 8*b13c0e40SEric Biggers * Use of this source code is governed by an MIT-style 9*b13c0e40SEric Biggers * license that can be found in the LICENSE file or at 10*b13c0e40SEric Biggers * https://opensource.org/licenses/MIT. 11*b13c0e40SEric Biggers */ 12*b13c0e40SEric Biggers 13*b13c0e40SEric Biggers #ifndef LIBFSVERITY_H 14*b13c0e40SEric Biggers #define LIBFSVERITY_H 15*b13c0e40SEric Biggers 16*b13c0e40SEric Biggers #include <errno.h> 17*b13c0e40SEric Biggers #include <stddef.h> 18*b13c0e40SEric Biggers #include <stdint.h> 19*b13c0e40SEric Biggers 20*b13c0e40SEric Biggers #ifdef __cplusplus 21*b13c0e40SEric Biggers extern "C" { 22*b13c0e40SEric Biggers #endif 23*b13c0e40SEric Biggers 24*b13c0e40SEric Biggers #define FSVERITY_UTILS_MAJOR_VERSION 1 25*b13c0e40SEric Biggers #define FSVERITY_UTILS_MINOR_VERSION 6 26*b13c0e40SEric Biggers 27*b13c0e40SEric Biggers #define FS_VERITY_HASH_ALG_SHA256 1 28*b13c0e40SEric Biggers #define FS_VERITY_HASH_ALG_SHA512 2 29*b13c0e40SEric Biggers 30*b13c0e40SEric Biggers /** 31*b13c0e40SEric Biggers * struct libfsverity_merkle_tree_params - properties of a file's Merkle tree 32*b13c0e40SEric Biggers * 33*b13c0e40SEric Biggers * Zero this, then fill in at least @version and @file_size. 34*b13c0e40SEric Biggers */ 35*b13c0e40SEric Biggers struct libfsverity_merkle_tree_params { 36*b13c0e40SEric Biggers 37*b13c0e40SEric Biggers /** @version: must be 1 */ 38*b13c0e40SEric Biggers uint32_t version; 39*b13c0e40SEric Biggers 40*b13c0e40SEric Biggers /** 41*b13c0e40SEric Biggers * @hash_algorithm: one of FS_VERITY_HASH_ALG_*, or 0 to use the default 42*b13c0e40SEric Biggers * of FS_VERITY_HASH_ALG_SHA256 43*b13c0e40SEric Biggers */ 44*b13c0e40SEric Biggers uint32_t hash_algorithm; 45*b13c0e40SEric Biggers 46*b13c0e40SEric Biggers /** @file_size: the file size in bytes */ 47*b13c0e40SEric Biggers uint64_t file_size; 48*b13c0e40SEric Biggers 49*b13c0e40SEric Biggers /** 50*b13c0e40SEric Biggers * @block_size: the Merkle tree block size in bytes, or 0 to use the 51*b13c0e40SEric Biggers * default of 4096 bytes 52*b13c0e40SEric Biggers */ 53*b13c0e40SEric Biggers uint32_t block_size; 54*b13c0e40SEric Biggers 55*b13c0e40SEric Biggers /** @salt_size: the salt size in bytes, or 0 if unsalted */ 56*b13c0e40SEric Biggers uint32_t salt_size; 57*b13c0e40SEric Biggers 58*b13c0e40SEric Biggers /** @salt: pointer to the salt, or NULL if unsalted */ 59*b13c0e40SEric Biggers const uint8_t *salt; 60*b13c0e40SEric Biggers 61*b13c0e40SEric Biggers /** @reserved1: must be 0 */ 62*b13c0e40SEric Biggers uint64_t reserved1[8]; 63*b13c0e40SEric Biggers 64*b13c0e40SEric Biggers /** 65*b13c0e40SEric Biggers * @metadata_callbacks: if non-NULL, this gives a set of callback 66*b13c0e40SEric Biggers * functions to which libfsverity_compute_digest() will pass the Merkle 67*b13c0e40SEric Biggers * tree blocks and fs-verity descriptor after they are computed. 68*b13c0e40SEric Biggers * Normally this isn't useful, but this can be needed in rare cases 69*b13c0e40SEric Biggers * where the metadata needs to be consumed by something other than one 70*b13c0e40SEric Biggers * of the native Linux kernel implementations of fs-verity. 71*b13c0e40SEric Biggers */ 72*b13c0e40SEric Biggers const struct libfsverity_metadata_callbacks *metadata_callbacks; 73*b13c0e40SEric Biggers 74*b13c0e40SEric Biggers /** @reserved2: must be 0 */ 75*b13c0e40SEric Biggers uintptr_t reserved2[7]; 76*b13c0e40SEric Biggers }; 77*b13c0e40SEric Biggers 78*b13c0e40SEric Biggers struct libfsverity_digest { 79*b13c0e40SEric Biggers uint16_t digest_algorithm; /* one of FS_VERITY_HASH_ALG_* */ 80*b13c0e40SEric Biggers uint16_t digest_size; /* digest size in bytes */ 81*b13c0e40SEric Biggers uint8_t digest[]; /* the actual digest */ 82*b13c0e40SEric Biggers }; 83*b13c0e40SEric Biggers 84*b13c0e40SEric Biggers /** 85*b13c0e40SEric Biggers * struct libfsverity_signature_params - certificate and private key information 86*b13c0e40SEric Biggers * 87*b13c0e40SEric Biggers * Zero this, then set @certfile. Then, to specify the private key by key file, 88*b13c0e40SEric Biggers * set @keyfile. Alternatively, to specify the private key by PKCS#11 token, 89*b13c0e40SEric Biggers * set @pkcs11_engine, @pkcs11_module, and optionally @pkcs11_keyid. 90*b13c0e40SEric Biggers * 91*b13c0e40SEric Biggers * Support for PKCS#11 tokens is unavailable when libfsverity was linked to 92*b13c0e40SEric Biggers * BoringSSL rather than OpenSSL. 93*b13c0e40SEric Biggers */ 94*b13c0e40SEric Biggers struct libfsverity_signature_params { 95*b13c0e40SEric Biggers 96*b13c0e40SEric Biggers /** @keyfile: the path to the key file in PEM format, when applicable */ 97*b13c0e40SEric Biggers const char *keyfile; 98*b13c0e40SEric Biggers 99*b13c0e40SEric Biggers /** @certfile: the path to the certificate file in PEM format */ 100*b13c0e40SEric Biggers const char *certfile; 101*b13c0e40SEric Biggers 102*b13c0e40SEric Biggers /** @reserved1: must be 0 */ 103*b13c0e40SEric Biggers uint64_t reserved1[8]; 104*b13c0e40SEric Biggers 105*b13c0e40SEric Biggers /** 106*b13c0e40SEric Biggers * @pkcs11_engine: the path to the PKCS#11 engine .so file, when 107*b13c0e40SEric Biggers * applicable 108*b13c0e40SEric Biggers */ 109*b13c0e40SEric Biggers const char *pkcs11_engine; 110*b13c0e40SEric Biggers 111*b13c0e40SEric Biggers /** 112*b13c0e40SEric Biggers * @pkcs11_module: the path to the PKCS#11 module .so file, when 113*b13c0e40SEric Biggers * applicable 114*b13c0e40SEric Biggers */ 115*b13c0e40SEric Biggers const char *pkcs11_module; 116*b13c0e40SEric Biggers 117*b13c0e40SEric Biggers /** @pkcs11_keyid: the PKCS#11 key identifier, when applicable */ 118*b13c0e40SEric Biggers const char *pkcs11_keyid; 119*b13c0e40SEric Biggers 120*b13c0e40SEric Biggers /** @reserved2: must be 0 */ 121*b13c0e40SEric Biggers uintptr_t reserved2[5]; 122*b13c0e40SEric Biggers }; 123*b13c0e40SEric Biggers 124*b13c0e40SEric Biggers struct libfsverity_metadata_callbacks { 125*b13c0e40SEric Biggers 126*b13c0e40SEric Biggers /** @ctx: context passed to the below callbacks (opaque to library) */ 127*b13c0e40SEric Biggers void *ctx; 128*b13c0e40SEric Biggers 129*b13c0e40SEric Biggers /** 130*b13c0e40SEric Biggers * @merkle_tree_size: if non-NULL, called with the total size of the 131*b13c0e40SEric Biggers * Merkle tree in bytes, prior to any call to @merkle_tree_block. Must 132*b13c0e40SEric Biggers * return 0 on success, or a negative errno value on failure. 133*b13c0e40SEric Biggers */ 134*b13c0e40SEric Biggers int (*merkle_tree_size)(void *ctx, uint64_t size); 135*b13c0e40SEric Biggers 136*b13c0e40SEric Biggers /** 137*b13c0e40SEric Biggers * @merkle_tree_block: if non-NULL, called with each block of the 138*b13c0e40SEric Biggers * Merkle tree after it is computed. The offset is the offset in bytes 139*b13c0e40SEric Biggers * to the block within the Merkle tree, using the Merkle tree layout 140*b13c0e40SEric Biggers * used by FS_IOC_READ_VERITY_METADATA. The offsets won't necessarily 141*b13c0e40SEric Biggers * be in increasing order. Must return 0 on success, or a negative 142*b13c0e40SEric Biggers * errno value on failure. 143*b13c0e40SEric Biggers */ 144*b13c0e40SEric Biggers int (*merkle_tree_block)(void *ctx, const void *block, size_t size, 145*b13c0e40SEric Biggers uint64_t offset); 146*b13c0e40SEric Biggers 147*b13c0e40SEric Biggers /** 148*b13c0e40SEric Biggers * @descriptor: if non-NULL, called with the fs-verity descriptor after 149*b13c0e40SEric Biggers * it is computed. Must return 0 on success, or a negative errno value 150*b13c0e40SEric Biggers * on failure. 151*b13c0e40SEric Biggers */ 152*b13c0e40SEric Biggers int (*descriptor)(void *ctx, const void *descriptor, size_t size); 153*b13c0e40SEric Biggers }; 154*b13c0e40SEric Biggers 155*b13c0e40SEric Biggers /* 156*b13c0e40SEric Biggers * libfsverity_read_fn_t - callback that incrementally provides a file's data 157*b13c0e40SEric Biggers * @fd: the user-provided "file descriptor" (opaque to library) 158*b13c0e40SEric Biggers * @buf: buffer into which to read the next chunk of the file's data 159*b13c0e40SEric Biggers * @count: number of bytes to read in this chunk 160*b13c0e40SEric Biggers * 161*b13c0e40SEric Biggers * Must return 0 on success (all 'count' bytes read), or a negative errno value 162*b13c0e40SEric Biggers * on failure. 163*b13c0e40SEric Biggers */ 164*b13c0e40SEric Biggers typedef int (*libfsverity_read_fn_t)(void *fd, void *buf, size_t count); 165*b13c0e40SEric Biggers 166*b13c0e40SEric Biggers /** 167*b13c0e40SEric Biggers * libfsverity_compute_digest() - Compute digest of a file 168*b13c0e40SEric Biggers * A fs-verity file digest is the hash of a file's fsverity_descriptor. 169*b13c0e40SEric Biggers * Not to be confused with a traditional file digest computed over the 170*b13c0e40SEric Biggers * entire file, or with the bare fsverity_descriptor::root_hash. 171*b13c0e40SEric Biggers * @fd: context that will be passed to @read_fn 172*b13c0e40SEric Biggers * @read_fn: a function that will read the data of the file 173*b13c0e40SEric Biggers * @params: Pointer to the Merkle tree parameters 174*b13c0e40SEric Biggers * @digest_ret: Pointer to pointer for computed digest. 175*b13c0e40SEric Biggers * 176*b13c0e40SEric Biggers * Returns: 177*b13c0e40SEric Biggers * * 0 for success, -EINVAL for invalid input arguments, -ENOMEM if libfsverity 178*b13c0e40SEric Biggers * failed to allocate memory, or an error returned by @read_fn or by one of 179*b13c0e40SEric Biggers * the @params->metadata_callbacks. 180*b13c0e40SEric Biggers * * digest_ret returns a pointer to the digest on success. The digest object 181*b13c0e40SEric Biggers * is allocated by libfsverity and must be freed by the caller using free(). 182*b13c0e40SEric Biggers */ 183*b13c0e40SEric Biggers int 184*b13c0e40SEric Biggers libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn, 185*b13c0e40SEric Biggers const struct libfsverity_merkle_tree_params *params, 186*b13c0e40SEric Biggers struct libfsverity_digest **digest_ret); 187*b13c0e40SEric Biggers 188*b13c0e40SEric Biggers /** 189*b13c0e40SEric Biggers * libfsverity_sign_digest() - Sign a file for built-in signature verification 190*b13c0e40SEric Biggers * Sign a file digest in a way that is compatible with the Linux 191*b13c0e40SEric Biggers * kernel's fs-verity built-in signature verification support. The 192*b13c0e40SEric Biggers * resulting signature will be a PKCS#7 message in DER format. Note 193*b13c0e40SEric Biggers * that this is not the only way to do signatures with fs-verity. For 194*b13c0e40SEric Biggers * more details, refer to the fsverity-utils README and to 195*b13c0e40SEric Biggers * Documentation/filesystems/fsverity.rst in the kernel source tree. 196*b13c0e40SEric Biggers * @digest: pointer to previously computed digest 197*b13c0e40SEric Biggers * @sig_params: pointer to the certificate and private key information 198*b13c0e40SEric Biggers * @sig_ret: Pointer to pointer for signed digest 199*b13c0e40SEric Biggers * @sig_size_ret: Pointer to size of signed return digest 200*b13c0e40SEric Biggers * 201*b13c0e40SEric Biggers * Return: 202*b13c0e40SEric Biggers * * 0 for success, -EINVAL for invalid input arguments or if the cryptographic 203*b13c0e40SEric Biggers * operations to sign the digest failed, -EBADMSG if the key and/or 204*b13c0e40SEric Biggers * certificate file is invalid, or another negative errno value. 205*b13c0e40SEric Biggers * * sig_ret returns a pointer to the signed digest on success. This object 206*b13c0e40SEric Biggers * is allocated by libfsverity and must be freed by the caller using free(). 207*b13c0e40SEric Biggers * * sig_size_ret returns the size (in bytes) of the signed digest on success. 208*b13c0e40SEric Biggers */ 209*b13c0e40SEric Biggers int 210*b13c0e40SEric Biggers libfsverity_sign_digest(const struct libfsverity_digest *digest, 211*b13c0e40SEric Biggers const struct libfsverity_signature_params *sig_params, 212*b13c0e40SEric Biggers uint8_t **sig_ret, size_t *sig_size_ret); 213*b13c0e40SEric Biggers 214*b13c0e40SEric Biggers /** 215*b13c0e40SEric Biggers * libfsverity_enable() - Enable fs-verity on a file 216*b13c0e40SEric Biggers * @fd: read-only file descriptor to the file 217*b13c0e40SEric Biggers * @params: pointer to the Merkle tree parameters 218*b13c0e40SEric Biggers * 219*b13c0e40SEric Biggers * This is a simple wrapper around the FS_IOC_ENABLE_VERITY ioctl. 220*b13c0e40SEric Biggers * 221*b13c0e40SEric Biggers * Return: 0 on success, -EINVAL for invalid arguments, or a negative errno 222*b13c0e40SEric Biggers * value from the FS_IOC_ENABLE_VERITY ioctl. See 223*b13c0e40SEric Biggers * Documentation/filesystems/fsverity.rst in the kernel source tree for 224*b13c0e40SEric Biggers * the possible error codes from FS_IOC_ENABLE_VERITY. 225*b13c0e40SEric Biggers */ 226*b13c0e40SEric Biggers int 227*b13c0e40SEric Biggers libfsverity_enable(int fd, const struct libfsverity_merkle_tree_params *params); 228*b13c0e40SEric Biggers 229*b13c0e40SEric Biggers /** 230*b13c0e40SEric Biggers * libfsverity_enable_with_sig() - Enable fs-verity on a file, with a signature 231*b13c0e40SEric Biggers * @fd: read-only file descriptor to the file 232*b13c0e40SEric Biggers * @params: pointer to the Merkle tree parameters 233*b13c0e40SEric Biggers * @sig: pointer to the file's signature 234*b13c0e40SEric Biggers * @sig_size: size of the file's signature in bytes 235*b13c0e40SEric Biggers * 236*b13c0e40SEric Biggers * Like libfsverity_enable(), but allows specifying a built-in signature (i.e. a 237*b13c0e40SEric Biggers * singature created with libfsverity_sign_digest()) to associate with the file. 238*b13c0e40SEric Biggers * This is only needed if the in-kernel signature verification support is being 239*b13c0e40SEric Biggers * used; it is not needed if signatures are being verified in userspace. 240*b13c0e40SEric Biggers * 241*b13c0e40SEric Biggers * If @sig is NULL and @sig_size is 0, this is the same as libfsverity_enable(). 242*b13c0e40SEric Biggers * 243*b13c0e40SEric Biggers * Return: See libfsverity_enable(). 244*b13c0e40SEric Biggers */ 245*b13c0e40SEric Biggers int 246*b13c0e40SEric Biggers libfsverity_enable_with_sig(int fd, 247*b13c0e40SEric Biggers const struct libfsverity_merkle_tree_params *params, 248*b13c0e40SEric Biggers const uint8_t *sig, size_t sig_size); 249*b13c0e40SEric Biggers 250*b13c0e40SEric Biggers /** 251*b13c0e40SEric Biggers * libfsverity_find_hash_alg_by_name() - Find hash algorithm by name 252*b13c0e40SEric Biggers * @name: Pointer to name of hash algorithm 253*b13c0e40SEric Biggers * 254*b13c0e40SEric Biggers * Return: The hash algorithm number, or zero if not found. 255*b13c0e40SEric Biggers */ 256*b13c0e40SEric Biggers uint32_t libfsverity_find_hash_alg_by_name(const char *name); 257*b13c0e40SEric Biggers 258*b13c0e40SEric Biggers /** 259*b13c0e40SEric Biggers * libfsverity_get_digest_size() - Get size of digest for a given algorithm 260*b13c0e40SEric Biggers * @alg_num: Number of hash algorithm 261*b13c0e40SEric Biggers * 262*b13c0e40SEric Biggers * Return: size of digest in bytes, or -1 if algorithm is unknown. 263*b13c0e40SEric Biggers */ 264*b13c0e40SEric Biggers int libfsverity_get_digest_size(uint32_t alg_num); 265*b13c0e40SEric Biggers 266*b13c0e40SEric Biggers /** 267*b13c0e40SEric Biggers * libfsverity_get_hash_name() - Get name of hash algorithm by number 268*b13c0e40SEric Biggers * @alg_num: Number of hash algorithm 269*b13c0e40SEric Biggers * 270*b13c0e40SEric Biggers * Return: The name of the hash algorithm, or NULL if algorithm is unknown. 271*b13c0e40SEric Biggers */ 272*b13c0e40SEric Biggers const char *libfsverity_get_hash_name(uint32_t alg_num); 273*b13c0e40SEric Biggers 274*b13c0e40SEric Biggers /** 275*b13c0e40SEric Biggers * libfsverity_set_error_callback() - Set callback to handle error messages 276*b13c0e40SEric Biggers * @cb: the callback function. 277*b13c0e40SEric Biggers * 278*b13c0e40SEric Biggers * If a callback is already set, it is replaced. @cb may be NULL in order to 279*b13c0e40SEric Biggers * remove the existing callback. 280*b13c0e40SEric Biggers */ 281*b13c0e40SEric Biggers void libfsverity_set_error_callback(void (*cb)(const char *msg)); 282*b13c0e40SEric Biggers 283*b13c0e40SEric Biggers #ifdef __cplusplus 284*b13c0e40SEric Biggers } 285*b13c0e40SEric Biggers #endif 286*b13c0e40SEric Biggers 287*b13c0e40SEric Biggers #endif /* LIBFSVERITY_H */ 288