Make the EVP API available from within the FIPS module#8728
Make the EVP API available from within the FIPS module#8728mattcaswell wants to merge 5 commits intoopenssl:masterfrom
Conversation
|
I assume at some point we may want to select properties such as "asm=no" or "asm=yes" Does this fit is well with the capability tests??... or should this be handled differently. i.e 2 dispatch entries (one for the generic version + others for asm version(s)) |
I'm not sure that is actually desirable. But if we decide to do it then we can split the dispatch table entries at that point. |
|
Now that #8700 has gone in I have rebased this and addressed all comments received so far. |
|
Not sure why AppVeyor is claiming this is non-mergeable with the master branch because this is a fresh rebase, Travis has no such problems, and github reports no merge conflicts. |
crypto/asn1/a_object.c
Outdated
|
I look at this, and gotta say that I'm very very doubtful about bringing the library context stuff into the FIPS provider (or really, any provider). |
Note that it's not like I understand why it gets dragged in... I think I need a little bit of time to digest this. |
providers/fips/fipsprov.c
Outdated
There was a problem hiding this comment.
So.... instead of all of that, could we simply have a provider module global library context, i.e. use OPENSSL_CTX_new() to create it and OPENSSL_CTX_free() to free it, and use it everywhere we can? It seems like a saner approach than doing all kinds of internal calls, with all the entanglement that could result in in the future.
There was a problem hiding this comment.
Yes, I think that would be nice. We should use OPENSSL_CTX wherever we have global state we need to initialise. But I see that as outside of the scope of this PR.
There was a problem hiding this comment.
I don't. Basically, you've made a load of static initialization functions more widely available, which has a risk of entanglement I already see with current init functionality. You could achieve the exact same thing by simply creating a library context within the FIPS provider, and by freeing it on teardown. No need to go call all those internal initializers from outside (or should not be any need at the very least).
Since you do already include context.c in the FIPS module, you already have all you need to do this, so leaving it for another PR will basically mean undoing the bunch of init stuff you've entangled yourself with here. Therefore, I'd say this is very much in scope.
This PR brings EVP inside the FIPS boundary. EVP uses core in order to fetch algorithms and all of that code depends on OPENSSL_CTX. So if you want EVP inside the boundary, you must have OPENSSL_CTX. |
|
I pushed a fixup commit addressing the comment above. I also took this out of WIP. |
Unless you only pass NULL, right? I'd go further and remove the library context stuff for this release (I forget which PR I made that comment) and only allow NULL and the global context. As I said "over there," I think the context stuff isn't fully thought out yet. |
You misunderstand my statement. I am saying that in order for the EVP code to be inside the FIPS boundary, there is a dependency on the OPENSSL_CTX code. This is nothing to do with passing NULL for the default context or not. |
|
Yes, I misunderstood, thanks. I wonder if we should ask the lab for a viewpoint on this? |
crypto/evp/evp_fetch.c
Outdated
There was a problem hiding this comment.
This is unnecessary, as this only initializes the EX_DATA index, which is to be seen as constant after initialization and throughout the .bss and .data section lifetime. When those sections are rewritten, the RUN_ONCE flag will be cleared as well, which allows a new index initialization, which means that module unload and reload isn't a concern here.
There was a problem hiding this comment.
A key point to see this throughout the code is that no OPENSSL_atexit callback is registered.
crypto/provider_core.c
Outdated
There was a problem hiding this comment.
Just as with evp_fetch.c, this change is not necessary, since it only creates an EX_DATA index.
|
Hmmm... assuming that there is just the default library context and none else means that we can ignore issues with multiple initialization (i.e. the RUN_ONCE problem that we're seeing here). That would be @richsalz' point, yeah? I'm not too keen on ignoring the library context thing, but I have to admit it's a line of thinking worth spending more than just a fleeting thought on. |
With multiple library contexts, it's possible that the same module runs its init and teardown functions multiple times during its lifetime. This would normally not cause much trouble, except that our FIPS module is a bit special and will include code that handles a library context internally, just to be able to make internal EVP calls. This means that the provider init function will potentially be called multiple times, and the teardown as well, and those may do initializations and deinitializations, including the ex_data cleanup. This may mean that the ex_data lock gets freed too early (on first cleanup instead of last). To ensure that the ex_data lock isn't freed before its last use, we associate a reference counter with it, which gets incremented for everytime there's an attempt to create that lock, and gets decremented when there's an attempt to clean it up, thereby ensuring that construction will only happen on first init and destruction on last deinit. Related to openssl#8728
|
I've updated this to make the changes suggested above and I've pulled in OPENSSL_atexit() and OPENSSL_cleanup() into the FIPS module. The ex_data stuff isn't really properly handled yet. That will take #8828 to go in first. |
|
I don't understand why atext and cleanup are pulled in. If there is module-specific "cleanup on unload" code, then the core should query for a function pointer and call into the module once it is unloaded. No shared-library module is loaded before the OpenSSL core is initialized. If an application calls init without a flag that the module needs, then loading the module can signal an error; the app is broken for the module it is trying to use. |
This is exactly what does happen. And the module specific function that is called by the core to cleanup on unload is called....OPENSSL_cleanup(). The objective is to share as much code as possible between libcrypto and the FIPS module. We do not want to write two versions of code for everything: once for libcrypto and once for the FIPS module. That has been our approach all the way through the design process. This approach applies to initialisation and cleanup too. |
|
I rebased this now that #8878 has gone in. There are no longer any dependencies on ASN.1 code. |
|
NOTE: the new namemap stuff introduces an issue with aliases. The old maps had both the short name and long names registered with the NID. We would now need a duplicated name for every value in the provider tables. |
|
The new namemap doesn't introduce said issue with aliases, the issue was always there! The only reason we didn't notice was that we piggy-backed on the object database, but as soon as a provider offered algorithm names we don't know beforehand, there are no aliases in sight. I remember that we talked about aliases at some point, but we never concluded anything that I can recall. |
|
Would an alias API make sense here? The numeric value could map to the first string registered and all string aliases could map to the same numeric value. The obvious alternatives would be to:
|
|
On the recursive provider activation:
Well yeah, it simply uses itself (
Come again? I want to have one
The big deal for me is 1) the recursive activation is added complexity, especially if you want to follow what's going on in something like a debugger, and 2) that's quite a few cycles spent on a no-op. |
|
On aliases: The provider will have to be involved somehow... who else should decide what's an alias of what? |
But surely if we don't go into provider_core.c at all we never end up calling provider_activate(), which means we never setup the provider callback functions...most importantly "query_operation"? |
|
I doubt that most providers will want to know about aliases for existing algorithms -- these should be setup by For new algorithms, a provider needs to be able to register such and add aliases but this will be the exception. |
The providers already have the knowledge of algorithm names, why should they not have the knowledge of appropriate aliases? Code wise, it's not very hard to implement: diff --git a/include/openssl/core.h b/include/openssl/core.h
index cf4d3f41de..ea066bd4a4 100644
--- a/include/openssl/core.h
+++ b/include/openssl/core.h
@@ -61,7 +61,7 @@ struct ossl_item_st {
* An array of these is always terminated by algorithm_name == NULL
*/
struct ossl_algorithm_st {
- const char *algorithm_name; /* key */
+ const char **algorithm_names; /* key */
const char *property_definition; /* key */
const OSSL_DISPATCH *implementation;
};Granted, that means that the provider will have to have a separate array of names, but that's not very hard either. I don't believe it's very hard to add alias handling to |
|
It also means that every provider needs to know all of the names for each algorithm. I'd prefer the core to add the aliases it knows about and for providers to not need to know about them (although they could if they wanted to). |
|
@paulidale, I completely disagree with you on this... but also, that's not necessarily something that needs to be resolved in this PR, so we should take that discussion elsewhere. |
|
On the recursive provider activation:
Why do we need to call |
OSSL_PROVIDER is an opaque type. The OSSL_PROVIDER object that is passed to |
Yup, I just realised that as well... so OK, I'm backing off on this one, but would like some prominent commentary on this, 'cause believe you me, the question I raised will surely be asked again unless we provide justification. |
…S module In addition this commit ensures that the "provctx" value is defaulted to the current library context when we are recurively initialising the FIPS provider when already inside the FIPS module.
I added a new commit with some additional commentary in provider_activate to explain the recursive nature of this. I also fixed an issue where we need to set the provctx value for the recursive initialisation call to be the current library context. This will ensure that EVP calls made from within the FIPS module are always associated with the current library context. |
levitte
left a comment
There was a problem hiding this comment.
Note that this is only a review of the last added commit.
|
Fixup commit pushed to addressed your latest comments. I reversed the changes to @levitte - please take another look. |
|
Woop!!!! Pushed.....finally!!! Thanks to everyone involved. We got there in the end. :-) |
Reviewed-by: Richard Levitte <[email protected]> (Merged from #8728)
Reviewed-by: Richard Levitte <[email protected]> (Merged from #8728)
Reviewed-by: Richard Levitte <[email protected]> (Merged from #8728)
…S module In addition this commit ensures that the "provctx" value is defaulted to the current library context when we are recurively initialising the FIPS provider when already inside the FIPS module. Reviewed-by: Richard Levitte <[email protected]> (Merged from #8728)
The FIPS module will itself need to be able to use the EVP API internally. For example:
This makes the necessary changes to enable some limited EVP calls from within the module itself. Specifically we enable the EVP_Digest* and EVP_Cipher* functions (although currently the only algorithm available in the FIPS module is SHA256). To demonstrate this working I've included some dummy EVP calls. These are for demonstration purposes only and will eventually be removed.
This is marked as WIP because it uses #8700 as a starting point. Only the last 2 commits are relevant to this PR.