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

kdf_sp800108.c (3654B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * SP800-108 Key-derivation function
      5 *
      6 * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
      7 */
      8
      9#include <linux/fips.h>
     10#include <linux/module.h>
     11#include <crypto/kdf_sp800108.h>
     12#include <crypto/internal/kdf_selftest.h>
     13
     14/*
     15 * SP800-108 CTR KDF implementation
     16 */
     17int crypto_kdf108_ctr_generate(struct crypto_shash *kmd,
     18			       const struct kvec *info, unsigned int info_nvec,
     19			       u8 *dst, unsigned int dlen)
     20{
     21	SHASH_DESC_ON_STACK(desc, kmd);
     22	__be32 counter = cpu_to_be32(1);
     23	const unsigned int h = crypto_shash_digestsize(kmd), dlen_orig = dlen;
     24	unsigned int i;
     25	int err = 0;
     26	u8 *dst_orig = dst;
     27
     28	desc->tfm = kmd;
     29
     30	while (dlen) {
     31		err = crypto_shash_init(desc);
     32		if (err)
     33			goto out;
     34
     35		err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32));
     36		if (err)
     37			goto out;
     38
     39		for (i = 0; i < info_nvec; i++) {
     40			err = crypto_shash_update(desc, info[i].iov_base,
     41						  info[i].iov_len);
     42			if (err)
     43				goto out;
     44		}
     45
     46		if (dlen < h) {
     47			u8 tmpbuffer[HASH_MAX_DIGESTSIZE];
     48
     49			err = crypto_shash_final(desc, tmpbuffer);
     50			if (err)
     51				goto out;
     52			memcpy(dst, tmpbuffer, dlen);
     53			memzero_explicit(tmpbuffer, h);
     54			goto out;
     55		}
     56
     57		err = crypto_shash_final(desc, dst);
     58		if (err)
     59			goto out;
     60
     61		dlen -= h;
     62		dst += h;
     63		counter = cpu_to_be32(be32_to_cpu(counter) + 1);
     64	}
     65
     66out:
     67	if (err)
     68		memzero_explicit(dst_orig, dlen_orig);
     69	shash_desc_zero(desc);
     70	return err;
     71}
     72EXPORT_SYMBOL(crypto_kdf108_ctr_generate);
     73
     74/*
     75 * The seeding of the KDF
     76 */
     77int crypto_kdf108_setkey(struct crypto_shash *kmd,
     78			 const u8 *key, size_t keylen,
     79			 const u8 *ikm, size_t ikmlen)
     80{
     81	unsigned int ds = crypto_shash_digestsize(kmd);
     82
     83	/* SP800-108 does not support IKM */
     84	if (ikm || ikmlen)
     85		return -EINVAL;
     86
     87	/* Check according to SP800-108 section 7.2 */
     88	if (ds > keylen)
     89		return -EINVAL;
     90
     91	/* Set the key for the MAC used for the KDF. */
     92	return crypto_shash_setkey(kmd, key, keylen);
     93}
     94EXPORT_SYMBOL(crypto_kdf108_setkey);
     95
     96/*
     97 * Test vector obtained from
     98 * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/CounterMode.zip
     99 */
    100static const struct kdf_testvec kdf_ctr_hmac_sha256_tv_template[] = {
    101	{
    102		.key = "\xdd\x1d\x91\xb7\xd9\x0b\x2b\xd3"
    103		       "\x13\x85\x33\xce\x92\xb2\x72\xfb"
    104		       "\xf8\xa3\x69\x31\x6a\xef\xe2\x42"
    105		       "\xe6\x59\xcc\x0a\xe2\x38\xaf\xe0",
    106		.keylen = 32,
    107		.ikm = NULL,
    108		.ikmlen = 0,
    109		.info = {
    110			.iov_base = "\x01\x32\x2b\x96\xb3\x0a\xcd\x19"
    111				    "\x79\x79\x44\x4e\x46\x8e\x1c\x5c"
    112				    "\x68\x59\xbf\x1b\x1c\xf9\x51\xb7"
    113				    "\xe7\x25\x30\x3e\x23\x7e\x46\xb8"
    114				    "\x64\xa1\x45\xfa\xb2\x5e\x51\x7b"
    115				    "\x08\xf8\x68\x3d\x03\x15\xbb\x29"
    116				    "\x11\xd8\x0a\x0e\x8a\xba\x17\xf3"
    117				    "\xb4\x13\xfa\xac",
    118			.iov_len  = 60
    119		},
    120		.expected	  = "\x10\x62\x13\x42\xbf\xb0\xfd\x40"
    121				    "\x04\x6c\x0e\x29\xf2\xcf\xdb\xf0",
    122		.expectedlen	  = 16
    123	}
    124};
    125
    126static int __init crypto_kdf108_init(void)
    127{
    128	int ret = kdf_test(&kdf_ctr_hmac_sha256_tv_template[0], "hmac(sha256)",
    129			   crypto_kdf108_setkey, crypto_kdf108_ctr_generate);
    130
    131	if (ret) {
    132		if (fips_enabled)
    133			panic("alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
    134			      ret);
    135
    136		WARN(1,
    137		     "alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
    138		     ret);
    139	} else {
    140		pr_info("alg: self-tests for CTR-KDF (hmac(sha256)) passed\n");
    141	}
    142
    143	return ret;
    144}
    145
    146static void __exit crypto_kdf108_exit(void) { }
    147
    148module_init(crypto_kdf108_init);
    149module_exit(crypto_kdf108_exit);
    150
    151MODULE_LICENSE("GPL v2");
    152MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
    153MODULE_DESCRIPTION("Key Derivation Function conformant to SP800-108");