1 // darn.h - written and placed in public domain by Jeffrey Walton
2 //          DARN requires POWER9/ISA 3.0.
3 
4 // At the moment only GCC 7.0 (and above) seems to support __builtin_darn()
5 // and __builtin_darn_32(). However, GCC generates incorrect code. Clang 7.0
6 // does not provide them, but it does support assembly instructions. XLC is
7 // unknown, but there are no hits when searching IBM's site. To cover more
8 // platforms we provide GCC inline assembly like we do with RDRAND and RDSEED.
9 // Platforms that don't support GCC inline assembly or the builtin will fail
10 // to compile. Also see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91481 and
11 // https://gcc.gnu.org/onlinedocs/gcc/Basic-PowerPC-Built-in-Functions-Available-on-ISA-3_002e0.html
12 
13 /// \file darn.h
14 /// \brief Classes for DARN RNG
15 /// \sa <A HREF="https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0">Power
16 ///   ISA Version 3.0B</A>
17 /// \since Crypto++ 8.0
18 
19 #ifndef CRYPTOPP_DARN_H
20 #define CRYPTOPP_DARN_H
21 
22 #include "cryptlib.h"
23 
NAMESPACE_BEGIN(CryptoPP)24 NAMESPACE_BEGIN(CryptoPP)
25 
26 /// \brief Exception thrown when a DARN generator encounters
27 ///    a generator related error.
28 /// \since Crypto++ 8.0
29 class DARN_Err : public Exception
30 {
31 public:
32     DARN_Err(const std::string &operation)
33         : Exception(OTHER_ERROR, "DARN: " + operation + " operation failed") {}
34 };
35 
36 /// \brief Hardware generated random numbers using DARN instruction
37 /// \details DARN() provides access to Power9's random number generator. The
38 ///   Crypto++ implementation provides conditioned random numbers from the
39 ///   generator as opposed to raw random numbers. According to Power ISA 3.0B
40 ///   manual, a conditioned random number has been processed by hardware to
41 ///   reduce bias. A raw random number is unconditioned noise source output.
42 /// \details According to Power ISA 3.0B manual, the random number generator
43 ///   provided by the <tt>darn</tt> instruction is NIST SP800-90B and SP800-90C
44 ///   compliant to the extent possible given the completeness of the standards
45 ///   at the time the hardware is designed. The random number generator provides
46 ///   a minimum of 0.5 bits of entropy per bit.
47 /// \par Wraps
48 ///   darn instruction
49 /// \sa <A HREF="https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0">Power
50 ///   ISA Version 3.0B</A>, MaurerRandomnessTest() for random bit generators
51 /// \since Crypto++ 8.0
52 class DARN : public RandomNumberGenerator
53 {
54 public:
StaticAlgorithmName()55     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "DARN"; }
56 
~DARN()57     virtual ~DARN() {}
58 
59     /// \brief Construct a DARN generator
60      /// \throw DARN_Err if the random number generator is not available
61     DARN();
62 
63     /// \brief Generate random array of bytes
64     /// \param output the byte buffer
65     /// \param size the length of the buffer, in bytes
66     virtual void GenerateBlock(byte *output, size_t size);
67 
68     /// \brief Generate and discard n bytes
69     /// \param n the number of bytes to generate and discard
70     /// \details the RDSEED generator discards words, not bytes. If n is
71     ///   not a multiple of a machine word, then it is rounded up to
72     ///   that size.
73     virtual void DiscardBytes(size_t n);
74 
75     /// \brief Update RNG state with additional unpredictable values
76     /// \param input unused
77     /// \param length unused
78     /// \details The operation is a nop for this generator.
IncorporateEntropy(const byte * input,size_t length)79     virtual void IncorporateEntropy(const byte *input, size_t length)
80     {
81         // Override to avoid the base class' throw.
82         CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
83     }
84 
AlgorithmProvider()85     std::string AlgorithmProvider() const {
86         return "Power9";
87     }
88 
89 private:
90     SecBlock<byte, AllocatorWithCleanup<byte, true> > m_temp;
91 };
92 
93 NAMESPACE_END
94 
95 #endif // CRYPTOPP_DARN_H
96