RDRAND and RDSEED CPU Functions Now Available

    Hello!

    I myself do not do cryptography, but my little research may very well come in handy. I decided to deal with the built-in processor functions RDRAND and RDSEED. The Delphi compiler said an Undeclared identifier. Hmm BMI, BMI2, AVX, AVX2, and even AVX-512 have long existed, and Delphians settled on SSE4.2. No problem. We compile the code ourselves.

    First I made a check for support of these functions by the processor. Of course, CPUID. You can use CPUID starting with the first Pentium processors. I hope no one thinks of running CPUID on a 486 machine, because it has not been there yet. By the way, RDRAND and RDSEED before IvyBridge processors also do not exist.

    function CPU_support_RDRAND: Boolean;
    asm
      mov rax, $01
      cpuid
      test ecx, 40000000h //тестируем 30-й бит
      setne al
    end;
    function CPU_support_RDSEED: Boolean;
    asm
      mov rcx, 0
      mov rax, $07 //страница №7
      cpuid
      test ebx, 40000h //тестируем 18-й бит
      setne al
    end;
    

    It turned out that my Core i7 G6950X Extreme supports these features. So then I decided to compile the bytecode manually. For experienced I will give the code REX and REX.W prefixes. You might want to write the result in a different register:

    const
      REX_RDRAND32: Byte = $F0; //(11b:REG, 110b:OPCODE, 000b:EAX) 
      REX_RDSEED32: Byte = $F8; //(11b:REG, 111b:OPCODE, 000b:EAX)
      REX_W_RDRAND64: Byte = $48; //(11b:REG, 110b:OPCODE, 000b:RAX)
      REX_W_RDSEED64: Byte = $48; //(11b:REG, 111b:OPCODE, 000b:RAX)
    

    Functions can work both in 32-bit mode and in 64-bit mode. Therefore, I did both, and even in two versions. The result is 4 functions:

    function RDRand32: DWord;
    asm
     @Retry:
      db $0F, $C7, $F0 //RDRAND EAX (CF = 1 говорит о корректности данных)
      jnc @Retry
    end;
    function RDSeed32: DWord;
    asm
     @Retry:
      db $0F, $C7, $F8 //RDSEED EAX (CF = 1 говорит о корректности данных)
      jnc @Retry
    end;
    function RDRand64: QWord;
    asm
      .NOFRAME
     @Retry:
      db $48, $0F, $C7, $F0  //RDRAND RAX (CF = 1 говорит о корректности данных)
      jnc @Retry
    end;
    function RDSeed64: QWord;
    asm
      .NOFRAME
     @Retry:
      db $48, $0F, $C7, $F8 //RDSEED RAX (CF = 1 говорит о корректности данных)
      jnc @Retry
    end;

    They are slower in speed than the library function Random. RDRand is about 35%, and RDSeed is 50% or more, but the quality of the uniqueness of the generated values ​​is much higher. There are some good articles on this subject on this resource, but my mission (to make functions available in Delphi) has been completed. I did not test it in Lazarus, but it will most likely work without any changes. At the end of the function declaration, you just need to add the backup word assembler.

    Here is the source code for the test console application. There you can find a prototype of the functions Random32 and Random64 based on the built-in processor. Perhaps this is what you were looking for. Bye everyone!

    Also popular now: