Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * SP800-108 Key-derivation function
0005  *
0006  * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
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  * SP800-108 CTR KDF implementation
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  * The seeding of the KDF
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     /* SP800-108 does not support IKM */
0084     if (ikm || ikmlen)
0085         return -EINVAL;
0086 
0087     /* Check according to SP800-108 section 7.2 */
0088     if (ds > keylen)
0089         return -EINVAL;
0090 
0091     /* Set the key for the MAC used for the KDF. */
0092     return crypto_shash_setkey(kmd, key, keylen);
0093 }
0094 EXPORT_SYMBOL(crypto_kdf108_setkey);
0095 
0096 /*
0097  * Test vector obtained from
0098  * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/CounterMode.zip
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");