Skip to content

Add basic EVP_KEYMGMT API and libcrypto <-> provider interface#9312

Closed
levitte wants to merge 11 commits intoopenssl:masterfrom
levitte:evp_keymgmt
Closed

Add basic EVP_KEYMGMT API and libcrypto <-> provider interface#9312
levitte wants to merge 11 commits intoopenssl:masterfrom
levitte:evp_keymgmt

Conversation

@levitte
Copy link
Member

@levitte levitte commented Jul 4, 2019

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.

@levitte levitte added the branch: master Applies to master branch label Jul 4, 2019
@levitte
Copy link
Member Author

levitte commented Jul 4, 2019

Do note that this is a very early draft. The primary purpose for submitting this PR this early is to expose they ideas and get early feedback on the line of thoughts.

I hope that this will be useful for changes such as #9266

@levitte
Copy link
Member Author

levitte commented Jul 4, 2019

  • Key loading (HSM / hidden key support)

This is highly experimental for now, but does provide the necessary support for getting keys through provider OSSL_STORE backends. More on that in a separate PR.

@paulidale paulidale self-requested a review July 5, 2019 08:17
@paulidale
Copy link
Contributor

I really want to review this in more detail. I didn't get to it today and am too tired to think too hard this evening.

@petrovr
Copy link

petrovr commented Jul 8, 2019

Key Derivation?

I'm not sure about operations "Key loading" vs "Key import". Second is defined for private and public. What will load first one?

@petrovr
Copy link

petrovr commented Jul 8, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 8, 2019

Key Derivation?

Different operation, see #9266... but yes, it has occured to @mattcaswell and me that key exchange result in a key as well, that wasn't lost on us. There will be some form of integration eventually, I'm sure, but not now and not in this PR. Let's take it a step at a time, yeah?

@levitte
Copy link
Member Author

levitte commented Jul 8, 2019

Perhaps API could be based on basic(elementary/atomic) operations defined in "key management protocol".

Not sure if that would make things better or not. Maybe...

@levitte
Copy link
Member Author

levitte commented Jul 8, 2019

I'm not sure about operations "Key loading" vs "Key import".

The key import function takes key material from the input OSSL_PARAM array and creates a key from that input (usually a bunch of big numbers).
The key loading function is aimed at HSMs, and gives the option to "load" an HSM protected key given some kind of identity. The identity isn't defined at all for the moment, and I'm thinking of it as highly provider specific, i.e. unstandardised. My current thinking is that it can work together with a provider OSSL_STORE implementation that returns such identities instead of EVP_PKEYs, and leaves it to libcrypto to actually "load" the key given such an identity. I've an unsubmitted branch where I currently experiment with this.

@levitte
Copy link
Member Author

levitte commented Jul 9, 2019

Documentation added

@petrovr
Copy link

petrovr commented Jul 9, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 9, 2019

I think you need to read up in https://www.openssl.org/docs/OpenSSL300Design.html and https://www.openssl.org/docs/OpenSSLStrategicArchitecture.html. The former is what were working toward, and is the reason you're seeing so much moving around right now.

@petrovr
Copy link

petrovr commented Jul 9, 2019 via email

@levitte
Copy link
Member Author

levitte commented Jul 9, 2019

Working with different cryptographic libraries I note that common part is exchange of DER encoded data (key, cert). So instead ASN1 encoding you prefer data encoded as OSSL_PARAM, right?

We have chosen the OSSL_PARAM array as a data transfer medium between libcrypto and provider, yes. We wanted something that isn't tied to any particular form of serialization. I've realized after the fact that they have certain similarities with PKCS#11's attribute templates.

@levitte
Copy link
Member Author

levitte commented Jul 9, 2019

The key loading function is aimed at HSMs, and gives the option to "load" an HSM protected key given some kind of identity. The identity isn't defined at all for the moment, and I'm thinking of it as highly provider specific, i.e. unstandardised.

This cannot be restricted to "hardware" only. Software "key-store" may not allow private part to be exported.

Correct, I use "HSM" loosly, i.e. for something that keeps keys and other sensitive data for themselves.

@levitte levitte marked this pull request as ready for review July 11, 2019 11:10
@levitte levitte changed the title WIP: Add basic EVP_KEYMGMT API and libcrypto <-> provider interface Add basic EVP_KEYMGMT API and libcrypto <-> provider interface Jul 11, 2019
@levitte
Copy link
Member Author

levitte commented Jul 11, 2019

This is not a draft any more

@mattcaswell
Copy link
Member

"make doc-nits" is complaining.

Copy link
Member

@mattcaswell mattcaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some tests for this code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be documenting what "importdomain" actually does? Similarly with the other lines below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we should. I also think we should document the dispatch functions, I just dunno how, or rather where. (I'm trying to document in the header file at the very least, something we generally suck at, I might add...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whether in this PR or another, we're going to need to document all of these provider functions in the man pages. A provider author should be able to find all the information they need in the man pages, without have to read the source.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. For the core_numbers.h stuff, that will be another PR. I have ideas on that...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realised nothing is done about the case where all the slots of pk->pkeys are filled in and none of them matched the given keymgmt, i.e. we're not dropping any single entry from the cache... Needs to be fixed.

@levitte
Copy link
Member Author

levitte commented Jul 12, 2019

We should have some tests for this code.

Ah, in test/evp_extra_test.c? (I noticed that EVP_MD_fetch has a few tests there)

Sure, I will, if you add one for EVP_CIPHER_fetch 😉

@levitte
Copy link
Member Author

levitte commented Jul 12, 2019

"make doc-nits" is complaining.

Fixed

@levitte
Copy link
Member Author

levitte commented Jul 16, 2019

Looks like you need a rebase

Yup, I noticed. Especially with #9266 just being merged...

@levitte levitte force-pushed the evp_keymgmt branch 2 times, most recently from 8134a5b to 4017ca5 Compare July 16, 2019 10:45
@levitte
Copy link
Member Author

levitte commented Jul 16, 2019

Rebased and squashed, to get a clean slate.

@levitte levitte force-pushed the evp_keymgmt branch 2 times, most recently from 3c8faa8 to 5ad4970 Compare July 17, 2019 12:01
@levitte
Copy link
Member Author

levitte commented Jul 17, 2019

I think this is ready for final review. There was a failure in Travis, but that turned out to be an unrelated timeout. I've restarted that job, just for the hope of greenery 😉

Copy link
Member

@mattcaswell mattcaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. A couple of minor comments which may or may not be addressed before committing. Approval counts either way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence doesn't seem to quite make sense

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rephrased.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should add a TODO here (or somewhere else appropriate) to remind us to go and implement these for the various legacy keys that we have?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okie, added one here

levitte added 11 commits July 22, 2019 06:05
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.
This function is used to transport private key materia from whatever
is already attached to the EVP_PKEY to the new provider, using key
data export and import functionality.

If a legacy lower level key has been assigned to the EVP_PKEY, we use
its data to create a provider side key, and thereby have a bridge
between old style public key types and the EVP_PKEY on providers.

If successful, this function returns a reference to the appropriate
provider side data for the key.

This can be used by any operation that wants to use this key.
This affects all its callers: EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id().
They are now possible to called with "zero" values, i.e.:

    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(NULL, NULL);

or

    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(0, NULL);

This is suitable for provider use, as the key functionality is tied
with its keys, and the operation time is determined by the init
functions the EVP_PKEY_CTX is used with.
This function clears the cache of provider key references, and is used
in evp_keymgmt_export_to_provider() when the internal key is dirty, as
well as by EVP_PKEY_free_it().
@levitte
Copy link
Member Author

levitte commented Jul 22, 2019

Merged.

a94a3e0 Add basic EVP_KEYMGMT API and libcrypto <-> provider interface
70a1f7b Add evp_keymgmt_export_to_provider(), for key transfer between providers
d0ea49a Adapt int_ctx_new() to use with providers
4cae07f Add evp_keymgmt_clear_pkey_cache() and use it
fa9faf0 Add an internal API to access the KEYMGMT provider functions

@levitte levitte closed this Jul 22, 2019
levitte added a commit that referenced this pull request Jul 22, 2019
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 #9312)
levitte added a commit that referenced this pull request Jul 22, 2019
This function is used to transport private key materia from whatever
is already attached to the EVP_PKEY to the new provider, using key
data export and import functionality.

If a legacy lower level key has been assigned to the EVP_PKEY, we use
its data to create a provider side key, and thereby have a bridge
between old style public key types and the EVP_PKEY on providers.

If successful, this function returns a reference to the appropriate
provider side data for the key.

This can be used by any operation that wants to use this key.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #9312)
levitte added a commit that referenced this pull request Jul 22, 2019
This affects all its callers: EVP_PKEY_CTX_new(), EVP_PKEY_CTX_new_id().
They are now possible to called with "zero" values, i.e.:

    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(NULL, NULL);

or

    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(0, NULL);

This is suitable for provider use, as the key functionality is tied
with its keys, and the operation time is determined by the init
functions the EVP_PKEY_CTX is used with.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #9312)
levitte added a commit that referenced this pull request Jul 22, 2019
This function clears the cache of provider key references, and is used
in evp_keymgmt_export_to_provider() when the internal key is dirty, as
well as by EVP_PKEY_free_it().

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #9312)
levitte added a commit that referenced this pull request Jul 22, 2019
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #9312)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch: master Applies to master branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants