conversion of RAND_bytes to rand in fips apporved way

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

conversion of RAND_bytes to rand in fips apporved way

pavan
Hi, we have linked FIPS compliant openssl version against our applications. 
Now few applications are using libc rand function. For FIPS compliance,
applications have 
to call approved SP 800-90A DRBG implementation. I was planning to replace
libc rand with RAND_bytes
for the same. 

But rand() returns max value of 32767 .  Is there a recomended way to
convert RAND_bytes to libc rand() 
something like this?

unsigned char buf[2];
RAND_bytes(buf,2)
int *rndp = malloc(4);
memcpy(rndp,buf,2); 
return (unsigned) ((*rndp) % 32768)


Please suggest . Is there a way to give number of bits instead of bytes  to
RAND_bytes?

Regards,

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

OpenSSL - User mailing list

If RAND_MAX is a power of 2, then just ask RAND_bytes for the right number of bytes (four for 32768) and use bit-shifting to pack the value.


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

Viktor Dukhovni
In reply to this post by pavan
On Wed, Jul 25, 2018 at 11:42:34PM +0530, Sudarshan Soma wrote:

> Now few applications are using libc rand function. For FIPS compliance,
> applications have to call approved SP 800-90A DRBG implementation.

If you're using libc's rand() for non-cryptographic purposes, you
can surely continue to do that.

> I was planning to replace libc rand with RAND_bytes for the same.
>
> But rand() returns max value of 32767.  Is there a recomended way to
> convert RAND_bytes to libc rand() something like this?

Since 16-bit random numbers do not provide any meaningful security,
it makes little sense to use a CSPRNG in a context where 16-bit
random values are sufficient.

> Please suggest. Is there a way to give number of bits instead of bytes  to
> RAND_bytes?

This is probably the wrong question.

--
        Viktor.
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

Michael Wojcik
In reply to this post by pavan
> From: openssl-users [mailto:[hidden email]] On Behalf Of Sudarshan Soma
> Sent: Wednesday, July 25, 2018 12:13

> But rand() returns max value of 32767 .  Is there a recomended way to
> convert RAND_bytes to libc rand()
> something like this?

> unsigned char buf[2];
> RAND_bytes(buf,2)
> int *rndp = malloc(4);
> memcpy(rndp,buf,2);
> return (unsigned) ((*rndp) % 32768)

Ugh. Memory leak, unnecessary malloc, undefined behavior (only part of the rdnp object is initialized)... I really hope you don't have code like this in your application.

C guarantees unsigned integer types use a pure binary representation, and 32767 is 2**15 - 1. So assuming you're only using octet-based C implementations (limits.h defines CHAR_BIT as 8), which is very likely the case, just do this:

unsigned int openssl_rand(void) {
   unsigned char bytes[2];
   RAND_bytes(bytes, 2);
   return (bytes[0] | (bytes[1] << 8)) & 0x7fff;
}

Untested, but I think that will work on any conforming C implementation with CHAR_BIT == 8, and as long as the 15 least-significant bits of the output of RAND_bytes are unbiased, the result will be an unbiased value in [0,32767].

Note this does not give you the semantics of C's rand, as it ignores any invocation of srand. Some C programs require a predictable rand; they use it for reproducible Monte Carlo test runs, for example. So replacing rand this way is not necessarily valid.

Also, calling it "rand" would be a violation of the C specification, so if you want your C applications to conform to the spec, you'll have to change them anyway. Or use a macro, provided the application code never suppresses a macro definition for rand.

--
Michael Wojcik
Distinguished Engineer, Micro Focus


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

William Roberts
On Wed, Jul 25, 2018 at 11:30 AM, Michael Wojcik
<[hidden email]> wrote:

>> From: openssl-users [mailto:[hidden email]] On Behalf Of Sudarshan Soma
>> Sent: Wednesday, July 25, 2018 12:13
>
>> But rand() returns max value of 32767 .  Is there a recomended way to
>> convert RAND_bytes to libc rand()
>> something like this?
>
>> unsigned char buf[2];
>> RAND_bytes(buf,2)
>> int *rndp = malloc(4);
>> memcpy(rndp,buf,2);
>> return (unsigned) ((*rndp) % 32768)
>
> Ugh. Memory leak, unnecessary malloc, undefined behavior (only part of the rdnp object is initialized)... I really hope you don't have code like this in your application.
>
> C guarantees unsigned integer types use a pure binary representation, and 32767 is 2**15 - 1. So assuming you're only using octet-based C implementations (limits.h defines CHAR_BIT as 8), which is very likely the case, just do this:
>
> unsigned int openssl_rand(void) {

LibC's rand() is int, so if it matters you'll want to match that
interface. But usually, you want to avoid signed numbers when negative
doesn't matter..

>    unsigned char bytes[2];
>    RAND_bytes(bytes, 2);
>    return (bytes[0] | (bytes[1] << 8)) & 0x7fff;

You can ditch the shift logic. Offhand,  i'm not sure what would
happen on Big Endian machine, would it leave bit 15 high since it's in
byte 0?

int openssl_rand(void) {
    uint16_t x;
    RAND_bytes((unsigned char *)&x, sizeof(x));
    return x & 0x7FFF;
}


> }
>
> Untested, but I think that will work on any conforming C implementation with CHAR_BIT == 8, and as long as the 15 least-significant bits of the output of RAND_bytes are unbiased, the result will be an unbiased value in [0,32767].
>
> Note this does not give you the semantics of C's rand, as it ignores any invocation of srand. Some C programs require a predictable rand; they use it for reproducible Monte Carlo test runs, for example. So replacing rand this way is not necessarily valid.
>
> Also, calling it "rand" would be a violation of the C specification, so if you want your C applications to conform to the spec, you'll have to change them anyway. Or use a macro, provided the application code never suppresses a macro definition for rand.
>
> --
> Michael Wojcik
> Distinguished Engineer, Micro Focus
>
>
> --
> openssl-users mailing list
> To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

Michael Wojcik
> From: openssl-users [mailto:[hidden email]] On Behalf
> Of William Roberts
> Sent: Wednesday, July 25, 2018 13:00
>
> >    unsigned char bytes[2];
> >    RAND_bytes(bytes, 2);
> >    return (bytes[0] | (bytes[1] << 8)) & 0x7fff;
>
> You can ditch the shift logic. Offhand,  i'm not sure what would
> happen on Big Endian machine, would it leave bit 15 high since it's in
> byte 0?

No. Bitwise operators in C work according to value, not representation, regardless of the byte order of multibyte integer types in that implementation.

> int openssl_rand(void) {
>     uint16_t x;
>     RAND_bytes((unsigned char *)&x, sizeof(x));
>     return x & 0x7FFF;
> }

That's OK if you include stdint.h, because you don't care which of the two permissible representations uint15_t has (it has to be pure-binary with no trap representations) - IF your implementation has a 16-bit unsigned integer type. uint16_t won't be defined for an implementation that doesn't. Offhand I don't know of one that is CHAR_BIT 8, though.

Personally, I don't care for your version, because I don't like to see code manipulate the representation of an object without specific reason. My version follows the same pattern that correctly-written integer-marshaling code should use, for example; it has the same behavior regardless of implementation details (assuming, once again, that CHAR_BIT is 8).

By the way, sizeof is an operator. There's no need to parenthesize its operand, unless the operand is a type.

Of course, as Viktor pointed out, this all may be pointless anyway; it's not clear that the OP needs this functionality.

--
Michael Wojcik
Distinguished Engineer, Micro Focus



--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: conversion of RAND_bytes to rand in fips apporved way

pavan
Thanks very much for valuable suggestions.

Few applciations like RADIUS/TACACS+/snmp protocol (IV generation for AES)
are using rand functions. As they are related to security, i am changing the
rand function used by them.

>>>> and as long as the 15 least-significant bits of the output of
>>>> RAND_bytes are unbiased

the above input might cause FIPS compliance issues as RAND_bytes doesnt
guarantee the biasing after we truncate one bit.  I shall check this once.

Regards,




--
Sent from: http://openssl.6102.n7.nabble.com/OpenSSL-User-f3.html
--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users