libressl/0086-kdftree-add-support-for-TLSTREE-rekeying-algorithm.patch

276 lines
8.7 KiB
Diff
Raw Normal View History

From 363239bfbe92bfe654c21f1b181531ebdd8fa8ad Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Sat, 18 Apr 2020 18:34:28 +0300
Subject: [PATCH 86/87] kdftree: add support for TLSTREE rekeying algorithm
GOST CTR-OMAC ciphersuites use external rekeying names TLSTREE. Add
support for this transformation.
Sponsored by ROSA Linux
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
src/lib/libcrypto/kdftree/kdftree.c | 3 +-
src/lib/libcrypto/kdftree/kdftree.h | 23 ++++
src/lib/libcrypto/kdftree/kdftree_locl.h | 31 +++++
src/lib/libcrypto/kdftree/tlstree.c | 154 +++++++++++++++++++++++
4 files changed, 210 insertions(+), 1 deletion(-)
create mode 100644 src/lib/libcrypto/kdftree/kdftree_locl.h
create mode 100644 src/lib/libcrypto/kdftree/tlstree.c
diff --git a/src/lib/libcrypto/kdftree/kdftree.c b/src/lib/libcrypto/kdftree/kdftree.c
index 4dc7b0096..957ca2875 100644
--- a/src/lib/libcrypto/kdftree/kdftree.c
+++ b/src/lib/libcrypto/kdftree/kdftree.c
@@ -18,6 +18,7 @@
#include <openssl/kdftree.h>
#include <openssl/hmac.h>
+#include "kdftree_locl.h"
#include <string.h>
@@ -26,7 +27,7 @@
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
-static int
+int
kdf_tree_block(HMAC_CTX *ctx,
const unsigned char *i, unsigned int i_length,
const unsigned char *label, unsigned int label_length,
diff --git a/src/lib/libcrypto/kdftree/kdftree.h b/src/lib/libcrypto/kdftree/kdftree.h
index 132f70690..378b06b51 100644
--- a/src/lib/libcrypto/kdftree/kdftree.h
+++ b/src/lib/libcrypto/kdftree/kdftree.h
@@ -40,6 +40,29 @@ int KDF_TREE_SIMPLE(const EVP_MD *md, ENGINE *impl,
const unsigned char *seed, unsigned int seed_length,
unsigned char *out);
+/* TLSTREE is an external re-keying function (see
+ * draft-smyshlyaev-tls12-gost-suites Section 8 for the definition, RFC 8645
+ * Section 5.2.2 for the discussion of the approach. */
+
+/* Opaque */
+typedef struct TLSTREE_CTX_st TLSTREE_CTX;
+
+typedef struct tlstree_const_st {
+ uint64_t c1, c2, c3;
+} TLSTREE_CONST;
+
+TLSTREE_CTX *TLSTREE_CTX_new(void);
+void TLSTREE_CTX_free(TLSTREE_CTX *ctx);
+
+int TLSTREE_Init(TLSTREE_CTX *ctx,
+ const TLSTREE_CONST *tlsconst,
+ const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key,
+ int key_length);
+int TLSTREE_GET(TLSTREE_CTX *ctx,
+ unsigned char *seq,
+ unsigned char *out);
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/src/lib/libcrypto/kdftree/kdftree_locl.h b/src/lib/libcrypto/kdftree/kdftree_locl.h
new file mode 100644
index 000000000..0eff3156d
--- /dev/null
+++ b/src/lib/libcrypto/kdftree/kdftree_locl.h
@@ -0,0 +1,31 @@
+/* $OpenBSD: kdftree_locl.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_LOCL_H
+#define OPENSSL_HEADER_KDFTREE_LOCL_H
+
+#include <openssl/hmac.h>
+
+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);
+
+#endif /* OPENSSL_HEADER_KDFTREE_LOCL_H */
diff --git a/src/lib/libcrypto/kdftree/tlstree.c b/src/lib/libcrypto/kdftree/tlstree.c
new file mode 100644
index 000000000..5c3322675
--- /dev/null
+++ b/src/lib/libcrypto/kdftree/tlstree.c
@@ -0,0 +1,154 @@
+/* $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 "kdftree_locl.h"
+#include <string.h>
+
+#define ll2c(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>48)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>40)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+#define c2ll(c,l) (l =((uint64_t)(*((c)++))) , \
+ l|=((uint64_t)(*((c)++)))<< 8, \
+ l|=((uint64_t)(*((c)++)))<<16, \
+ l|=((uint64_t)(*((c)++)))<<24, \
+ l|=((uint64_t)(*((c)++)))<<32, \
+ l|=((uint64_t)(*((c)++)))<<40, \
+ l|=((uint64_t)(*((c)++)))<<48, \
+ l|=((uint64_t)(*((c)++)))<<56)
+
+#define TLSTREE_L1 ((const unsigned char *)"level1")
+#define TLSTREE_L2 ((const unsigned char *)"level2")
+#define TLSTREE_L3 ((const unsigned char *)"level3")
+#define TLSTREE_L_LENGTH 6
+
+#define TLSTREE_KEY_LENGTH 32
+
+struct TLSTREE_CTX_st {
+ uint64_t seq;
+ const TLSTREE_CONST *tlsconst;
+ HMAC_CTX ctx1, ctx2, ctx3;
+ unsigned char current[TLSTREE_KEY_LENGTH];
+};
+
+TLSTREE_CTX *
+TLSTREE_CTX_new(void)
+{
+ TLSTREE_CTX *ctx;
+
+ ctx = malloc(sizeof(TLSTREE_CTX));
+ if (!ctx)
+ return NULL;
+
+ HMAC_CTX_init(&ctx->ctx1);
+ HMAC_CTX_init(&ctx->ctx2);
+ HMAC_CTX_init(&ctx->ctx3);
+ ctx->tlsconst = NULL;
+
+ return ctx;
+}
+
+void
+TLSTREE_CTX_free(TLSTREE_CTX *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ HMAC_CTX_cleanup(&ctx->ctx1);
+ HMAC_CTX_cleanup(&ctx->ctx2);
+ HMAC_CTX_cleanup(&ctx->ctx3);
+}
+
+static int tlstree_one(HMAC_CTX *ctx, const unsigned char *label, uint64_t seq, unsigned char *out)
+{
+ unsigned char seed[8], *p = seed;
+ static const unsigned char data1[1] = { 0x01 };
+ static const unsigned char data2[2] = { 0x01, 0x00 };
+ int dummy = TLSTREE_KEY_LENGTH;
+
+ ll2c(seq, p);
+ return kdf_tree_block(ctx, data1, 1, label, TLSTREE_L_LENGTH, seed, 8, data2, 2, out, &dummy);
+}
+
+int
+TLSTREE_Init(TLSTREE_CTX *ctx,
+ const TLSTREE_CONST *tlsconst,
+ const EVP_MD *md, ENGINE *impl,
+ const unsigned char *key,
+ int key_length)
+{
+ unsigned char tmp[TLSTREE_KEY_LENGTH];
+
+ /* Support only reasonable cases, which allow simplification of KDF_TREE calls */
+ if (key_length != EVP_MD_size(md) ||
+ key_length != TLSTREE_KEY_LENGTH)
+ return 0;
+
+ if (!ctx || !tlsconst || !md || !key)
+ return 0;
+
+ ctx->tlsconst = tlsconst;
+ ctx->seq = 0;
+
+ if (!HMAC_Init_ex(&ctx->ctx1, key, TLSTREE_KEY_LENGTH, md, impl) ||
+ !tlstree_one(&ctx->ctx1, TLSTREE_L1, 0, tmp) ||
+ !HMAC_Init_ex(&ctx->ctx2, tmp, TLSTREE_KEY_LENGTH, md, impl) ||
+ !tlstree_one(&ctx->ctx2, TLSTREE_L2, 0, tmp) ||
+ !HMAC_Init_ex(&ctx->ctx3, tmp, TLSTREE_KEY_LENGTH, md, impl) ||
+ !tlstree_one(&ctx->ctx3, TLSTREE_L3, 0, ctx->current))
+ return 0;
+
+ return 1;
+}
+
+int
+TLSTREE_GET(TLSTREE_CTX *ctx,
+ unsigned char *seq,
+ unsigned char *out)
+{
+ uint64_t s;
+ unsigned char *p = seq;
+ unsigned char tmp[TLSTREE_KEY_LENGTH];
+
+ c2ll(p, s);
+
+ if ((s & ctx->tlsconst->c1) != (ctx->seq & ctx->tlsconst->c1)) {
+ if (!tlstree_one(&ctx->ctx1, TLSTREE_L1, 0, tmp) ||
+ !HMAC_Init_ex(&ctx->ctx2, tmp, TLSTREE_KEY_LENGTH, NULL, NULL))
+ return 0;
+ }
+ if ((s & ctx->tlsconst->c2) != (ctx->seq & ctx->tlsconst->c2)) {
+ if (!tlstree_one(&ctx->ctx2, TLSTREE_L2, 0, tmp) ||
+ !HMAC_Init_ex(&ctx->ctx3, tmp, TLSTREE_KEY_LENGTH, NULL, NULL))
+ return 0;
+ }
+ if ((s & ctx->tlsconst->c3) != (ctx->seq & ctx->tlsconst->c3)) {
+ if (!tlstree_one(&ctx->ctx3, TLSTREE_L3, 0, ctx->current))
+ return 0;
+ }
+
+ memcpy(out, ctx->current, TLSTREE_KEY_LENGTH);
+
+ return 1;
+}
--
2.17.1