From 608d04f4bc23c308b6792b414b8782669379ff09 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov 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 --- 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 +#include + +#include + +#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 + +/* 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