-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Reorganize providers #10088
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reorganize providers #10088
Conversation
033bb71
to
3111716
Compare
Either I am confused, or I just don't see how this works. Using the the AESNI assembly version(s) of AES as an example, can you explain where the code goes? Is it a single source file compiled into two libraries? What about the filter/checksum approach that's already defined? |
The AES assembler stuff ends up in I haven't forgotten about the checksum part. There will be a db with the necessary information. That will also tell exactly what algo implementations may be included in the FIPS module. |
And the several-dozen crypto implementation files that use FIPS_MODE? Which libraries do they go into? Use crypto/ec/ecp_nistp224.c as an example. |
Same story. Basically, anything that ends up in |
So FIPS version of ecp_nist224p.c ends up in libfips, but where does the non-FIPS version end up? As I read the intro comment, it seems a bit misleading since "libfips is more substantial." Maybe, but there are several dozen files with FIPS_MODE ifdef's. They all get compiled twice into two libraries, but it's not clear where. (To forestall one reply, I think a high-level description is needed, not just reading the details of the build.info files and trying to reverse-engineer what's going on.) |
I have to ask, is "and will include all the bits from libcrypto that need to be built specially for the FIPS module to make it self contained" unclear? How can I express that better? |
By saying where all the non-fips parts of libcrypto go? And not implying that this will be small? |
For the non-fips providers the same source ends up built into libcrypto, same as usual. |
Or are you depending on a FIPS module linking fips.a nonfips.a in that order will pick up the FIPS implementation? |
No. The FIPS module is built on libimplementations.a + libfips.a + fipsprov.c + selftest.c. Nothing else. |
Great work, Richard. This should work for the downstream FIPS validation fine. And hopefully it will not complicate the upstream OpenSSL FIPS module validation much. |
From the interaction with @richsalz last night, I realised that the description was lacking a bit. I've added a practical summary, I hope that clarifies things. |
Open questionShould implementations from the legacy provider end up in a separate static library, say Making a switch from Update: it would be silly to have a Update 2: However, the legacy implementations source should still be located in the same directory structure as the non-legacy ones, to avoid having to move around files as implementations age. This is another objective from #10070 |
This makes sense to me as well. |
Yeah, it seems like a sane way forward, doesn't it? Is there any reason to have the Legacy provider use the "menu of implementations" idea, i.e. to make the included algorithms selectable? That would be a reason to collect them in |
(is it just me, or are we kinda removing all the |
Yeah, it would be kind of cool to make the decision to move an algorithm from default to legacy a simple change that could be done at Configure time. So while we might make decisions about what algorithms get moved out to legacy or not, it gives downstream the opportunity to be more or less aggressive. |
Wait what? That's not at all what I'm proposing. What I'm proposing is that in a
and when we decide it's legacy, all that will be needed is to change the variable:
BUT, what I'm proposing is that it could be configurable what things we consider legacy that will actually end up in What you seem to propose is that legacy implementations should end up in |
Ah, ok. I'm fine with your approach too. |
I think I'll go for the
Then, any build.info file that carries instructions for legacy algorithms can simply have this:
The rest will work itself out regardless of if the Legacy provider becomes a separate module or built in. |
82d2fe7
to
d1a6c2b
Compare
Looking at
Anyone for? Against? |
3842634
to
ffbb0f1
Compare
This seems much cleaner. It should have a more detailed write-up somewhere, probably in the design doc, but FWIW I support this. |
I have done enough with this for today... if CIs agree, it could actually be approved as is, and leave the templating stuff for the next PR |
Description updated. |
Added functionality to use static libraries as source for other libraries. When done this way, the target library will use the object files from the sourced static libraries, making the sourced libraries work as "containers" for object files. We also need to make sure that the Unix Makefile template knows how to deal with shared libraries and modules that depend on static libraries. That's new situation we haven't had before.
We put almost everything in these internal static libraries: libcommon Block building code that can be used by all our implementations, legacy and non-legacy alike. libimplementations All non-legacy algorithm implementations and only them. All the code that ends up here is agnostic to the definitions of FIPS_MODE. liblegacy All legacy implementations. libnonfips Support code for the algorithm implementations. Built with FIPS_MODE undefined. Any code that checks that FIPS_MODE isn't defined must end up in this library. libfips Support code for the algorithm implementations. Built with FIPS_MODE defined. Any code that checks that FIPS_MODE is defined must end up in this library. The FIPS provider module is built from providers/fips/*.c and linked with libimplementations, libcommon and libfips. The Legacy provider module is built from providers/legacy/*.c and linked with liblegacy, libcommon and libcrypto. If module building is disabled, the object files from liblegacy and libcommon are added to libcrypto and the Legacy provider becomes a built-in provider. The Default provider module is built-in, so it ends up being linked with libimplementations, libcommon and libnonfips. For libcrypto in form of static library, the object files from those other libraries are simply being added to libcrypto.
From providers/common/ to providers/implementations/
From providers/default/ to providers/implementations/
From providers/{common,default,legacy}/ to providers/implementations/ However, providers/common/digests/digest_common.c stays where it is, because it's support code rather than an implementation. To better support all kinds of implementations with common code, we add the library providers/libcommon.a. Code that ends up in this library must be FIPS agnostic. While we're moving things around, though, we move digestscommon.h from providers/common/include/internal to providers/common/include/prov, thereby starting on a provider specific include structure, which follows the line of thoughts of the recent header file reorganization. We modify the affected '#include "internal/something.h"' to '#include "prov/something.h"'.
From providers/{common,default}/ to providers/implementations/ Except for common code, which remains in providers/common/ciphers/. However, we do move providers/common/include/internal/ciphers/*.h to providers/common/include/prov/, and adjust all source including any of those header files.
New name is providers/implementations/include/prov/implementations.h All inclusions are adapted accordingly.
The end up in providers/common/include/prov/. All inclusions are adjusted accordingly.
providers/default/defltprov.c and providers/legacy/legacyprov.c are moved up to providers/ and providers/build.info is adjusted accordingly.
cc12247
to
43eea3f
Compare
All review comments addressed, and rebased |
The build.info grammar's regular expressions were a horrible read. By assigning certain sub-expressions to variables, we hope to make it a little more readable. Also, the handling of build.info attributes is reworked to use a common function instead of having copies of the same code. Finally, the attributes are reorganized to specify if they belong with programs, libraries, modules or scripts. This will enable more intricate attribute assignment in changes to come. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
We want to attach attributes on dependencies. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
The dependency resolution is made uniquely to resolve proper library order when linking a program, a module or a shared library. resolvedepends() did a little too much at once, so it's now reduced to only collect dependencies (and is renamed to collectdepends()), while a new function, expanddepends(), expands a list of dependency to insure that dependent libraries are present after depending libraries, and finally there is reducedepends() which removes unnecessary duplicates, leaving only the last one. resolvedepends() is now a simple utility routine that calls the three mentioned above in correct order. As part of this, we implement weak dependencies through the 'weak' build.info attribute. This is meant to cause a specific order between libraries without requiring that they are all present. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
Added functionality to use static libraries as source for other libraries. When done this way, the target library will use the object files from the sourced static libraries, making the sourced libraries work as "containers" for object files. We also need to make sure that the Unix Makefile template knows how to deal with shared libraries and modules that depend on static libraries. That's new situation we haven't had before. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
We put almost everything in these internal static libraries: libcommon Block building code that can be used by all our implementations, legacy and non-legacy alike. libimplementations All non-legacy algorithm implementations and only them. All the code that ends up here is agnostic to the definitions of FIPS_MODE. liblegacy All legacy implementations. libnonfips Support code for the algorithm implementations. Built with FIPS_MODE undefined. Any code that checks that FIPS_MODE isn't defined must end up in this library. libfips Support code for the algorithm implementations. Built with FIPS_MODE defined. Any code that checks that FIPS_MODE is defined must end up in this library. The FIPS provider module is built from providers/fips/*.c and linked with libimplementations, libcommon and libfips. The Legacy provider module is built from providers/legacy/*.c and linked with liblegacy, libcommon and libcrypto. If module building is disabled, the object files from liblegacy and libcommon are added to libcrypto and the Legacy provider becomes a built-in provider. The Default provider module is built-in, so it ends up being linked with libimplementations, libcommon and libnonfips. For libcrypto in form of static library, the object files from those other libraries are simply being added to libcrypto. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
From providers/common/ to providers/implementations/ Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
From providers/default/ to providers/implementations/ Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
From providers/{common,default,legacy}/ to providers/implementations/ However, providers/common/digests/digest_common.c stays where it is, because it's support code rather than an implementation. To better support all kinds of implementations with common code, we add the library providers/libcommon.a. Code that ends up in this library must be FIPS agnostic. While we're moving things around, though, we move digestscommon.h from providers/common/include/internal to providers/common/include/prov, thereby starting on a provider specific include structure, which follows the line of thoughts of the recent header file reorganization. We modify the affected '#include "internal/something.h"' to '#include "prov/something.h"'. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
From providers/{common,default}/ to providers/implementations/ Except for common code, which remains in providers/common/ciphers/. However, we do move providers/common/include/internal/ciphers/*.h to providers/common/include/prov/, and adjust all source including any of those header files. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
New name is providers/implementations/include/prov/implementations.h All inclusions are adapted accordingly. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
The end up in providers/common/include/prov/. All inclusions are adjusted accordingly. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
providers/default/defltprov.c and providers/legacy/legacyprov.c are moved up to providers/ and providers/build.info is adjusted accordingly. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from #10088)
Merged. 285dacc Configure: rework build.info grammar and attributes |
Great work! Thanks Richard! |
This is in response to #10070
The idea is to rework our provider build by place all algorithm implementations in a static library and let each provider main (
fipsprov.c
,defltprov.c
,legacyprov.c
) get what they like from it by simply using the symbols supplied by the implementations.So far, the following is submitted:
Changes to Configure and build file templates to allow libraries to be "linked" with other static libraries through
build.info
SOURCE[]
statements. This will allow the static library with implementations to be included into any built-in provider (such as the default provider).Rearrangement of the provider build.info files to create static libraries for the algorithm implementations. These are:
libimplementations.a
, containing everything that's FIPS agnostic. That's essentially all the code fromproviders/common/{ciphers,digests,exchange,kdfs,keymgmt,macs,signature}
,/providers/default/{ciphers,digests,kdfs,macs}
andproviders/legacy/digests
.libnonfips.a
, containing any special support that the implementations need when used with non-FIPS providers. This should be a fairly minimal library, as those providers are linked with libcrypto, or built in. With this library,FIPS_MODE
is undefined.libfips.a
, containing any special support that the implementations need when used with the FIPS provider. This is a bit more substantial, and will include all the bits from libcrypto that need to be built specially for the FIPS module to make it self contained. With this library,FIPS_MODE
is defined.There are two places among the implementations where
FIPS_MODE
is checked. These are two small code sections taht only set a couple of constants, so I'll move them to source files of their own, which will be used both for libfips.a and libnonfips.a, thereby having them compiled twice, once withFIPS_MODE
defined and once with it undefined.Moved around the provider source code as follows:
providers/implementations
now contains all implementations. Thebuild.info
files in there are made in such a way that "moving" an implementation to the legacy provider is changing the its goal variable.providers/common
, and its object files are collected in a separate library,providers/libcommon.a
, which is then used by all the providers.providers/default
andproviders/legacy
are emptied and gone. The provider mains have moved up, i.e.providers/defltprov.c
andproviders/legacyprov.c
. Since the FIPS provider is composed or more than one file, I've left them alone for now.providers/common/include/internal
has been renamed toproviders/common/include/prov
, so we're now including the provider header files like this:#include "prov/header.h"
provider_algs.h
is renamed toimplementations.h
and is located inproviders/implementations/include/prov
.providers/common
, and is used as source for bothlibfips.a
andlibnonfips.a
.Summary - In practical terms:
[This will be updated as this PR progresses]
providers/libcommon.a
.providers/common/
,providers/default/
andproviders/legacy/
are now collected inproviders/libimplementations.a
, except for the two nuggest ofFIPS_MODE
sensitive code.FIPS_MODE
sensitive code have been placed in their own source, and are built into two object files each, one that is collected inproviders/libfips.a
(for whichFIPS_MODE
is defined) and one that is collected inproviders/libnonfips.a
(for whichFIPS_MODE
is undefined).crypto/
that are built a second time specially for the FIPS module (in other words, withFIPS_MODE
defined) and got used directly to buildprovider/fips.so
are now collected inproviders/libfips.a
.providers/fips/fipsprov.c
andproviders/fips/selftest.c
and linked withproviders/libimplementations.a
,providers/libcommon.a
andproviders/libfips.a
providers/legacy/legacyprov.c
and linked withproviders/libimplementations.a
,providers/libcommon.a
,providers/libnonfips.a
andlibcrypto
.libcrypto
, so all that it needs is essentially added tolibcrypto
, including the same object files that were collected inproviders/libimplementations.a
,providers/libcommon.a
and inproviders/libnonfips.a
, and finally the object file built fromproviders/default/defltprov.c
.(this may seem unnecessary, but it avoids having the algorithm implementations getting built twice, once for
libcrypto
and once forproviders/libimplementations.a
, which is needed anyway)(also, should we ever want to make the default provider a separate module, it's a turnkey change)
To do:
providers/fipsprov.c
as a templates, so it can use a selection of algorithms, as given by configuration. [needs more thought]