Skip to content

Commit

Permalink
Added EVP_KDF (similiar to the EVP_MAC)
Browse files Browse the repository at this point in the history
Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Richard Levitte <[email protected]>
(Merged from openssl#8808)
  • Loading branch information
slontis authored and levitte committed May 3, 2019
1 parent e616c11 commit d2ba812
Show file tree
Hide file tree
Showing 21 changed files with 336 additions and 204 deletions.
2 changes: 1 addition & 1 deletion crypto/evp/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SOURCE[../../libcrypto]=\
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_allc.c c_alld.c evp_lib.c bio_ok.c \
evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
pkey_kdf.c \
pkey_kdf.c c_allkdf.c \
e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
e_chacha20_poly1305.c cmeth_lib.c \
Expand Down
23 changes: 23 additions & 0 deletions crypto/evp/c_allkdf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (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 <openssl/evp.h>
#include "internal/evp_int.h"

void openssl_add_all_kdfs_int(void)
{
EVP_add_kdf(&pbkdf2_kdf_meth);
#ifndef OPENSSL_NO_SCRYPT
EVP_add_kdf(&scrypt_kdf_meth);
#endif
EVP_add_kdf(&tls1_prf_kdf_meth);
EVP_add_kdf(&hkdf_kdf_meth);
EVP_add_kdf(&sshkdf_kdf_meth);
EVP_add_kdf(&ss_kdf_meth);
}
2 changes: 1 addition & 1 deletion crypto/evp/evp_locl.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct evp_mac_ctx_st {
} /* EVP_MAC_CTX */;

struct evp_kdf_ctx_st {
const EVP_KDF_METHOD *kmeth;
const EVP_KDF *meth; /* Method structure */
EVP_KDF_IMPL *impl; /* Algorithm-specific data */
} /* EVP_KDF_CTX */ ;

Expand Down
98 changes: 32 additions & 66 deletions crypto/evp/kdf_lib.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
Expand All @@ -20,78 +20,45 @@
#include "internal/numbers.h"
#include "evp_locl.h"

typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);

/* This array needs to be in order of NIDs */
static const EVP_KDF_METHOD *standard_methods[] = {
&pbkdf2_kdf_meth,
#ifndef OPENSSL_NO_SCRYPT
&scrypt_kdf_meth,
#endif
&tls1_prf_kdf_meth,
&hkdf_kdf_meth,
&sshkdf_kdf_meth,
&ss_kdf_meth
};

DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);

static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
const EVP_KDF_METHOD *const *b)
EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf)
{
return ((*a)->type - (*b)->type);
EVP_KDF_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_KDF_CTX));

if (ctx == NULL || (ctx->impl = kdf->new()) == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ctx);
ctx = NULL;
} else {
ctx->meth = kdf;
}
return ctx;
}

IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);

static const EVP_KDF_METHOD *kdf_meth_find(int type)
EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
{
EVP_KDF_METHOD tmp;
const EVP_KDF_METHOD *t = &tmp, **ret;
const EVP_KDF *kdf = EVP_get_kdfbynid(id);

tmp.type = type;
ret = OBJ_bsearch_kmeth(&t, standard_methods,
OSSL_NELEM(standard_methods));
if (ret == NULL || *ret == NULL)
if (kdf == NULL)
return NULL;

return *ret;
return EVP_KDF_CTX_new(kdf);
}

EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
int EVP_KDF_nid(const EVP_KDF *kdf)
{
EVP_KDF_CTX *ret;
const EVP_KDF_METHOD *kmeth;

kmeth = kdf_meth_find(id);
if (kmeth == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}

ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
return NULL;
}

if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
EVP_KDF_CTX_free(ret);
return NULL;
}
return kdf->type;
}

ret->kmeth = kmeth;
return ret;
const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx)
{
return ctx->meth;
}

void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return;

ctx->kmeth->free(ctx->impl);
ctx->meth->free(ctx->impl);
OPENSSL_free(ctx);
}

Expand All @@ -100,8 +67,8 @@ void EVP_KDF_reset(EVP_KDF_CTX *ctx)
if (ctx == NULL)
return;

if (ctx->kmeth->reset != NULL)
ctx->kmeth->reset(ctx->impl);
if (ctx->meth->reset != NULL)
ctx->meth->reset(ctx->impl);
}

int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
Expand All @@ -124,7 +91,7 @@ int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
if (ctx == NULL)
return 0;

return ctx->kmeth->ctrl(ctx->impl, cmd, args);
return ctx->meth->ctrl(ctx->impl, cmd, args);
}

int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
Expand All @@ -134,12 +101,12 @@ int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
if (ctx == NULL)
return 0;

if (ctx->kmeth->ctrl_str == NULL) {
if (ctx->meth->ctrl_str == NULL) {
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}

ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
ret = ctx->meth->ctrl_str(ctx->impl, type, value);
if (ret == -2)
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);

Expand All @@ -151,17 +118,16 @@ size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
if (ctx == NULL)
return 0;

if (ctx->kmeth->size == NULL)
if (ctx->meth->size == NULL)
return SIZE_MAX;

return ctx->kmeth->size(ctx->impl);
return ctx->meth->size(ctx->impl);
}

int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
{
if (ctx == NULL)
return 0;

return ctx->kmeth->derive(ctx->impl, key, keylen);
return ctx->meth->derive(ctx->impl, key, keylen);
}

33 changes: 32 additions & 1 deletion crypto/evp/names.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/objects.h"
#include <openssl/x509.h>
#include "internal/evp_int.h"
Expand Down Expand Up @@ -71,6 +72,23 @@ int EVP_add_mac(const EVP_MAC *m)
return r;
}

/* TODO(3.0) Is this needed after changing to providers? */
int EVP_add_kdf(const EVP_KDF *k)
{
int r;

if (k == NULL)
return 0;

r = OBJ_NAME_add(OBJ_nid2sn(k->type), OBJ_NAME_TYPE_KDF_METH,
(const char *)k);
if (r == 0)
return 0;
r = OBJ_NAME_add(OBJ_nid2ln(k->type), OBJ_NAME_TYPE_KDF_METH,
(const char *)k);
return r;
}

const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
{
const EVP_CIPHER *cp;
Expand Down Expand Up @@ -104,9 +122,22 @@ const EVP_MAC *EVP_get_macbyname(const char *name)
return mp;
}

/* TODO(3.0) Is this API needed after implementing providers? */
const EVP_KDF *EVP_get_kdfbyname(const char *name)
{
const EVP_KDF *kdf;

if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_KDFS, NULL))
return NULL;

kdf = (const EVP_KDF *)OBJ_NAME_get(name, OBJ_NAME_TYPE_KDF_METH);
return kdf;
}

void evp_cleanup_int(void)
{
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH);
OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH);
OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
/*
Expand Down Expand Up @@ -207,6 +238,7 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
}

/* TODO(3.0) Are these do_all API's needed for MAC? */
struct doall_mac {
void *arg;
void (*fn) (const EVP_MAC *ciph,
Expand Down Expand Up @@ -250,4 +282,3 @@ void EVP_MAC_do_all_sorted(void (*fn)
dc.arg = arg;
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
}

18 changes: 10 additions & 8 deletions crypto/include/internal/evp_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ const EVP_MD *evp_keccak_kmac256(void);
* object database.
*/
int EVP_add_mac(const EVP_MAC *mac);
int EVP_add_kdf(const EVP_KDF *kdf);

/* struct evp_kdf_impl_st is defined by the implementation */
typedef struct evp_kdf_impl_st EVP_KDF_IMPL;
typedef struct {
struct evp_kdf_st {
int type;
EVP_KDF_IMPL *(*new) (void);
void (*free) (EVP_KDF_IMPL *impl);
Expand All @@ -163,14 +164,14 @@ typedef struct {
int (*ctrl_str) (EVP_KDF_IMPL *impl, const char *type, const char *value);
size_t (*size) (EVP_KDF_IMPL *impl);
int (*derive) (EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen);
} EVP_KDF_METHOD;
};

extern const EVP_KDF_METHOD pbkdf2_kdf_meth;
extern const EVP_KDF_METHOD scrypt_kdf_meth;
extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
extern const EVP_KDF_METHOD hkdf_kdf_meth;
extern const EVP_KDF_METHOD sshkdf_kdf_meth;
extern const EVP_KDF_METHOD ss_kdf_meth;
extern const EVP_KDF pbkdf2_kdf_meth;
extern const EVP_KDF scrypt_kdf_meth;
extern const EVP_KDF tls1_prf_kdf_meth;
extern const EVP_KDF hkdf_kdf_meth;
extern const EVP_KDF sshkdf_kdf_meth;
extern const EVP_KDF ss_kdf_meth;

struct evp_md_st {
/* nid */
Expand Down Expand Up @@ -528,6 +529,7 @@ struct evp_pkey_st {
void openssl_add_all_ciphers_int(void);
void openssl_add_all_digests_int(void);
void openssl_add_all_macs_int(void);
void openssl_add_all_kdfs_int(void);
void evp_cleanup_int(void);
void evp_app_cleanup_int(void);

Expand Down
29 changes: 29 additions & 0 deletions crypto/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,26 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_macs, ossl_init_add_all_macs)
return 1;
}

static CRYPTO_ONCE add_all_kdfs = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_kdfs)
{
/*
* OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
* pulling in all the macs during static linking
*/
#ifndef OPENSSL_NO_AUTOALGINIT
OSSL_TRACE(INIT, "openssl_add_all_kdfs_int()\n");
openssl_add_all_kdfs_int();
#endif
return 1;
}

DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_kdfs, ossl_init_add_all_kdfs)
{
/* Do nothing */
return 1;
}

static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
static int config_inited = 0;
static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
Expand Down Expand Up @@ -666,6 +686,15 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
&& !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs))
return 0;

if ((opts & OPENSSL_INIT_NO_ADD_ALL_KDFS)
&& !RUN_ONCE_ALT(&add_all_kdfs, ossl_init_no_add_all_kdfs,
ossl_init_add_all_kdfs))
return 0;

if ((opts & OPENSSL_INIT_ADD_ALL_KDFS)
&& !RUN_ONCE(&add_all_kdfs, ossl_init_add_all_kdfs))
return 0;

if ((opts & OPENSSL_INIT_ATFORK)
&& !openssl_init_fork_handlers())
return 0;
Expand Down
2 changes: 1 addition & 1 deletion crypto/kdf/hkdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
}
}

const EVP_KDF_METHOD hkdf_kdf_meth = {
const EVP_KDF hkdf_kdf_meth = {
EVP_KDF_HKDF,
kdf_hkdf_new,
kdf_hkdf_free,
Expand Down
2 changes: 1 addition & 1 deletion crypto/kdf/pbkdf2.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
impl->md, key, keylen);
}

const EVP_KDF_METHOD pbkdf2_kdf_meth = {
const EVP_KDF pbkdf2_kdf_meth = {
EVP_KDF_PBKDF2,
kdf_pbkdf2_new,
kdf_pbkdf2_free,
Expand Down
2 changes: 1 addition & 1 deletion crypto/kdf/scrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static int kdf_scrypt_derive(EVP_KDF_IMPL *impl, unsigned char *key,
impl->maxmem_bytes, key, keylen);
}

const EVP_KDF_METHOD scrypt_kdf_meth = {
const EVP_KDF scrypt_kdf_meth = {
EVP_KDF_SCRYPT,
kdf_scrypt_new,
kdf_scrypt_free,
Expand Down
2 changes: 1 addition & 1 deletion crypto/kdf/sshkdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ static int kdf_sshkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
impl->type, key, keylen);
}

const EVP_KDF_METHOD sshkdf_kdf_meth = {
const EVP_KDF sshkdf_kdf_meth = {
EVP_KDF_SSHKDF,
kdf_sshkdf_new,
kdf_sshkdf_free,
Expand Down
Loading

0 comments on commit d2ba812

Please sign in to comment.