Hello,

I discovered recently a bug in vmac.cpp affecting VMAC-64 and resulting in 
the repeated use of the same nonce even if the user is providing a proper 
unique nonce, which opens the possibility of an attack.

The vulnerability is affecting VMAC-64 when using arbitratry nonce, such as 
a timestamp. Appplications using a counter as nonce are not affected by the 
vulnerability, but do not conform to the specification (see below).

The bug in in the Resynchronize(const byte* nonce) function. This function 
executes the PDF algorithm and produces a pad of 128 bit. 2 equal nonces 
except the LSB bit produce the same pad value, this allows to save an AES 
operation, The code of the function implements the optimization that 
consists in comparing the last nonce with the nonce provided by the user 
(except the LSB bit) and running the PDF algorithm only if they differ, 
otherwise use the same pad.

The bug is at line 114 of vmac.cpp, here is the code with the diff showing 
how to fix the bug:
 
--              if (m_padCached && (storedNonce[s-1] | 1) == 
(nonce[length-1] | 1))
++            if (m_padCached && (m_padCached = (storedNonce[s-1] | 1) == 
(nonce[length-1] | 1)))
                {
                        m_padCached = VerifyBufsEqual(storedNonce+s-length, 
nonce, length-1);
                        for (size_t i=0; m_padCached && i<s-length; i++) 
                                m_padCached = (storedNonce[i] == 0);
                }       
                if (!m_padCached)
                {               
                        memset(storedNonce, 0, s-length);
                        memcpy(storedNonce+s-length, nonce, length-1);
                        storedNonce[s-1] = nonce[length-1] & 0xfe;
                        AccessCipher().ProcessBlock(storedNonce, m_pad());
                        m_padCached = true;
                }       
                storedNonce[s-1] = nonce[length-1];

The issue is that the result of the comparison (storedNonce[s-1] | 1) == 
(nonce[length-1] | 1) is not stored in m_padCached. When the result is 
false, the first block is not executed, but the second block is skipped 
also, and the pad is not generated. The implementation uses the same pad 
again and again until the result of the test is true.

Using a counter as nonce, the implementation does not strictly conform to 
the specifications but the security level is not decreased since a pad is 
still computed every 2 nonces.

The code below computes the digest of the same message using a different 
nonce, but the tag produced will be the same:

VMAC<AES,64> hasher;
hasher.SetKeywithIV(key, keylength, nonce0);
std::string msg("test");
hasher.ComputeDigest(digest0, msg, 4);
hasher.Resynchronize(nonce1); // nonce1 ! = nonce0, has no effect
hasher.ComputeDigest(digest1, msg, 4);
// digest0 == digest1

-- 
-- 
You received this message because you are subscribed to the "Crypto++ Users" 
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at 
http://www.cryptopp.com.
--- 
You received this message because you are subscribed to the Google Groups 
"Crypto++ Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to