// SPDX-License-Identifier: GPL-2.01/*2* This is used to derive keys from the fscrypt master keys (or from the3* "software secrets" which hardware derives from the fscrypt master keys, in4* the case that the fscrypt master keys are hardware-wrapped keys).5*6* Copyright 2019 Google LLC7*/89#include <crypto/hash.h>10#include <crypto/hkdf.h>11#include <crypto/sha2.h>1213#include "fscrypt_private.h"1415/*16* HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses17* SHA-512 because it is well-established, secure, and reasonably efficient.18*19* HKDF-SHA256 was also considered, as its 256-bit security strength would be20* sufficient here. A 512-bit security strength is "nice to have", though.21* Also, on 64-bit CPUs, SHA-512 is usually just as fast as SHA-256. In the22* common case of deriving an AES-256-XTS key (512 bits), that can result in23* HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of24* SHA-512 causes HKDF-Expand to only need to do one iteration rather than two.25*/26#define HKDF_HMAC_ALG "hmac(sha512)"27#define HKDF_HASHLEN SHA512_DIGEST_SIZE2829/*30* HKDF consists of two steps:31*32* 1. HKDF-Extract: extract a pseudorandom key of length HKDF_HASHLEN bytes from33* the input keying material and optional salt.34* 2. HKDF-Expand: expand the pseudorandom key into output keying material of35* any length, parameterized by an application-specific info string.36*37* HKDF-Extract can be skipped if the input is already a pseudorandom key of38* length HKDF_HASHLEN bytes. However, cipher modes other than AES-256-XTS take39* shorter keys, and we don't want to force users of those modes to provide40* unnecessarily long master keys. Thus fscrypt still does HKDF-Extract. No41* salt is used, since fscrypt master keys should already be pseudorandom and42* there's no way to persist a random salt per master key from kernel mode.43*/4445/*46* Compute HKDF-Extract using the given master key as the input keying material,47* and prepare an HMAC transform object keyed by the resulting pseudorandom key.48*49* Afterwards, the keyed HMAC transform object can be used for HKDF-Expand many50* times without having to recompute HKDF-Extract each time.51*/52int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,53unsigned int master_key_size)54{55struct crypto_shash *hmac_tfm;56static const u8 default_salt[HKDF_HASHLEN];57u8 prk[HKDF_HASHLEN];58int err;5960hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, FSCRYPT_CRYPTOAPI_MASK);61if (IS_ERR(hmac_tfm)) {62fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld",63PTR_ERR(hmac_tfm));64return PTR_ERR(hmac_tfm);65}6667if (WARN_ON_ONCE(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) {68err = -EINVAL;69goto err_free_tfm;70}7172err = hkdf_extract(hmac_tfm, master_key, master_key_size,73default_salt, HKDF_HASHLEN, prk);74if (err)75goto err_free_tfm;7677err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk));78if (err)79goto err_free_tfm;8081hkdf->hmac_tfm = hmac_tfm;82goto out;8384err_free_tfm:85crypto_free_shash(hmac_tfm);86out:87memzero_explicit(prk, sizeof(prk));88return err;89}9091/*92* HKDF-Expand (RFC 5869 section 2.3). This expands the pseudorandom key, which93* was already keyed into 'hkdf->hmac_tfm' by fscrypt_init_hkdf(), into 'okmlen'94* bytes of output keying material parameterized by the application-specific95* 'info' of length 'infolen' bytes, prefixed by "fscrypt\0" and the 'context'96* byte. This is thread-safe and may be called by multiple threads in parallel.97*98* ('context' isn't part of the HKDF specification; it's just a prefix fscrypt99* adds to its application-specific info strings to guarantee that it doesn't100* accidentally repeat an info string when using HKDF for different purposes.)101*/102int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,103const u8 *info, unsigned int infolen,104u8 *okm, unsigned int okmlen)105{106SHASH_DESC_ON_STACK(desc, hkdf->hmac_tfm);107u8 *full_info;108int err;109110full_info = kzalloc(infolen + 9, GFP_KERNEL);111if (!full_info)112return -ENOMEM;113desc->tfm = hkdf->hmac_tfm;114115memcpy(full_info, "fscrypt\0", 8);116full_info[8] = context;117memcpy(full_info + 9, info, infolen);118119err = hkdf_expand(hkdf->hmac_tfm, full_info, infolen + 9,120okm, okmlen);121kfree_sensitive(full_info);122return err;123}124125void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf)126{127crypto_free_shash(hkdf->hmac_tfm);128}129130131