cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hkdf.c (5493B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation
      4 * Function"), aka RFC 5869.  See also the original paper (Krawczyk 2010):
      5 * "Cryptographic Extraction and Key Derivation: The HKDF Scheme".
      6 *
      7 * This is used to derive keys from the fscrypt master keys.
      8 *
      9 * Copyright 2019 Google LLC
     10 */
     11
     12#include <crypto/hash.h>
     13#include <crypto/sha2.h>
     14
     15#include "fscrypt_private.h"
     16
     17/*
     18 * HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses
     19 * SHA-512 because it is well-established, secure, and reasonably efficient.
     20 *
     21 * HKDF-SHA256 was also considered, as its 256-bit security strength would be
     22 * sufficient here.  A 512-bit security strength is "nice to have", though.
     23 * Also, on 64-bit CPUs, SHA-512 is usually just as fast as SHA-256.  In the
     24 * common case of deriving an AES-256-XTS key (512 bits), that can result in
     25 * HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of
     26 * SHA-512 causes HKDF-Expand to only need to do one iteration rather than two.
     27 */
     28#define HKDF_HMAC_ALG		"hmac(sha512)"
     29#define HKDF_HASHLEN		SHA512_DIGEST_SIZE
     30
     31/*
     32 * HKDF consists of two steps:
     33 *
     34 * 1. HKDF-Extract: extract a pseudorandom key of length HKDF_HASHLEN bytes from
     35 *    the input keying material and optional salt.
     36 * 2. HKDF-Expand: expand the pseudorandom key into output keying material of
     37 *    any length, parameterized by an application-specific info string.
     38 *
     39 * HKDF-Extract can be skipped if the input is already a pseudorandom key of
     40 * length HKDF_HASHLEN bytes.  However, cipher modes other than AES-256-XTS take
     41 * shorter keys, and we don't want to force users of those modes to provide
     42 * unnecessarily long master keys.  Thus fscrypt still does HKDF-Extract.  No
     43 * salt is used, since fscrypt master keys should already be pseudorandom and
     44 * there's no way to persist a random salt per master key from kernel mode.
     45 */
     46
     47/* HKDF-Extract (RFC 5869 section 2.2), unsalted */
     48static int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm,
     49			unsigned int ikmlen, u8 prk[HKDF_HASHLEN])
     50{
     51	static const u8 default_salt[HKDF_HASHLEN];
     52	int err;
     53
     54	err = crypto_shash_setkey(hmac_tfm, default_salt, HKDF_HASHLEN);
     55	if (err)
     56		return err;
     57
     58	return crypto_shash_tfm_digest(hmac_tfm, ikm, ikmlen, prk);
     59}
     60
     61/*
     62 * Compute HKDF-Extract using the given master key as the input keying material,
     63 * and prepare an HMAC transform object keyed by the resulting pseudorandom key.
     64 *
     65 * Afterwards, the keyed HMAC transform object can be used for HKDF-Expand many
     66 * times without having to recompute HKDF-Extract each time.
     67 */
     68int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
     69		      unsigned int master_key_size)
     70{
     71	struct crypto_shash *hmac_tfm;
     72	u8 prk[HKDF_HASHLEN];
     73	int err;
     74
     75	hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0);
     76	if (IS_ERR(hmac_tfm)) {
     77		fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld",
     78			    PTR_ERR(hmac_tfm));
     79		return PTR_ERR(hmac_tfm);
     80	}
     81
     82	if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) {
     83		err = -EINVAL;
     84		goto err_free_tfm;
     85	}
     86
     87	err = hkdf_extract(hmac_tfm, master_key, master_key_size, prk);
     88	if (err)
     89		goto err_free_tfm;
     90
     91	err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk));
     92	if (err)
     93		goto err_free_tfm;
     94
     95	hkdf->hmac_tfm = hmac_tfm;
     96	goto out;
     97
     98err_free_tfm:
     99	crypto_free_shash(hmac_tfm);
    100out:
    101	memzero_explicit(prk, sizeof(prk));
    102	return err;
    103}
    104
    105/*
    106 * HKDF-Expand (RFC 5869 section 2.3).  This expands the pseudorandom key, which
    107 * was already keyed into 'hkdf->hmac_tfm' by fscrypt_init_hkdf(), into 'okmlen'
    108 * bytes of output keying material parameterized by the application-specific
    109 * 'info' of length 'infolen' bytes, prefixed by "fscrypt\0" and the 'context'
    110 * byte.  This is thread-safe and may be called by multiple threads in parallel.
    111 *
    112 * ('context' isn't part of the HKDF specification; it's just a prefix fscrypt
    113 * adds to its application-specific info strings to guarantee that it doesn't
    114 * accidentally repeat an info string when using HKDF for different purposes.)
    115 */
    116int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
    117			const u8 *info, unsigned int infolen,
    118			u8 *okm, unsigned int okmlen)
    119{
    120	SHASH_DESC_ON_STACK(desc, hkdf->hmac_tfm);
    121	u8 prefix[9];
    122	unsigned int i;
    123	int err;
    124	const u8 *prev = NULL;
    125	u8 counter = 1;
    126	u8 tmp[HKDF_HASHLEN];
    127
    128	if (WARN_ON(okmlen > 255 * HKDF_HASHLEN))
    129		return -EINVAL;
    130
    131	desc->tfm = hkdf->hmac_tfm;
    132
    133	memcpy(prefix, "fscrypt\0", 8);
    134	prefix[8] = context;
    135
    136	for (i = 0; i < okmlen; i += HKDF_HASHLEN) {
    137
    138		err = crypto_shash_init(desc);
    139		if (err)
    140			goto out;
    141
    142		if (prev) {
    143			err = crypto_shash_update(desc, prev, HKDF_HASHLEN);
    144			if (err)
    145				goto out;
    146		}
    147
    148		err = crypto_shash_update(desc, prefix, sizeof(prefix));
    149		if (err)
    150			goto out;
    151
    152		err = crypto_shash_update(desc, info, infolen);
    153		if (err)
    154			goto out;
    155
    156		BUILD_BUG_ON(sizeof(counter) != 1);
    157		if (okmlen - i < HKDF_HASHLEN) {
    158			err = crypto_shash_finup(desc, &counter, 1, tmp);
    159			if (err)
    160				goto out;
    161			memcpy(&okm[i], tmp, okmlen - i);
    162			memzero_explicit(tmp, sizeof(tmp));
    163		} else {
    164			err = crypto_shash_finup(desc, &counter, 1, &okm[i]);
    165			if (err)
    166				goto out;
    167		}
    168		counter++;
    169		prev = &okm[i];
    170	}
    171	err = 0;
    172out:
    173	if (unlikely(err))
    174		memzero_explicit(okm, okmlen); /* so caller doesn't need to */
    175	shash_desc_zero(desc);
    176	return err;
    177}
    178
    179void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf)
    180{
    181	crypto_free_shash(hkdf->hmac_tfm);
    182}