Browse Source

Add basic EVP_KEYMGMT API and libcrypto <-> provider interface

The idea with the key management "operation" is to support the
following set of functionality:

- Key domain parameter generation
- Key domain parameter import
- Key domain parameter export

- Key generation
- Key import
- Key export
- Key loading (HSM / hidden key support)

With that set of function, we can support handling domain parameters
on one provider, key handling on another, and key usage on a third,
with transparent export / import of applicable data.  Of course, if a
provider doesn't offer export / import functionality, then all
operations surrounding a key must be performed with the same
provider.

This method also avoids having to do anything special with legacy
assignment of libcrypto key structures, i.e. EVP_PKEY_assign_RSA().
They will simply be used as keys to be exported from whenever they are
used with provider based operations.

This change only adds the EVP_KEYMGMT API and the libcrypto <->
provider interface.  Further changes will integrate them into existing
libcrypto functionality.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9312)
master
Richard Levitte 3 years ago
parent
commit
a94a3e0d91
10 changed files with 405 additions and 6 deletions
  1. +2
    -1
      crypto/evp/build.info
  2. +26
    -1
      crypto/evp/evp_locl.h
  3. +189
    -0
      crypto/evp/keymgmt_meth.c
  4. +19
    -3
      crypto/include/internal/evp_int.h
  5. +84
    -0
      doc/man3/EVP_KEYMGMT.pod
  6. +72
    -1
      include/openssl/core_numbers.h
  7. +6
    -0
      include/openssl/evp.h
  8. +2
    -0
      include/openssl/ossl_typ.h
  9. +4
    -0
      util/libcrypto.num
  10. +1
    -0
      util/private.num

+ 2
- 1
crypto/evp/build.info View File

@ -1,5 +1,6 @@
LIBS=../../libcrypto
$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c
$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c keymgmt_meth.c \
evp_utils.c
SOURCE[../../libcrypto]=$COMMON\
encode.c evp_key.c evp_cnf.c \
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\


+ 26
- 1
crypto/evp/evp_locl.h View File

@ -62,6 +62,32 @@ struct evp_kdf_ctx_st {
EVP_KDF_IMPL *impl; /* Algorithm-specific data */
} /* EVP_KDF_CTX */ ;
struct evp_keymgmt_st {
int id; /* libcrypto internal */
const char *name;
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
/* Domain parameter routines */
OSSL_OP_keymgmt_importdomparams_fn *importdomparams;
OSSL_OP_keymgmt_gendomparams_fn *gendomparams;
OSSL_OP_keymgmt_freedomparams_fn *freedomparams;
OSSL_OP_keymgmt_exportdomparams_fn *exportdomparams;
OSSL_OP_keymgmt_importdomparam_types_fn *importdomparam_types;
OSSL_OP_keymgmt_exportdomparam_types_fn *exportdomparam_types;
/* Key routines */
OSSL_OP_keymgmt_importkey_fn *importkey;
OSSL_OP_keymgmt_genkey_fn *genkey;
OSSL_OP_keymgmt_loadkey_fn *loadkey;
OSSL_OP_keymgmt_freekey_fn *freekey;
OSSL_OP_keymgmt_exportkey_fn *exportkey;
OSSL_OP_keymgmt_importkey_types_fn *importkey_types;
OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
} /* EVP_KEYMGMT */ ;
struct evp_keyexch_st {
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
@ -76,7 +102,6 @@ struct evp_keyexch_st {
OSSL_OP_keyexch_set_params_fn *set_params;
} /* EVP_KEYEXCH */;
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md,


+ 189
- 0
crypto/evp/keymgmt_meth.c View File

@ -0,0 +1,189 @@
/*
* 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/crypto.h>
#include <openssl/core_numbers.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/provider.h"
#include "internal/refcount.h"
#include "internal/evp_int.h"
#include "evp_locl.h"
static void *keymgmt_new(void)
{
EVP_KEYMGMT *keymgmt = NULL;
if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
|| (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
keymgmt->refcnt = 1;
return keymgmt;
}
static void *keymgmt_from_dispatch(const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov)
{
EVP_KEYMGMT *keymgmt = NULL;
if ((keymgmt = keymgmt_new()) == NULL)
return NULL;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS:
if (keymgmt->importdomparams != NULL)
break;
keymgmt->importdomparams =
OSSL_get_OP_keymgmt_importdomparams(fns);
break;
case OSSL_FUNC_KEYMGMT_GENDOMPARAMS:
if (keymgmt->gendomparams != NULL)
break;
keymgmt->gendomparams = OSSL_get_OP_keymgmt_gendomparams(fns);
break;
case OSSL_FUNC_KEYMGMT_FREEDOMPARAMS:
if (keymgmt->freedomparams != NULL)
break;
keymgmt->freedomparams = OSSL_get_OP_keymgmt_freedomparams(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS:
if (keymgmt->exportdomparams != NULL)
break;
keymgmt->exportdomparams =
OSSL_get_OP_keymgmt_exportdomparams(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES:
if (keymgmt->importdomparam_types != NULL)
break;
keymgmt->importdomparam_types =
OSSL_get_OP_keymgmt_importdomparam_types(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES:
if (keymgmt->exportdomparam_types != NULL)
break;
keymgmt->exportdomparam_types =
OSSL_get_OP_keymgmt_exportdomparam_types(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTKEY:
if (keymgmt->importkey != NULL)
break;
keymgmt->importkey = OSSL_get_OP_keymgmt_importkey(fns);
break;
case OSSL_FUNC_KEYMGMT_GENKEY:
if (keymgmt->genkey != NULL)
break;
keymgmt->genkey = OSSL_get_OP_keymgmt_genkey(fns);
break;
case OSSL_FUNC_KEYMGMT_LOADKEY:
if (keymgmt->loadkey != NULL)
break;
keymgmt->loadkey = OSSL_get_OP_keymgmt_loadkey(fns);
break;
case OSSL_FUNC_KEYMGMT_FREEKEY:
if (keymgmt->freekey != NULL)
break;
keymgmt->freekey = OSSL_get_OP_keymgmt_freekey(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTKEY:
if (keymgmt->exportkey != NULL)
break;
keymgmt->exportkey = OSSL_get_OP_keymgmt_exportkey(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES:
if (keymgmt->importkey_types != NULL)
break;
keymgmt->importkey_types =
OSSL_get_OP_keymgmt_importkey_types(fns);
break;
case OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES:
if (keymgmt->exportkey_types != NULL)
break;
keymgmt->exportkey_types =
OSSL_get_OP_keymgmt_exportkey_types(fns);
break;
}
}
/*
* Try to check that the method is sensible.
* It makes no sense being able to free stuff if you can't create it.
* It makes no sense providing OSSL_PARAM descriptors for import and
* export if you can't import or export.
*/
if ((keymgmt->freedomparams != NULL
&& (keymgmt->importdomparams == NULL
&& keymgmt->gendomparams == NULL))
|| (keymgmt->freekey != NULL
&& (keymgmt->importkey == NULL
&& keymgmt->genkey == NULL
&& keymgmt->loadkey == NULL))
|| (keymgmt->importdomparam_types != NULL
&& keymgmt->importdomparams == NULL)
|| (keymgmt->exportdomparam_types != NULL
&& keymgmt->exportdomparams == NULL)
|| (keymgmt->importkey_types != NULL
&& keymgmt->importkey == NULL)
|| (keymgmt->exportkey_types != NULL
&& keymgmt->exportkey == NULL)) {
EVP_KEYMGMT_free(keymgmt);
EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
}
keymgmt->prov = prov;
if (prov != NULL)
ossl_provider_up_ref(prov);
return keymgmt;
}
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties)
{
EVP_KEYMGMT *keymgmt =
evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
keymgmt_from_dispatch,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
return keymgmt;
}
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
return 1;
}
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
if (keymgmt == NULL)
return;
CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
if (ref > 0)
return;
ossl_provider_free(keymgmt->prov);
CRYPTO_THREAD_lock_free(keymgmt->lock);
OPENSSL_free(keymgmt);
}
const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->prov;
}

+ 19
- 3
crypto/include/internal/evp_int.h View File

@ -504,9 +504,9 @@ typedef struct {
* method, as in, can it do arbitrary encryption....
*/
struct evp_pkey_st {
/* == Legacy attributes == */
int type;
int save_type;
CRYPTO_REF_COUNT references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
@ -526,9 +526,25 @@ struct evp_pkey_st {
ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */
# endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
/* == Common attributes == */
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
int save_parameters;
/* == Provider attributes == */
/*
* To support transparent export/import between providers that
* support the methods for it, and still not having to do the
* export/import every time a key is used, we maintain a cache
* of imported key, indexed by provider address.
* pkeys[0] is *always* the "original" key.
*/
struct {
EVP_KEYMGMT *keymgmt;
void *provkey;
} pkeys[10];
} /* EVP_PKEY */ ;


+ 84
- 0
doc/man3/EVP_KEYMGMT.pod View File

@ -0,0 +1,84 @@
=pod
=head1 NAME
EVP_KEYMGMT,
EVP_KEYMGMT_fetch,
EVP_KEYMGMT_up_ref,
EVP_KEYMGMT_free,
EVP_KEYMGMT_provider
- EVP key management routines
=head1 SYNOPSIS
#include <openssl/evp.h>
typedef struct evp_keymgmt_st EVP_KEYMGMT;
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties);
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt);
=head1 DESCRIPTION
B<EVP_KEYMGMT> is a method object that represents key management
implementations for different cryptographic algorithms.
This method object provides functionality to have providers import key
material from the outside, as well as export key material to the
outside.
Most of the functionality can only be used internally and has no
public interface, this object is simply passed into other functions
when needed.
EVP_KEYMGMT_fetch() looks for an algorithm within the provider that
has been loaded into the B<OPENSSL_CTX> given by I<ctx>, having the
name given by I<algorithm> and the properties given by I<properties>.
EVP_KEYMGMT_up_ref() increments the reference count for the given
B<EVP_KEYMGMT> I<keymgmt>.
EVP_KEYMGMT_free() decrements the reference count for the given
B<EVP_KEYMGMT> I<keymgmt>, and when the count reaches zero, frees it.
EVP_KEYMGMT_provider() returns the provider that has this particular
implementation.
=head1 NOTES
EVP_KEYMGMT_fetch() may be called implicitly by other fetching
functions, using the same library context and properties.
Any other API that uses keys will typically do this.
=head1 RETURN VALUES
EVP_KEYMGMT_fetch() returns a pointer to the key management
implementation represented by an EVP_KEYMGMT object, or NULL on
error.
EVP_KEYMGMT_up_ref() returns 1 on success, or 0 on error.
EVP_KEYMGMT_free() doesn't return any value.
EVP_KEYMGMT_provider() returns a pointer to a provider object, or NULL
on error.
=head1 SEE ALSO
L<EVP_MD_fetch(3)>, L<OPENSSL_CTX(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT
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
L<https://www.openssl.org/source/license.html>.
=cut

+ 72
- 1
include/openssl/core_numbers.h View File

@ -229,9 +229,80 @@ OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *cctx,
OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *cctx,
const OSSL_PARAM params[]))
/*-
* Key management
*
* Key domain parameter references can be created in several manners:
* - by importing the domain parameter material via an OSSL_PARAM array.
* - by generating key domain parameters, given input via an OSSL_PARAM
* array.
*
* Key references can be created in several manners:
* - by importing the key material via an OSSL_PARAM array.
* - by generating a key, given optional domain parameters and
* additional keygen parameters.
* If domain parameters are given, they must have been generated using
* the domain parameter generator functions.
* If the domain parameters comes from a different provider, results
* are undefined.
* THE CALLER MUST ENSURE THAT CORRECT DOMAIN PARAMETERS ARE USED.
* - by loading an internal key, given a binary blob that forms an identity.
* THE CALLER MUST ENSURE THAT A CORRECT IDENTITY IS USED.
*/
# define OSSL_OP_KEYMGMT 10
/* Key domain parameter creation and destruction */
# define OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS 1
# define OSSL_FUNC_KEYMGMT_GENDOMPARAMS 2
# define OSSL_FUNC_KEYMGMT_FREEDOMPARAMS 3
OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_importdomparams,
(void *provctx, const OSSL_PARAM params[]))
OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_gendomparams,
(void *provctx, const OSSL_PARAM params[]))
OSSL_CORE_MAKE_FUNC(void, OP_keymgmt_freedomparams, (void *domparams))
/* Key domain parameter export */
# define OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS 4
OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportdomparams,
(void *domparams, OSSL_PARAM params[]))
/* Key domain parameter discovery */
# define OSSL_FUNC_KEYMGMT_IMPORTDOMPARAM_TYPES 5
# define OSSL_FUNC_KEYMGMT_EXPORTDOMPARAM_TYPES 6
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_importdomparam_types,
(void))
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportdomparam_types,
(void))
/* Key creation and destruction */
# define OSSL_FUNC_KEYMGMT_IMPORTKEY 10
# define OSSL_FUNC_KEYMGMT_GENKEY 11
# define OSSL_FUNC_KEYMGMT_LOADKEY 12
# define OSSL_FUNC_KEYMGMT_FREEKEY 13
OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_importkey,
(void *provctx, const OSSL_PARAM params[]))
OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_genkey,
(void *provctx,
void *domparams, const OSSL_PARAM genkeyparams[]))
OSSL_CORE_MAKE_FUNC(void *, OP_keymgmt_loadkey,
(void *provctx, void *id, size_t idlen))
OSSL_CORE_MAKE_FUNC(void, OP_keymgmt_freekey, (void *key))
/* Key export */
# define OSSL_FUNC_KEYMGMT_EXPORTKEY 14
OSSL_CORE_MAKE_FUNC(int, OP_keymgmt_exportkey,
(void *key, OSSL_PARAM params[]))
/* Key discovery */
# define OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES 15
# define OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES 16
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_importkey_types, (void))
OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportkey_types, (void))
/* Key Exchange */
# define OSSL_OP_KEYEXCH 3
# define OSSL_OP_KEYEXCH 11
# define OSSL_FUNC_KEYEXCH_NEWCTX 1
# define OSSL_FUNC_KEYEXCH_INIT 2


+ 6
- 0
include/openssl/evp.h View File

@ -1411,6 +1411,12 @@ int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
size_t EVP_PKEY_meth_get_count(void);
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties);
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt);
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt);
const OSSL_PROVIDER *EVP_KEYMGMT_provider(const EVP_KEYMGMT *keymgmt);
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx);


+ 2
- 0
include/openssl/ossl_typ.h View File

@ -101,6 +101,8 @@ typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
typedef struct evp_keymgmt_st EVP_KEYMGMT;
typedef struct evp_kdf_st EVP_KDF;
typedef struct evp_kdf_ctx_st EVP_KDF_CTX;


+ 4
- 0
util/libcrypto.num View File

@ -4685,3 +4685,7 @@ EVP_KEYEXCH_up_ref 4790 3_0_0 EXIST::FUNCTION:
EVP_KEYEXCH_fetch 4791 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_set_dh_pad 4792 3_0_0 EXIST::FUNCTION:DH
EVP_PKEY_CTX_set_params 4793 3_0_0 EXIST::FUNCTION:
EVP_KEYMGMT_fetch 4794 3_0_0 EXIST::FUNCTION:
EVP_KEYMGMT_up_ref 4795 3_0_0 EXIST::FUNCTION:
EVP_KEYMGMT_free 4796 3_0_0 EXIST::FUNCTION:
EVP_KEYMGMT_provider 4797 3_0_0 EXIST::FUNCTION:

+ 1
- 0
util/private.num View File

@ -24,6 +24,7 @@ CRYPTO_EX_new datatype
DTLS_timer_cb datatype
EVP_KDF datatype
EVP_KDF_CTX datatype
EVP_KEYMGMT datatype
EVP_MAC datatype
EVP_MAC_CTX datatype
EVP_PKEY_gen_cb datatype


Loading…
Cancel
Save