Skip to content

In scrypt remove the check that N < 2^(128 * r / 8)#24741

Closed
randombit wants to merge 1 commit into
openssl:masterfrom
randombit:jack/fix-24650-part-1
Closed

In scrypt remove the check that N < 2^(128 * r / 8)#24741
randombit wants to merge 1 commit into
openssl:masterfrom
randombit:jack/fix-24650-part-1

Conversation

@randombit

Copy link
Copy Markdown
Contributor

This bound is given in RFC 7914, and would imply that scrypt could not make use of more than 16 MB of memory. This bound is contradicted by the RFC itself, which includes tests which use up to 1 GB.

An errata was filed for the RFC in 2020 regarding this issue, but never acted upon by the authors.

See #24650 for background

@nhorman

nhorman commented Jun 26, 2024

Copy link
Copy Markdown
Contributor

looks like maybe you need to modify the appropriate ci builds such that they compile with a higher SCRYPT_MAX_MEMORY limit defined on the command line?

@t8m t8m added branch: master Applies to master branch approval: review pending This pull request needs review by a committer approval: otc review pending triaged: feature The issue/pr requests/adds a feature tests: present The PR has suitable tests present labels Jun 26, 2024
@t8m t8m added the waiting-for: contributor response This pull request is awaiting a response by the contributor label Jul 18, 2024
@openssl-machine

Copy link
Copy Markdown
Collaborator

This PR is waiting for the creator to make requested changes but it has not been updated for 30 days. If you have made changes or commented to the reviewer please make sure you re-request a review (see icon in the 'reviewers' section).

This bound is given in RFC 7914, and would imply that scrypt could not
make use of more than 16 MB of memory. This bound is contradicted by
the RFC itself, which includes tests which use up to 1 GB.

An errata was filed for the RFC in 2020 regarding this issue, but
never acted upon by the authors.

See openssl#24650 for background

Co-Authored-By: Neil Horman <nhorman@openssl.org>
@randombit randombit force-pushed the jack/fix-24650-part-1 branch from 28c83ff to 8f0e4db Compare August 26, 2024 19:33
@randombit

Copy link
Copy Markdown
Contributor Author

Sorry about the delay, should be ready for review now

@davidben

Copy link
Copy Markdown
Contributor

Something seems off here. #24650 cites N=1048576, r=8, p=1 tests in the RFC as evidence that the restriction is wrong. It further cites other implementations...

Golang x/crypto and BoringSSL both include the N=1048576 test from RFC 7914 (though in both cases commented out since it takes a while to run). Tarsnap/scrypt (written by the designer of scrypt and co-author of RFC 7914) also includes this test, as does the original scrypt paper (Appendix B).

However, BoringSSL includes this check:
https://github.com/google/boringssl/blob/master/crypto/evp/scrypt.c#L152-L153

And indeed, using those parameters, 2(128 * r / 8) = 2128, which is much larger than N = 1048576. So it seems this check is perfectly consistent with that tests and also with inputs that use lots of memory.

@nhorman

nhorman commented Aug 26, 2024

Copy link
Copy Markdown
Contributor

hmm, @davidben you're right. I took the pkcs8 key in #24650, and ran it through gdb:

tarting program: /home/nhorman/git/openssl/apps/openssl pkcs8 -inform PEM -in /home/nhorman/key.pem
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".
Enter Password:

Breakpoint 1, scrypt_alg (pass=0x552180 "", passlen=0, salt=0x5521a0 "", saltlen=0, N=1048576, r=8, p=1, maxmem=33554432, 
    key=0x0, keylen=0, sha256=0x552c20, libctx=0x7ffff7e0ec40 <default_context_int>, propq=0x0)
    at providers/implementations/kdfs/scrypt.c:449
449	    int rv = 0;

So we can confirm N = 1048576 , r = 8 and p =1

gdb) n
456	    if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
(gdb) n
459	    if (p > SCRYPT_PR_MAX / r) {
(gdb) n
469	    if (16 * r <= LOG2_UINT64_MAX) {
(gdb) n
483	    Blen = p * 128 * r;

So we can see that we skip the bounds check entirely, as 16 * 8 > LOG2_UINT64_MAX (63).
Continuing:

488	    if (Blen > INT_MAX) {
(gdb) 
497	    i = UINT64_MAX / (32 * sizeof(uint32_t));
(gdb) 
498	    if (N + 2 > i / r) {
(gdb) 
502	    Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
(gdb) 
505	    if (Blen > UINT64_MAX - Vlen) {
(gdb) 
514	    if (Blen + Vlen > maxmem) {
(gdb) 
515	        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);

We're just tripping over the maxmem sizing of 16MB that is fixed inside the scrypt code, which we had discussed here:
#24650 (comment)

It seems the test is fine regardless, we just need to settle on the best method for adjusting that sizing

@nhorman

nhorman commented Aug 26, 2024

Copy link
Copy Markdown
Contributor

though it does beg the question about what (if anything) to do with that unaddressed errata

@davidben

Copy link
Copy Markdown
Contributor

Sounds like the erratum is invalid and should be marked as such.

@davidben

Copy link
Copy Markdown
Contributor

Ah, nevermind, I see. The erratum wasn't filed because of this misdiagnosis but something else.

paulidale
paulidale previously approved these changes Aug 26, 2024
@openssl-machine

Copy link
Copy Markdown
Collaborator

This PR is waiting for the creator to make requested changes but it has not been updated for 30 days. If you have made changes or commented to the reviewer please make sure you re-request a review (see icon in the 'reviewers' section).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: review pending This pull request needs review by a committer branch: master Applies to master branch tests: present The PR has suitable tests present triaged: feature The issue/pr requests/adds a feature waiting-for: contributor response This pull request is awaiting a response by the contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants