Updated documentation. Whitespace

pull/347/head
Jeffrey Walton 2016-11-27 18:54:09 -05:00
parent 484da03c7b
commit 7b36f81dc5
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 124 additions and 119 deletions

View File

@ -52,39 +52,38 @@ template <class T>
void Poly1305_Base<T>::Update(const byte *input, size_t length) void Poly1305_Base<T>::Update(const byte *input, size_t length)
{ {
CRYPTOPP_ASSERT((input && length) || !(input || length)); CRYPTOPP_ASSERT((input && length) || !(input || length));
// if(!input || !length) {return;}
size_t rem, num = m_idx; size_t rem, num = m_idx;
if (num) if (num)
{ {
rem = BLOCKSIZE - num; rem = BLOCKSIZE - num;
if (length >= rem) if (length >= rem)
{ {
// Process // Process
memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem); memcpy_s(m_acc + num, BLOCKSIZE - num, input, rem);
ProcessBlocks(m_acc, BLOCKSIZE, 1); ProcessBlocks(m_acc, BLOCKSIZE, 1);
input += rem; input += rem;
length -= rem; length -= rem;
} }
else else
{ {
// Accumulate // Accumulate
memcpy_s(m_acc + num, BLOCKSIZE - num, input, length); memcpy_s(m_acc + num, BLOCKSIZE - num, input, length);
m_idx = num + length; m_idx = num + length;
return; return;
} }
} }
rem = length % BLOCKSIZE; rem = length % BLOCKSIZE;
length -= rem; length -= rem;
if (length >= BLOCKSIZE) { if (length >= BLOCKSIZE) {
ProcessBlocks(input, length, 1); ProcessBlocks(input, length, 1);
input += length; input += length;
} }
if (rem) if (rem)
memcpy(m_acc, input, rem); memcpy(m_acc, input, rem);
m_idx = rem; m_idx = rem;
} }
@ -92,64 +91,64 @@ void Poly1305_Base<T>::Update(const byte *input, size_t length)
template <class T> template <class T>
void Poly1305_Base<T>::ProcessBlocks(const byte *input, size_t length, word32 padbit) void Poly1305_Base<T>::ProcessBlocks(const byte *input, size_t length, word32 padbit)
{ {
word32 r0 = m_r[0], r1 = m_r[1], r2 = m_r[2], r3 = m_r[3]; word32 r0 = m_r[0], r1 = m_r[1], r2 = m_r[2], r3 = m_r[3];
word32 h0 = m_h[0], h1 = m_h[1], h2 = m_h[2], h3 = m_h[3], h4 = m_h[4]; word32 h0 = m_h[0], h1 = m_h[1], h2 = m_h[2], h3 = m_h[3], h4 = m_h[4];
word32 c, s1 = r1 + (r1 >> 2), s2 = r2 + (r2 >> 2), s3 = r3 + (r3 >> 2); word32 c, s1 = r1 + (r1 >> 2), s2 = r2 + (r2 >> 2), s3 = r3 + (r3 >> 2);
word64 d0, d1, d2, d3; word64 d0, d1, d2, d3;
while (length >= BLOCKSIZE) while (length >= BLOCKSIZE)
{ {
// h += m[i] // h += m[i]
h0 = (word32)(d0 = (word64)h0 + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 0)); h0 = (word32)(d0 = (word64)h0 + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 0));
h1 = (word32)(d1 = (word64)h1 + (d0 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 4)); h1 = (word32)(d1 = (word64)h1 + (d0 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 4));
h2 = (word32)(d2 = (word64)h2 + (d1 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 8)); h2 = (word32)(d2 = (word64)h2 + (d1 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 8));
h3 = (word32)(d3 = (word64)h3 + (d2 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 12)); h3 = (word32)(d3 = (word64)h3 + (d2 >> 32) + GetWord<word32>(false, LITTLE_ENDIAN_ORDER, input + 12));
h4 += (word32)(d3 >> 32) + padbit; h4 += (word32)(d3 >> 32) + padbit;
// h *= r "%" p // h *= r "%" p
d0 = ((word64)h0 * r0) + d0 = ((word64)h0 * r0) +
((word64)h1 * s3) + ((word64)h1 * s3) +
((word64)h2 * s2) + ((word64)h2 * s2) +
((word64)h3 * s1); ((word64)h3 * s1);
d1 = ((word64)h0 * r1) + d1 = ((word64)h0 * r1) +
((word64)h1 * r0) + ((word64)h1 * r0) +
((word64)h2 * s3) + ((word64)h2 * s3) +
((word64)h3 * s2) + ((word64)h3 * s2) +
(h4 * s1); (h4 * s1);
d2 = ((word64)h0 * r2) + d2 = ((word64)h0 * r2) +
((word64)h1 * r1) + ((word64)h1 * r1) +
((word64)h2 * r0) + ((word64)h2 * r0) +
((word64)h3 * s3) + ((word64)h3 * s3) +
(h4 * s2); (h4 * s2);
d3 = ((word64)h0 * r3) + d3 = ((word64)h0 * r3) +
((word64)h1 * r2) + ((word64)h1 * r2) +
((word64)h2 * r1) + ((word64)h2 * r1) +
((word64)h3 * r0) + ((word64)h3 * r0) +
(h4 * s3); (h4 * s3);
h4 = (h4 * r0); h4 = (h4 * r0);
// a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0 // a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0
h0 = (word32)d0; h0 = (word32)d0;
h1 = (word32)(d1 += d0 >> 32); h1 = (word32)(d1 += d0 >> 32);
h2 = (word32)(d2 += d1 >> 32); h2 = (word32)(d2 += d1 >> 32);
h3 = (word32)(d3 += d2 >> 32); h3 = (word32)(d3 += d2 >> 32);
h4 += (word32)(d3 >> 32); h4 += (word32)(d3 >> 32);
// b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130 // b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130
c = (h4 >> 2) + (h4 & ~3U); c = (h4 >> 2) + (h4 & ~3U);
h4 &= 3; h4 &= 3;
h0 += c; h0 += c;
h1 += (c = CONSTANT_TIME_CARRY(h0,c)); h1 += (c = CONSTANT_TIME_CARRY(h0,c));
h2 += (c = CONSTANT_TIME_CARRY(h1,c)); h2 += (c = CONSTANT_TIME_CARRY(h1,c));
h3 += (c = CONSTANT_TIME_CARRY(h2,c)); h3 += (c = CONSTANT_TIME_CARRY(h2,c));
h4 += CONSTANT_TIME_CARRY(h3,c); h4 += CONSTANT_TIME_CARRY(h3,c);
input += BLOCKSIZE; input += BLOCKSIZE;
length -= BLOCKSIZE; length -= BLOCKSIZE;
} }
m_h[0] = h0; m_h[1] = h1; m_h[2] = h2; m_h[0] = h0; m_h[1] = h1; m_h[2] = h2;
m_h[3] = h3; m_h[4] = h4; m_h[3] = h3; m_h[4] = h4;
} }
template <class T> template <class T>
@ -160,13 +159,13 @@ void Poly1305_Base<T>::TruncatedFinal(byte *mac, size_t size)
ThrowIfInvalidTruncatedSize(size); ThrowIfInvalidTruncatedSize(size);
size_t num = m_idx; size_t num = m_idx;
if (num) if (num)
{ {
m_acc[num++] = 1; /* pad bit */ m_acc[num++] = 1; /* pad bit */
while (num < BLOCKSIZE) while (num < BLOCKSIZE)
m_acc[num++] = 0; m_acc[num++] = 0;
ProcessBlocks(m_acc, BLOCKSIZE, 0); ProcessBlocks(m_acc, BLOCKSIZE, 0);
} }
ProcessFinal(mac, size); ProcessFinal(mac, size);
@ -179,43 +178,43 @@ template <class T>
void Poly1305_Base<T>::ProcessFinal(byte *mac, size_t size) void Poly1305_Base<T>::ProcessFinal(byte *mac, size_t size)
{ {
word32 h0 = m_h[0], h1 = m_h[1], h2 = m_h[2], h3 = m_h[3], h4 = m_h[4]; word32 h0 = m_h[0], h1 = m_h[1], h2 = m_h[2], h3 = m_h[3], h4 = m_h[4];
word32 g0, g1, g2, g3, g4, mask; word32 g0, g1, g2, g3, g4, mask;
word64 t; word64 t;
// compare to modulus by computing h + -p // compare to modulus by computing h + -p
g0 = (word32)(t = (word64)h0 + 5); g0 = (word32)(t = (word64)h0 + 5);
g1 = (word32)(t = (word64)h1 + (t >> 32)); g1 = (word32)(t = (word64)h1 + (t >> 32));
g2 = (word32)(t = (word64)h2 + (t >> 32)); g2 = (word32)(t = (word64)h2 + (t >> 32));
g3 = (word32)(t = (word64)h3 + (t >> 32)); g3 = (word32)(t = (word64)h3 + (t >> 32));
g4 = h4 + (word32)(t >> 32); g4 = h4 + (word32)(t >> 32);
// if there was carry into 131st bit, h3:h0 = g3:g0 // if there was carry into 131st bit, h3:h0 = g3:g0
mask = 0 - (g4 >> 2); mask = 0 - (g4 >> 2);
g0 &= mask; g1 &= mask; g0 &= mask; g1 &= mask;
g2 &= mask; g3 &= mask; g2 &= mask; g3 &= mask;
mask = ~mask; mask = ~mask;
h0 = (h0 & mask) | g0; h1 = (h1 & mask) | g1; h0 = (h0 & mask) | g0; h1 = (h1 & mask) | g1;
h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3; h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3;
// mac = (h + nonce) % (2^128) // mac = (h + nonce) % (2^128)
h0 = (word32)(t = (word64)h0 + m_n[0]); h0 = (word32)(t = (word64)h0 + m_n[0]);
h1 = (word32)(t = (word64)h1 + (t >> 32) + m_n[1]); h1 = (word32)(t = (word64)h1 + (t >> 32) + m_n[1]);
h2 = (word32)(t = (word64)h2 + (t >> 32) + m_n[2]); h2 = (word32)(t = (word64)h2 + (t >> 32) + m_n[2]);
h3 = (word32)(t = (word64)h3 + (t >> 32) + m_n[3]); h3 = (word32)(t = (word64)h3 + (t >> 32) + m_n[3]);
if (size >= BLOCKSIZE) if (size >= BLOCKSIZE)
{ {
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 0, h0); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 4, h1); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 4, h1);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 8, h2); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 8, h2);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 12, h3); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, mac + 12, h3);
} }
else else
{ {
FixedSizeAlignedSecBlock<byte, BLOCKSIZE> t; FixedSizeAlignedSecBlock<byte, BLOCKSIZE> t;
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 0, h0); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 0, h0);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 4, h1); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 4, h1);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 8, h2); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 8, h2);
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 12, h3); PutWord<word32>(false, LITTLE_ENDIAN_ORDER, t + 12, h3);
memcpy(mac, t, size); memcpy(mac, t, size);
} }

View File

@ -7,9 +7,9 @@
//! \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide //! \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
//! variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length //! variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
//! message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce. //! message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
//! \details Each message must use a uniqus security context, which means either the key or nonce //! \details Each message must use a unique security context, which means either the key or nonce
//! must be changed between message authenticators. It can be accomplished in one of two ways. //! must be changed after each message. It can be accomplished in one of two ways. First, you
//! First, you can create a Poly1305 object with a key and nonce each time its needed as shown below. //! can create a new Poly1305 object with a key and nonce each time its needed.
//! <pre> SecByteBlock key(32), nonce(16); //! <pre> SecByteBlock key(32), nonce(16);
//! prng.GenerateBlock(key, key.size()); //! prng.GenerateBlock(key, key.size());
//! prng.GenerateBlock(nonce, nonce.size()); //! prng.GenerateBlock(nonce, nonce.size());
@ -18,9 +18,9 @@
//! poly1305.Update(...); //! poly1305.Update(...);
//! poly1305.Final(...);</pre> //! poly1305.Final(...);</pre>
//! //!
//! \details Second, you can create a Poly1305, reuse the key, and set a fresh nonce as needed //! \details Second, you can create a Poly1305, reuse the key, and set a fresh nonce for
//! as shown below. The second (and subsequent) nonce can be generated directly using a //! each message. The second and subsequent nonces can be generated directly using a
//! RandomNumberGenerator() drived class; or it can b generated using GetNextIV(). //! RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
//! <pre> SecByteBlock key(32), nonce(16); //! <pre> SecByteBlock key(32), nonce(16);
//! prng.GenerateBlock(key, key.size()); //! prng.GenerateBlock(key, key.size());
//! prng.GenerateBlock(nonce, nonce.size()); //! prng.GenerateBlock(nonce, nonce.size());
@ -31,7 +31,7 @@
//! poly1305.Update(...); //! poly1305.Update(...);
//! poly1305.Final(...); //! poly1305.Final(...);
//! //!
//! // Second message //! // Third message
//! poly1305.GetNextIV(prng, nonce); //! poly1305.GetNextIV(prng, nonce);
//! poly1305.Resynchronize(nonce, nonce.size()); //! poly1305.Resynchronize(nonce, nonce.size());
//! poly1305.Update(...); //! poly1305.Update(...);
@ -101,14 +101,12 @@ protected:
}; };
//! \class Poly1305 //! \class Poly1305
//! \brief Poly1305 message authentication code
//! \tparam T class derived from BlockCipherDocumentation
//! \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide //! \details Poly1305-AES is a state-of-the-art message-authentication code suitable for a wide
//! variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length //! variety of applications. Poly1305-AES computes a 16-byte authenticator of a variable-length
//! message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce. //! message, using a 16-byte AES key, a 16-byte additional key, and a 16-byte nonce.
//! \details Each message must use a uniqus security context, which means either the key or nonce //! \details Each message must use a unique security context, which means either the key or nonce
//! must be changed between message authenticators. It can be accomplished in one of two ways. //! must be changed after each message. It can be accomplished in one of two ways. First, you
//! First, you can create a Poly1305 object with a key and nonce each time its needed as shown below. //! can create a new Poly1305 object with a key and nonce each time its needed.
//! <pre> SecByteBlock key(32), nonce(16); //! <pre> SecByteBlock key(32), nonce(16);
//! prng.GenerateBlock(key, key.size()); //! prng.GenerateBlock(key, key.size());
//! prng.GenerateBlock(nonce, nonce.size()); //! prng.GenerateBlock(nonce, nonce.size());
@ -117,9 +115,9 @@ protected:
//! poly1305.Update(...); //! poly1305.Update(...);
//! poly1305.Final(...);</pre> //! poly1305.Final(...);</pre>
//! //!
//! \details Second, you can create a Poly1305, reuse the key, and set a fresh nonce as needed //! \details Second, you can create a Poly1305, reuse the key, and set a fresh nonce for
//! as shown below. The second (and subsequent) nonce can be generated directly using a //! each message. The second and subsequent nonces can be generated directly using a
//! RandomNumberGenerator() drived class; or it can b generated using GetNextIV(). //! RandomNumberGenerator() derived class; or it can be generated using GetNextIV().
//! <pre> SecByteBlock key(32), nonce(16); //! <pre> SecByteBlock key(32), nonce(16);
//! prng.GenerateBlock(key, key.size()); //! prng.GenerateBlock(key, key.size());
//! prng.GenerateBlock(nonce, nonce.size()); //! prng.GenerateBlock(nonce, nonce.size());
@ -134,6 +132,12 @@ protected:
//! poly1305.GetNextIV(prng, nonce); //! poly1305.GetNextIV(prng, nonce);
//! poly1305.Resynchronize(nonce, nonce.size()); //! poly1305.Resynchronize(nonce, nonce.size());
//! poly1305.Update(...); //! poly1305.Update(...);
//! poly1305.Final(...);
//!
//! // Third message
//! poly1305.GetNextIV(prng, nonce);
//! poly1305.Resynchronize(nonce, nonce.size());
//! poly1305.Update(...);
//! poly1305.Final(...);</pre> //! poly1305.Final(...);</pre>
//! \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES //! \sa Daniel J. Bernstein <A HREF="http://cr.yp.to/mac/poly1305-20050329.pdf">The Poly1305-AES
//! Message-Authentication Code (20050329)</A> and Andy Polyakov <A //! Message-Authentication Code (20050329)</A> and Andy Polyakov <A
@ -153,6 +157,8 @@ public:
//! \param keyLength the size of the byte array, in bytes //! \param keyLength the size of the byte array, in bytes
//! \param nonce a byte array used to key the cipher //! \param nonce a byte array used to key the cipher
//! \param nonceLength the size of the byte array, in bytes //! \param nonceLength the size of the byte array, in bytes
//! \details key is the 32-byte key composed of the 16-byte AES key and the 16 additional key
//! bytes used for <tt>r</tt>.
//! \details Each message requires a unique security context. //! \details Each message requires a unique security context.
Poly1305(const byte *key, size_t keyLength=DEFAULT_KEYLENGTH, const byte *nonce=NULL, size_t nonceLength=0) Poly1305(const byte *key, size_t keyLength=DEFAULT_KEYLENGTH, const byte *nonce=NULL, size_t nonceLength=0)
{this->SetKey(key, keyLength, MakeParameters(Name::IV(), ConstByteArrayParameter(nonce, nonceLength)));} {this->SetKey(key, keyLength, MakeParameters(Name::IV(), ConstByteArrayParameter(nonce, nonceLength)));}