diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2019-09-05 16:04:43 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2019-09-05 16:04:43 +0000 |
commit | 23355bb2d9b8b1e6dc858a27fcd08fae97d032df (patch) | |
tree | c37153fcee78c6ea616b1f6ddd22aec63e998749 | |
parent | d10988fc0026109f8ab4fd6fb76b1feb609129ff (diff) |
Provide ECDH KDF for X9.63 as needed for CMS ECC.
From OpenSSL 1.1.1b.
ok tb@ inoguchi@
-rw-r--r-- | lib/libcrypto/ecdh/ecdh_kdf.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/libcrypto/ecdh/ecdh_kdf.c b/lib/libcrypto/ecdh/ecdh_kdf.c new file mode 100644 index 00000000000..d686f9d897d --- /dev/null +++ b/lib/libcrypto/ecdh/ecdh_kdf.c @@ -0,0 +1,81 @@ +/* + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <string.h> +#include <openssl/ec.h> +#include <openssl/evp.h> +#include "ec_lcl.h" + +/* Key derivation function from X9.63/SECG */ +/* Way more than we will ever need */ +#define ECDH_KDF_MAX (1 << 30) + +int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md) +{ + EVP_MD_CTX *mctx = NULL; + int rv = 0; + unsigned int i; + size_t mdlen; + unsigned char ctr[4]; + if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX + || Zlen > ECDH_KDF_MAX) + return 0; + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + return 0; + mdlen = EVP_MD_size(md); + for (i = 1;; i++) { + unsigned char mtmp[EVP_MAX_MD_SIZE]; + if (!EVP_DigestInit_ex(mctx, md, NULL)) + goto err; + ctr[3] = i & 0xFF; + ctr[2] = (i >> 8) & 0xFF; + ctr[1] = (i >> 16) & 0xFF; + ctr[0] = (i >> 24) & 0xFF; + if (!EVP_DigestUpdate(mctx, Z, Zlen)) + goto err; + if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr))) + goto err; + if (!EVP_DigestUpdate(mctx, sinfo, sinfolen)) + goto err; + if (outlen >= mdlen) { + if (!EVP_DigestFinal(mctx, out, NULL)) + goto err; + outlen -= mdlen; + if (outlen == 0) + break; + out += mdlen; + } else { + if (!EVP_DigestFinal(mctx, mtmp, NULL)) + goto err; + memcpy(out, mtmp, outlen); + OPENSSL_cleanse(mtmp, mdlen); + break; + } + } + rv = 1; + err: + EVP_MD_CTX_free(mctx); + return rv; +} + +/*- + * The old name for ecdh_KDF_X9_63 + * Retained for ABI compatibility + */ +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md) +{ + return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md); +} |