11// SPDX-License-Identifier: GPL-2.0
22/*
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+ *
37 * This is used to derive keys from the fscrypt master keys (or from the
48 * "software secrets" which hardware derives from the fscrypt master keys, in
59 * the case that the fscrypt master keys are hardware-wrapped keys).
610 *
711 * Copyright 2019 Google LLC
812 */
913
10- #include <crypto/hash.h>
11- #include <crypto/hkdf.h>
12- #include <crypto/sha2.h>
13-
1414#include "fscrypt_private.h"
1515
1616/*
2424 * HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of
2525 * SHA-512 causes HKDF-Expand to only need to do one iteration rather than two.
2626 */
27- #define HKDF_HMAC_ALG "hmac(sha512)"
2827#define HKDF_HASHLEN SHA512_DIGEST_SIZE
2928
3029/*
4443 */
4544
4645/*
47- * Compute HKDF-Extract using the given master key as the input keying material,
48- * and prepare an HMAC transform object keyed by the resulting pseudorandom key.
49- *
50- * Afterwards, the keyed HMAC transform object can be used for HKDF-Expand many
51- * times without having to recompute HKDF-Extract each time.
46+ * Compute HKDF-Extract using 'master_key' as the input keying material, and
47+ * prepare the resulting HMAC key in 'hkdf'. Afterwards, 'hkdf' can be used for
48+ * HKDF-Expand many times without having to recompute HKDF-Extract each time.
5249 */
53- int fscrypt_init_hkdf (struct fscrypt_hkdf * hkdf , const u8 * master_key ,
54- unsigned int master_key_size )
50+ void fscrypt_init_hkdf (struct hmac_sha512_key * hkdf , const u8 * master_key ,
51+ unsigned int master_key_size )
5552{
56- struct crypto_shash * hmac_tfm ;
5753 static const u8 default_salt [HKDF_HASHLEN ];
5854 u8 prk [HKDF_HASHLEN ];
59- int err ;
60-
61- hmac_tfm = crypto_alloc_shash (HKDF_HMAC_ALG , 0 , FSCRYPT_CRYPTOAPI_MASK );
62- if (IS_ERR (hmac_tfm )) {
63- fscrypt_err (NULL , "Error allocating " HKDF_HMAC_ALG ": %ld" ,
64- PTR_ERR (hmac_tfm ));
65- return PTR_ERR (hmac_tfm );
66- }
67-
68- if (WARN_ON_ONCE (crypto_shash_digestsize (hmac_tfm ) != sizeof (prk ))) {
69- err = - EINVAL ;
70- goto err_free_tfm ;
71- }
72-
73- err = hkdf_extract (hmac_tfm , master_key , master_key_size ,
74- default_salt , HKDF_HASHLEN , prk );
75- if (err )
76- goto err_free_tfm ;
77-
78- err = crypto_shash_setkey (hmac_tfm , prk , sizeof (prk ));
79- if (err )
80- goto err_free_tfm ;
8155
82- hkdf -> hmac_tfm = hmac_tfm ;
83- goto out ;
84-
85- err_free_tfm :
86- crypto_free_shash (hmac_tfm );
87- out :
56+ hmac_sha512_usingrawkey (default_salt , sizeof (default_salt ),
57+ master_key , master_key_size , prk );
58+ hmac_sha512_preparekey (hkdf , prk , sizeof (prk ));
8859 memzero_explicit (prk , sizeof (prk ));
89- return err ;
9060}
9161
9262/*
93- * HKDF-Expand (RFC 5869 section 2.3). This expands the pseudorandom key, which
94- * was already keyed into 'hkdf->hmac_tfm' by fscrypt_init_hkdf(), into 'okmlen'
63+ * HKDF-Expand (RFC 5869 section 2.3). Expand the HMAC key 'hkdf' into 'okmlen'
9564 * bytes of output keying material parameterized by the application-specific
9665 * 'info' of length 'infolen' bytes, prefixed by "fscrypt\0" and the 'context'
9766 * byte. This is thread-safe and may be called by multiple threads in parallel.
@@ -100,30 +69,32 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
10069 * adds to its application-specific info strings to guarantee that it doesn't
10170 * accidentally repeat an info string when using HKDF for different purposes.)
10271 */
103- int fscrypt_hkdf_expand (const struct fscrypt_hkdf * hkdf , u8 context ,
104- const u8 * info , unsigned int infolen ,
105- u8 * okm , unsigned int okmlen )
106- {
107- SHASH_DESC_ON_STACK (desc , hkdf -> hmac_tfm );
108- u8 * full_info ;
109- int err ;
110-
111- full_info = kzalloc (infolen + 9 , GFP_KERNEL );
112- if (!full_info )
113- return - ENOMEM ;
114- desc -> tfm = hkdf -> hmac_tfm ;
115-
116- memcpy (full_info , "fscrypt\0" , 8 );
117- full_info [8 ] = context ;
118- memcpy (full_info + 9 , info , infolen );
119-
120- err = hkdf_expand (hkdf -> hmac_tfm , full_info , infolen + 9 ,
121- okm , okmlen );
122- kfree_sensitive (full_info );
123- return err ;
124- }
125-
126- void fscrypt_destroy_hkdf (struct fscrypt_hkdf * hkdf )
72+ void fscrypt_hkdf_expand (const struct hmac_sha512_key * hkdf , u8 context ,
73+ const u8 * info , unsigned int infolen ,
74+ u8 * okm , unsigned int okmlen )
12775{
128- crypto_free_shash (hkdf -> hmac_tfm );
76+ struct hmac_sha512_ctx ctx ;
77+ u8 counter = 1 ;
78+ u8 tmp [HKDF_HASHLEN ];
79+
80+ WARN_ON_ONCE (okmlen > 255 * HKDF_HASHLEN );
81+
82+ for (unsigned int i = 0 ; i < okmlen ; i += HKDF_HASHLEN ) {
83+ hmac_sha512_init (& ctx , hkdf );
84+ if (i != 0 )
85+ hmac_sha512_update (& ctx , & okm [i - HKDF_HASHLEN ],
86+ HKDF_HASHLEN );
87+ hmac_sha512_update (& ctx , "fscrypt\0" , 8 );
88+ hmac_sha512_update (& ctx , & context , 1 );
89+ hmac_sha512_update (& ctx , info , infolen );
90+ hmac_sha512_update (& ctx , & counter , 1 );
91+ if (okmlen - i < HKDF_HASHLEN ) {
92+ hmac_sha512_final (& ctx , tmp );
93+ memcpy (& okm [i ], tmp , okmlen - i );
94+ memzero_explicit (tmp , sizeof (tmp ));
95+ } else {
96+ hmac_sha512_final (& ctx , & okm [i ]);
97+ }
98+ counter ++ ;
99+ }
129100}
0 commit comments