Skip to content

Comments

Remove RAND_DRBG API#12509

Closed
paulidale wants to merge 2 commits intoopenssl:masterfrom
paulidale:dep-rand
Closed

Remove RAND_DRBG API#12509
paulidale wants to merge 2 commits intoopenssl:masterfrom
paulidale:dep-rand

Conversation

@paulidale
Copy link
Contributor

The RAND_DRBG API and implementation is convoluted and difficult. With the move to providers, it is being deprecated. The RAND APIs, however, remain unchanged.

Checklist
  • documentation is added or updated
  • tests are added or updated

@paulidale paulidale added the branch: master Applies to master branch label Jul 22, 2020
@paulidale paulidale added this to the 3.0.0 milestone Jul 22, 2020
@paulidale paulidale requested a review from mspncp July 22, 2020 05:39
@paulidale paulidale marked this pull request as ready for review July 23, 2020 03:39
@paulidale paulidale changed the title WIP: Deprecate RAND_DRBG Deprecate RAND_DRBG Jul 23, 2020
@paulidale paulidale added the approval: review pending This pull request needs review by a committer label Jul 24, 2020
@paulidale
Copy link
Contributor Author

Conflicts resolved, rebased to master. Ping @openssl/committers for review please.

Copy link
Contributor

@mspncp mspncp left a comment

Choose a reason for hiding this comment

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

If I understand it correctly, the APIs RAND_DRBG_get0_{public,private,primary}() and RAND_get0_{public,private,primary}_drbg() return two unrelated triples of random generators. For example, if

    RAND_DRBG*    drbg_public = RAND_DRBG_get0_public();
    EVP_RAND_CTX* rand_public = RAND_get0_public_drbg(NULL);

then drbg_public->rand != rand_public. The same holds for drbg_private and drbg_primary. If that is the case (which I checked in the debugger, see example below), then your construction does not work, because it breaks the API promise in the following way: The documented behaviour of version 1.1.1 is that you can change the seed source for the default OpenSSL CSPRNG, which implements the RAND_bytes() call, by replacing the callbacks of the primary DRBG (RAND_DRBG_set_callbacks(RAND_DRBG_get0_primary(), ...)). In your setup, modifying the primary DRBG will not have an effect on RAND_bytes(), because it calls into the primary EVP_RAND_CTX.

The good news: The situation might not be entirely lost, if manage to construct the legacy DRBGs in such a way that drbg_{pub,priv,prim}->rand == rand_{pub,priv,prim}.

Example

I modified the openssl rand command as follows to verify in the debugger that drbg->rand != rand.

diff --git a/apps/rand.c b/apps/rand.c
index 1ad6894597..66d9a41308 100644
--- a/apps/rand.c
+++ b/apps/rand.c
@@ -17,6 +17,7 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
+#include <openssl/rand_drbg.h>
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
@@ -48,6 +49,9 @@ const OPTIONS rand_options[] = {
 
 int rand_main(int argc, char **argv)
 {
+    RAND_DRBG *drbg_pub, *drbg_priv, *drbg_prim;
+    EVP_RAND_CTX *rand_pub, *rand_priv, *rand_prim;
+
     ENGINE *e = NULL;
     BIO *out = NULL;
     char *outfile = NULL, *prog;
@@ -109,6 +113,15 @@ int rand_main(int argc, char **argv)
         out = BIO_push(b64, out);
     }
 
+    drbg_pub = RAND_DRBG_get0_public();
+    rand_pub = RAND_get0_public_drbg(NULL);
+
+    drbg_priv = RAND_DRBG_get0_private();
+    rand_priv = RAND_get0_private_drbg(NULL);
+
+    drbg_prim = RAND_DRBG_get0_master();
+    rand_prim = RAND_get0_primary_drbg(NULL);
+
     while (num > 0) {
         unsigned char buf[4096];
         int chunk;

@mspncp
Copy link
Contributor

mspncp commented Jul 27, 2020

A general remark about the documentation: The new EVP_RAND interface is intended to be more generic than the RAND_DRBG interface, which it supersedes. A DRBG is just a specific type of EVP_RAND implementation (it happens to be OpenSSL's current default implementation).

Currently there are a lot of places in the documentation (in particular EVP_RAND.pod) and the source code, where the term 'DRBG' is used for an arbitrary EVP_RAND_CTX instance. This is a bit misleading, so we should find these locations and replace 'DRBG' by something more general, for example 'CSPRNG' or simply 'RNG'. (BTW: Maybe EVP_RNG (resp. OSSL_RNG) would be a better name than EVP_RAND resp. OSSL_RAND. Then we wouldn't have to call EVP_RAND_CTX instances a "rand" (which you do in some places), but instead we could call EVP_RNG_CTX instances an "rng".)

@paulidale
Copy link
Contributor Author

The good news: The situation might not be entirely lost, if manage to construct the legacy DRBGs in such a way that drbg_{pub,priv,prim}->rand == rand_{pub,priv,prim}.

This doesn't work well because RAND_DRBG allows far too much invasive control over the internals for the underlying EVP_RAND. If there are shared, we're back to having the additional layer which this PR is trying to remove.

@mspncp
Copy link
Contributor

mspncp commented Jul 27, 2020

This doesn't work well because RAND_DRBG allows far too much invasive control over the internals for the underlying EVP_RAND. If there are shared, we're back to having the additional layer which this PR is trying to remove.

That's exactly what I am trying to tell you all the time: the only way to get rid of the mess is to remove the RAND_DRBG interface in 3.0 entirely, not just to deprecate it. This is a breaking change, I know, but it's a clean break and we can give good reasons for doing it. Your current approach is also a breaking change, in a very subtle way which will cause much more confusion.

@paulidale
Copy link
Contributor Author

Okay, we're going to need an OMC vote either on: "remove RAND_DRBG complete" or "deprecate it but with slightly different behaviour".

@mspncp
Copy link
Contributor

mspncp commented Jul 27, 2020

Okay, we're going to need an OMC vote either on: "remove RAND_DRBG complete" or "deprecate it but with slightly different behaviour".

Yes, I agree. But preceding the vote I expect a public discussion on openssl-project. ;-)

@paulidale
Copy link
Contributor Author

Pausing this pending the vote outcome.

@paulidale paulidale added hold: discussion The community needs to establish a consensus how to move forward with the issue or PR hold: need omc decision and removed hold: discussion The community needs to establish a consensus how to move forward with the issue or PR labels Jul 27, 2020
@paulidale
Copy link
Contributor Author

@mspncp, I'm not sure where to relocate the text in RAND_DRBG(7). RAND(7) is responsible for setting up the trio of DRBGs but it doesn't sit well there. Any thoughts or suggestions?

@paulidale
Copy link
Contributor Author

Two removal commits added -- if the current vote passes, this is roughly in the state we want.

@mspncp
Copy link
Contributor

mspncp commented Jul 30, 2020

@mspncp, I'm not sure where to relocate the text in RAND_DRBG(7). RAND(7) is responsible for setting up the trio of DRBGs but it doesn't sit well there. Any thoughts or suggestions?

Sorry for not answering earlier, I was too busy yesterday. Moving RAND_DRBG(7) to EVP_RAND(7) looks like a reasonable solution.

@paulidale
Copy link
Contributor Author

I moved some of the text to RAND(7) as well.

@paulidale paulidale force-pushed the dep-rand branch 2 times, most recently from e5028e0 to cc56c2c Compare August 3, 2020 00:58
@paulidale
Copy link
Contributor Author

"These" as in changes and news.

@paulidale
Copy link
Contributor Author

The last commit pushed avoids the memory leak. There is something peculiar going on and preallocating the primary DRBG avoids it. Without this fix, the leak happens on the first RAND_get0_primary() call executed by the tests near the start of test_rand_drbg_reseed(). Any ideas @levitte ?

Copy link
Contributor

@mspncp mspncp left a comment

Choose a reason for hiding this comment

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

Last fixups look good.

@mspncp
Copy link
Contributor

mspncp commented Aug 6, 2020

GitHub has truncated thread #12509 (comment) and some posts are missing for unknown reason, so I quote them here:

@t8m commented on this pull request.

I agree with @paulidale that these calls do not belong to the EVP_RAND API. On the other hand I'd prefer keeping the RAND_ API basically sealed i.e. not add anything to it as the RAND prefix is quite generic. For that reason I'd prefer these calls to be OPENSSL_get0_primary_rand or OPENSSL_CTX_get0_primary_rand. But I do not insist on that.

@paulidale commented on this pull request.

I'm okay to change the names. If this gets merged for the alpha, it will need to be a separate PR but that's not a problem.

@paulidale commented on this pull request.

We need to agree on the naming first. OPENSSL_get0_primary_rand() is okay. Would OPENSSL_RAND_get0_primary() be more appropriate?>

I'm not keen to add yet another rand prefix, for just three functions. Also, it should be OSSL_, not OPENSSL_, if it is used in conjunction with another prefix, but OSSL_RAND has been already been suggested by @levitte as alternative for EVP_RAND. Long story short, if EVP_RAND_get0_{primary,public,private}() does not seem appropriate, then RAND_get0_{primary,public,private}() is my second favorite. And it does fit to the RAND API, whose default implementation is based on this RNG triplet.

@mspncp mspncp removed the severity: urgent Fixes an urgent issue (exempt from 24h grace period) label Aug 6, 2020
@mspncp
Copy link
Contributor

mspncp commented Aug 6, 2020

@paulidale I removed the 'urgent' label, since we missed the alpha release anyway. Could you reorganize your commits and bring them into the final form in which you intend to merge them? (Preferrably without moving the merge-base).

@paulidale
Copy link
Contributor Author

Ugg, conflicts in libcrypto.num. I'll rebase to master and squash everything up.

The RAND_DRBG API did not fit well into the new provider concept as
implemented by EVP_RAND and EVP_RAND_CTX. The main reason is that the
RAND_DRBG API is a mixture of 'front end' and 'back end' API calls
and some of its API calls are rather low-level. This holds in particular
for the callback mechanism (RAND_DRBG_set_callbacks()) and the RAND_DRBG
type changing mechanism (RAND_DRBG_set()).

Adding a compatibility layer to continue supporting the RAND_DRBG API as
a legacy API for a regular deprecation period turned out to come at the
price of complicating the new provider API unnecessarily. Since the
RAND_DRBG API exists only since version 1.1.1, it was decided by the OMC
to drop it entirely.

Other related changes:

Use RNG instead of DRBG in EVP_RAND documentation.  The documentation was
using DRBG in places where it should have been RNG or CSRNG.

Move the RAND_DRBG(7) documentation to EVP_RAND(7).
@paulidale
Copy link
Contributor Author

paulidale commented Aug 6, 2020

I've squashed it down to one commit for the removal plus a second commit for the drgbtest fix. The latter should be removed in due course.

No need to reset the approval timer for this.

@openssl-machine
Copy link
Collaborator

24 hours has passed since 'approval: done' was set, but as this PR has been updated in that time the label 'approval: ready to merge' is not being automatically set. Please review the updates and set the label manually.

openssl-machine pushed a commit that referenced this pull request Aug 7, 2020
The RAND_DRBG API did not fit well into the new provider concept as
implemented by EVP_RAND and EVP_RAND_CTX. The main reason is that the
RAND_DRBG API is a mixture of 'front end' and 'back end' API calls
and some of its API calls are rather low-level. This holds in particular
for the callback mechanism (RAND_DRBG_set_callbacks()) and the RAND_DRBG
type changing mechanism (RAND_DRBG_set()).

Adding a compatibility layer to continue supporting the RAND_DRBG API as
a legacy API for a regular deprecation period turned out to come at the
price of complicating the new provider API unnecessarily. Since the
RAND_DRBG API exists only since version 1.1.1, it was decided by the OMC
to drop it entirely.

Other related changes:

Use RNG instead of DRBG in EVP_RAND documentation.  The documentation was
using DRBG in places where it should have been RNG or CSRNG.

Move the RAND_DRBG(7) documentation to EVP_RAND(7).

Reviewed-by: Matthias St. Pierre <[email protected]>
(Merged from #12509)
openssl-machine pushed a commit that referenced this pull request Aug 7, 2020
Reviewed-by: Matthias St. Pierre <[email protected]>
(Merged from #12509)
@paulidale paulidale added approval: ready to merge The 24 hour grace period has passed, ready to merge and removed approval: done This pull request has the required number of approvals labels Aug 7, 2020
@paulidale
Copy link
Contributor Author

Merged to master. Thanks for the reviews and feedback.

@paulidale paulidale closed this Aug 7, 2020
@paulidale paulidale deleted the dep-rand branch August 7, 2020 04:18
@paulidale paulidale mentioned this pull request Aug 7, 2020
swenkeratmicrosoft pushed a commit to swenkeratmicrosoft/openssl that referenced this pull request Sep 1, 2020
The RAND_DRBG API did not fit well into the new provider concept as
implemented by EVP_RAND and EVP_RAND_CTX. The main reason is that the
RAND_DRBG API is a mixture of 'front end' and 'back end' API calls
and some of its API calls are rather low-level. This holds in particular
for the callback mechanism (RAND_DRBG_set_callbacks()) and the RAND_DRBG
type changing mechanism (RAND_DRBG_set()).

Adding a compatibility layer to continue supporting the RAND_DRBG API as
a legacy API for a regular deprecation period turned out to come at the
price of complicating the new provider API unnecessarily. Since the
RAND_DRBG API exists only since version 1.1.1, it was decided by the OMC
to drop it entirely.

Other related changes:

Use RNG instead of DRBG in EVP_RAND documentation.  The documentation was
using DRBG in places where it should have been RNG or CSRNG.

Move the RAND_DRBG(7) documentation to EVP_RAND(7).

Reviewed-by: Matthias St. Pierre <[email protected]>
(Merged from openssl#12509)
swenkeratmicrosoft pushed a commit to swenkeratmicrosoft/openssl that referenced this pull request Sep 1, 2020
Reviewed-by: Matthias St. Pierre <[email protected]>
(Merged from openssl#12509)
mspncp added a commit to mspncp/openssl that referenced this pull request Sep 12, 2020
These are leftovers from the RAND_DRBG removal (openssl#12509).
openssl-machine pushed a commit that referenced this pull request Sep 14, 2020
These are leftovers from the RAND_DRBG removal (#12509).

Reviewed-by: Paul Dale <[email protected]>
(Merged from #12866)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: ready to merge The 24 hour grace period has passed, ready to merge branch: master Applies to master branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants