Skip to content
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

Augment rand argument parsing to allow scaling #22624

Closed
wants to merge 9 commits into from

Conversation

nhorman
Copy link
Contributor

@nhorman nhorman commented Nov 4, 2023

Extend opts parsing to parse long long values, and use it to have openssl rand accept requests for more than 2^32-1 bytes of data

Fixes #22622

apps/lib/opt.c Outdated
Comment on lines 593 to 594
/* Parse a long long, put it into *result; return 0 on failure, else 1. */
int opt_long_long(const char *value, long long *result)
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned elsewhere (#22622 (comment)), a size_t would be my preferred choice.

Suggested change
/* Parse a long long, put it into *result; return 0 on failure, else 1. */
int opt_long_long(const char *value, long long *result)
/* Parse a size argument with an optional size suffix (e.g., 1024, 1k, 30M), put it into *result; return 0 on failure, else 1. */
int opt_size(const char *value, size_t *result)

Copy link
Contributor

Choose a reason for hiding this comment

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

It's signed here, so size_t wouldn't be correct. int64_t is the one to change to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think if we allow for scaling (i.e. 256k, 800g, etc), opt_long is still perfectly acceptable no?

apps/rand.c Outdated Show resolved Hide resolved
@mspncp
Copy link
Contributor

mspncp commented Nov 4, 2023

I guess you meant to write openssl rand, not opt rand (commit message & pr title)?

allow openssl rand to accept larger data requests

apps/rand.c Outdated Show resolved Hide resolved
apps/rand.c Outdated Show resolved Hide resolved
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.

Nice work. Some suggestions for minor enhancements.

apps/rand.c Outdated Show resolved Hide resolved
apps/rand.c Outdated
Comment on lines 112 to 139
if (!isdigit((int)(argv[0][factoridx]))) {
switch(argv[0][factoridx]) {
case 'k':
scale = 10;
break;
case 'm':
scale = 20;
break;
case 'g':
scale = 30;
break;
case 't':
scale = 40;
default:
goto opthelp;
}
break;
}
factoridx++;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd make it case insensitive and disallow multiple suffixes:

Suggested change
if (!isdigit((int)(argv[0][factoridx]))) {
switch(argv[0][factoridx]) {
case 'k':
scale = 10;
break;
case 'm':
scale = 20;
break;
case 'g':
scale = 30;
break;
case 't':
scale = 40;
default:
goto opthelp;
}
break;
}
factoridx++;
if (!isdigit((int)(argv[0][factoridx]))) {
if (shift != 0)
goto opthelp;
switch(argv[0][factoridx]) {
case 'k':
case 'K':
shift = 10;
break;
case 'm':
case 'M':
shift = 20;
break;
case 'g':
case 'G':
shift = 30;
break;
case 't':
case 'T':
shift = 40;
default:
goto opthelp;
}
break;
}
factoridx++;

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not do as dd(1) does for size suffixes?

N and BYTES may be followed by the following multiplicative suffixes: c=1, w=2, b=512, kB=1000, K=1024, MB=10001000, M=10241024, xM=M, GB=100010001000, G=102410241024, and so on for T, P, E, Z, Y. Bi‐ nary prefixes can be used, too: KiB=K, MiB=M, and so on.

Also noting that m and M are distinct SI prefixes so case insensitivity could be confusing.

Copy link
Contributor

Choose a reason for hiding this comment

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

This seams to be consistent with what head(1) uses

NUM may have a multiplier suffix: b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024, GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.  Binary prefixes can be used, too: KiB=K, MiB=M, and so on.

apps/rand.c Outdated Show resolved Hide resolved
apps/rand.c Outdated Show resolved Hide resolved
doc/man1/openssl-rand.pod.in Outdated Show resolved Hide resolved
@mspncp
Copy link
Contributor

mspncp commented Nov 6, 2023

A general remark: just doing a goto opthelp; without printing any useful error message will create a lot of frustration for the app user, because he will only see the same usage message over and over again until he guesses what he messed up. (I know this from my own experience).

@tom-cosgrove-arm
Copy link
Contributor

@nhorman Do let us know when you want a full review (this is still a draft PR)

@nhorman
Copy link
Contributor Author

nhorman commented Nov 7, 2023

@tom-cosgrove-arm ack, I think its ready now

@nhorman nhorman marked this pull request as ready for review November 7, 2023 10:20
@mspncp
Copy link
Contributor

mspncp commented Nov 7, 2023

I very much appreciate that you try to avoid force pushes, but now is a good time to do an interactive rebase in order to cleanup your history. If you do it without moving the merge-base (git rebase -i --keep-base ...) it will be easy for the reviewers to verify that you didn't introduce any tree changes, using GitHub's force-push diff.

Please note, that the commit message is outdated, the terabytes are still missing.

Augment rand argument parsing to allow scaling

Instead of just accepting a number of bytes, allows openssl rand to
accept a k|m|g suffix to scale to kbytes/mbytes/gbytes

Fixes #22622

I'd also appreciate if you'd change your PR title to match the subject line of the commit: Augment rand argument parsing to allow scaling

@mspncp
Copy link
Contributor

mspncp commented Nov 7, 2023

And be warned: I will insist on strict parsing of the suffixes (with a meaningful error message). Or do you really want to get a bug report because someone called

openssl rand 10km

and didn't get 10 kilometres of random output? 😉

@mspncp
Copy link
Contributor

mspncp commented Nov 7, 2023

At least in the commit message and the documentation (usage, manpage) we should use the correct official abbreviations KiB / MiB / GiB / TiB for clarity:

accept a [k|m|g|t] suffix to scale to KiB/MiB/GiB/TiB

(BTW: I noticed that @jirka-h forgot to request support for PiB) 😉

@mspncp mspncp added branch: master Merge to master branch triaged: feature The issue/pr requests/adds a feature labels Nov 7, 2023
@nhorman nhorman changed the title allow opt rand to accept larger data requests Augment rand argument parsing to allow scaling Nov 7, 2023
@mspncp
Copy link
Contributor

mspncp commented Nov 7, 2023

Fun Trivia: NIST has a really neat page about Prefixes for binary multiples, which applies in particular to the section about the historical context.

Instead of just accepting a number of bytes, allows openssl rand to
accept a k|m|g suffix to scale to kbytes/mbytes/gbytes

Fixes openssl#22622
@jirka-h
Copy link

jirka-h commented Nov 7, 2023

(BTW: I noticed that @jirka-h forgot to request support for PiB) 😉

😄 Check man head - it supports prefixes all the way up to YiB (2^80). That's future ready:-)

Joking aside: SP 800-90C limits DRBG output to 2^64 bits per instantiation. We can go up to EiB (2^60). I have been testing RNGs (batteries of statistical tests) in the past (~6 years ago), going up to 128 TiB. With today's HW, reaching PiB is no problem - openssl rand achieves rate of around 1.5GiB/s on my laptop, meaning you can generate 1PiB in just ~6 days on decent HW.

doc/man1/openssl-rand.pod.in Outdated Show resolved Hide resolved
apps/rand.c Outdated Show resolved Hide resolved
doc/man1/openssl-rand.pod.in Outdated Show resolved Hide resolved
apps/rand.c Outdated Show resolved Hide resolved
t8m
t8m previously approved these changes Nov 9, 2023
@t8m
Copy link
Member

t8m commented Nov 9, 2023

CI is relevant, other than that this looks good.

apps/rand.c Outdated Show resolved Hide resolved
Copy link
Contributor

@tom-cosgrove-arm tom-cosgrove-arm left a comment

Choose a reason for hiding this comment

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

LGTM

@tom-cosgrove-arm tom-cosgrove-arm removed the approval: review pending This pull request needs review by a committer label Nov 9, 2023
apps/rand.c Outdated Show resolved Hide resolved
@t8m t8m dismissed their stale review November 9, 2023 19:21

CI failing

@nhorman
Copy link
Contributor Author

nhorman commented Nov 9, 2023

Its the intermittent sslapi failure

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.

I don't see a need for stopping the timer or getting re-reviews for the final case change in the comment.

@tom-cosgrove-arm
Copy link
Contributor

My approval still stands

@tom-cosgrove-arm
Copy link
Contributor

I think full approval is done, so updating labels

@tom-cosgrove-arm tom-cosgrove-arm added approval: done This pull request has the required number of approvals and removed approval: otc review pending This pull request needs review by an OTC member labels Nov 9, 2023
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.

I don't see a need for stopping the timer or getting re-reviews for the final case change in the comment.

It's more than just a simple case change: As I pointed out three days ago the terabytes are not mentioned yet, and I'd like to see the official abbreviations.

The commit message is part of the review, so I'd like to get to see it before the pull request can be approved. @nhorman could either autosquash the pull request (without moving the merge base) and edit the commit message, or alternatively he could post the intended commit message here, e.g., like this:

Augment rand argument parsing to allow scaling

Instead of just accepting a number of bytes, allows openssl rand to
accept a K|M|G|T suffix to scale to KiB/MiB/GiB/TiB.

Fixes #22622

Considering how picky we sometimes are about trivial whitespace errors in the code, I really don't understand why we don't care in the same way about the correctness and quality of the commit messages.

Also, I requested strict parsing, i.e. we shouldn't allow multiple suffixes with undefined behaviour. It was already the second time I asked for it, but up to now my request has simply been ignored.

@t8m
Copy link
Member

t8m commented Nov 10, 2023

Considering how picky we sometimes are about trivial whitespace errors in the code, I really don't understand why we don't care in the same way about the correctness and quality of the commit messages.

@mspncp Please bring up this topic on the next OTC meeting. We aren't picky about commit messages (maybe we should be) but it seems to me unfair to be particularly picky on this particular PR.

Also, I requested strict parsing, i.e. we shouldn't allow multiple suffixes with undefined behaviour. It was already the second time I asked for it, but up to now my request has simply been ignored.

But if I understand the current code right it does NOT allow multiple suffixes. That's one of the things I particularly looked at when reviewing this PR.

If you really really want to block this PR in this form from merging, please put an OTC hold there. Otherwise IMO this is good to go in once the 24h timeout expires (with possible commit message adjustments that can be done during merging).

@mspncp
Copy link
Contributor

mspncp commented Nov 10, 2023

Considering how picky we sometimes are about trivial whitespace errors in the code, I really don't understand why we don't care in the same way about the correctness and quality of the commit messages.

@mspncp Please bring up this topic on the next OTC meeting. We aren't picky about commit messages (maybe we should be) but it seems to me unfair to be particularly picky on this particular PR.

Fair point, you are right.

But if I understand the current code right it does NOT allow multiple suffixes. That's one of the things I particularly looked at when reviewing this PR.

To be honest, I only looked at the source code and didn't compile and test it. But it looks to me like the app loops over the suffixes and every suffix overwrites the previous one, such that 10KM effectively becomes 10M, right? A simple check for shift != 0 before the switch statement with an error message about multiple suffixes would have prevented this.

openssl/apps/rand.c

Lines 125 to 133 in b273c3d

while (argv[0][factoridx]) {
if (!isdigit((int)(argv[0][factoridx]))) {
switch(argv[0][factoridx]) {
case 'K':
shift = 10;
break;
case 'M':
shift = 20;
break;

If you really really want to block this PR in this form from merging, please put an OTC hold there. Otherwise IMO this is good to go in once the 24h timeout expires (with possible commit message adjustments that can be done during merging).

No, I'm not blocking it, because overall I really like the change. It's ok for me if people have different opinions and change requests can be debated and/or rejected. But the fact that my requests were simply ignored is what annoyed me a little bit and this was the reason for my reply. Sorry @nhorman if my last reply was too harsh, it wasn't meant personal.

@nhorman
Copy link
Contributor Author

nhorman commented Nov 10, 2023

To be honest, I only looked at the source code and didn't compile and test it. But it looks to me like the app loops over the suffixes and every suffix overwrites the previous one, such that 10KM effectively becomes 10M, right?
@mspncp Thats not what it does:

            while (argv[0][factoridx]) {
                if (!isdigit((int)(argv[0][factoridx]))) {
                    switch(argv[0][factoridx]) {
                    case 'K':
                        shift = 10;
                        break;
                    case 'M':
                        shift = 20;
                        break;
                    case 'G':
                        shift = 30;
                        break;
                    case 'T':
                        shift = 40;
                        break;
                    default:
                        BIO_printf(bio_err, "Invalid size suffix %s\n",
                                   &argv[0][factoridx]);
                        goto opthelp;
                    }
                    break;   <=== Outside the switch statement
                }
                factoridx++;
            }

We scan for non-digit characters, and on the first one we find, we parse it, set the shift or error out accordingly, break from the case statement, then break from the while loop.

The algorithm considers only the first non digit suffix. So:

openssl rand 256MetersPerSecondSquared

translates to:

openssl rand 256M

Which seems to me is ok. At the very least I would get a chuckle out of someone opening a bug indicating that openssl has poor acceleration.

@mspncp
Copy link
Contributor

mspncp commented Nov 10, 2023

Oh, thanks for the clarification! Indeed, I overlooked this little break:

                    break;   <=== Outside the switch statement

@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.

@t8m
Copy link
Member

t8m commented Nov 13, 2023

Merged to the master branch. Thank you.

@t8m t8m closed this Nov 13, 2023
openssl-machine pushed a commit that referenced this pull request Nov 13, 2023
Instead of just accepting a number of bytes, allows openssl rand to
accept a k|m|g suffix to scale to kbytes/mbytes/gbytes

Fixes #22622

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #22624)
@jirka-h
Copy link

jirka-h commented Nov 13, 2023

THANK YOU, EVERYBODY!

wanghao75 pushed a commit to openeuler-mirror/openssl that referenced this pull request Nov 20, 2023
Instead of just accepting a number of bytes, allows openssl rand to
accept a k|m|g suffix to scale to kbytes/mbytes/gbytes

Fixes #22622

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from openssl/openssl#22624)

Signed-off-by: fly2x <fly2x@hitls.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approval: done This pull request has the required number of approvals branch: master Merge to master branch tests: present The PR has suitable tests present triaged: feature The issue/pr requests/adds a feature
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

openssl rand - please allow to generate more than 2 GiB of data.
8 participants