Skip to content

Move PKCS#3 DH to the default provider#9266

Closed
mattcaswell wants to merge 5 commits intoopenssl:masterfrom
mattcaswell:provider-dh
Closed

Move PKCS#3 DH to the default provider#9266
mattcaswell wants to merge 5 commits intoopenssl:masterfrom
mattcaswell:provider-dh

Conversation

@mattcaswell
Copy link
Member

This PR implements a new EVP_EXCHANGE type to represent key exchange algorithms. It then provides an implementation of PKCS#3 DH as an EVP_EXCHANGE algorithm in the default provider.

Note that only the shared secret derivation portion is covered at this stage. Key and parameter generation is deferred to later PRs.

@mattcaswell mattcaswell added the branch: master Applies to master branch label Jun 28, 2019
@mattcaswell
Copy link
Member Author

Rebased to fix merge conflict with master, and also to include some misc travis fixes.

@mattcaswell
Copy link
Member Author

More fixups pushed to try and address travis issues.

@levitte levitte self-requested a review June 28, 2019 19:15
Copy link
Contributor

@paulidale paulidale left a comment

Choose a reason for hiding this comment

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

Just a quick pass over and it looks good.
Neither comment is expecting a change, just questions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this worth being a separate PR?

BTW: I like this approach. The native types might stretch it a bit to handle things going out of scoping.

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 originally wrote this as a means to an end. If we think this is good general approach then I can have a go a pulling this out as a separate PR and making it more generic.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm willing to have a go at the other types once this is merged (or before). I coded something which addresses the alignment issues in #9246. That should be reusable.

The other thing I think that could be addressed is scoping -- it would be nice if a function could be called that added an auto variable to a template without losing the value. This shouldn't be too difficult to support. For the two string types and BIGNUM, it should also be possible (and the _PTR versions not cloning the value).

@levitte what do you think about this approach compared to #9246 and #9254 ? To me, it seems to sit nicely in the middle.

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'm willing to have a go at the other types once this is merged

Great. In that case. I'll leave this within this PR, and let you refactor it as part of a wider PR.

Copy link
Member

Choose a reason for hiding this comment

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

I see this a a temporary measure until we have better key management (i.e. where non-legacy keys are entirely managed in the provider and treated as an object in its own right rather than just a bunch or parameters passed via init).

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 see this a a temporary measure until we have better key management (i.e. where non-legacy keys are entirely managed in the provider and treated as an object in its own right rather than just a bunch or parameters passed via init).

Even with the better key management in place we will still need this. For example some keys will be loaded from file by libcrypto and then transferred to the provider. Or similarly keys will be exported from a provider. Or transferred from one provider to another. Some providers may not implement import/export, but I expect at least our providers will.

Copy link
Member

Choose a reason for hiding this comment

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

I guess we'll have to see.

Copy link
Contributor

Choose a reason for hiding this comment

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

Refer #9305 for a first stab at something similar but including other types.

Copy link
Member

@slontis slontis Jul 1, 2019

Choose a reason for hiding this comment

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

Could this be just key B<exchange> algorithm.
Maybe Keyexchange is a better name for the type???

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 find it more confusing to just write key B<exchange> algorithm.

I'm open to a different type name, but EVP_KEYEXCHANGE seems a little long. Other possibilities could be EVP_KEYEXCH, EVP_KEYEX, EVP_KEXCHANGE

Copy link
Member

Choose a reason for hiding this comment

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

I dont like EVP_KEYEX, either of the other 2 are fine.

@mattcaswell
Copy link
Member Author

Rebased to resolve conflicts with master, and updated with fixups for the various feedback comments.

Copy link
Member

Choose a reason for hiding this comment

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

I have absolutely no idea what this "internal" property really does..
I cant see this property anywhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

There are a number of algorithms (such as HKDF) which (for historical reasons) have been forced into the "derive" API. They have nothing to do with key exchange - they are KDFs, and are now available via the EVP_KDF APIs. For backwards compatibility we need to be able to support them when doing implicit fetches. But I don't think we should encourage their use in an explicit fetch. For that reason I thought we might add an additional "internal" property only for use when doing implicit fetching. I'd expect those "key exchange" algorithms which are really KDFs to have the internal property, but not have the "default" property.

It's not currently used because I've only brought DH across as part of this PR. I expect future PRs to pull across the other algorithms.

If this is controversial I could drop this from this PR, and reintroduce it when we bring those algorithms across.

Copy link
Member

Choose a reason for hiding this comment

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

Even a TODO above it would be fine..

Copy link
Member Author

Choose a reason for hiding this comment

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

TODO added

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should have a behaviour difference like this between implicit and explicit handling - that is asking for issues. Basically the decision on implicit/explicit shouldn't remove something that is available on implicit simply because the caller is using the explicit interface. That inconsistency is (in my view) substantially more concerning than someone using a less desirable interface.

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't the code just fail in this situation? This is the key exchange code and it's considering (the unrelated) KDFs. That seems wrong.

Would a better way be having the PKEY legacy support make the decision to go to either the key exchange code or the KDF code?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is the legacy support code....it shouldn't fail, it should dispatch to the "correct" API.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since this is controversial, I've just removed this for now. We can think more about what to do with this when we move the KDFs that use the "derive" API into the providers in a later PR.

@mattcaswell
Copy link
Member Author

I renamed the EVP_EXCHANGE type to EVP_KEYEXCH. This turned out to be more involved than I expected, and I had to rebase and change various commit messages. Also all additional feedback above has been incorporated.

New commits pushed.

@t8m
Copy link
Member

t8m commented Jul 1, 2019

The usual shortcut for key exchange is KEX :)

@mattcaswell
Copy link
Member Author

I'd also be ok with KEX....@slontis?

@paulidale
Copy link
Contributor

I'd prefer KEYEXCH., one less search for somebody starting out in the code.
KEX is livable too.

@levitte
Copy link
Member

levitte commented Jul 1, 2019

Considering acronyms like KDF and MAC (oh, and MD for that matter), KEX would actually be fitting. On the other hand, there's going to be a whole family of operations around public keys, so we need to consider that pile of names too (it would be easier if we had them all listed, is that possible @mattcaswell?)

@slontis
Copy link
Member

slontis commented Jul 1, 2019

We have functions that end in EX as well - so maybe not a good idea.

@levitte
Copy link
Member

levitte commented Jul 1, 2019

Argh. True.

@slontis
Copy link
Member

slontis commented Jul 1, 2019

If we are sticking to just 3 letters acronyms its probably the best one.

@mattcaswell
Copy link
Member Author

I see no reason to stick to three letter acronyms. On reflection I think KEYEXCH is better. It is much more suggestive of its intent. KEX only means something if you already know what it stands for.

@levitte
Copy link
Member

levitte commented Jul 1, 2019

One might argue that KEX is a commonly used acronym. I don't currently know if that absolutely true, I only know that I have seen it in a number of places.

That being said, I have nothing against KEYEXCH.

@levitte
Copy link
Member

levitte commented Jul 8, 2019

I've done an adaptation of this to #9312, currently available in this branch:

https://github.com/levitte/openssl/tree/evp_keymgmt%2Bmattcaswell-provider-dh

Tests fine now

Copy link
Contributor

@paulidale paulidale left a comment

Choose a reason for hiding this comment

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

LGTM, one question about secure allocation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should this use secure memory?

Or more generally, is a way for the OSSL_PARAM_get_BN call to allocate in secure memory desirable?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think having a "get_privateBN" API makes sense. Of course you'll need #8886 (or a replacement) merged first.

Copy link
Contributor

Choose a reason for hiding this comment

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

|| (priv_key = BN_secure_new()) == NULL would work here, but the problem will be more widespread I suspect.

Copy link
Contributor

Choose a reason for hiding this comment

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

Whether you do it in two steps (allocate the BN) or one (add a params API) doesn't matter to me. But yes, the provider will have to know which parameters are private key material, which doesn't seem like a big deal to me.

Copy link
Member

Choose a reason for hiding this comment

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

If it's a common consensus that all keys (or at least their private bits) should reside in secure memory if possible, then the provider can decide on its own what to put there and what not. If the provider of an algorithm implementation doesn't intimately know its own keys, that provider needs a rewrite.

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 changed this to explicitly allocate the BN via BN_secure_new()

@mattcaswell
Copy link
Member Author

Rebased to resolve a conflict with master and addressed the one feedback item above.

Ping @paulidale

Copy link
Contributor

@paulidale paulidale left a comment

Choose a reason for hiding this comment

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

There is a mismatch with secure allocation and free but the code will be changing once the supporting PR is done. Kludge for now seems like it would be okay.

Copy link
Contributor

Choose a reason for hiding this comment

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

This should be either secure_free or normal free shouldn't it?

I don't think this needs to be fixed here, it will be resolved by #9305 or #9254 (which ever ends up being selected). But a TODO might be worthwhile.

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, good point. Most of the time it should actually be OPENSSL_secure_clear_free, because we expect the key to have a private element. I've changed it to that for now, and added a TODO.

Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment about secure_free.

Copy link
Member Author

Choose a reason for hiding this comment

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

Most of the time OPENSSL_free should be fine because we don't expect this key to have a private element - but I added a TODO anyway.

We introduce a new EVP_KEYEXCH type to represent key exchange algorithms
and refactor the existing code to use it where available.
We add the capability for the default provider to perform PKCS#3
Diffie-Hellman key exchange. At this point the implementation is not used
because libcrypto still uses legacy handling for Diffie-Hellman.

Note X9.42 DH is not touched by this commit.
The default provider now has support for PKCS#3 Diffie-Hellman so we
switch libcrypto to using providers for that algorithm.
This also adds the ability to set arbitrary parameters on key exchange
algorithms. The ability to pad the output is one such parameter for DH.
Previous commits added the EVP_KEYEXCH type for representing key exchange
algorithms. They also added various functions for fetching and using them,
so we document all of those functions.
@mattcaswell
Copy link
Member Author

I rebased this due to some significant conflicts with master and addressed the feedback above.

@paulidale - please reconfirm.

Copy link
Contributor

@paulidale paulidale left a comment

Choose a reason for hiding this comment

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

Looks good still.

@mattcaswell
Copy link
Member Author

The travis failure was not relevant. Pushed.

levitte pushed a commit that referenced this pull request Jul 16, 2019
We introduce a new EVP_KEYEXCH type to represent key exchange algorithms
and refactor the existing code to use it where available.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #9266)
levitte pushed a commit that referenced this pull request Jul 16, 2019
We add the capability for the default provider to perform PKCS#3
Diffie-Hellman key exchange. At this point the implementation is not used
because libcrypto still uses legacy handling for Diffie-Hellman.

Note X9.42 DH is not touched by this commit.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #9266)
levitte pushed a commit that referenced this pull request Jul 16, 2019
The default provider now has support for PKCS#3 Diffie-Hellman so we
switch libcrypto to using providers for that algorithm.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #9266)
levitte pushed a commit that referenced this pull request Jul 16, 2019
This also adds the ability to set arbitrary parameters on key exchange
algorithms. The ability to pad the output is one such parameter for DH.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #9266)
levitte pushed a commit that referenced this pull request Jul 16, 2019
Previous commits added the EVP_KEYEXCH type for representing key exchange
algorithms. They also added various functions for fetching and using them,
so we document all of those functions.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #9266)
paulidale added a commit to paulidale/openssl that referenced this pull request Jul 16, 2019
A fuller implementation of PARAMS_TEMPLATE as per openssl#9266 but renamed.
This introduces a statis data type which can be used to constructor a
description of a parameter array.  It can then be converted into a OSSL_PARAM
array and the allocated storage freed by a single call to OPENSSL_free.
levitte pushed a commit that referenced this pull request Jul 17, 2019
A fuller implementation of PARAMS_TEMPLATE as per #9266 but renamed.
This introduces a statis data type which can be used to constructor a
description of a parameter array.  It can then be converted into a OSSL_PARAM
array and the allocated storage freed by a single call to OPENSSL_free.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from #9305)
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.

7 participants