Add Divisor and MSR member variables
Guard ASM based on CRYPTOPP_X86_ASM_AVAILABLE Increased depth of internal buffer Update documentation for using the generator Whitespace check-inpull/462/head
parent
bc4bb9a952
commit
61c8b74951
2
config.h
2
config.h
|
|
@ -461,7 +461,7 @@ NAMESPACE_END
|
|||
|
||||
#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
|
||||
// C++Builder 2010 does not allow "call label" where label is defined within inline assembly
|
||||
#define CRYPTOPP_X86_ASM_AVAILABLE
|
||||
#define CRYPTOPP_X86_ASM_AVAILABLE 1
|
||||
|
||||
#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(_MSC_VER) || CRYPTOPP_GCC_VERSION >= 30300 || defined(__SSE2__))
|
||||
#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
|
||||
|
|
|
|||
55
padlkrng.cpp
55
padlkrng.cpp
|
|
@ -7,66 +7,67 @@
|
|||
#include "padlkrng.h"
|
||||
#include "cpu.h"
|
||||
|
||||
// The Padlock Security Engine RNG has a few items to be aware of. You can
|
||||
// find copies of the Programmer's manual, Cryptography Research Inc audit
|
||||
// report, and other goodies at http://www.cryptopp.com/wiki/VIA_Padlock.
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
PadlockRNG::PadlockRNG()
|
||||
PadlockRNG::PadlockRNG(word32 divisor)
|
||||
: m_divisor(DivisorHelper(divisor))
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X86
|
||||
#if CRYPTOPP_X86_ASM_AVAILABLE
|
||||
if (!HasPadlockRNG())
|
||||
throw PadlockRNG_Err("HasPadlockRNG");
|
||||
throw PadlockRNG_Err("PadlockRNG", "PadlockRNG generator not available");
|
||||
#else
|
||||
throw PadlockRNG_Err("HasPadlockRNG");
|
||||
throw PadlockRNG_Err("PadlockRNG", "PadlockRNG generator not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
void PadlockRNG::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size);
|
||||
#if CRYPTOPP_BOOL_X86
|
||||
#if defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__GNUC__)
|
||||
while (size)
|
||||
{
|
||||
# if defined(__GNUC__)
|
||||
|
||||
word32 result;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"movl %1, %%edi ;\n"
|
||||
"movl $1, %%edx ;\n"
|
||||
"movl $2, %%edx ;\n"
|
||||
".byte 0x0f, 0xa7, 0xc0 ;\n"
|
||||
"andl $31, %%eax ;\n"
|
||||
"movl %%eax, %0 ;\n"
|
||||
|
||||
: "=g" (result) : "g" (m_buffer.begin()) : "eax", "edx", "edi", "cc"
|
||||
: "=g" (m_msr) : "g" (m_buffer.data()), "g" (m_divisor)
|
||||
: "eax", "edx", "edi", "cc"
|
||||
);
|
||||
|
||||
const size_t rem = STDMIN(result, STDMIN(size, m_buffer.SizeInBytes()));
|
||||
const size_t ret = m_msr & 0x1f;
|
||||
const size_t rem = STDMIN(ret, STDMIN(size, 16U));
|
||||
std::memcpy(output, m_buffer, rem);
|
||||
size -= rem; output += rem;
|
||||
|
||||
# elif defined(_MSC_VER)
|
||||
|
||||
word32 result;
|
||||
byte* buffer = reinterpret_cast<byte*>(m_buffer.begin());
|
||||
|
||||
}
|
||||
#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(_MSC_VER)
|
||||
while (size)
|
||||
{
|
||||
word32 result, divisor = m_divisor;
|
||||
byte *buffer = reinterpret_cast<byte*>(m_buffer.data());
|
||||
__asm {
|
||||
mov edi, buffer
|
||||
mov edx, 0x01
|
||||
mov edx, divisor
|
||||
_emit 0x0f
|
||||
_emit 0xa7
|
||||
_emit 0xc0
|
||||
and eax, 31
|
||||
mov result, eax
|
||||
}
|
||||
|
||||
const size_t rem = STDMIN(result, STDMIN(size, m_buffer.SizeInBytes()));
|
||||
std::memcpy(output, m_buffer, rem);
|
||||
const size_t ret = (m_msr = result) & 0x1f;
|
||||
const size_t rem = STDMIN(ret, STDMIN(size, 16U));
|
||||
std::memcpy(output, buffer, rem);
|
||||
size -= rem; output += rem;
|
||||
|
||||
# else
|
||||
throw NotImplemented("PadlockRNG::GenerateBlock");
|
||||
# endif
|
||||
}
|
||||
#endif // CRYPTOPP_BOOL_X86
|
||||
#else
|
||||
throw PadlockRNG_Err("GenerateBlock", "PadlockRNG generator not available");
|
||||
#endif // CRYPTOPP_X86_ASM_AVAILABLE
|
||||
}
|
||||
|
||||
void PadlockRNG::DiscardBytes(size_t n)
|
||||
|
|
|
|||
76
padlkrng.h
76
padlkrng.h
|
|
@ -1,8 +1,10 @@
|
|||
// via-rng.h - written and placed in public domain by Jeffrey Walton
|
||||
|
||||
//! \file PadlockRNG.h
|
||||
//! \brief Class for VIA Padlock RNG
|
||||
//! \file padlkrng.h
|
||||
//! \brief Classes for VIA Padlock RNG
|
||||
//! \since Crypto++ 6.0
|
||||
//! \sa <A HREF="http://www.cryptopp.com/wiki/VIA_Padlock">VIA
|
||||
//! Padlock</A> on the Crypto++ wiki
|
||||
|
||||
#ifndef CRYPTOPP_PADLOCK_RNG_H
|
||||
#define CRYPTOPP_PADLOCK_RNG_H
|
||||
|
|
@ -20,9 +22,26 @@ class PadlockRNG_Err : public Exception
|
|||
public:
|
||||
PadlockRNG_Err(const std::string &operation)
|
||||
: Exception(OTHER_ERROR, "PadlockRNG: " + operation + " operation failed") {}
|
||||
PadlockRNG_Err(const std::string &component, const std::string &message)
|
||||
: Exception(OTHER_ERROR, component + ": " + message) {}
|
||||
};
|
||||
|
||||
//! \brief Hardware generated random numbers using PadlockRNG instruction
|
||||
//! \details The PadlockRNG uses an 8 byte FIFO buffer for random numbers. The
|
||||
//! generator can be configured to discard bits from the buffer to resist analysis.
|
||||
//! The <tt>divisor</tt> controls the number of bytes discarded. The formula for
|
||||
//! the discard amount is <tt>2**divisor - 1</tt>. When <tt>divisor=0</tt> no bits
|
||||
//! are discarded and the entire 8 byte buffer is read. If <tt>divisor=3</tt> then
|
||||
//! 7 bytes are discarded and 1 byte is read. TheVIA SDK samples use <tt>divisor=1</tt>.
|
||||
//! \details Cryptography Research, Inc (CRI) audited the Padlock Security Engine
|
||||
//! in 2003. CRI provided recommendations to operate the generator for secure and
|
||||
//! non-secure applications. Additionally, the Programmers Guide and SDK provided a
|
||||
//! different configuration in the sample code.
|
||||
//! \details You can operate the generator according to CRI recommendations by setting
|
||||
//! <tt>divisor</tt>, reading one word (or partial word) at a time, and then inspecting
|
||||
//! the MSR after each read.
|
||||
//! \details The audit report with recommendations is available on the Crypto++ wiki
|
||||
//! at <A HREF="http://www.cryptopp.com/wiki/VIA_Padlock">VIA Padlock</A>.
|
||||
//! \sa MaurerRandomnessTest() for random bit generators
|
||||
//! \since Crypto++ 6.0
|
||||
class PadlockRNG : public RandomNumberGenerator
|
||||
|
|
@ -33,11 +52,21 @@ public:
|
|||
virtual ~PadlockRNG() {}
|
||||
|
||||
//! \brief Construct a PadlockRNG generator
|
||||
//! \details According to DJ of Intel, the Intel PadlockRNG circuit does not underflow.
|
||||
//! If it did hypothetically underflow, then it would return 0 for the random value.
|
||||
//! AMD's PadlockRNG implementation appears to provide the same behavior.
|
||||
//! \throws PadlockRNG_Err if the random number generator is not available
|
||||
PadlockRNG();
|
||||
//! \param divisor the XSTORE divisor
|
||||
//! \details The PadlockRNG uses an 8 byte FIFO buffer for random numbers. The
|
||||
//! generator can be configured to discard bits from the buffer to resist analysis.
|
||||
//! The <tt>divisor</tt> controls the number of bytes discarded. The formula for
|
||||
//! the discard amount is <tt>2**divisor - 1</tt>. When <tt>divisor=0</tt> no bits
|
||||
//! are discarded and the entire 8 byte buffer is read. If <tt>divisor=3</tt> then
|
||||
//! 7 bytes are discarded and 1 byte is read. VIA SDK samples use <tt>divisor=1</tt>.
|
||||
//! \details Cryptography Research, Inc (CRI) audited the Padlock Security Engine
|
||||
//! in 2003. CRI provided recommendations to operate the generator for secure and
|
||||
//! non-secure applications. Additionally, the Programmers SDK provided a different
|
||||
//! configuration in the sample code.
|
||||
//! \details The audit report with recommendations is available on the Crypto++ wiki
|
||||
//! at <A HREF="http://www.cryptopp.com/wiki/VIA_Padlock">VIA Padlock</A>.
|
||||
//! \sa SetDivisor, GetDivisor
|
||||
PadlockRNG(word32 divisor=1);
|
||||
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
|
|
@ -61,8 +90,39 @@ public:
|
|||
CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
|
||||
}
|
||||
|
||||
//! \brief Set the XSTORE divisor
|
||||
//! \param divisor the XSTORE divisor
|
||||
//! \returns the old XSTORE divisor
|
||||
word32 SetDivisor(word32 divisor)
|
||||
{
|
||||
word32 old = m_divisor;
|
||||
m_divisor = DivisorHelper(divisor);
|
||||
return old;
|
||||
}
|
||||
|
||||
//! \brief Get the XSTORE divisor
|
||||
//! \returns the current XSTORE divisor
|
||||
word32 GetDivisor() const
|
||||
{
|
||||
return m_divisor;
|
||||
}
|
||||
|
||||
//! \brief Get the MSR for the last operation
|
||||
//! \returns the MSR for the last read operation
|
||||
word32 GetMSR() const
|
||||
{
|
||||
return m_msr;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline word32 DivisorHelper(word32 divisor)
|
||||
{
|
||||
return divisor > 3 ? 3 : divisor;
|
||||
}
|
||||
|
||||
private:
|
||||
FixedSizeAlignedSecBlock<word32, 1, true> m_buffer;
|
||||
FixedSizeAlignedSecBlock<word32, 4, true> m_buffer;
|
||||
word32 m_divisor, m_msr;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Reference in New Issue