13241cd0cSHannes Reinecke // SPDX-License-Identifier: GPL-2.0
23241cd0cSHannes Reinecke /*
33241cd0cSHannes Reinecke * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation
43241cd0cSHannes Reinecke * Function"), aka RFC 5869. See also the original paper (Krawczyk 2010):
53241cd0cSHannes Reinecke * "Cryptographic Extraction and Key Derivation: The HKDF Scheme".
63241cd0cSHannes Reinecke *
73241cd0cSHannes Reinecke * Copyright 2019 Google LLC
83241cd0cSHannes Reinecke */
93241cd0cSHannes Reinecke
103241cd0cSHannes Reinecke #include <crypto/internal/hash.h>
113241cd0cSHannes Reinecke #include <crypto/sha2.h>
123241cd0cSHannes Reinecke #include <crypto/hkdf.h>
133241cd0cSHannes Reinecke #include <linux/module.h>
143241cd0cSHannes Reinecke
153241cd0cSHannes Reinecke /*
163241cd0cSHannes Reinecke * HKDF consists of two steps:
173241cd0cSHannes Reinecke *
183241cd0cSHannes Reinecke * 1. HKDF-Extract: extract a pseudorandom key from the input keying material
193241cd0cSHannes Reinecke * and optional salt.
203241cd0cSHannes Reinecke * 2. HKDF-Expand: expand the pseudorandom key into output keying material of
213241cd0cSHannes Reinecke * any length, parameterized by an application-specific info string.
223241cd0cSHannes Reinecke *
233241cd0cSHannes Reinecke */
243241cd0cSHannes Reinecke
253241cd0cSHannes Reinecke /**
263241cd0cSHannes Reinecke * hkdf_extract - HKDF-Extract (RFC 5869 section 2.2)
273241cd0cSHannes Reinecke * @hmac_tfm: an HMAC transform using the hash function desired for HKDF. The
283241cd0cSHannes Reinecke * caller is responsible for setting the @prk afterwards.
293241cd0cSHannes Reinecke * @ikm: input keying material
303241cd0cSHannes Reinecke * @ikmlen: length of @ikm
313241cd0cSHannes Reinecke * @salt: input salt value
323241cd0cSHannes Reinecke * @saltlen: length of @salt
333241cd0cSHannes Reinecke * @prk: resulting pseudorandom key
343241cd0cSHannes Reinecke *
353241cd0cSHannes Reinecke * Extracts a pseudorandom key @prk from the input keying material
363241cd0cSHannes Reinecke * @ikm with length @ikmlen and salt @salt with length @saltlen.
373241cd0cSHannes Reinecke * The length of @prk is given by the digest size of @hmac_tfm.
383241cd0cSHannes Reinecke * For an 'unsalted' version of HKDF-Extract @salt must be set
393241cd0cSHannes Reinecke * to all zeroes and @saltlen must be set to the length of @prk.
403241cd0cSHannes Reinecke *
413241cd0cSHannes Reinecke * Returns 0 on success with the pseudorandom key stored in @prk,
423241cd0cSHannes Reinecke * or a negative errno value otherwise.
433241cd0cSHannes Reinecke */
hkdf_extract(struct crypto_shash * hmac_tfm,const u8 * ikm,unsigned int ikmlen,const u8 * salt,unsigned int saltlen,u8 * prk)443241cd0cSHannes Reinecke int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm,
453241cd0cSHannes Reinecke unsigned int ikmlen, const u8 *salt, unsigned int saltlen,
463241cd0cSHannes Reinecke u8 *prk)
473241cd0cSHannes Reinecke {
483241cd0cSHannes Reinecke int err;
493241cd0cSHannes Reinecke
503241cd0cSHannes Reinecke err = crypto_shash_setkey(hmac_tfm, salt, saltlen);
513241cd0cSHannes Reinecke if (!err)
523241cd0cSHannes Reinecke err = crypto_shash_tfm_digest(hmac_tfm, ikm, ikmlen, prk);
533241cd0cSHannes Reinecke
543241cd0cSHannes Reinecke return err;
553241cd0cSHannes Reinecke }
563241cd0cSHannes Reinecke EXPORT_SYMBOL_GPL(hkdf_extract);
573241cd0cSHannes Reinecke
583241cd0cSHannes Reinecke /**
593241cd0cSHannes Reinecke * hkdf_expand - HKDF-Expand (RFC 5869 section 2.3)
603241cd0cSHannes Reinecke * @hmac_tfm: hash context keyed with pseudorandom key
613241cd0cSHannes Reinecke * @info: application-specific information
623241cd0cSHannes Reinecke * @infolen: length of @info
633241cd0cSHannes Reinecke * @okm: output keying material
643241cd0cSHannes Reinecke * @okmlen: length of @okm
653241cd0cSHannes Reinecke *
663241cd0cSHannes Reinecke * This expands the pseudorandom key, which was already keyed into @hmac_tfm,
673241cd0cSHannes Reinecke * into @okmlen bytes of output keying material parameterized by the
683241cd0cSHannes Reinecke * application-specific @info of length @infolen bytes.
693241cd0cSHannes Reinecke * This is thread-safe and may be called by multiple threads in parallel.
703241cd0cSHannes Reinecke *
713241cd0cSHannes Reinecke * Returns 0 on success with output keying material stored in @okm,
723241cd0cSHannes Reinecke * or a negative errno value otherwise.
733241cd0cSHannes Reinecke */
hkdf_expand(struct crypto_shash * hmac_tfm,const u8 * info,unsigned int infolen,u8 * okm,unsigned int okmlen)743241cd0cSHannes Reinecke int hkdf_expand(struct crypto_shash *hmac_tfm,
753241cd0cSHannes Reinecke const u8 *info, unsigned int infolen,
763241cd0cSHannes Reinecke u8 *okm, unsigned int okmlen)
773241cd0cSHannes Reinecke {
783241cd0cSHannes Reinecke SHASH_DESC_ON_STACK(desc, hmac_tfm);
793241cd0cSHannes Reinecke unsigned int i, hashlen = crypto_shash_digestsize(hmac_tfm);
803241cd0cSHannes Reinecke int err;
813241cd0cSHannes Reinecke const u8 *prev = NULL;
823241cd0cSHannes Reinecke u8 counter = 1;
833241cd0cSHannes Reinecke u8 tmp[HASH_MAX_DIGESTSIZE] = {};
843241cd0cSHannes Reinecke
853241cd0cSHannes Reinecke if (WARN_ON(okmlen > 255 * hashlen))
863241cd0cSHannes Reinecke return -EINVAL;
873241cd0cSHannes Reinecke
883241cd0cSHannes Reinecke desc->tfm = hmac_tfm;
893241cd0cSHannes Reinecke
903241cd0cSHannes Reinecke for (i = 0; i < okmlen; i += hashlen) {
913241cd0cSHannes Reinecke err = crypto_shash_init(desc);
923241cd0cSHannes Reinecke if (err)
933241cd0cSHannes Reinecke goto out;
943241cd0cSHannes Reinecke
953241cd0cSHannes Reinecke if (prev) {
963241cd0cSHannes Reinecke err = crypto_shash_update(desc, prev, hashlen);
973241cd0cSHannes Reinecke if (err)
983241cd0cSHannes Reinecke goto out;
993241cd0cSHannes Reinecke }
1003241cd0cSHannes Reinecke
1013241cd0cSHannes Reinecke if (infolen) {
1023241cd0cSHannes Reinecke err = crypto_shash_update(desc, info, infolen);
1033241cd0cSHannes Reinecke if (err)
1043241cd0cSHannes Reinecke goto out;
1053241cd0cSHannes Reinecke }
1063241cd0cSHannes Reinecke
1073241cd0cSHannes Reinecke BUILD_BUG_ON(sizeof(counter) != 1);
1083241cd0cSHannes Reinecke if (okmlen - i < hashlen) {
1093241cd0cSHannes Reinecke err = crypto_shash_finup(desc, &counter, 1, tmp);
1103241cd0cSHannes Reinecke if (err)
1113241cd0cSHannes Reinecke goto out;
1123241cd0cSHannes Reinecke memcpy(&okm[i], tmp, okmlen - i);
1133241cd0cSHannes Reinecke memzero_explicit(tmp, sizeof(tmp));
1143241cd0cSHannes Reinecke } else {
1153241cd0cSHannes Reinecke err = crypto_shash_finup(desc, &counter, 1, &okm[i]);
1163241cd0cSHannes Reinecke if (err)
1173241cd0cSHannes Reinecke goto out;
1183241cd0cSHannes Reinecke }
1193241cd0cSHannes Reinecke counter++;
1203241cd0cSHannes Reinecke prev = &okm[i];
1213241cd0cSHannes Reinecke }
1223241cd0cSHannes Reinecke err = 0;
1233241cd0cSHannes Reinecke out:
1243241cd0cSHannes Reinecke if (unlikely(err))
1253241cd0cSHannes Reinecke memzero_explicit(okm, okmlen); /* so caller doesn't need to */
1263241cd0cSHannes Reinecke shash_desc_zero(desc);
1273241cd0cSHannes Reinecke memzero_explicit(tmp, HASH_MAX_DIGESTSIZE);
1283241cd0cSHannes Reinecke return err;
1293241cd0cSHannes Reinecke }
1303241cd0cSHannes Reinecke EXPORT_SYMBOL_GPL(hkdf_expand);
1313241cd0cSHannes Reinecke
1323241cd0cSHannes Reinecke struct hkdf_testvec {
1333241cd0cSHannes Reinecke const char *test;
1343241cd0cSHannes Reinecke const u8 *ikm;
1353241cd0cSHannes Reinecke const u8 *salt;
1363241cd0cSHannes Reinecke const u8 *info;
1373241cd0cSHannes Reinecke const u8 *prk;
1383241cd0cSHannes Reinecke const u8 *okm;
1393241cd0cSHannes Reinecke u16 ikm_size;
1403241cd0cSHannes Reinecke u16 salt_size;
1413241cd0cSHannes Reinecke u16 info_size;
1423241cd0cSHannes Reinecke u16 prk_size;
1433241cd0cSHannes Reinecke u16 okm_size;
1443241cd0cSHannes Reinecke };
1453241cd0cSHannes Reinecke
1463241cd0cSHannes Reinecke /*
1473241cd0cSHannes Reinecke * HKDF test vectors from RFC5869
1483241cd0cSHannes Reinecke *
1493241cd0cSHannes Reinecke * Additional HKDF test vectors from
1503241cd0cSHannes Reinecke * https://github.com/brycx/Test-Vector-Generation/blob/master/HKDF/hkdf-hmac-sha2-test-vectors.md
1513241cd0cSHannes Reinecke */
1523241cd0cSHannes Reinecke static const struct hkdf_testvec hkdf_sha256_tv[] = {
1533241cd0cSHannes Reinecke {
1543241cd0cSHannes Reinecke .test = "basic hdkf test",
1553241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
1563241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
1573241cd0cSHannes Reinecke .ikm_size = 22,
1583241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
1593241cd0cSHannes Reinecke .salt_size = 13,
1603241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
1613241cd0cSHannes Reinecke .info_size = 10,
1623241cd0cSHannes Reinecke .prk = "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b\xba\x63"
1633241cd0cSHannes Reinecke "\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a\xd7\xc2\xb3\xe5",
1643241cd0cSHannes Reinecke .prk_size = 32,
1653241cd0cSHannes Reinecke .okm = "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36\x2f\x2a"
1663241cd0cSHannes Reinecke "\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56\xec\xc4\xc5\xbf"
1673241cd0cSHannes Reinecke "\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65",
1683241cd0cSHannes Reinecke .okm_size = 42,
1693241cd0cSHannes Reinecke }, {
1703241cd0cSHannes Reinecke .test = "hkdf test with long input",
1713241cd0cSHannes Reinecke .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
1723241cd0cSHannes Reinecke "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
1733241cd0cSHannes Reinecke "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
1743241cd0cSHannes Reinecke "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
1753241cd0cSHannes Reinecke "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
1763241cd0cSHannes Reinecke .ikm_size = 80,
1773241cd0cSHannes Reinecke .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
1783241cd0cSHannes Reinecke "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
1793241cd0cSHannes Reinecke "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
1803241cd0cSHannes Reinecke "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
1813241cd0cSHannes Reinecke "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
1823241cd0cSHannes Reinecke .salt_size = 80,
1833241cd0cSHannes Reinecke .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
1843241cd0cSHannes Reinecke "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
1853241cd0cSHannes Reinecke "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
1863241cd0cSHannes Reinecke "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
1873241cd0cSHannes Reinecke "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
1883241cd0cSHannes Reinecke .info_size = 80,
1893241cd0cSHannes Reinecke .prk = "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35\xb4\x5c"
1903241cd0cSHannes Reinecke "\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40\xc1\x5f\xc2\x44",
1913241cd0cSHannes Reinecke .prk_size = 32,
1923241cd0cSHannes Reinecke .okm = "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a\x49\x34"
1933241cd0cSHannes Reinecke "\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c\x19\xaf\xa9\x7c"
1943241cd0cSHannes Reinecke "\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb\x41\xc6\x5e\x59\x0e\x09"
1953241cd0cSHannes Reinecke "\xda\x32\x75\x60\x0c\x2f\x09\xb8\x36\x77\x93\xa9\xac\xa3\xdb\x71"
1963241cd0cSHannes Reinecke "\xcc\x30\xc5\x81\x79\xec\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f"
1973241cd0cSHannes Reinecke "\x1d\x87",
1983241cd0cSHannes Reinecke .okm_size = 82,
1993241cd0cSHannes Reinecke }, {
2003241cd0cSHannes Reinecke .test = "hkdf test with zero salt and info",
2013241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
2023241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
2033241cd0cSHannes Reinecke .ikm_size = 22,
2043241cd0cSHannes Reinecke .salt = NULL,
2053241cd0cSHannes Reinecke .salt_size = 0,
2063241cd0cSHannes Reinecke .info = NULL,
2073241cd0cSHannes Reinecke .info_size = 0,
2083241cd0cSHannes Reinecke .prk = "\x19\xef\x24\xa3\x2c\x71\x7b\x16\x7f\x33\xa9\x1d\x6f\x64\x8b\xdf"
2093241cd0cSHannes Reinecke "\x96\x59\x67\x76\xaf\xdb\x63\x77\xac\x43\x4c\x1c\x29\x3c\xcb\x04",
2103241cd0cSHannes Reinecke .prk_size = 32,
2113241cd0cSHannes Reinecke .okm = "\x8d\xa4\xe7\x75\xa5\x63\xc1\x8f\x71\x5f\x80\x2a\x06\x3c\x5a\x31"
2123241cd0cSHannes Reinecke "\xb8\xa1\x1f\x5c\x5e\xe1\x87\x9e\xc3\x45\x4e\x5f\x3c\x73\x8d\x2d"
2133241cd0cSHannes Reinecke "\x9d\x20\x13\x95\xfa\xa4\xb6\x1a\x96\xc8",
2143241cd0cSHannes Reinecke .okm_size = 42,
2153241cd0cSHannes Reinecke }, {
2163241cd0cSHannes Reinecke .test = "hkdf test with short input",
2173241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
2183241cd0cSHannes Reinecke .ikm_size = 11,
2193241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
2203241cd0cSHannes Reinecke .salt_size = 13,
2213241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
2223241cd0cSHannes Reinecke .info_size = 10,
2233241cd0cSHannes Reinecke .prk = "\x82\x65\xf6\x9d\x7f\xf7\xe5\x01\x37\x93\x01\x5c\xa0\xef\x92\x0c"
2243241cd0cSHannes Reinecke "\xb1\x68\x21\x99\xc8\xbc\x3a\x00\xda\x0c\xab\x47\xb7\xb0\x0f\xdf",
2253241cd0cSHannes Reinecke .prk_size = 32,
2263241cd0cSHannes Reinecke .okm = "\x58\xdc\xe1\x0d\x58\x01\xcd\xfd\xa8\x31\x72\x6b\xfe\xbc\xb7\x43"
2273241cd0cSHannes Reinecke "\xd1\x4a\x7e\xe8\x3a\xa0\x57\xa9\x3d\x59\xb0\xa1\x31\x7f\xf0\x9d"
2283241cd0cSHannes Reinecke "\x10\x5c\xce\xcf\x53\x56\x92\xb1\x4d\xd5",
2293241cd0cSHannes Reinecke .okm_size = 42,
2303241cd0cSHannes Reinecke }, {
2313241cd0cSHannes Reinecke .test = "unsalted hkdf test with zero info",
2323241cd0cSHannes Reinecke .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
2333241cd0cSHannes Reinecke "\x0c\x0c\x0c\x0c\x0c\x0c",
2343241cd0cSHannes Reinecke .ikm_size = 22,
2353241cd0cSHannes Reinecke .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
2363241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
2373241cd0cSHannes Reinecke .salt_size = 32,
2383241cd0cSHannes Reinecke .info = NULL,
2393241cd0cSHannes Reinecke .info_size = 0,
2403241cd0cSHannes Reinecke .prk = "\xaa\x84\x1e\x1f\x35\x74\xf3\x2d\x13\xfb\xa8\x00\x5f\xcd\x9b\x8d"
2413241cd0cSHannes Reinecke "\x77\x67\x82\xa5\xdf\xa1\x92\x38\x92\xfd\x8b\x63\x5d\x3a\x89\xdf",
2423241cd0cSHannes Reinecke .prk_size = 32,
2433241cd0cSHannes Reinecke .okm = "\x59\x68\x99\x17\x9a\xb1\xbc\x00\xa7\xc0\x37\x86\xff\x43\xee\x53"
2443241cd0cSHannes Reinecke "\x50\x04\xbe\x2b\xb9\xbe\x68\xbc\x14\x06\x63\x6f\x54\xbd\x33\x8a"
2453241cd0cSHannes Reinecke "\x66\xa2\x37\xba\x2a\xcb\xce\xe3\xc9\xa7",
2463241cd0cSHannes Reinecke .okm_size = 42,
2473241cd0cSHannes Reinecke }
2483241cd0cSHannes Reinecke };
2493241cd0cSHannes Reinecke
2503241cd0cSHannes Reinecke static const struct hkdf_testvec hkdf_sha384_tv[] = {
2513241cd0cSHannes Reinecke {
2523241cd0cSHannes Reinecke .test = "basic hkdf test",
2533241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
2543241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
2553241cd0cSHannes Reinecke .ikm_size = 22,
2563241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
2573241cd0cSHannes Reinecke .salt_size = 13,
2583241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
2593241cd0cSHannes Reinecke .info_size = 10,
2603241cd0cSHannes Reinecke .prk = "\x70\x4b\x39\x99\x07\x79\xce\x1d\xc5\x48\x05\x2c\x7d\xc3\x9f\x30"
2613241cd0cSHannes Reinecke "\x35\x70\xdd\x13\xfb\x39\xf7\xac\xc5\x64\x68\x0b\xef\x80\xe8\xde"
2623241cd0cSHannes Reinecke "\xc7\x0e\xe9\xa7\xe1\xf3\xe2\x93\xef\x68\xec\xeb\x07\x2a\x5a\xde",
2633241cd0cSHannes Reinecke .prk_size = 48,
2643241cd0cSHannes Reinecke .okm = "\x9b\x50\x97\xa8\x60\x38\xb8\x05\x30\x90\x76\xa4\x4b\x3a\x9f\x38"
2653241cd0cSHannes Reinecke "\x06\x3e\x25\xb5\x16\xdc\xbf\x36\x9f\x39\x4c\xfa\xb4\x36\x85\xf7"
2663241cd0cSHannes Reinecke "\x48\xb6\x45\x77\x63\xe4\xf0\x20\x4f\xc5",
2673241cd0cSHannes Reinecke .okm_size = 42,
2683241cd0cSHannes Reinecke }, {
2693241cd0cSHannes Reinecke .test = "hkdf test with long input",
2703241cd0cSHannes Reinecke .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
2713241cd0cSHannes Reinecke "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
2723241cd0cSHannes Reinecke "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
2733241cd0cSHannes Reinecke "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
2743241cd0cSHannes Reinecke "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
2753241cd0cSHannes Reinecke .ikm_size = 80,
2763241cd0cSHannes Reinecke .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
2773241cd0cSHannes Reinecke "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
2783241cd0cSHannes Reinecke "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
2793241cd0cSHannes Reinecke "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
2803241cd0cSHannes Reinecke "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
2813241cd0cSHannes Reinecke .salt_size = 80,
2823241cd0cSHannes Reinecke .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
2833241cd0cSHannes Reinecke "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
2843241cd0cSHannes Reinecke "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
2853241cd0cSHannes Reinecke "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
2863241cd0cSHannes Reinecke "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
2873241cd0cSHannes Reinecke .info_size = 80,
2883241cd0cSHannes Reinecke .prk = "\xb3\x19\xf6\x83\x1d\xff\x93\x14\xef\xb6\x43\xba\xa2\x92\x63\xb3"
2893241cd0cSHannes Reinecke "\x0e\x4a\x8d\x77\x9f\xe3\x1e\x9c\x90\x1e\xfd\x7d\xe7\x37\xc8\x5b"
2903241cd0cSHannes Reinecke "\x62\xe6\x76\xd4\xdc\x87\xb0\x89\x5c\x6a\x7d\xc9\x7b\x52\xce\xbb",
2913241cd0cSHannes Reinecke .prk_size = 48,
2923241cd0cSHannes Reinecke .okm = "\x48\x4c\xa0\x52\xb8\xcc\x72\x4f\xd1\xc4\xec\x64\xd5\x7b\x4e\x81"
2933241cd0cSHannes Reinecke "\x8c\x7e\x25\xa8\xe0\xf4\x56\x9e\xd7\x2a\x6a\x05\xfe\x06\x49\xee"
2943241cd0cSHannes Reinecke "\xbf\x69\xf8\xd5\xc8\x32\x85\x6b\xf4\xe4\xfb\xc1\x79\x67\xd5\x49"
2953241cd0cSHannes Reinecke "\x75\x32\x4a\x94\x98\x7f\x7f\x41\x83\x58\x17\xd8\x99\x4f\xdb\xd6"
2963241cd0cSHannes Reinecke "\xf4\xc0\x9c\x55\x00\xdc\xa2\x4a\x56\x22\x2f\xea\x53\xd8\x96\x7a"
2973241cd0cSHannes Reinecke "\x8b\x2e",
2983241cd0cSHannes Reinecke .okm_size = 82,
2993241cd0cSHannes Reinecke }, {
3003241cd0cSHannes Reinecke .test = "hkdf test with zero salt and info",
3013241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
3023241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
3033241cd0cSHannes Reinecke .ikm_size = 22,
3043241cd0cSHannes Reinecke .salt = NULL,
3053241cd0cSHannes Reinecke .salt_size = 0,
3063241cd0cSHannes Reinecke .info = NULL,
3073241cd0cSHannes Reinecke .info_size = 0,
3083241cd0cSHannes Reinecke .prk = "\x10\xe4\x0c\xf0\x72\xa4\xc5\x62\x6e\x43\xdd\x22\xc1\xcf\x72\x7d"
3093241cd0cSHannes Reinecke "\x4b\xb1\x40\x97\x5c\x9a\xd0\xcb\xc8\xe4\x5b\x40\x06\x8f\x8f\x0b"
3103241cd0cSHannes Reinecke "\xa5\x7c\xdb\x59\x8a\xf9\xdf\xa6\x96\x3a\x96\x89\x9a\xf0\x47\xe5",
3113241cd0cSHannes Reinecke .prk_size = 48,
3123241cd0cSHannes Reinecke .okm = "\xc8\xc9\x6e\x71\x0f\x89\xb0\xd7\x99\x0b\xca\x68\xbc\xde\xc8\xcf"
3133241cd0cSHannes Reinecke "\x85\x40\x62\xe5\x4c\x73\xa7\xab\xc7\x43\xfa\xde\x9b\x24\x2d\xaa"
3143241cd0cSHannes Reinecke "\xcc\x1c\xea\x56\x70\x41\x5b\x52\x84\x9c",
3153241cd0cSHannes Reinecke .okm_size = 42,
3163241cd0cSHannes Reinecke }, {
3173241cd0cSHannes Reinecke .test = "hkdf test with short input",
3183241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
3193241cd0cSHannes Reinecke .ikm_size = 11,
3203241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
3213241cd0cSHannes Reinecke .salt_size = 13,
3223241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
3233241cd0cSHannes Reinecke .info_size = 10,
3243241cd0cSHannes Reinecke .prk = "\x6d\x31\x69\x98\x28\x79\x80\x88\xb3\x59\xda\xd5\x0b\x8f\x01\xb0"
3253241cd0cSHannes Reinecke "\x15\xf1\x7a\xa3\xbd\x4e\x27\xa6\xe9\xf8\x73\xb7\x15\x85\xca\x6a"
3263241cd0cSHannes Reinecke "\x00\xd1\xf0\x82\x12\x8a\xdb\x3c\xf0\x53\x0b\x57\xc0\xf9\xac\x72",
3273241cd0cSHannes Reinecke .prk_size = 48,
3283241cd0cSHannes Reinecke .okm = "\xfb\x7e\x67\x43\xeb\x42\xcd\xe9\x6f\x1b\x70\x77\x89\x52\xab\x75"
3293241cd0cSHannes Reinecke "\x48\xca\xfe\x53\x24\x9f\x7f\xfe\x14\x97\xa1\x63\x5b\x20\x1f\xf1"
3303241cd0cSHannes Reinecke "\x85\xb9\x3e\x95\x19\x92\xd8\x58\xf1\x1a",
3313241cd0cSHannes Reinecke .okm_size = 42,
3323241cd0cSHannes Reinecke }, {
3333241cd0cSHannes Reinecke .test = "unsalted hkdf test with zero info",
3343241cd0cSHannes Reinecke .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
3353241cd0cSHannes Reinecke "\x0c\x0c\x0c\x0c\x0c\x0c",
3363241cd0cSHannes Reinecke .ikm_size = 22,
3373241cd0cSHannes Reinecke .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
3383241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
3393241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
3403241cd0cSHannes Reinecke .salt_size = 48,
3413241cd0cSHannes Reinecke .info = NULL,
3423241cd0cSHannes Reinecke .info_size = 0,
3433241cd0cSHannes Reinecke .prk = "\x9d\x2d\xa5\x06\x6f\x05\xd1\x6c\x59\xfe\xdf\x6c\x5f\x32\xc7\x5e"
3443241cd0cSHannes Reinecke "\xda\x9a\x47\xa7\x9c\x93\x6a\xa4\x4c\xb7\x63\xa8\xe2\x2f\xfb\xfc"
3453241cd0cSHannes Reinecke "\xd8\xfe\x55\x43\x58\x53\x47\x21\x90\x39\xd1\x68\x28\x36\x33\xf5",
3463241cd0cSHannes Reinecke .prk_size = 48,
3473241cd0cSHannes Reinecke .okm = "\x6a\xd7\xc7\x26\xc8\x40\x09\x54\x6a\x76\xe0\x54\x5d\xf2\x66\x78"
3483241cd0cSHannes Reinecke "\x7e\x2b\x2c\xd6\xca\x43\x73\xa1\xf3\x14\x50\xa7\xbd\xf9\x48\x2b"
3493241cd0cSHannes Reinecke "\xfa\xb8\x11\xf5\x54\x20\x0e\xad\x8f\x53",
3503241cd0cSHannes Reinecke .okm_size = 42,
3513241cd0cSHannes Reinecke }
3523241cd0cSHannes Reinecke };
3533241cd0cSHannes Reinecke
3543241cd0cSHannes Reinecke static const struct hkdf_testvec hkdf_sha512_tv[] = {
3553241cd0cSHannes Reinecke {
3563241cd0cSHannes Reinecke .test = "basic hkdf test",
3573241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
3583241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
3593241cd0cSHannes Reinecke .ikm_size = 22,
3603241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
3613241cd0cSHannes Reinecke .salt_size = 13,
3623241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
3633241cd0cSHannes Reinecke .info_size = 10,
3643241cd0cSHannes Reinecke .prk = "\x66\x57\x99\x82\x37\x37\xde\xd0\x4a\x88\xe4\x7e\x54\xa5\x89\x0b"
3653241cd0cSHannes Reinecke "\xb2\xc3\xd2\x47\xc7\xa4\x25\x4a\x8e\x61\x35\x07\x23\x59\x0a\x26"
3663241cd0cSHannes Reinecke "\xc3\x62\x38\x12\x7d\x86\x61\xb8\x8c\xf8\x0e\xf8\x02\xd5\x7e\x2f"
3673241cd0cSHannes Reinecke "\x7c\xeb\xcf\x1e\x00\xe0\x83\x84\x8b\xe1\x99\x29\xc6\x1b\x42\x37",
3683241cd0cSHannes Reinecke .prk_size = 64,
3693241cd0cSHannes Reinecke .okm = "\x83\x23\x90\x08\x6c\xda\x71\xfb\x47\x62\x5b\xb5\xce\xb1\x68\xe4"
3703241cd0cSHannes Reinecke "\xc8\xe2\x6a\x1a\x16\xed\x34\xd9\xfc\x7f\xe9\x2c\x14\x81\x57\x93"
3713241cd0cSHannes Reinecke "\x38\xda\x36\x2c\xb8\xd9\xf9\x25\xd7\xcb",
3723241cd0cSHannes Reinecke .okm_size = 42,
3733241cd0cSHannes Reinecke }, {
3743241cd0cSHannes Reinecke .test = "hkdf test with long input",
3753241cd0cSHannes Reinecke .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
3763241cd0cSHannes Reinecke "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
3773241cd0cSHannes Reinecke "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
3783241cd0cSHannes Reinecke "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
3793241cd0cSHannes Reinecke "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
3803241cd0cSHannes Reinecke .ikm_size = 80,
3813241cd0cSHannes Reinecke .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
3823241cd0cSHannes Reinecke "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
3833241cd0cSHannes Reinecke "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
3843241cd0cSHannes Reinecke "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
3853241cd0cSHannes Reinecke "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
3863241cd0cSHannes Reinecke .salt_size = 80,
3873241cd0cSHannes Reinecke .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
3883241cd0cSHannes Reinecke "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
3893241cd0cSHannes Reinecke "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
3903241cd0cSHannes Reinecke "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
3913241cd0cSHannes Reinecke "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
3923241cd0cSHannes Reinecke .info_size = 80,
3933241cd0cSHannes Reinecke .prk = "\x35\x67\x25\x42\x90\x7d\x4e\x14\x2c\x00\xe8\x44\x99\xe7\x4e\x1d"
3943241cd0cSHannes Reinecke "\xe0\x8b\xe8\x65\x35\xf9\x24\xe0\x22\x80\x4a\xd7\x75\xdd\xe2\x7e"
3953241cd0cSHannes Reinecke "\xc8\x6c\xd1\xe5\xb7\xd1\x78\xc7\x44\x89\xbd\xbe\xb3\x07\x12\xbe"
3963241cd0cSHannes Reinecke "\xb8\x2d\x4f\x97\x41\x6c\x5a\x94\xea\x81\xeb\xdf\x3e\x62\x9e\x4a",
3973241cd0cSHannes Reinecke .prk_size = 64,
3983241cd0cSHannes Reinecke .okm = "\xce\x6c\x97\x19\x28\x05\xb3\x46\xe6\x16\x1e\x82\x1e\xd1\x65\x67"
3993241cd0cSHannes Reinecke "\x3b\x84\xf4\x00\xa2\xb5\x14\xb2\xfe\x23\xd8\x4c\xd1\x89\xdd\xf1"
4003241cd0cSHannes Reinecke "\xb6\x95\xb4\x8c\xbd\x1c\x83\x88\x44\x11\x37\xb3\xce\x28\xf1\x6a"
4013241cd0cSHannes Reinecke "\xa6\x4b\xa3\x3b\xa4\x66\xb2\x4d\xf6\xcf\xcb\x02\x1e\xcf\xf2\x35"
4023241cd0cSHannes Reinecke "\xf6\xa2\x05\x6c\xe3\xaf\x1d\xe4\x4d\x57\x20\x97\xa8\x50\x5d\x9e"
4033241cd0cSHannes Reinecke "\x7a\x93",
4043241cd0cSHannes Reinecke .okm_size = 82,
4053241cd0cSHannes Reinecke }, {
4063241cd0cSHannes Reinecke .test = "hkdf test with zero salt and info",
4073241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
4083241cd0cSHannes Reinecke "\x0b\x0b\x0b\x0b\x0b\x0b",
4093241cd0cSHannes Reinecke .ikm_size = 22,
4103241cd0cSHannes Reinecke .salt = NULL,
4113241cd0cSHannes Reinecke .salt_size = 0,
4123241cd0cSHannes Reinecke .info = NULL,
4133241cd0cSHannes Reinecke .info_size = 0,
4143241cd0cSHannes Reinecke .prk = "\xfd\x20\x0c\x49\x87\xac\x49\x13\x13\xbd\x4a\x2a\x13\x28\x71\x21"
4153241cd0cSHannes Reinecke "\x24\x72\x39\xe1\x1c\x9e\xf8\x28\x02\x04\x4b\x66\xef\x35\x7e\x5b"
4163241cd0cSHannes Reinecke "\x19\x44\x98\xd0\x68\x26\x11\x38\x23\x48\x57\x2a\x7b\x16\x11\xde"
4173241cd0cSHannes Reinecke "\x54\x76\x40\x94\x28\x63\x20\x57\x8a\x86\x3f\x36\x56\x2b\x0d\xf6",
4183241cd0cSHannes Reinecke .prk_size = 64,
4193241cd0cSHannes Reinecke .okm = "\xf5\xfa\x02\xb1\x82\x98\xa7\x2a\x8c\x23\x89\x8a\x87\x03\x47\x2c"
4203241cd0cSHannes Reinecke "\x6e\xb1\x79\xdc\x20\x4c\x03\x42\x5c\x97\x0e\x3b\x16\x4b\xf9\x0f"
4213241cd0cSHannes Reinecke "\xff\x22\xd0\x48\x36\xd0\xe2\x34\x3b\xac",
4223241cd0cSHannes Reinecke .okm_size = 42,
4233241cd0cSHannes Reinecke }, {
4243241cd0cSHannes Reinecke .test = "hkdf test with short input",
4253241cd0cSHannes Reinecke .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
4263241cd0cSHannes Reinecke .ikm_size = 11,
4273241cd0cSHannes Reinecke .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c",
4283241cd0cSHannes Reinecke .salt_size = 13,
4293241cd0cSHannes Reinecke .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
4303241cd0cSHannes Reinecke .info_size = 10,
4313241cd0cSHannes Reinecke .prk = "\x67\x40\x9c\x9c\xac\x28\xb5\x2e\xe9\xfa\xd9\x1c\x2f\xda\x99\x9f"
4323241cd0cSHannes Reinecke "\x7c\xa2\x2e\x34\x34\xf0\xae\x77\x28\x63\x83\x65\x68\xad\x6a\x7f"
4333241cd0cSHannes Reinecke "\x10\xcf\x11\x3b\xfd\xdd\x56\x01\x29\xa5\x94\xa8\xf5\x23\x85\xc2"
4343241cd0cSHannes Reinecke "\xd6\x61\xd7\x85\xd2\x9c\xe9\x3a\x11\x40\x0c\x92\x06\x83\x18\x1d",
4353241cd0cSHannes Reinecke .prk_size = 64,
4363241cd0cSHannes Reinecke .okm = "\x74\x13\xe8\x99\x7e\x02\x06\x10\xfb\xf6\x82\x3f\x2c\xe1\x4b\xff"
4373241cd0cSHannes Reinecke "\x01\x87\x5d\xb1\xca\x55\xf6\x8c\xfc\xf3\x95\x4d\xc8\xaf\xf5\x35"
4383241cd0cSHannes Reinecke "\x59\xbd\x5e\x30\x28\xb0\x80\xf7\xc0\x68",
4393241cd0cSHannes Reinecke .okm_size = 42,
4403241cd0cSHannes Reinecke }, {
4413241cd0cSHannes Reinecke .test = "unsalted hkdf test with zero info",
4423241cd0cSHannes Reinecke .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
4433241cd0cSHannes Reinecke "\x0c\x0c\x0c\x0c\x0c\x0c",
4443241cd0cSHannes Reinecke .ikm_size = 22,
4453241cd0cSHannes Reinecke .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
4463241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
4473241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
4483241cd0cSHannes Reinecke "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
4493241cd0cSHannes Reinecke .salt_size = 64,
4503241cd0cSHannes Reinecke .info = NULL,
4513241cd0cSHannes Reinecke .info_size = 0,
4523241cd0cSHannes Reinecke .prk = "\x53\x46\xb3\x76\xbf\x3a\xa9\xf8\x4f\x8f\x6e\xd5\xb1\xc4\xf4\x89"
4533241cd0cSHannes Reinecke "\x17\x2e\x24\x4d\xac\x30\x3d\x12\xf6\x8e\xcc\x76\x6e\xa6\x00\xaa"
4543241cd0cSHannes Reinecke "\x88\x49\x5e\x7f\xb6\x05\x80\x31\x22\xfa\x13\x69\x24\xa8\x40\xb1"
4553241cd0cSHannes Reinecke "\xf0\x71\x9d\x2d\x5f\x68\xe2\x9b\x24\x22\x99\xd7\x58\xed\x68\x0c",
4563241cd0cSHannes Reinecke .prk_size = 64,
4573241cd0cSHannes Reinecke .okm = "\x14\x07\xd4\x60\x13\xd9\x8b\xc6\xde\xce\xfc\xfe\xe5\x5f\x0f\x90"
4583241cd0cSHannes Reinecke "\xb0\xc7\xf6\x3d\x68\xeb\x1a\x80\xea\xf0\x7e\x95\x3c\xfc\x0a\x3a"
4593241cd0cSHannes Reinecke "\x52\x40\xa1\x55\xd6\xe4\xda\xa9\x65\xbb",
4603241cd0cSHannes Reinecke .okm_size = 42,
4613241cd0cSHannes Reinecke }
4623241cd0cSHannes Reinecke };
4633241cd0cSHannes Reinecke
hkdf_test(const char * shash,const struct hkdf_testvec * tv)4643241cd0cSHannes Reinecke static int hkdf_test(const char *shash, const struct hkdf_testvec *tv)
4653241cd0cSHannes Reinecke { struct crypto_shash *tfm = NULL;
4663241cd0cSHannes Reinecke u8 *prk = NULL, *okm = NULL;
4673241cd0cSHannes Reinecke unsigned int prk_size;
4683241cd0cSHannes Reinecke const char *driver;
4693241cd0cSHannes Reinecke int err;
4703241cd0cSHannes Reinecke
4713241cd0cSHannes Reinecke tfm = crypto_alloc_shash(shash, 0, 0);
4723241cd0cSHannes Reinecke if (IS_ERR(tfm)) {
4733241cd0cSHannes Reinecke pr_err("%s(%s): failed to allocate transform: %ld\n",
4743241cd0cSHannes Reinecke tv->test, shash, PTR_ERR(tfm));
4753241cd0cSHannes Reinecke return PTR_ERR(tfm);
4763241cd0cSHannes Reinecke }
4773241cd0cSHannes Reinecke driver = crypto_shash_driver_name(tfm);
4783241cd0cSHannes Reinecke
4793241cd0cSHannes Reinecke prk_size = crypto_shash_digestsize(tfm);
4803241cd0cSHannes Reinecke prk = kzalloc(prk_size, GFP_KERNEL);
4813241cd0cSHannes Reinecke if (!prk) {
4823241cd0cSHannes Reinecke err = -ENOMEM;
4833241cd0cSHannes Reinecke goto out_free;
4843241cd0cSHannes Reinecke }
4853241cd0cSHannes Reinecke
4863241cd0cSHannes Reinecke if (tv->prk_size != prk_size) {
4873241cd0cSHannes Reinecke pr_err("%s(%s): prk size mismatch (vec %u, digest %u\n",
4883241cd0cSHannes Reinecke tv->test, driver, tv->prk_size, prk_size);
4893241cd0cSHannes Reinecke err = -EINVAL;
4903241cd0cSHannes Reinecke goto out_free;
4913241cd0cSHannes Reinecke }
4923241cd0cSHannes Reinecke
4933241cd0cSHannes Reinecke err = hkdf_extract(tfm, tv->ikm, tv->ikm_size,
4943241cd0cSHannes Reinecke tv->salt, tv->salt_size, prk);
4953241cd0cSHannes Reinecke if (err) {
4963241cd0cSHannes Reinecke pr_err("%s(%s): hkdf_extract failed with %d\n",
4973241cd0cSHannes Reinecke tv->test, driver, err);
4983241cd0cSHannes Reinecke goto out_free;
4993241cd0cSHannes Reinecke }
5003241cd0cSHannes Reinecke
5013241cd0cSHannes Reinecke if (memcmp(prk, tv->prk, tv->prk_size)) {
5023241cd0cSHannes Reinecke pr_err("%s(%s): hkdf_extract prk mismatch\n",
5033241cd0cSHannes Reinecke tv->test, driver);
5043241cd0cSHannes Reinecke print_hex_dump(KERN_ERR, "prk: ", DUMP_PREFIX_NONE,
5053241cd0cSHannes Reinecke 16, 1, prk, tv->prk_size, false);
5063241cd0cSHannes Reinecke err = -EINVAL;
5073241cd0cSHannes Reinecke goto out_free;
5083241cd0cSHannes Reinecke }
5093241cd0cSHannes Reinecke
5103241cd0cSHannes Reinecke okm = kzalloc(tv->okm_size, GFP_KERNEL);
5113241cd0cSHannes Reinecke if (!okm) {
5123241cd0cSHannes Reinecke err = -ENOMEM;
5133241cd0cSHannes Reinecke goto out_free;
5143241cd0cSHannes Reinecke }
5153241cd0cSHannes Reinecke
5163241cd0cSHannes Reinecke err = crypto_shash_setkey(tfm, tv->prk, tv->prk_size);
5173241cd0cSHannes Reinecke if (err) {
5183241cd0cSHannes Reinecke pr_err("%s(%s): failed to set prk, error %d\n",
5193241cd0cSHannes Reinecke tv->test, driver, err);
5203241cd0cSHannes Reinecke goto out_free;
5213241cd0cSHannes Reinecke }
5223241cd0cSHannes Reinecke
5233241cd0cSHannes Reinecke err = hkdf_expand(tfm, tv->info, tv->info_size,
5243241cd0cSHannes Reinecke okm, tv->okm_size);
5253241cd0cSHannes Reinecke if (err) {
5263241cd0cSHannes Reinecke pr_err("%s(%s): hkdf_expand() failed with %d\n",
5273241cd0cSHannes Reinecke tv->test, driver, err);
5283241cd0cSHannes Reinecke } else if (memcmp(okm, tv->okm, tv->okm_size)) {
5293241cd0cSHannes Reinecke pr_err("%s(%s): hkdf_expand() okm mismatch\n",
5303241cd0cSHannes Reinecke tv->test, driver);
5313241cd0cSHannes Reinecke print_hex_dump(KERN_ERR, "okm: ", DUMP_PREFIX_NONE,
5323241cd0cSHannes Reinecke 16, 1, okm, tv->okm_size, false);
5333241cd0cSHannes Reinecke err = -EINVAL;
5343241cd0cSHannes Reinecke }
5353241cd0cSHannes Reinecke out_free:
5363241cd0cSHannes Reinecke kfree(okm);
5373241cd0cSHannes Reinecke kfree(prk);
5383241cd0cSHannes Reinecke crypto_free_shash(tfm);
5393241cd0cSHannes Reinecke return err;
5403241cd0cSHannes Reinecke }
5413241cd0cSHannes Reinecke
crypto_hkdf_module_init(void)5423241cd0cSHannes Reinecke static int __init crypto_hkdf_module_init(void)
5433241cd0cSHannes Reinecke {
5443241cd0cSHannes Reinecke int ret = 0, i;
5453241cd0cSHannes Reinecke
54640b99697SEric Biggers if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS))
5473241cd0cSHannes Reinecke return 0;
5483241cd0cSHannes Reinecke
5493241cd0cSHannes Reinecke for (i = 0; i < ARRAY_SIZE(hkdf_sha256_tv); i++) {
5503241cd0cSHannes Reinecke ret = hkdf_test("hmac(sha256)", &hkdf_sha256_tv[i]);
5513241cd0cSHannes Reinecke if (ret)
5523241cd0cSHannes Reinecke return ret;
5533241cd0cSHannes Reinecke }
5543241cd0cSHannes Reinecke for (i = 0; i < ARRAY_SIZE(hkdf_sha384_tv); i++) {
5553241cd0cSHannes Reinecke ret = hkdf_test("hmac(sha384)", &hkdf_sha384_tv[i]);
5563241cd0cSHannes Reinecke if (ret)
5573241cd0cSHannes Reinecke return ret;
5583241cd0cSHannes Reinecke }
5593241cd0cSHannes Reinecke for (i = 0; i < ARRAY_SIZE(hkdf_sha512_tv); i++) {
5603241cd0cSHannes Reinecke ret = hkdf_test("hmac(sha512)", &hkdf_sha512_tv[i]);
5613241cd0cSHannes Reinecke if (ret)
5623241cd0cSHannes Reinecke return ret;
5633241cd0cSHannes Reinecke }
5643241cd0cSHannes Reinecke return 0;
5653241cd0cSHannes Reinecke }
5663241cd0cSHannes Reinecke
crypto_hkdf_module_exit(void)5673241cd0cSHannes Reinecke static void __exit crypto_hkdf_module_exit(void) {}
5683241cd0cSHannes Reinecke
569*40a98e70SEric Biggers late_initcall(crypto_hkdf_module_init);
5703241cd0cSHannes Reinecke module_exit(crypto_hkdf_module_exit);
5713241cd0cSHannes Reinecke
5723241cd0cSHannes Reinecke MODULE_LICENSE("GPL");
5733241cd0cSHannes Reinecke MODULE_DESCRIPTION("HMAC-based Key Derivation Function (HKDF)");
574