* [PATCH 0/4] crypto: Key Derivation Function (SP800-108)
@ 2016-01-26 6:19 Stephan Mueller
2016-01-26 6:19 ` [PATCH 1/4] crypto: add template handling for RNGs Stephan Mueller
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 6:19 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto
Hi,
this patch set implements all three key derivation functions defined in
SP800-108.
The implementation is provided as a template for random number generators,
since a KDF can be considered a form of deterministic RNG where the key
material is used as a seed.
With the KDF implemented as a template, all types of keyed hashes can be
utilized, including HMAC and CMAC. The testmgr tests are derived from
publicly available test vectors from NIST.
The KDF are all tested with a complete round of CAVS testing on 32 and 64 bit.
The patch set introduces an extension to the kernel crypto API in the first
patch by adding a template handling for random number generators based on the
same logic as for keyed hashes.
Stephan Mueller (4):
crypto: add template handling for RNGs
crypto: kdf - add known answer tests
crypto: kdf - SP800-108 Key Derivation Function
crypto: kdf - enable compilation
crypto/Kconfig | 7 +
crypto/Makefile | 1 +
crypto/kdf.c | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/rng.c | 31 ++++
crypto/testmgr.c | 167 +++++++++++++++++
crypto/testmgr.h | 111 +++++++++++
include/crypto/rng.h | 39 ++++
7 files changed, 870 insertions(+)
create mode 100644 crypto/kdf.c
--
2.5.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/4] crypto: add template handling for RNGs
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
@ 2016-01-26 6:19 ` Stephan Mueller
2016-01-26 6:20 ` [PATCH 2/4] crypto: kdf - add known answer tests Stephan Mueller
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 6:19 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto
This patch adds the ability to register templates for RNGs. RNGs are
"meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
implemented as templates to allow the complete flexibility the kernel
crypto API provides.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/rng.c | 31 +++++++++++++++++++++++++++++++
include/crypto/rng.h | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/crypto/rng.c b/crypto/rng.c
index b81cffb..92cc02a 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -232,5 +232,36 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count)
}
EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
+void rng_free_instance(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(rng_instance(inst));
+}
+EXPORT_SYMBOL_GPL(rng_free_instance);
+
+static int rng_prepare_alg(struct rng_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+
+ base->cra_type = &crypto_rng_type;
+ base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+ base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
+
+ return 0;
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+ struct rng_instance *inst)
+{
+ int err;
+
+ err = rng_prepare_alg(&inst->alg);
+ if (err)
+ return err;
+
+ return crypto_register_instance(tmpl, rng_crypto_instance(inst));
+}
+EXPORT_SYMBOL_GPL(rng_register_instance);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Random Number Generator");
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index b95ede3..b8a6ea3 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -15,6 +15,7 @@
#define _CRYPTO_RNG_H
#include <linux/crypto.h>
+#include <crypto/algapi.h>
struct crypto_rng;
@@ -197,4 +198,42 @@ static inline int crypto_rng_seedsize(struct crypto_rng *tfm)
return crypto_rng_alg(tfm)->seedsize;
}
+struct rng_instance {
+ struct rng_alg alg;
+};
+
+static inline struct rng_instance *rng_alloc_instance(
+ const char *name, struct crypto_alg *alg)
+{
+ return crypto_alloc_instance2(name, alg,
+ sizeof(struct rng_alg) - sizeof(*alg));
+}
+
+static inline struct crypto_instance *rng_crypto_instance(
+ struct rng_instance *inst)
+{
+ return container_of(&inst->alg.base, struct crypto_instance, alg);
+}
+
+static inline void *rng_instance_ctx(struct rng_instance *inst)
+{
+ return crypto_instance_ctx(rng_crypto_instance(inst));
+}
+
+static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
+{
+ return container_of(alg, struct rng_alg, base);
+}
+
+static inline struct rng_instance *rng_instance(
+ struct crypto_instance *inst)
+{
+ return container_of(__crypto_rng_alg(&inst->alg),
+ struct rng_instance, alg);
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+ struct rng_instance *inst);
+void rng_free_instance(struct crypto_instance *inst);
+
#endif
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/4] crypto: kdf - add known answer tests
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-01-26 6:19 ` [PATCH 1/4] crypto: add template handling for RNGs Stephan Mueller
@ 2016-01-26 6:20 ` Stephan Mueller
2016-01-26 6:20 ` [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 6:20 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto
Add known answer tests to the testmgr for the KDF (SP800-108) cipher.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/testmgr.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.h | 111 ++++++++++++++++++++++++++++++++++++
2 files changed, 278 insertions(+)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ae8c57fd..f6401e7 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -118,6 +118,11 @@ struct drbg_test_suite {
unsigned int count;
};
+struct kdf_test_suite {
+ struct kdf_testvec *vecs;
+ unsigned int count;
+};
+
struct akcipher_test_suite {
struct akcipher_testvec *vecs;
unsigned int count;
@@ -137,6 +142,7 @@ struct alg_test_desc {
struct hash_test_suite hash;
struct cprng_test_suite cprng;
struct drbg_test_suite drbg;
+ struct kdf_test_suite kdf;
struct akcipher_test_suite akcipher;
} suite;
};
@@ -1846,6 +1852,65 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
}
+static int kdf_cavs_test(struct kdf_testvec *test,
+ const char *driver, u32 type, u32 mask)
+{
+ int ret = -EAGAIN;
+ struct crypto_rng *drng;
+ unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ drng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask);
+ if (IS_ERR(drng)) {
+ printk(KERN_ERR "alg: kdf: could not allocate cipher handle "
+ "for %s\n", driver);
+ kzfree(buf);
+ return -ENOMEM;
+ }
+
+ ret = crypto_rng_reset(drng, test->K1, test->K1len);
+ if (ret) {
+ printk(KERN_ERR "alg: kdf: could not set key derivation key\n");
+ goto err;
+ }
+
+ ret = crypto_rng_generate(drng, test->context, test->contextlen,
+ buf, test->expectedlen);
+ if (ret) {
+ printk(KERN_ERR "alg: kdf: could not obtain key data\n");
+ goto err;
+ }
+
+ ret = memcmp(test->expected, buf, test->expectedlen);
+
+err:
+ crypto_free_rng(drng);
+ kzfree(buf);
+ return ret;
+}
+
+static int alg_test_kdf(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ int err = 0;
+ unsigned int i = 0;
+ struct kdf_testvec *template = desc->suite.kdf.vecs;
+ unsigned int tcount = desc->suite.kdf.count;
+
+ for (i = 0; i < tcount; i++) {
+ err = kdf_cavs_test(&template[i], driver, type, mask);
+ if (err) {
+ printk(KERN_ERR "alg: kdf: Test %d failed for %s\n",
+ i, driver);
+ err = -EINVAL;
+ break;
+ }
+ }
+ return err;
+}
+
static int do_test_rsa(struct crypto_akcipher *tfm,
struct akcipher_testvec *vecs)
{
@@ -3287,6 +3352,108 @@ static const struct alg_test_desc alg_test_descs[] = {
.fips_allowed = 1,
.test = alg_test_null,
}, {
+ .alg = "kdf_ctr(cmac(aes))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(cmac(des3_ede))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(hmac(sha1))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(hmac(sha224))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(hmac(sha256))",
+ .test = alg_test_kdf,
+ .fips_allowed = 1,
+ .suite = {
+ .kdf = {
+ .vecs = kdf_ctr_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(kdf_ctr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ .alg = "kdf_ctr(hmac(sha384))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(hmac(sha512))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(cmac(aes))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(cmac(des3_ede))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(hmac(sha1))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(hmac(sha224))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(hmac(sha256))",
+ .test = alg_test_kdf,
+ .fips_allowed = 1,
+ .suite = {
+ .kdf = {
+ .vecs = kdf_dpi_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(kdf_dpi_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ .alg = "kdf_dpi(hmac(sha384))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(hmac(sha512))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(cmac(aes))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(cmac(des3_ede))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(hmac(sha1))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(hmac(sha224))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(hmac(sha256))",
+ .test = alg_test_kdf,
+ .fips_allowed = 1,
+ .suite = {
+ .kdf = {
+ .vecs = kdf_fb_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(kdf_fb_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ .alg = "kdf_fb(hmac(sha384))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(hmac(sha512))",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
.alg = "kw(aes)",
.test = alg_test_skcipher,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index da0a8fd..c53dd32 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -126,6 +126,15 @@ struct drbg_testvec {
size_t expectedlen;
};
+struct kdf_testvec {
+ unsigned char *K1;
+ size_t K1len;
+ unsigned char *context;
+ size_t contextlen;
+ unsigned char *expected;
+ size_t expectedlen;
+};
+
struct akcipher_testvec {
unsigned char *key;
unsigned char *m;
@@ -24796,6 +24805,108 @@ static struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
},
};
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/CounterMode.zip
+ */
+static struct kdf_testvec kdf_ctr_hmac_sha256_tv_template[] = {
+ {
+ .K1 = (unsigned char *)
+ "\xdd\x1d\x91\xb7\xd9\x0b\x2b\xd3"
+ "\x13\x85\x33\xce\x92\xb2\x72\xfb"
+ "\xf8\xa3\x69\x31\x6a\xef\xe2\x42"
+ "\xe6\x59\xcc\x0a\xe2\x38\xaf\xe0",
+ .K1len = 32,
+ .context = (unsigned char *)
+ "\x01\x32\x2b\x96\xb3\x0a\xcd\x19"
+ "\x79\x79\x44\x4e\x46\x8e\x1c\x5c"
+ "\x68\x59\xbf\x1b\x1c\xf9\x51\xb7"
+ "\xe7\x25\x30\x3e\x23\x7e\x46\xb8"
+ "\x64\xa1\x45\xfa\xb2\x5e\x51\x7b"
+ "\x08\xf8\x68\x3d\x03\x15\xbb\x29"
+ "\x11\xd8\x0a\x0e\x8a\xba\x17\xf3"
+ "\xb4\x13\xfa\xac",
+ .contextlen = 60,
+ .expected = (unsigned char *)
+ "\x10\x62\x13\x42\xbf\xb0\xfd\x40"
+ "\x04\x6c\x0e\x29\xf2\xcf\xdb\xf0",
+ .expectedlen = 16
+ }
+};
+
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/FeedbackModeNOzeroiv.zip
+ */
+static struct kdf_testvec kdf_fb_hmac_sha256_tv_template[] = {
+ {
+ .K1 = (unsigned char *)
+ "\x93\xf6\x98\xe8\x42\xee\xd7\x53"
+ "\x94\xd6\x29\xd9\x57\xe2\xe8\x9c"
+ "\x6e\x74\x1f\x81\x0b\x62\x3c\x8b"
+ "\x90\x1e\x38\x37\x6d\x06\x8e\x7b",
+ .K1len = 32,
+ .context = (unsigned char *)
+ "\x9f\x57\x5d\x90\x59\xd3\xe0\xc0"
+ "\x80\x3f\x08\x11\x2f\x8a\x80\x6d"
+ "\xe3\xc3\x47\x19\x12\xcd\xf4\x2b"
+ "\x09\x53\x88\xb1\x4b\x33\x50\x8e"
+ "\x53\xb8\x9c\x18\x69\x0e\x20\x57"
+ "\xa1\xd1\x67\x82\x2e\x63\x6d\xe5"
+ "\x0b\xe0\x01\x85\x32\xc4\x31\xf7"
+ "\xf5\xe3\x7f\x77\x13\x92\x20\xd5"
+ "\xe0\x42\x59\x9e\xbe\x26\x6a\xf5"
+ "\x76\x7e\xe1\x8c\xd2\xc5\xc1\x9a"
+ "\x1f\x0f\x80",
+ .contextlen = 83,
+ .expected = (unsigned char *)
+ "\xbd\x14\x76\xf4\x3a\x4e\x31\x57"
+ "\x47\xcf\x59\x18\xe0\xea\x5b\xc0"
+ "\xd9\x87\x69\x45\x74\x77\xc3\xab"
+ "\x18\xb7\x42\xde\xf0\xe0\x79\xa9"
+ "\x33\xb7\x56\x36\x5a\xfb\x55\x41"
+ "\xf2\x53\xfe\xe4\x3c\x6f\xd7\x88"
+ "\xa4\x40\x41\x03\x85\x09\xe9\xee"
+ "\xb6\x8f\x7d\x65\xff\xbb\x5f\x95",
+ .expectedlen = 64
+ }
+};
+
+/*
+ * Test vector obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/KBKDF800-108/PipelineModewithCounter.zip
+ */
+static struct kdf_testvec kdf_dpi_hmac_sha256_tv_template[] = {
+ {
+ .K1 = (unsigned char *)
+ "\x02\xd3\x6f\xa0\x21\xc2\x0d\xdb"
+ "\xde\xe4\x69\xf0\x57\x94\x68\xba"
+ "\xe5\xcb\x13\xb5\x48\xb6\xc6\x1c"
+ "\xdf\x9d\x3e\xc4\x19\x11\x1d\xe2",
+ .K1len = 32,
+ .context = (unsigned char *)
+ "\x85\xab\xe3\x8b\xf2\x65\xfb\xdc"
+ "\x64\x45\xae\x5c\x71\x15\x9f\x15"
+ "\x48\xc7\x3b\x7d\x52\x6a\x62\x31"
+ "\x04\x90\x4a\x0f\x87\x92\x07\x0b"
+ "\x3d\xf9\x90\x2b\x96\x69\x49\x04"
+ "\x25\xa3\x85\xea\xdb\x0f\x9c\x76"
+ "\xe4\x6f\x0f",
+ .contextlen = 51,
+ .expected = (unsigned char *)
+ "\xd6\x9f\x74\xf5\x18\xc9\xf6\x4f"
+ "\x90\xa0\xbe\xeb\xab\x69\xf6\x89"
+ "\xb7\x3b\x5c\x13\xeb\x0f\x86\x0a"
+ "\x95\xca\xd7\xd9\x81\x4f\x8c\x50"
+ "\x6e\xb7\xb1\x79\xa5\xc5\xb4\x46"
+ "\x6a\x9e\xc1\x54\xc3\xbf\x1c\x13"
+ "\xef\xd6\xec\x0d\x82\xb0\x2c\x29"
+ "\xaf\x2c\x69\x02\x99\xed\xc4\x53",
+ .expectedlen = 64
+ }
+};
+
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 4
#define CAST5_DEC_TEST_VECTORS 4
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-01-26 6:19 ` [PATCH 1/4] crypto: add template handling for RNGs Stephan Mueller
2016-01-26 6:20 ` [PATCH 2/4] crypto: kdf - add known answer tests Stephan Mueller
@ 2016-01-26 6:20 ` Stephan Mueller
2016-01-26 10:28 ` Herbert Xu
2016-01-26 6:21 ` [PATCH 4/4] crypto: kdf - enable compilation Stephan Mueller
2016-01-27 5:14 ` [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Herbert Xu
4 siblings, 1 reply; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 6:20 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto
The SP800-108 compliant Key Derivation Function is implemented as a
random number generator considering that it behaves like a deterministic
RNG.
All three KDF types specified in SP800-108 are implemented.
The code comments provide details about how to invoke the different KDF
types.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/kdf.c | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 514 insertions(+)
create mode 100644 crypto/kdf.c
diff --git a/crypto/kdf.c b/crypto/kdf.c
new file mode 100644
index 0000000..b39bddf
--- /dev/null
+++ b/crypto/kdf.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+/*
+ * For performing a KDF operation, the following input is required
+ * from the caller:
+ *
+ * * Keying material to be used to derive the new keys from
+ * (denoted as Ko in SP800-108)
+ * * Label -- a free form binary string
+ * * Context -- a free form binary string
+ *
+ * The KDF is implemented as a random number generator.
+ *
+ * The Ko keying material is to be provided with the initialization of the KDF
+ * "random number generator", i.e. with the crypto_rng_reset function.
+ *
+ * The Label and Context concatenated string is provided when obtaining random
+ * numbers, i.e. with the crypto_rng_generate function. The caller must format
+ * the free-form Label || Context input as deemed necessary for the given
+ * purpose. Note, SP800-108 mandates that the Label and Context are separated
+ * by a 0x00 byte, i.e. the caller shall provide the input as
+ * Label || 0x00 || Context when trying to be compliant to SP800-108. For
+ * the feedback KDF, an IV is required as documented below.
+ *
+ * Example without proper error handling:
+ * char *keying_material = "\x00\x11\x22\x33\x44\x55\x66\x77";
+ * char *label_context = "\xde\xad\xbe\xef\x00\xde\xad\xbe\xef";
+ * kdf = crypto_alloc_rng(name, 0, 0);
+ * crypto_rng_reset(kdf, keying_material, 8);
+ * crypto_rng_generate(kdf, label_context, 9, outbuf, outbuflen);
+ *
+ * NOTE: Technically you can use one buffer for holding the label_context and
+ * the outbuf in the example above. Howerver, multiple rounds of the
+ * KDF are to be expected with the input must always be the same.
+ * The first round would replace the input in case of one buffer, and the
+ * KDF would calculate a cryptographically strong result which, however,
+ * is not portable to other KDF implementations! Thus, always use
+ * different buffers for the label_context and the outbuf. A safe
+ * in-place operation can only be done when only one round of the KDF
+ * is executed (i.e. the size of the requested buffer is equal to the
+ * digestsize of the used MAC).
+ */
+
+#include <linux/module.h>
+#include <crypto/rng.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+
+struct crypto_kdf_ctx {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+/* convert 32 bit integer into its string representation */
+static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf)
+{
+ __be32 *a = (__be32 *)buf;
+
+ *a = cpu_to_be32(val);
+}
+
+/*
+ * Implementation of the KDF in double pipeline iteration mode according with
+ * counter to SP800-108 section 5.3.
+ *
+ * The caller must provide Label || 0x00 || Context in src. This src pointer
+ * may also be NULL if the caller wishes not to provide anything.
+ */
+static int crypto_kdf_dpi_random(struct crypto_rng *rng,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+ struct shash_desc *desc = &ctx->shash;
+ unsigned int h = crypto_shash_digestsize(desc->tfm);
+ unsigned int alignmask = crypto_shash_alignmask(desc->tfm);
+ int err = 0;
+ u8 *dst_orig = dst;
+ u8 Aiblock[h + alignmask];
+ u8 *Ai = PTR_ALIGN((u8 *)Aiblock, alignmask + 1);
+ u32 i = 1;
+ u8 iteration[sizeof(u32)];
+
+ /* enforce the note from above */
+ if (dlen != h && src == dst)
+ return -EINVAL;
+
+ memset(Ai, 0, h);
+
+ while (dlen) {
+ /* Calculate A(i) */
+ if (dst == dst_orig && src && slen)
+ /* 5.3 step 4 and 5.a */
+ err = crypto_shash_digest(desc, src, slen, Ai);
+ else
+ /* 5.3 step 5.a */
+ err = crypto_shash_digest(desc, Ai, h, Ai);
+ if (err)
+ goto err;
+
+ /* Calculate K(i) -- step 5.b */
+ err = crypto_shash_init(desc);
+ if (err)
+ goto err;
+
+ err = crypto_shash_update(desc, Ai, h);
+ if (err)
+ goto err;
+
+ crypto_kw_cpu_to_be32(i, iteration);
+ err = crypto_shash_update(desc, iteration, sizeof(u32));
+ if (err)
+ goto err;
+ if (src && slen) {
+ err = crypto_shash_update(desc, src, slen);
+ if (err)
+ goto err;
+ }
+
+ if (dlen < h) {
+ u8 tmpbuffer[h];
+
+ err = crypto_shash_final(desc, tmpbuffer);
+ if (err)
+ goto err;
+ memcpy(dst, tmpbuffer, dlen);
+ memzero_explicit(tmpbuffer, h);
+ goto ret;
+ } else {
+ err = crypto_shash_final(desc, dst);
+ if (err)
+ goto err;
+ dlen -= h;
+ dst += h;
+ i++;
+ }
+ }
+
+err:
+ memzero_explicit(dst_orig, dlen);
+ret:
+ memzero_explicit(Ai, h);
+ return err;
+}
+
+/*
+ * Implementation of the KDF in feedback mode with a non-NULL IV and with
+ * counter according to SP800-108 section 5.2. The IV is supplied with src
+ * and must be equal to the digestsize of the used cipher.
+ *
+ * In addition, the caller must provide Label || 0x00 || Context in src. This
+ * src pointer must not be NULL as the IV is required. The ultimate format of
+ * the src pointer is IV || Label || 0x00 || Context where the length of the
+ * IV is equal to the output size of the PRF.
+ */
+static int crypto_kdf_fb_random(struct crypto_rng *rng,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+ struct shash_desc *desc = &ctx->shash;
+ unsigned int h = crypto_shash_digestsize(desc->tfm);
+ int err = 0;
+ u8 *dst_orig = dst;
+ const u8 *label;
+ unsigned int labellen = 0;
+ u32 i = 1;
+ u8 iteration[sizeof(u32)];
+
+ /* enforce the note from above */
+ if (dlen != h && src == dst)
+ return -EINVAL;
+
+ /* require the presence of an IV */
+ if (!src || slen < h)
+ return -EINVAL;
+
+ /* calculate the offset of the label / context data */
+ label = src + h;
+ labellen = slen - h;
+
+ while (dlen) {
+ err = crypto_shash_init(desc);
+ if (err)
+ goto err;
+
+ /*
+ * Feedback mode applies to all rounds except first which uses
+ * the IV.
+ */
+ if (dst_orig == dst)
+ err = crypto_shash_update(desc, src, h);
+ else
+ err = crypto_shash_update(desc, dst - h, h);
+ if (err)
+ goto err;
+
+ crypto_kw_cpu_to_be32(i, iteration);
+ err = crypto_shash_update(desc, iteration, sizeof(u32));
+ if (err)
+ goto err;
+ if (labellen) {
+ err = crypto_shash_update(desc, label, labellen);
+ if (err)
+ goto err;
+ }
+
+ if (dlen < h) {
+ u8 tmpbuffer[h];
+
+ err = crypto_shash_final(desc, tmpbuffer);
+ if (err)
+ goto err;
+ memcpy(dst, tmpbuffer, dlen);
+ memzero_explicit(tmpbuffer, h);
+ return 0;
+ } else {
+ err = crypto_shash_final(desc, dst);
+ if (err)
+ goto err;
+ dlen -= h;
+ dst += h;
+ i++;
+ }
+ }
+
+ return 0;
+
+err:
+ memzero_explicit(dst_orig, dlen);
+ return err;
+}
+
+/*
+ * Implementation of the KDF in counter mode according to SP800-108 section 5.1.
+ *
+ * The caller must provide Label || 0x00 || Context in src. This src pointer
+ * may also be NULL if the caller wishes not to provide anything.
+ */
+static int crypto_kdf_ctr_random(struct crypto_rng *rng,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+ struct shash_desc *desc = &ctx->shash;
+ unsigned int h = crypto_shash_digestsize(desc->tfm);
+ int err = 0;
+ u8 *dst_orig = dst;
+ u32 i = 1;
+ u8 iteration[sizeof(u32)];
+
+ /* enforce the note from above */
+ if (dlen != h && src == dst)
+ return -EINVAL;
+
+ while (dlen) {
+ err = crypto_shash_init(desc);
+ if (err)
+ goto err;
+
+ crypto_kw_cpu_to_be32(i, iteration);
+ err = crypto_shash_update(desc, iteration, sizeof(u32));
+ if (err)
+ goto err;
+
+ if (src && slen) {
+ err = crypto_shash_update(desc, src, slen);
+ if (err)
+ goto err;
+ }
+
+ if (dlen < h) {
+ u8 tmpbuffer[h];
+
+ err = crypto_shash_final(desc, tmpbuffer);
+ if (err)
+ goto err;
+ memcpy(dst, tmpbuffer, dlen);
+ memzero_explicit(tmpbuffer, h);
+ return 0;
+ } else {
+ err = crypto_shash_final(desc, dst);
+ if (err)
+ goto err;
+
+ dlen -= h;
+ dst += h;
+ i++;
+ }
+ }
+
+ return 0;
+
+err:
+ memzero_explicit(dst_orig, dlen);
+ return err;
+}
+
+/*
+ * The seeding of the KDF allows to set a key which must be at least
+ * digestsize long.
+ */
+static int crypto_kdf_seed(struct crypto_rng *rng,
+ const u8 *seed, unsigned int slen)
+{
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
+ unsigned int ds = crypto_shash_digestsize(ctx->shash.tfm);
+
+ /* Check according to SP800-108 section 7.2 */
+ if (ds > slen)
+ return -EINVAL;
+
+ /*
+ * We require that we operate on a MAC -- if we do not operate on a
+ * MAC, this function returns an error.
+ */
+ return crypto_shash_setkey(ctx->shash.tfm, seed, slen);
+}
+
+static int crypto_kdf_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst);
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_shash *hash;
+
+ hash = crypto_spawn_shash(spawn);
+ if (IS_ERR(hash))
+ return PTR_ERR(hash);
+
+ ctx->shash.tfm = hash;
+
+ return 0;
+}
+
+static void crypto_kdf_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_shash(ctx->shash.tfm);
+}
+
+static int crypto_kdf_alloc_common(struct crypto_template *tmpl,
+ struct rtattr **tb,
+ const u8 *name,
+ int (*generate)(struct crypto_rng *tfm,
+ const u8 *src,
+ unsigned int slen,
+ u8 *dst, unsigned int dlen))
+{
+ struct rng_instance *inst;
+ struct crypto_alg *alg;
+ struct shash_alg *salg;
+ int err;
+ unsigned int ds, ss;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_RNG);
+ if (err)
+ return err;
+
+ salg = shash_attr_alg(tb[1], 0, 0);
+ if (IS_ERR(salg))
+ return PTR_ERR(salg);
+
+ ds = salg->digestsize;
+ ss = salg->statesize;
+ alg = &salg->base;
+
+ inst = rng_alloc_instance(name, alg);
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ err = crypto_init_shash_spawn(rng_instance_ctx(inst), salg,
+ rng_crypto_instance(inst));
+ if (err)
+ goto out_free_inst;
+
+ inst->alg.base.cra_priority = alg->cra_priority;
+ inst->alg.base.cra_blocksize = alg->cra_blocksize;
+ inst->alg.base.cra_alignmask = alg->cra_alignmask;
+
+ inst->alg.generate = generate;
+ inst->alg.seed = crypto_kdf_seed;
+ inst->alg.seedsize = ds;
+
+ inst->alg.base.cra_init = crypto_kdf_init_tfm;
+ inst->alg.base.cra_exit = crypto_kdf_exit_tfm;
+ inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct crypto_kdf_ctx) +
+ ss * 2, crypto_tfm_ctx_alignment());
+
+ err = rng_register_instance(tmpl, inst);
+
+ if (err) {
+out_free_inst:
+ rng_free_instance(rng_crypto_instance(inst));
+ }
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return err;
+}
+
+static int crypto_kdf_ctr_create(struct crypto_template *tmpl,
+ struct rtattr **tb)
+{
+ return crypto_kdf_alloc_common(tmpl, tb, "kdf_ctr",
+ crypto_kdf_ctr_random);
+}
+
+static struct crypto_template crypto_kdf_ctr_tmpl = {
+ .name = "kdf_ctr",
+ .create = crypto_kdf_ctr_create,
+ .free = rng_free_instance,
+ .module = THIS_MODULE,
+};
+
+static int crypto_kdf_fb_create(struct crypto_template *tmpl,
+ struct rtattr **tb) {
+ return crypto_kdf_alloc_common(tmpl, tb, "kdf_fb",
+ crypto_kdf_fb_random);
+}
+
+static struct crypto_template crypto_kdf_fb_tmpl = {
+ .name = "kdf_fb",
+ .create = crypto_kdf_fb_create,
+ .free = rng_free_instance,
+ .module = THIS_MODULE,
+};
+
+static int crypto_kdf_dpi_create(struct crypto_template *tmpl,
+ struct rtattr **tb) {
+ return crypto_kdf_alloc_common(tmpl, tb, "kdf_dpi",
+ crypto_kdf_dpi_random);
+}
+
+static struct crypto_template crypto_kdf_dpi_tmpl = {
+ .name = "kdf_dpi",
+ .create = crypto_kdf_dpi_create,
+ .free = rng_free_instance,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_kdf_init(void)
+{
+ int err = crypto_register_template(&crypto_kdf_ctr_tmpl);
+
+ if (err)
+ return err;
+
+ err = crypto_register_template(&crypto_kdf_fb_tmpl);
+ if (err) {
+ crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+ return err;
+ }
+
+ err = crypto_register_template(&crypto_kdf_dpi_tmpl);
+ if (err) {
+ crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+ crypto_unregister_template(&crypto_kdf_fb_tmpl);
+ }
+ return err;
+}
+
+static void __exit crypto_kdf_exit(void)
+{
+ crypto_unregister_template(&crypto_kdf_ctr_tmpl);
+ crypto_unregister_template(&crypto_kdf_fb_tmpl);
+ crypto_unregister_template(&crypto_kdf_dpi_tmpl);
+}
+
+module_init(crypto_kdf_init);
+module_exit(crypto_kdf_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Key Derivation Function according to SP800-108");
+MODULE_ALIAS_CRYPTO("kdf_ctr");
+MODULE_ALIAS_CRYPTO("kdf_fb");
+MODULE_ALIAS_CRYPTO("kdf_dpi");
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/4] crypto: kdf - enable compilation
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
` (2 preceding siblings ...)
2016-01-26 6:20 ` [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
@ 2016-01-26 6:21 ` Stephan Mueller
2016-01-27 5:14 ` [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Herbert Xu
4 siblings, 0 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 6:21 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto
Include KDF into Kconfig and Makefile for compilation
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/Kconfig | 7 +++++++
crypto/Makefile | 1 +
2 files changed, 8 insertions(+)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7240821..aa4e1a4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -355,6 +355,13 @@ config CRYPTO_KEYWRAP
Support for key wrapping (NIST SP800-38F / RFC3394) without
padding.
+config CRYPTO_KDF
+ tristate "Key Derivation Function (SP800-108)"
+ select CRYPTO_RNG
+ help
+ Support for KDF compliant to SP800-108. All three types of
+ KDF specified in SP800-108 are implemented.
+
comment "Hash modes"
config CRYPTO_CMAC
diff --git a/crypto/Makefile b/crypto/Makefile
index 2acdbbd..79a2092 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
obj-$(CONFIG_CRYPTO_XTS) += xts.o
obj-$(CONFIG_CRYPTO_CTR) += ctr.o
obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_KDF) += kdf.o
obj-$(CONFIG_CRYPTO_GCM) += gcm.o
obj-$(CONFIG_CRYPTO_CCM) += ccm.o
obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-01-26 6:20 ` [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
@ 2016-01-26 10:28 ` Herbert Xu
2016-01-26 13:20 ` Stephan Mueller
0 siblings, 1 reply; 11+ messages in thread
From: Herbert Xu @ 2016-01-26 10:28 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto
On Tue, Jan 26, 2016 at 07:20:59AM +0100, Stephan Mueller wrote:
>
> +/*
> + * Implementation of the KDF in counter mode according to SP800-108 section 5.1.
> + *
> + * The caller must provide Label || 0x00 || Context in src. This src pointer
> + * may also be NULL if the caller wishes not to provide anything.
> + */
> +static int crypto_kdf_ctr_random(struct crypto_rng *rng,
> + const u8 *src, unsigned int slen,
> + u8 *dst, unsigned int dlen)
> +{
> + struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
> + struct shash_desc *desc = &ctx->shash;
> + unsigned int h = crypto_shash_digestsize(desc->tfm);
> + int err = 0;
> + u8 *dst_orig = dst;
> + u32 i = 1;
> + u8 iteration[sizeof(u32)];
> +
> + /* enforce the note from above */
> + if (dlen != h && src == dst)
> + return -EINVAL;
Why is this an RNG? It always produces exactly h bytes so it looks
like a hash function to me, no?
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-01-26 10:28 ` Herbert Xu
@ 2016-01-26 13:20 ` Stephan Mueller
0 siblings, 0 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-26 13:20 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto
Am Dienstag, 26. Januar 2016, 18:28:14 schrieb Herbert Xu:
Hi Herbert,
>On Tue, Jan 26, 2016 at 07:20:59AM +0100, Stephan Mueller wrote:
>> +/*
>> + * Implementation of the KDF in counter mode according to SP800-108
>> section 5.1. + *
>> + * The caller must provide Label || 0x00 || Context in src. This src
>> pointer + * may also be NULL if the caller wishes not to provide anything.
>> + */
>> +static int crypto_kdf_ctr_random(struct crypto_rng *rng,
>> + const u8 *src, unsigned int slen,
>> + u8 *dst, unsigned int dlen)
>> +{
>> + struct crypto_kdf_ctx *ctx = crypto_tfm_ctx(crypto_rng_tfm(rng));
>> + struct shash_desc *desc = &ctx->shash;
>> + unsigned int h = crypto_shash_digestsize(desc->tfm);
>> + int err = 0;
>> + u8 *dst_orig = dst;
>> + u32 i = 1;
>> + u8 iteration[sizeof(u32)];
>> +
>> + /* enforce the note from above */
>> + if (dlen != h && src == dst)
>> + return -EINVAL;
>
>Why is this an RNG? It always produces exactly h bytes so it looks
>like a hash function to me, no?
It generates an arbitrary number of bytes like an RNG -- see dlen. The check
you quote here is only for the special case where the caller wants exactly h
bytes where he can have an in-place cipher operation.
When he wants to generate more data, then we cannot have dst and src pointing
to the same location. We have multiple loops we always require the use of the
original src data. Thus, when we have multiple loops, src would be overwritten
in the first loop iteration which means that with the second loop iteration,
we would not be compliant to the spec any more.
Ciao
Stephan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] crypto: Key Derivation Function (SP800-108)
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
` (3 preceding siblings ...)
2016-01-26 6:21 ` [PATCH 4/4] crypto: kdf - enable compilation Stephan Mueller
@ 2016-01-27 5:14 ` Herbert Xu
2016-01-27 7:33 ` Stephan Mueller
4 siblings, 1 reply; 11+ messages in thread
From: Herbert Xu @ 2016-01-27 5:14 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto
On Tue, Jan 26, 2016 at 07:19:17AM +0100, Stephan Mueller wrote:
> Hi,
>
> this patch set implements all three key derivation functions defined in
> SP800-108.
>
> The implementation is provided as a template for random number generators,
> since a KDF can be considered a form of deterministic RNG where the key
> material is used as a seed.
>
> With the KDF implemented as a template, all types of keyed hashes can be
> utilized, including HMAC and CMAC. The testmgr tests are derived from
> publicly available test vectors from NIST.
>
> The KDF are all tested with a complete round of CAVS testing on 32 and 64 bit.
>
> The patch set introduces an extension to the kernel crypto API in the first
> patch by adding a template handling for random number generators based on the
> same logic as for keyed hashes.
What is this going to use this inside the kernel?
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] crypto: Key Derivation Function (SP800-108)
2016-01-27 5:14 ` [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Herbert Xu
@ 2016-01-27 7:33 ` Stephan Mueller
2016-01-27 7:35 ` Herbert Xu
0 siblings, 1 reply; 11+ messages in thread
From: Stephan Mueller @ 2016-01-27 7:33 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto
Am Mittwoch, 27. Januar 2016, 13:14:09 schrieb Herbert Xu:
Hi Herbert,
>On Tue, Jan 26, 2016 at 07:19:17AM +0100, Stephan Mueller wrote:
>> Hi,
>>
>> this patch set implements all three key derivation functions defined in
>> SP800-108.
>>
>> The implementation is provided as a template for random number generators,
>> since a KDF can be considered a form of deterministic RNG where the key
>> material is used as a seed.
>>
>> With the KDF implemented as a template, all types of keyed hashes can be
>> utilized, including HMAC and CMAC. The testmgr tests are derived from
>> publicly available test vectors from NIST.
>>
>> The KDF are all tested with a complete round of CAVS testing on 32 and 64
>> bit.
>>
>> The patch set introduces an extension to the kernel crypto API in the first
>> patch by adding a template handling for random number generators based on
>> the same logic as for keyed hashes.
>
>What is this going to use this inside the kernel?
With the current development of EXT4 encryption we currently have the
logic that the files are either open (read/writable) or closed (not
accessible).
There is a scenario for a third option: a file is writable in a "device-
locked" state, but not readable. The logic that would implement such mechanism
is nicely described in [1] section D.3.3, especially figure 4. To use such a
mechanism, the generated shared secret should definitely go through a KDF to
ensure that the key has the right size for the underlying symmetric cipher.
This approach would allow locking your device, but yet the system could still
write confidential data (like getting emails, generating logs, etc.) but the
data is not accessible unless you unlock the device.
So, my idea was to provide a building block for such encryption scenarios
which I would think will come.
Besides, if crypto network protocols are contemplated to be included into the
kernel (like TLS), I would think that the KDF should be handled by the kernel
crypto API as a central place for such logic. Thus, my patch would provide the
framework by providing the RNG template handling to have that KDF here.
[1] https://www.niap-ccevs.org/pp/pp_md_v2.0.pdf
(PS: please only read D.3.3 and especially figure 4 from that document as I
think this is the only real nice and generally useful information in there)
Ciao
Stephan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] crypto: Key Derivation Function (SP800-108)
2016-01-27 7:33 ` Stephan Mueller
@ 2016-01-27 7:35 ` Herbert Xu
2016-01-27 8:03 ` Stephan Mueller
0 siblings, 1 reply; 11+ messages in thread
From: Herbert Xu @ 2016-01-27 7:35 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto
On Wed, Jan 27, 2016 at 08:33:00AM +0100, Stephan Mueller wrote:
>
> With the current development of EXT4 encryption we currently have the
> logic that the files are either open (read/writable) or closed (not
> accessible).
>
> There is a scenario for a third option: a file is writable in a "device-
> locked" state, but not readable. The logic that would implement such mechanism
> is nicely described in [1] section D.3.3, especially figure 4. To use such a
> mechanism, the generated shared secret should definitely go through a KDF to
> ensure that the key has the right size for the underlying symmetric cipher.
>
> This approach would allow locking your device, but yet the system could still
> write confidential data (like getting emails, generating logs, etc.) but the
> data is not accessible unless you unlock the device.
>
> So, my idea was to provide a building block for such encryption scenarios
> which I would think will come.
>
> Besides, if crypto network protocols are contemplated to be included into the
> kernel (like TLS), I would think that the KDF should be handled by the kernel
> crypto API as a central place for such logic. Thus, my patch would provide the
> framework by providing the RNG template handling to have that KDF here.
While this is all very nice until such a user is ready for submission
into the kernel I'd rather not add this.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] crypto: Key Derivation Function (SP800-108)
2016-01-27 7:35 ` Herbert Xu
@ 2016-01-27 8:03 ` Stephan Mueller
0 siblings, 0 replies; 11+ messages in thread
From: Stephan Mueller @ 2016-01-27 8:03 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto
Am Mittwoch, 27. Januar 2016, 15:35:41 schrieb Herbert Xu:
Hi Herbert,
>On Wed, Jan 27, 2016 at 08:33:00AM +0100, Stephan Mueller wrote:
>> With the current development of EXT4 encryption we currently have the
>> logic that the files are either open (read/writable) or closed (not
>> accessible).
>>
>> There is a scenario for a third option: a file is writable in a "device-
>> locked" state, but not readable. The logic that would implement such
>> mechanism is nicely described in [1] section D.3.3, especially figure 4.
>> To use such a mechanism, the generated shared secret should definitely go
>> through a KDF to ensure that the key has the right size for the underlying
>> symmetric cipher.
>>
>> This approach would allow locking your device, but yet the system could
>> still write confidential data (like getting emails, generating logs, etc.)
>> but the data is not accessible unless you unlock the device.
>>
>> So, my idea was to provide a building block for such encryption scenarios
>> which I would think will come.
>>
>> Besides, if crypto network protocols are contemplated to be included into
>> the kernel (like TLS), I would think that the KDF should be handled by the
>> kernel crypto API as a central place for such logic. Thus, my patch would
>> provide the framework by providing the RNG template handling to have that
>> KDF here.
>While this is all very nice until such a user is ready for submission
>into the kernel I'd rather not add this.
Ok, I have no problems with that. I put the patches onto my web server if
people are interested in it [1].
[1] http://www.chronox.de/kdf.html
Ciao
Stephan
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2016-01-27 8:03 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-26 6:19 [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-01-26 6:19 ` [PATCH 1/4] crypto: add template handling for RNGs Stephan Mueller
2016-01-26 6:20 ` [PATCH 2/4] crypto: kdf - add known answer tests Stephan Mueller
2016-01-26 6:20 ` [PATCH 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
2016-01-26 10:28 ` Herbert Xu
2016-01-26 13:20 ` Stephan Mueller
2016-01-26 6:21 ` [PATCH 4/4] crypto: kdf - enable compilation Stephan Mueller
2016-01-27 5:14 ` [PATCH 0/4] crypto: Key Derivation Function (SP800-108) Herbert Xu
2016-01-27 7:33 ` Stephan Mueller
2016-01-27 7:35 ` Herbert Xu
2016-01-27 8:03 ` Stephan Mueller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).