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