0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/fips.h>
0010 #include <linux/module.h>
0011 #include <crypto/kdf_sp800108.h>
0012 #include <crypto/internal/kdf_selftest.h>
0013
0014
0015
0016
0017 int crypto_kdf108_ctr_generate(struct crypto_shash *kmd,
0018 const struct kvec *info, unsigned int info_nvec,
0019 u8 *dst, unsigned int dlen)
0020 {
0021 SHASH_DESC_ON_STACK(desc, kmd);
0022 __be32 counter = cpu_to_be32(1);
0023 const unsigned int h = crypto_shash_digestsize(kmd), dlen_orig = dlen;
0024 unsigned int i;
0025 int err = 0;
0026 u8 *dst_orig = dst;
0027
0028 desc->tfm = kmd;
0029
0030 while (dlen) {
0031 err = crypto_shash_init(desc);
0032 if (err)
0033 goto out;
0034
0035 err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32));
0036 if (err)
0037 goto out;
0038
0039 for (i = 0; i < info_nvec; i++) {
0040 err = crypto_shash_update(desc, info[i].iov_base,
0041 info[i].iov_len);
0042 if (err)
0043 goto out;
0044 }
0045
0046 if (dlen < h) {
0047 u8 tmpbuffer[HASH_MAX_DIGESTSIZE];
0048
0049 err = crypto_shash_final(desc, tmpbuffer);
0050 if (err)
0051 goto out;
0052 memcpy(dst, tmpbuffer, dlen);
0053 memzero_explicit(tmpbuffer, h);
0054 goto out;
0055 }
0056
0057 err = crypto_shash_final(desc, dst);
0058 if (err)
0059 goto out;
0060
0061 dlen -= h;
0062 dst += h;
0063 counter = cpu_to_be32(be32_to_cpu(counter) + 1);
0064 }
0065
0066 out:
0067 if (err)
0068 memzero_explicit(dst_orig, dlen_orig);
0069 shash_desc_zero(desc);
0070 return err;
0071 }
0072 EXPORT_SYMBOL(crypto_kdf108_ctr_generate);
0073
0074
0075
0076
0077 int crypto_kdf108_setkey(struct crypto_shash *kmd,
0078 const u8 *key, size_t keylen,
0079 const u8 *ikm, size_t ikmlen)
0080 {
0081 unsigned int ds = crypto_shash_digestsize(kmd);
0082
0083
0084 if (ikm || ikmlen)
0085 return -EINVAL;
0086
0087
0088 if (ds > keylen)
0089 return -EINVAL;
0090
0091
0092 return crypto_shash_setkey(kmd, key, keylen);
0093 }
0094 EXPORT_SYMBOL(crypto_kdf108_setkey);
0095
0096
0097
0098
0099
0100 static const struct kdf_testvec kdf_ctr_hmac_sha256_tv_template[] = {
0101 {
0102 .key = "\xdd\x1d\x91\xb7\xd9\x0b\x2b\xd3"
0103 "\x13\x85\x33\xce\x92\xb2\x72\xfb"
0104 "\xf8\xa3\x69\x31\x6a\xef\xe2\x42"
0105 "\xe6\x59\xcc\x0a\xe2\x38\xaf\xe0",
0106 .keylen = 32,
0107 .ikm = NULL,
0108 .ikmlen = 0,
0109 .info = {
0110 .iov_base = "\x01\x32\x2b\x96\xb3\x0a\xcd\x19"
0111 "\x79\x79\x44\x4e\x46\x8e\x1c\x5c"
0112 "\x68\x59\xbf\x1b\x1c\xf9\x51\xb7"
0113 "\xe7\x25\x30\x3e\x23\x7e\x46\xb8"
0114 "\x64\xa1\x45\xfa\xb2\x5e\x51\x7b"
0115 "\x08\xf8\x68\x3d\x03\x15\xbb\x29"
0116 "\x11\xd8\x0a\x0e\x8a\xba\x17\xf3"
0117 "\xb4\x13\xfa\xac",
0118 .iov_len = 60
0119 },
0120 .expected = "\x10\x62\x13\x42\xbf\xb0\xfd\x40"
0121 "\x04\x6c\x0e\x29\xf2\xcf\xdb\xf0",
0122 .expectedlen = 16
0123 }
0124 };
0125
0126 static int __init crypto_kdf108_init(void)
0127 {
0128 int ret = kdf_test(&kdf_ctr_hmac_sha256_tv_template[0], "hmac(sha256)",
0129 crypto_kdf108_setkey, crypto_kdf108_ctr_generate);
0130
0131 if (ret) {
0132 if (fips_enabled)
0133 panic("alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
0134 ret);
0135
0136 WARN(1,
0137 "alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
0138 ret);
0139 } else {
0140 pr_info("alg: self-tests for CTR-KDF (hmac(sha256)) passed\n");
0141 }
0142
0143 return ret;
0144 }
0145
0146 static void __exit crypto_kdf108_exit(void) { }
0147
0148 module_init(crypto_kdf108_init);
0149 module_exit(crypto_kdf108_exit);
0150
0151 MODULE_LICENSE("GPL v2");
0152 MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
0153 MODULE_DESCRIPTION("Key Derivation Function conformant to SP800-108");