php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #80214 random_bytes(): 0 random bytes should be a valid request
Submitted: 2020-10-10 12:34 UTC Modified: 2020-10-15 10:22 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: divinity76 at gmail dot com Assigned:
Status: Open Package: Unknown/Other Function
PHP Version: Next Minor Version OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: divinity76 at gmail dot com
New email:
PHP Version: OS:

 

 [2020-10-10 12:34 UTC] divinity76 at gmail dot com
Description:
------------
asking random_bytes() for 0 random bytes should be a perfectly valid request (but asking for <0 bytes should not be),

there are situations where code will dynamically determine that they need "0 random bytes", and then ask random_bytes to get them the number of bytes they determined that they needed
(as a real-life example of this, check https://3v4l.org/OCBiU , and to make that code runnable, go to line 35 and replace `for($i=0;$i<100;++$i){` with `for($i=1;$i<100;++$i){` )

but random_bytes will throw an Error when users ask for 0 random bytes. that should be a perfectly valid request, why is it throwing an Error? when you run str_repeat("",0) or hex2bin("") or bin2hex("") or base64_decode("") or base64_encode("") or fwrite($h,"") or file_put_contents("file",""), none of those requests are errors, why is it then an error to ask for 0 random bytes?

Test script:
---------------
<?php

for($i=0;$i<9;++$i){
    random_bytes($i);
}
echo "success!";

Expected result:
----------------
success!

Actual result:
--------------
Fatal error: Uncaught Error: Length must be greater than 0 in /in/elLeT:4
Stack trace:
#0 /in/elLeT(4): random_bytes(0)
#1 {main}
  thrown in /in/elLeT on line 4

Process exited with code 255.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-10-10 12:42 UTC] rtrtrtrtrt at dfdfdfdf dot dfd
seriously what value do you expect by random_bytes(0)

> there are situations where code will dynamically 
> determine that they need "0 random bytes"

your example below makes no sense at all - that's what the if-statement is for

> none of those requests are errors
> why is it then an error to ask for 0 random bytes

beause it's not a random string operation but asking fro cryptographic save random and in no valid real world usecase you really want to operate with an empty string
 [2020-10-15 03:32 UTC] a at b dot c dot de
Scenario: I have a block of bytes that I want to pad to a specific length by appending some randomness (after embedding the message length) because the length of the message would otherwise be a potential information leak.

The most straightforward way of doing it would be " . random_bytes(strlen($message) % BLOCK_SIZE)".

To claim that random_bytes(0) should be special-cased is like claiming if() statements should be written to protect sort() from an empty array argument.
 [2020-10-15 09:19 UTC] divinity76 at gmail dot com
let me get this straight guys,

requesting str_repeat("A",0) will give you an empty string, as one would expect (request: repeat "A" 0 times)

requesting random_bytes(0) will give you an exception... (request: give me 0 random bytes)

and both of these make sense to you? it's ok to request a string to be repeated 0 times, but it's not ok to ask for 0 random bytes? is that the opinion of you guys? or do you guys consider str_repeat() broken in this regard?
 [2020-10-15 09:32 UTC] rtrtrtrtrt at dfdfdfdf dot dfd
> it's ok to request a string to be repeated 0 times, 
> but it's not ok to ask for 0 random bytes? 

you still don#t get the difference of a random string operation and a function which is meant for for cryptographic safe randomness meat for security relevant context

are you sure that you don't absue random_bytes() at all in your sue case which likely don't need randomness in that quality

> is that the opinion of you guys? 

yes

> or do you guys consider str_repeat() broken in this regard?

no or how is it a security context line random_bytes()?
 [2020-10-15 09:50 UTC] nikic@php.net
FWIW I agree that random_bytes(0) should be legal.
 [2020-10-15 10:22 UTC] divinity76 at gmail dot com
@rtrtrtrtrt 

at least the Linux Kernel developers think it's ok to ask for 0 random bytes, when you ask the linux kernel getrandom() api ( https://man7.org/linux/man-pages/man2/getrandom.2.html ) for 0 random, it will check that you're capable of generating random bytes, then.. generate 0 random bytes, and return the number of bytes it generated... 0, and not set any error notice anywhere (not in the return value itself, and not in errno)

testing it:

hans@xDevAd:~/projects/misc$ cat ggg.cpp
#include <iostream>
#include <sys/random.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */

int main(){
	std::string buf;
	std::cout << "errno before: " << errno << std::endl;
	const int flags = 0;
	std::cout << "libc getrandom: " << getrandom((char*)buf.data(), buf.size(), flags) << std::endl;
	std::cout << "errno after: " << errno << std::endl;
	std::cout << "syscall getrandom (practically bypassing libc): " << syscall(SYS_getrandom, (char*)buf.data(), buf.size(), flags) << std::endl;
	std::cout << "errno after: " << errno << std::endl;
}
hans@xDevAd:~/projects/misc$ g++ -Wall -Wextra -Wpedantic -Werror ggg.cpp
hans@xDevAd:~/projects/misc$ ./a.out 
errno before: 0
libc getrandom: 0
errno after: 0
syscall getrandom (practically bypassing libc): 0
errno after: 0
hans@xDevAd:~/projects/misc$


- if the linux kernel had a problem with any of this, one of the numbers should have been <0
 [2020-10-29 08:50 UTC] a at b dot c dot de
It may be as simple as tweaking the size check in PHP_FUNCTION(random_bytes) and the corresponding error message. But that depends on whether all of the methods on all the platforms are as accommodating as the Linux kernel syscall (as demonstrated above).

If any are stroppy, php_random_bytes() would have to wend around the problem areas. It's not enough to just put a "if size is zero, return empty string" test at the top: for consistency, the function should still abort if there is no adequate entropy source available (I can think of at least three potential issues if php_random_bytes(0) always succeeded).
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri Dec 04 14:01:23 2020 UTC