libressl/0041-kdftree-add-functions-implementing-KDF_TREE-function.patch

250 lines
7.4 KiB
Diff
Raw Normal View History

From 608d04f4bc23c308b6792b414b8782669379ff09 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Sat, 18 Apr 2020 14:17:34 +0300
Subject: [PATCH 41/87] kdftree: add functions implementing KDF_TREE function
Add support for KDF_TREE function from RFC 7836. Unline original RFC
which enforces using of GOST R 34.11 (Streebog-256), these functions are
made generic to use any EVP_MD underneath.
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
src/lib/libcrypto/Symbols.list | 2 +
src/lib/libcrypto/kdftree/kdftree.c | 156 ++++++++++++++++++++++++++++
src/lib/libcrypto/kdftree/kdftree.h | 47 +++++++++
3 files changed, 205 insertions(+)
create mode 100644 src/lib/libcrypto/kdftree/kdftree.c
create mode 100644 src/lib/libcrypto/kdftree/kdftree.h
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
index c4edd9eb6..287c86d2c 100644
--- a/src/lib/libcrypto/Symbols.list
+++ b/src/lib/libcrypto/Symbols.list
@@ -1838,6 +1838,8 @@ HMAC_Update
ISSUING_DIST_POINT_free
ISSUING_DIST_POINT_it
ISSUING_DIST_POINT_new
+KDF_TREE
+KDF_TREE_SIMPLE
LONG_it
MD4
MD4_Final
diff --git a/src/lib/libcrypto/kdftree/kdftree.c b/src/lib/libcrypto/kdftree/kdftree.c
new file mode 100644
index 000000000..4dc7b0096
--- /dev/null
+++ b/src/lib/libcrypto/kdftree/kdftree.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: tlstree.h,v 1.4 2019/11/21 20:02:20 tim Exp $ */
+/* Copyright (c) 2020, Dmitry Baryshkov
+ *
+ * Sponsored by ROSA Linux
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openssl/kdftree.h>
+#include <openssl/hmac.h>
+
+#include <string.h>
+
+#define l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+static int
+kdf_tree_block(HMAC_CTX *ctx,
+ const unsigned char *i, unsigned int i_length,
+ const unsigned char *label, unsigned int label_length,
+ const unsigned char *seed, unsigned int seed_length,
+ const unsigned char *l, unsigned int l_length,
+ unsigned char *out, unsigned int *length)
+{
+ /* i label 0x00 seed l */
+ static const unsigned char data[1] = { 0x00 };
+
+ if (!HMAC_Init_ex(ctx, NULL, 0, NULL, NULL) ||
+ !HMAC_Update(ctx, i, i_length) ||
+ !HMAC_Update(ctx, label, label_length) ||
+ !HMAC_Update(ctx, data, 1) ||
+ !HMAC_Update(ctx, seed, seed_length) ||
+ !HMAC_Update(ctx, l, l_length))
+ return 0;
+
+ return HMAC_Final(ctx, out, length);
+}
+
+int KDF_TREE(const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key, unsigned int key_length,
+ const unsigned char *label, unsigned int label_length,
+ const unsigned char *seed, unsigned int seed_length,
+ size_t r,
+ unsigned char *out, unsigned int length)
+{
+ HMAC_CTX ctx;
+ unsigned int i;
+ unsigned char i_block[4], l_block[8];
+ unsigned int l_length, l_off;
+ unsigned char *p;
+ int md_size = EVP_MD_size(md);
+
+ HMAC_CTX_init(&ctx);
+
+ if (!HMAC_Init_ex(&ctx, key, key_length, md, impl))
+ return 0;
+
+ p = l_block;
+ /* bitlength */
+ l2c(length >> 29, p);
+ l2c(length * 8, p);
+
+ /* Calculate how many bytes will it take */
+ for (l_off = 0; l_off < 8; l_off++)
+ if (l_block[l_off] != 0)
+ break;
+
+ l_length = 8 - l_off;
+ for (i = 1; length >= md_size; i++) {
+ unsigned int block = md_size;
+ p = i_block;
+ l2c(i, p);
+ if (!kdf_tree_block(&ctx,
+ i_block + 4 - r, r,
+ label, label_length,
+ seed, seed_length,
+ l_block + l_off, l_length,
+ out, &block)) {
+ HMAC_CTX_cleanup(&ctx);
+ return 0;
+ }
+ out += block;
+ length -= block;
+ }
+ if (length > 0) {
+ unsigned char tmp[EVP_MAX_MD_SIZE];
+ unsigned int block = length;
+
+ p = i_block;
+ l2c(i, p);
+ if (!kdf_tree_block(&ctx,
+ i_block + 4 - r, r,
+ label, label_length,
+ seed, seed_length,
+ l_block + l_off, l_length,
+ tmp, &block)) {
+ HMAC_CTX_cleanup(&ctx);
+ return 0;
+ }
+ memcpy(out, tmp, length);
+ }
+ HMAC_CTX_cleanup(&ctx);
+
+ return 1;
+}
+
+int KDF_TREE_SIMPLE(const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key, unsigned int key_length,
+ const unsigned char *label, unsigned int label_length,
+ const unsigned char *seed, unsigned int seed_length,
+ unsigned char *out)
+{
+ HMAC_CTX ctx;
+ static unsigned char data1[1] = { 0x01 };
+ unsigned char data2[2];
+ int d2_length;
+ int md_size = EVP_MD_size(md);
+ int ret = 1;
+
+ /* bitlength */
+ if (md_size >= 32) {
+ data2[0] = md_size / 32;
+ data2[1] = (md_size * 8) & 0xff;
+ d2_length = 2;
+ } else {
+ data2[0] = (md_size * 8) & 0xff;
+ d2_length = 1;
+ }
+
+ HMAC_CTX_init(&ctx);
+
+ if (!HMAC_Init_ex(&ctx, key, key_length, md, impl) ||
+ !kdf_tree_block(&ctx,
+ data1, 1,
+ label, label_length,
+ seed, seed_length,
+ data2, d2_length,
+ out, &md_size))
+ ret = 0;
+
+ HMAC_CTX_cleanup(&ctx);
+
+ return ret;
+}
diff --git a/src/lib/libcrypto/kdftree/kdftree.h b/src/lib/libcrypto/kdftree/kdftree.h
new file mode 100644
index 000000000..132f70690
--- /dev/null
+++ b/src/lib/libcrypto/kdftree/kdftree.h
@@ -0,0 +1,47 @@
+/* $OpenBSD: kdftree.h,v 1.4 2019/11/21 20:02:20 tim Exp $ */
+/* Copyright (c) 2020, Dmitry Baryshkov
+ *
+ * Sponsored by ROSA Linux
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef OPENSSL_HEADER_KDFTREE_H
+#define OPENSSL_HEADER_KDFTREE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <openssl/evp.h>
+
+/* See RFC 7836 Sections 4.4 */
+int KDF_TREE(const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key, unsigned int key_length,
+ const unsigned char *label, unsigned int label_length,
+ const unsigned char *seed, unsigned int seed_length,
+ size_t r,
+ unsigned char *out, unsigned int length);
+
+/* KDF function from RFC 7836 Section 4.5. Fast equivalent of KDF_TREE with r=1 and L=EVP_MD_size(md) */
+int KDF_TREE_SIMPLE(const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key, unsigned int key_length,
+ const unsigned char *label, unsigned int label_length,
+ const unsigned char *seed, unsigned int seed_length,
+ unsigned char *out);
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_KDFTREE_H */
--
2.17.1