* [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108)
@ 2016-08-09 12:27 Stephan Mueller
2016-08-09 12:27 ` [PATCH v5 1/4] crypto: add template handling for RNGs Stephan Mueller
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Stephan Mueller @ 2016-08-09 12:27 UTC (permalink / raw)
To: herbert; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
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 and
non-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.
Changes v5:
* move rng_instance and __crypto_rng_alg into rng.c
Changes v4:
* removal of the check that src and dst buffers are not the same from the KDF
implementations as requested by Herbert
* implement and use new free API in the RNG instance handling as requested
by Herbert
* move the instance handling code from include/crypto/rng.h to
include/crypto/internal/rng.h
Changes v3:
* port testmgr patch to current cryptodev-2.6 tree
* add non-keyed KDF references to testmgr.c
Changes v2:
* port to 4.7-rc1
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 | 508 ++++++++++++++++++++++++++++++++++++++++++
crypto/rng.c | 44 ++++
crypto/testmgr.c | 226 +++++++++++++++++++
crypto/testmgr.h | 110 +++++++++
include/crypto/internal/rng.h | 26 +++
7 files changed, 922 insertions(+)
create mode 100644 crypto/kdf.c
--
2.7.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 1/4] crypto: add template handling for RNGs
2016-08-09 12:27 [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
@ 2016-08-09 12:27 ` Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 2/4] crypto: kdf - add known answer tests Stephan Mueller
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Stephan Mueller @ 2016-08-09 12:27 UTC (permalink / raw)
To: herbert; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
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 | 44 +++++++++++++++++++++++++++++++++++++++++++
include/crypto/internal/rng.h | 26 +++++++++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/crypto/rng.c b/crypto/rng.c
index b81cffb..a4ee894 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -63,6 +63,25 @@ static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
return 0;
}
+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);
+}
+
+static void crypto_rng_free_instance(struct crypto_instance *inst)
+{
+ struct rng_instance *rng = rng_instance(inst);
+
+ rng->free(rng);
+}
+
static unsigned int seedsize(struct crypto_alg *alg)
{
struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
@@ -105,6 +124,7 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
static const struct crypto_type crypto_rng_type = {
.extsize = crypto_alg_extsize,
.init_tfm = crypto_rng_init_tfm,
+ .free = crypto_rng_free_instance,
#ifdef CONFIG_PROC_FS
.show = crypto_rng_show,
#endif
@@ -232,5 +252,29 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count)
}
EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
+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/internal/rng.h b/include/crypto/internal/rng.h
index a52ef34..aeaf58f 100644
--- a/include/crypto/internal/rng.h
+++ b/include/crypto/internal/rng.h
@@ -42,4 +42,30 @@ static inline void crypto_rng_set_entropy(struct crypto_rng *tfm,
crypto_rng_alg(tfm)->set_ent(tfm, data, len);
}
+struct rng_instance {
+ void (*free)(struct rng_instance *inst);
+ 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_instance) - 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));
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+ struct rng_instance *inst);
+
#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 2/4] crypto: kdf - add known answer tests
2016-08-09 12:27 [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-08-09 12:27 ` [PATCH v5 1/4] crypto: add template handling for RNGs Stephan Mueller
@ 2016-08-09 12:28 ` Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 4/4] crypto: kdf - enable compilation Stephan Mueller
3 siblings, 0 replies; 10+ messages in thread
From: Stephan Mueller @ 2016-08-09 12:28 UTC (permalink / raw)
To: herbert; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
Add known answer tests to the testmgr for the KDF (SP800-108) cipher.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/testmgr.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.h | 110 +++++++++++++++++++++++++++
2 files changed, 336 insertions(+)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index c2a8bd3..8ac1a2d 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -116,6 +116,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;
@@ -139,6 +144,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;
struct kpp_test_suite kpp;
} suite;
@@ -1758,6 +1764,64 @@ outbuf:
return ret;
}
+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 alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
@@ -3467,6 +3531,168 @@ 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_ctr(sha1)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(sha224)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(sha256)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(sha384)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_ctr(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_dpi(sha1)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(sha224)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(sha256)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(sha384)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_dpi(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 = "kdf_fb(sha1)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(sha224)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(sha256)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(sha384)",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "kdf_fb(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 acb6bbf..1fe93ed 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -123,6 +123,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;
@@ -25827,6 +25836,107 @@ 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.7.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-09 12:27 [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-08-09 12:27 ` [PATCH v5 1/4] crypto: add template handling for RNGs Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 2/4] crypto: kdf - add known answer tests Stephan Mueller
@ 2016-08-09 12:28 ` Stephan Mueller
2016-08-16 8:57 ` Herbert Xu
2016-08-09 12:28 ` [PATCH v5 4/4] crypto: kdf - enable compilation Stephan Mueller
3 siblings, 1 reply; 10+ messages in thread
From: Stephan Mueller @ 2016-08-09 12:28 UTC (permalink / raw)
To: herbert; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
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 | 508 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 508 insertions(+)
create mode 100644 crypto/kdf.c
diff --git a/crypto/kdf.c b/crypto/kdf.c
new file mode 100644
index 0000000..6f9f082
--- /dev/null
+++ b/crypto/kdf.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2016, 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: In-place cipher operations are not supported.
+ */
+
+#include <linux/module.h>
+#include <crypto/rng.h>
+#include <crypto/internal/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)];
+
+ 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)];
+
+ /* 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
+ * as well as SP800-56A section 5.8.1 (Single-step KDF).
+ *
+ * SP800-108:
+ * The caller must provide Label || 0x00 || Context in src. This src pointer
+ * may also be NULL if the caller wishes not to provide anything.
+ *
+ * SP800-56A:
+ * The key provided for the HMAC during the crypto_rng_reset shall NOT be the
+ * shared secret from the DH operation, but an independently generated key.
+ * The src pointer is defined as Z || other info where Z is the shared secret
+ * from DH and other info is an arbitrary string (see SP800-56A section
+ * 5.8.1.2).
+ */
+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)];
+
+ 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 void crypto_kdf_free(struct rng_instance *inst)
+{
+ crypto_drop_spawn(rng_instance_ctx(inst));
+ kfree(inst);
+}
+
+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());
+
+ inst->free = crypto_kdf_free;
+
+ err = rng_register_instance(tmpl, inst);
+
+ if (err) {
+out_free_inst:
+ crypto_kdf_free(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,
+ .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,
+ .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,
+ .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 and SP800-56A");
+MODULE_ALIAS_CRYPTO("kdf_ctr");
+MODULE_ALIAS_CRYPTO("kdf_fb");
+MODULE_ALIAS_CRYPTO("kdf_dpi");
--
2.7.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 4/4] crypto: kdf - enable compilation
2016-08-09 12:27 [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
` (2 preceding siblings ...)
2016-08-09 12:28 ` [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
@ 2016-08-09 12:28 ` Stephan Mueller
3 siblings, 0 replies; 10+ messages in thread
From: Stephan Mueller @ 2016-08-09 12:28 UTC (permalink / raw)
To: herbert; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
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 84d7148..16f3221 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -372,6 +372,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 99cc64a..9022280 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -80,6 +80,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.7.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-09 12:28 ` [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
@ 2016-08-16 8:57 ` Herbert Xu
2016-08-16 9:11 ` Stephan Mueller
0 siblings, 1 reply; 10+ messages in thread
From: Herbert Xu @ 2016-08-16 8:57 UTC (permalink / raw)
To: Stephan Mueller; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
On Tue, Aug 09, 2016 at 02:28:37PM +0200, Stephan Mueller wrote:
> 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>
So I have no problems with this functionality existing in the kernel,
assuming that the keys patch using it is accepted.
However, I'm still at a loss as to why this has to be done as
an RNG. IOW what benefit does implementing this as an RNG give
us compared to just using the underlying hash directly from the
keys subsystem?
In general the crypto API caters to algorithms that carry more
than one implementation, especially if one of them is hardware-
dependent. I really can't see how KDF would fit this criterion.
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] 10+ messages in thread
* Re: [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-16 8:57 ` Herbert Xu
@ 2016-08-16 9:11 ` Stephan Mueller
2016-08-16 9:13 ` Herbert Xu
0 siblings, 1 reply; 10+ messages in thread
From: Stephan Mueller @ 2016-08-16 9:11 UTC (permalink / raw)
To: Herbert Xu; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
Am Dienstag, 16. August 2016, 16:57:45 CEST schrieb Herbert Xu:
Hi Herbert,
> On Tue, Aug 09, 2016 at 02:28:37PM +0200, Stephan Mueller wrote:
> > 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>
>
> So I have no problems with this functionality existing in the kernel,
> assuming that the keys patch using it is accepted.
>
> However, I'm still at a loss as to why this has to be done as
> an RNG. IOW what benefit does implementing this as an RNG give
> us compared to just using the underlying hash directly from the
> keys subsystem?
>
> In general the crypto API caters to algorithms that carry more
> than one implementation, especially if one of them is hardware-
> dependent. I really can't see how KDF would fit this criterion.
The KDF is logically equivalent to a block chaining mode. As the KDF can be
applied to arbitrary hash types (keyed and non-keyed), I thought of how to
integrate it with the existing framework. None of the template mechanisms seem
to fit what the KDF does.
Conceptually, a KDF is a random number generator by generating arbitrarily
sized strings from a fixed "seed". This lead me to add the RNG template
handling. Even the existing DRBG is more or less a "block chaining mode" that
is very similar to a KDF. Hence, the current plethora of 22 registered DRBGs
could be elegantly eliminated if the DRBG is turned into template using the
proposed RNG framework.
If you think that a KDF should not be a generic mechanism, then the KDF logic
would need to move directly into the keys subsystem. But since TLS is
something folks speak about, a TLS KDF would need to be considered eventually
too which is yet again some form of RNG.
Ciao
Stephan
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-16 9:11 ` Stephan Mueller
@ 2016-08-16 9:13 ` Herbert Xu
2016-08-16 9:25 ` Stephan Mueller
0 siblings, 1 reply; 10+ messages in thread
From: Herbert Xu @ 2016-08-16 9:13 UTC (permalink / raw)
To: Stephan Mueller; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
On Tue, Aug 16, 2016 at 11:11:47AM +0200, Stephan Mueller wrote:
>
> Conceptually, a KDF is a random number generator by generating arbitrarily
> sized strings from a fixed "seed". This lead me to add the RNG template
> handling. Even the existing DRBG is more or less a "block chaining mode" that
> is very similar to a KDF. Hence, the current plethora of 22 registered DRBGs
> could be elegantly eliminated if the DRBG is turned into template using the
> proposed RNG framework.
The point is that there is no alternative implementation for kdf,
nor is there likely to be one.
> If you think that a KDF should not be a generic mechanism, then the KDF logic
> would need to move directly into the keys subsystem. But since TLS is
> something folks speak about, a TLS KDF would need to be considered eventually
> too which is yet again some form of RNG.
If a TLS KDF comes with a hardware implementation then we could
include it. Otherwise the answer would be the same.
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] 10+ messages in thread
* Re: [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-16 9:13 ` Herbert Xu
@ 2016-08-16 9:25 ` Stephan Mueller
2016-08-16 9:26 ` Herbert Xu
0 siblings, 1 reply; 10+ messages in thread
From: Stephan Mueller @ 2016-08-16 9:25 UTC (permalink / raw)
To: Herbert Xu; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
Am Dienstag, 16. August 2016, 17:13:47 CEST schrieb Herbert Xu:
Hi Herbert,
> On Tue, Aug 16, 2016 at 11:11:47AM +0200, Stephan Mueller wrote:
> > Conceptually, a KDF is a random number generator by generating arbitrarily
> > sized strings from a fixed "seed". This lead me to add the RNG template
> > handling. Even the existing DRBG is more or less a "block chaining mode"
> > that is very similar to a KDF. Hence, the current plethora of 22
> > registered DRBGs could be elegantly eliminated if the DRBG is turned into
> > template using the proposed RNG framework.
>
> The point is that there is no alternative implementation for kdf,
> nor is there likely to be one.
I was thinking of the DRBG implementation: decouple it from the underlying
ciphers. Though, I am not fully sure that will work as there are several
specific settings that depend on the underlying ciphers (e.g. the state of a
Hash DRBG with SHA-256 is 444 bits whereas a Hash DRBG with SHA-512 has 888
bits).
>
> > If you think that a KDF should not be a generic mechanism, then the KDF
> > logic would need to move directly into the keys subsystem. But since TLS
> > is something folks speak about, a TLS KDF would need to be considered
> > eventually too which is yet again some form of RNG.
>
> If a TLS KDF comes with a hardware implementation then we could
> include it. Otherwise the answer would be the same.
It is certainly not an issue to move the KDF logic into the keys subsystem.
However, as it (may) resemble SP800-56A which is in line with FIPS 140-2,
folks may ask for a FIPS stamp on it. If a FIPS stamp is asked for, the KDF
itself must be subject to a self test (like what we have in testmgr.c). If we
move the KDF to the keys subsystem, the self test would then need to be
implemented there.
Ciao
Stephan
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function
2016-08-16 9:25 ` Stephan Mueller
@ 2016-08-16 9:26 ` Herbert Xu
0 siblings, 0 replies; 10+ messages in thread
From: Herbert Xu @ 2016-08-16 9:26 UTC (permalink / raw)
To: Stephan Mueller; +Cc: mathew.j.martineau, dhowells, linux-crypto, keyrings
On Tue, Aug 16, 2016 at 11:25:33AM +0200, Stephan Mueller wrote:
>> I was thinking of the DRBG implementation: decouple it from the underlying
> ciphers. Though, I am not fully sure that will work as there are several
> specific settings that depend on the underlying ciphers (e.g. the state of a
> Hash DRBG with SHA-256 is 444 bits whereas a Hash DRBG with SHA-512 has 888
> bits).
The only reason DRBG is in crypto is because it implements stdrng.
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] 10+ messages in thread
end of thread, other threads:[~2016-08-16 9:27 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-09 12:27 [PATCH v5 0/4] crypto: Key Derivation Function (SP800-108) Stephan Mueller
2016-08-09 12:27 ` [PATCH v5 1/4] crypto: add template handling for RNGs Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 2/4] crypto: kdf - add known answer tests Stephan Mueller
2016-08-09 12:28 ` [PATCH v5 3/4] crypto: kdf - SP800-108 Key Derivation Function Stephan Mueller
2016-08-16 8:57 ` Herbert Xu
2016-08-16 9:11 ` Stephan Mueller
2016-08-16 9:13 ` Herbert Xu
2016-08-16 9:25 ` Stephan Mueller
2016-08-16 9:26 ` Herbert Xu
2016-08-09 12:28 ` [PATCH v5 4/4] crypto: kdf - enable compilation Stephan Mueller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox