POWER9: Is there a way to improve the random number generation on PPC64?

Gustavo Romero gromero at linux.vnet.ibm.com
Mon Dec 4 23:24:17 UTC 2017


Hi Volker,

On 04-12-2017 12:00, Volker Simonis wrote:
> The solution is quite simple (took me a while though as well to see it
> :) - you have to define the intrinsic with the correct access flags.
> I.e.

Pretty cool!

Thanks a lot for the help and the quick answer :-)


>   do_intrinsic(_darn, securerandom, darn_name,
> serializePropertiesToByteArray_signature, F_R)
> 
> instead of using "F_S" as you did in your first attempt. The access
> flags are defined at the bottom of vmSymbols.hpp:
> 
>     F_R,                        // !static ?native !synchronized (R="regular")
>     F_S,                        //  static ?native !synchronized
> 
> If they don't correspond to the actual function, it won't be matched.
> 
> If you'll do this right you'll get the following error:
> 
> Compiler intrinsic is defined for method
> [java.security.SecureRandom.darn()[B], but the method is not annotated
> with @HotSpotIntrinsicCandidate. Exiting.
> 
> which can be pacified by using "-XX:-CheckIntrinisics" or better by
> using the  @HotSpotIntrinsicCandidate annotation on the
> SEcureRandom.darn()

Right. I also had to tweak the darn() intrinsic to return a 'long' instead of
a byte array just for quickly avoid dealing with any allocation inside it. The
prototype worked fine on interpreted mode. As expected it generated an illegal
instruction on P8 but returned 50 random numbers on P9 without getting blocked
:-) So test [0] that uses SecureRandom.generateSeed() blocks from time to time
(both on BM and VM it blocks always on a second run), but test [1] which uses
SecureRandom.darn() never blocks:

http://cr.openjdk.java.net/~gromero/logs/darn_prototype.log

Here is the final change for reference (hs + corelib):

https://github.com/gromero/darn/blob/a8ea0802018b0c4de946b548d4ede4bfc5fb6451/patches/darn_prototype.patch

I intend to implement the fallback now and run it against DayTrade7 bench, if
you have any other idea on how to test it, please let me know.


> Notice that in the real implementation you won't be able to add a
> public method to SecureRandom.

Yup, I'm aware of it. Initially I thought I could keep all the changes in
arch-specific files but due to the need to fallback to a Java method if 'darn'
intrinsic fails I understand that there is no way to not touch .java files. In
that case your suggestion is to create an entire new provider by adding a new on
to ./java.base/share/classes/com/sun/crypto/provider and listing it in
java.security, for instance?


Regards,
Gustavo

[0] https://github.com/gromero/darn/blob/eee8f0a480d7fd5cf6a307d3e7520e867d784ba3/patches/seed_current.java
[1] https://github.com/gromero/darn/blob/0591eaf338664222c2cd26188d56fdb5a56883ea/patches/seed_darn.java

> Regards,
> Volker
> 
> 
> On Fri, Dec 1, 2017 at 10:44 PM, Gustavo Romero
> <gromero at linux.vnet.ibm.com> wrote:
>> Hi Volker,
>>
>> On 29-11-2017 11:21, Volker Simonis wrote:
>>> On Wed, Nov 29, 2017 at 2:04 PM, Gustavo Romero
>>> <gromero at linux.vnet.ibm.com> wrote:
>>>> Hi Volker,
>>>>
>>>> On 24-11-2017 20:04, Volker Simonis wrote:
>>>>> in one of my talks [1,2] I have an example on how to intrinsify
>>>>> Random.nextInt() in C2 by using the Intel 'rdrandl' instruction. But
>>>>> please notice that this is just a "toy" example - it is not production
>>>>> ready. In fact I think the right way would be to create a new
>>>>> SecureRandom provider where you may implement "engineNextBytes" by
>>>>> using  the new Power instruction (maybe by calling a native function).
>>>>> This special implementation of "engineNextBytes" could then be
>>>>> intrinsified as described in the talk.
>>>>
>>>> I've implemented a simple interpreter intrinsic for 'darn' for a given
>>>> class/method provided by the user, similarly to what you did for
>>>> Helloword.sayHello() in your example. Thanks! I'm now looking for the correct
>>>> way to call back from the intrinsic a Java method to act as a fallback method,
>>>> since ISA says [1]:
>>>>
>>>> When the error value is obtained [i.e. 'darn' did not return a random number],
>>>> software is expected to repeat the operation. If a non-error value has not been
>>>> obtained after several attempts, a software random number generation method
>>>> should be used. The recommended number of attempts may be implementation
>>>> specific. In the absence of other guidance, ten attempts should be adequate.
>>>>
>>>> and so I need to call back from the intrinsic, let's say, SecureRandom.netInt()
>>>> non-intrinsified method after about 10 failures to get the random number so it
>>>> can take over the task again. You did something like that here:
>>>>
>>>> https://github.com/simonis/JBreak2016/blob/master/examples/hs_patches/JBreak_HelloWorldIntrinsic.patch#L55
>>>>
>>>> but for fputs() from libc.
>>>>
>>>> Do you know if it's possible to call, for instance, a loaded method like
>>>> SecureRandom.nextInt() from the instrinsic?
>>>>
>>>
>>> I don't think that would be easy to do (if possible at all).
>>>
>>> The correct way to handle such situations would be to define a Java
>>> method with the exact semantics of your 'darn' instruction. All the
>>> other logic should be implemented in Java. So for example you would
>>> implement SecureRandom.darn() and call it from engineNextBytes(). At
>>> the call site of darn() you check the error value and dispatch to the
>>> corresponding Java implementation if necessary.
>>
>> I've implemented a Java SecureRandom.darn() method [1]. I works as expected,
>> i.e. it returns 8 bytes of fake random number (using [3] example). However, when
>> I proceeded to intrinsify it [2, 0] as I did for the method provided by the user
>> (similarly to your HelloWorld example and for a user provided darn() method as I
>> mentioned previously) I hit the following check:
>>
>> Compiler intrinsic is defined for method [_darn: static SecureRandom.darn()[B], but the method is not available in class [java/security/SecureRandom]. Exiting.
>>
>> SecureRandom.darn() signature looks correct and I know that
>> java/security/SecureRandom::darn() is present in core libs because before trying
>> to intrinsify it worked ok (I've got the 8 bytes of fake random number - using
>> darning.java, below in references) and also 'javap' shows it's in .class:
>>
>> gromero at gromero16:~/hg/jdk10/hs$ javap -c -s ./build/linux-ppc64le-normal-server-slowdebug/jdk/modules/java.base/java/security/SecureRandom.class | fgrep -i darn
>>   public byte[] darn();
>>
>> I thought that no additional hack was necessary to get that intrinsic working as
>> it's in core libs, hence nothing like this is needed:
>>
>> https://github.com/simonis/JBreak2016/blob/master/examples/hs_patches/JBreak2JavaZone.patch#L57-L59
>>
>> On the other hand if I add @HotSpotIntrinsicCandidate to SecureRandom.darn() I
>> get:
>>
>> Method [java.security.SecureRandom.darn()[B] is annotated with @HotSpotIntrinsicCandidate, but no compiler intrinsic is defined for the method. Exiting.
>>
>> Any clue on what I'm missing? Is it correct to assume that since darn() now
>> is in core libs no check is necessary?
>>
>> Thanks a lot!
>>
>> Regards,
>> Gustavo
>>
>> The hs patches:
>>
>> [0] https://github.com/gromero/darn/blob/master/patches/0_darn_macroassembler.patch
>> [1] https://github.com/gromero/darn/blob/master/patches/1_SecureRandom_darn_Java.patch
>> [2] https://github.com/gromero/darn/blob/master/patches/2_SecureRandom_darn_intrinsic.patch
>>
>> and the test-case:
>>
>> [3] https://github.com/gromero/darn/blob/master/patches/darning.java
>>
>>>> Thanks!
>>>>
>>>> Regards,
>>>> Gustavo
>>>>
>>>>> Also, before you start this, please contact the security mailing list
>>>>> just to make sure you're not going into the wrong direction (I'm not a
>>>>> security expert :)
>>>>>
>>>>> Regards,
>>>>> Volker
>>>>>
>>>>> [1] https://vimeo.com/182074382
>>>>> [2] https://rawgit.com/simonis/JBreak2016/master/jbreak2016.xhtml#/
>>>>>
>>>>> On Fri, Nov 24, 2017 at 12:58 PM, Gustavo Romero
>>>>> <gromero at linux.vnet.ibm.com> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> POWER9 processors introduced a new single instruction to generate a random
>>>>>> number called 'darn' (Deliver A Random Number) [1, 2]. The random number
>>>>>> generator behind this instruction is NIST SP800-90B and SP800-90C compliant and
>>>>>> provides a minimum of 0.5 bits of entropy per bit. That instruction is as simple
>>>>>> as "darn RT, L", where RT is general 64-bit purpose register and L is a 2-bit
>>>>>> operand to select the random number format. One can call 'darn' many times to
>>>>>> obtain a new random number each time.
>>>>>>
>>>>>> Initially I think it can help on the improving (throughput) of SecureRandom.generateSeed()
>>>>>> method & friends from JCE (NativePRNG provider). If that holds, so it has to
>>>>>> be done both for Interpreter and JIT.
>>>>>>
>>>>>> Currently generateSeed() from NativePRNG basically reads from /dev/random by
>>>>>> default (which blocks from time to time) or /dev/urandom if instructed to do so.
>>>>>> Could somebody please help me to figure out the appropriate place to exploit
>>>>>> such a P9 instruction for interpreted mode, given that code for generateSeed()
>>>>>> is pure Java and behind scenes just opens /dev/random file and reads from
>>>>>> it? For instance, is it correct to exploit it on a C/C++ code and attach that
>>>>>> by means of a JNI?
>>>>>>
>>>>>> Finally, for JITed mode, I think that a way to exploit such a feature would be
>>>>>> by matching an specific sub-tree in Ideal Graph and from that emit a `darn`
>>>>>> instruction, however I could not figure one sound sub-tree with known nodes
>>>>>> (AddI, LoadN, Parm, etc) that could be matched for that purpose. How do porters
>>>>>> usually proceed in this case?
>>>>>>
>>>>>> Any comments shedding some light on that is much appreciated.
>>>>>>
>>>>>> Thanks and best regards,
>>>>>> Gustavo
>>>>>>
>>>>>> [1] https://www.docdroid.net/tWT7hjD/powerisa-v30.pdf, p. 79
>>>>>> [2] https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0
>>>>>>
>>>>>
>>>>
>>>
>>
> 



More information about the ppc-aix-port-dev mailing list