~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/crypto/kdf_sp800108.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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  */
 17 int 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 
 66 out:
 67         if (err)
 68                 memzero_explicit(dst_orig, dlen_orig);
 69         shash_desc_zero(desc);
 70         return err;
 71 }
 72 EXPORT_SYMBOL(crypto_kdf108_ctr_generate);
 73 
 74 /*
 75  * The seeding of the KDF
 76  */
 77 int 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 }
 94 EXPORT_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  */
100 static 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 
126 static int __init crypto_kdf108_init(void)
127 {
128         int ret;
129 
130         if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))
131                 return 0;
132 
133         ret = kdf_test(&kdf_ctr_hmac_sha256_tv_template[0], "hmac(sha256)",
134                        crypto_kdf108_setkey, crypto_kdf108_ctr_generate);
135         if (ret) {
136                 if (fips_enabled)
137                         panic("alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
138                               ret);
139 
140                 WARN(1,
141                      "alg: self-tests for CTR-KDF (hmac(sha256)) failed (rc=%d)\n",
142                      ret);
143         } else if (fips_enabled) {
144                 pr_info("alg: self-tests for CTR-KDF (hmac(sha256)) passed\n");
145         }
146 
147         return ret;
148 }
149 
150 static void __exit crypto_kdf108_exit(void) { }
151 
152 module_init(crypto_kdf108_init);
153 module_exit(crypto_kdf108_exit);
154 
155 MODULE_LICENSE("GPL v2");
156 MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
157 MODULE_DESCRIPTION("Key Derivation Function conformant to SP800-108");
158 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php