12 #if defined(CRYPTOPP_DISABLE_VMAC_ASM) 13 # undef CRYPTOPP_X86_ASM_AVAILABLE 14 # undef CRYPTOPP_X32_ASM_AVAILABLE 15 # undef CRYPTOPP_X64_ASM_AVAILABLE 16 # undef CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 19 #if CRYPTOPP_MSC_VERSION 20 # pragma warning(disable: 4731) 25 #if defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64 29 #if defined(CRYPTOPP_WORD128_AVAILABLE) && !defined(CRYPTOPP_X64_ASM_AVAILABLE) 30 # define VMAC_BOOL_WORD128 1 32 # define VMAC_BOOL_WORD128 0 36 #define const // Turbo C++ 2006 workaround 49 #define m126 ((word128(m62)<<64)|m64) 51 static const word128 m126 = (word128(m62)<<64)|m64;
58 if (digestLength != 8 && digestLength != 16)
64 throw InvalidArgument(
"VMAC: L1KeyLength must be a positive multiple of 128");
69 cipher.
SetKey(userKey, keylength, params);
70 const unsigned int blockSize = cipher.
BlockSize();
71 const unsigned int blockSizeInWords = blockSize /
sizeof(
word64);
85 for (i = 0; i <= (size_t)
m_is128; i++)
99 for (i = 0; i <= (size_t)
m_is128; i++)
106 }
while ((l3Key[i*2+0] >= p64) || (l3Key[i*2+1] >= p64));
124 byte *storedNonce = m_nonce();
128 memset(storedNonce, 0, s-length);
129 memcpy(storedNonce+s-length, nonce, length);
134 if (
m_padCached && (storedNonce[s-1] | 1) == (nonce[length-1] | 1))
142 memset(storedNonce, 0, s-length);
143 memcpy(storedNonce+s-length, nonce, length-1);
144 storedNonce[s-1] = nonce[length-1] & 0xfe;
148 storedNonce[s-1] = nonce[length-1];
158 throw NotImplemented(
"VMAC: HashEndianCorrectedBlock is not implemented");
164 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) 170 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32) 171 #if CRYPTOPP_MSC_VERSION 172 # pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code 183 const word64 *nhK = m_nhKey();
199 #
if defined(__INTEL_COMPILER)
201 AS2( mov ebx, [L1KeyLength])
202 AS2( mov dl, [isFirstBlock])
208 AS2( mov eax, tagPart)
216 AS2( mov ecx, blocksRemainingInWord64)
220 #if CRYPTOPP_BOOL_X32 232 AS2( lea ebp, [edi+8*ebp])
233 AS2( movq mm6, [esi])
234 AS2( paddq mm6, [edi])
235 AS2( movq mm5, [esi+8])
236 AS2( paddq mm5, [edi+8])
240 ASS( pshufw mm2, mm6, 1, 0, 3, 2)
241 AS2( pmuludq mm6, mm5)
242 ASS( pshufw mm3, mm5, 1, 0, 3, 2)
243 AS2( pmuludq mm5, mm2)
244 AS2( pmuludq mm2, mm3)
245 AS2( pmuludq mm3, mm4)
247 AS2( movd [esp], mm6)
249 #if CRYPTOPP_BOOL_X32 250 AS2( movd [esp+8], mm5)
252 AS2( movd [esp+4], mm5)
258 AS2( movq mm0, [esi])
259 AS2( paddq mm0, [edi])
260 AS2( movq mm1, [esi+8])
261 AS2( paddq mm1, [edi+8])
266 ASS( pshufw mm2, mm0, 1, 0, 3, 2)
267 AS2( pmuludq mm0, mm1)
268 #if CRYPTOPP_BOOL_X32 269 AS2( movd [esp+16], mm3)
271 AS2( movd [esp+8], mm3)
275 ASS( pshufw mm3, mm1, 1, 0, 3, 2)
276 AS2( pmuludq mm1, mm2)
277 AS2( pmuludq mm2, mm3)
278 AS2( pmuludq mm3, mm4)
279 AS2( movd mm4, [esp])
281 #if CRYPTOPP_BOOL_X32 282 AS2( movd mm4, [esp+8])
284 AS2( movd mm4, [esp+16])
286 AS2( movd mm4, [esp+4])
288 AS2( movd mm4, [esp+8])
291 AS2( movd [esp], mm0)
294 #if CRYPTOPP_BOOL_X32 295 AS2( movd [esp+8], mm1)
297 AS2( movd [esp+4], mm1)
305 #if CRYPTOPP_BOOL_X32 306 AS2( movd [esp+16], mm3)
308 AS2( movd [esp+8], mm3)
312 AS2( movd mm4, [esp])
314 #if CRYPTOPP_BOOL_X32 315 AS2( movd mm4, [esp+8])
317 AS2( movd mm4, [esp+16])
319 AS2( movd mm4, [esp+4])
321 AS2( movd mm4, [esp+8])
324 AS2( lea ebp, [8*ebx])
327 AS2( movd [esp], mm7)
330 #if CRYPTOPP_BOOL_X32 331 AS2( movd [esp+8], mm6)
333 AS2( movd [esp+4], mm6)
344 #define k0 [eax+2*8+2*4] 345 #define k1 [eax+2*8+3*4] 346 #define k2 [eax+2*8+0*4] 347 #define k3 [eax+2*8+1*4] 351 AS2( movd mm0, [esp])
356 #if CRYPTOPP_BOOL_X32 357 AS2( movd mm2, [esp+8])
359 AS2( movd mm2, [esp+4])
373 AS2( pmuludq mm0,
k3)
375 AS2( pmuludq mm1,
k2)
378 AS2( pmuludq mm2, mm6)
384 AS2( pmuludq mm3, mm7)
385 AS2( pmuludq mm4, mm7)
386 AS2( pmuludq mm5, mm6)
391 AS2( pmuludq mm1,
k2)
396 AS2( pmuludq mm2,
k3)
397 AS2( pmuludq mm3, mm7)
398 #if CRYPTOPP_BOOL_X32 399 AS2( movd [esp+16], mm0)
401 AS2( movd [esp+8], mm0)
404 AS2( pmuludq mm7, mm5)
405 AS2( pmuludq mm5,
k3)
408 AS2( pmuludq mm1,
k2)
413 AS2( pmuludq mm2, mm6)
414 AS2( pmuludq mm6, a0)
417 AS2( movd mm3, [esp])
420 AS2( pmuludq mm3,
k3)
423 AS2( pmuludq mm1,
k2)
425 #if CRYPTOPP_BOOL_X32 426 AS2( movd mm2, [esp+8])
428 AS2( movd mm2, [esp+4])
436 #if CRYPTOPP_BOOL_X32 437 AS2( movd mm7, [esp+16])
439 AS2( movd mm7, [esp+8])
464 #if CRYPTOPP_BOOL_X32 475 :
"m" (L1KeyLength),
"c" (blocksRemainingInWord64),
"S" (data),
"D" (nhK+tagPart*2),
"d" (
m_isFirstBlock),
"a" (polyS+tagPart*4)
482 #if VMAC_BOOL_WORD128 483 #define DeclareNH(a) word128 a=0 484 #define MUL64(rh,rl,i1,i2) {word128 p = word128(i1)*(i2); rh = word64(p>>64); rl = word64(p);} 485 #define AccumulateNH(a, b, c) a += word128(b)*(c) 486 #define Multiply128(r, i1, i2) r = word128(word64(i1)) * word64(i2) 488 #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(_M_ARM) 489 #define MUL32(a, b) __emulu(word32(a), word32(b)) 491 #define MUL32(a, b) ((word64)((word32)(a)) * (word32)(b)) 493 #if defined(CRYPTOPP_X64_ASM_AVAILABLE) 494 #define DeclareNH(a) word64 a##0=0, a##1=0 495 #define MUL64(rh,rl,i1,i2) asm ("mulq %3" : "=a"(rl), "=d"(rh) : "a"(i1), "g"(i2) : "cc"); 496 #define AccumulateNH(a, b, c) asm ("mulq %3; addq %%rax, %0; adcq %%rdx, %1" : "+r"(a##0), "+r"(a##1) : "a"(b), "g"(c) : "%rdx", "cc"); 497 #define ADD128(rh,rl,ih,il) asm ("addq %3, %1; adcq %2, %0" : "+r"(rh),"+r"(rl) : "r"(ih),"r"(il) : "cc"); 498 #elif defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64 499 #define DeclareNH(a) word64 a##0=0, a##1=0 500 #define MUL64(rh,rl,i1,i2) (rl) = _umul128(i1,i2,&(rh)); 501 #define AccumulateNH(a, b, c) {\ 503 pl = _umul128(b,c,&ph);\ 505 a##1 += ph + (a##0 < pl);} 507 #define VMAC_BOOL_32BIT 1 508 #define DeclareNH(a) word64 a##0=0, a##1=0, a##2=0 509 #define MUL64(rh,rl,i1,i2) \ 510 { word64 _i1 = (i1), _i2 = (i2); \ 511 word64 m1= MUL32(_i1,_i2>>32); \ 512 word64 m2= MUL32(_i1>>32,_i2); \ 513 rh = MUL32(_i1>>32,_i2>>32); \ 514 rl = MUL32(_i1,_i2); \ 515 ADD128(rh,rl,(m1 >> 32),(m1 << 32)); \ 516 ADD128(rh,rl,(m2 >> 32),(m2 << 32)); \ 518 #define AccumulateNH(a, b, c) {\ 519 word64 p = MUL32(b, c);\ 520 a##1 += word32((p)>>32);\ 522 p = MUL32((b)>>32, c);\ 523 a##2 += word32((p)>>32);\ 525 p = MUL32((b)>>32, (c)>>32);\ 527 p = MUL32(b, (c)>>32);\ 529 a##2 += word32(p>>32);} 532 #ifndef VMAC_BOOL_32BIT 533 #define VMAC_BOOL_32BIT 0 536 #define ADD128(rh,rl,ih,il) \ 537 { word64 _il = (il); \ 539 (rh) += (ih) + ((rl) < (_il)); \ 543 template <
bool T_128BitTag>
549 #define INNER_LOOP_ITERATION(j) {\ 550 word64 d0 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+0]);\ 551 word64 d1 = ConditionalByteReverse(LITTLE_ENDIAN_ORDER, data[i+2*j+1]);\ 552 AccumulateNH(nhA, d0+nhK[i+2*j+0], d1+nhK[i+2*j+1]);\ 554 AccumulateNH(nhB, d0+nhK[i+2*j+2], d1+nhK[i+2*j+3]);\ 558 size_t innerLoopEnd = L1KeyLengthInWord64;
559 const word64 *nhK = m_nhKey();
561 bool isFirstBlock =
true;
565 #if VMAC_BOOL_WORD128 568 word64 ah1=0, al1=0, ah2=0, al2=0;
570 word64 kh1, kl1, kh2, kl2;
571 kh1=(polyS+0*4+2)[0]; kl1=(polyS+0*4+2)[1];
574 kh2=(polyS+1*4+2)[0]; kl2=(polyS+1*4+2)[1];
584 if (blocksRemainingInWord64 < L1KeyLengthInWord64)
586 if (blocksRemainingInWord64 % 8)
588 innerLoopEnd = blocksRemainingInWord64 % 8;
589 for (; i<innerLoopEnd; i+=2)
592 innerLoopEnd = blocksRemainingInWord64;
594 for (; i<innerLoopEnd; i+=8)
601 blocksRemainingInWord64 -= innerLoopEnd;
602 data += innerLoopEnd;
609 nhA1 += (nhA0 >> 32);
611 nh2[0] = (nhA2 + (nhA1 >> 32)) & m62;
616 nhB1 += (nhB0 >> 32);
618 nh2[1] = (nhB2 + (nhB1 >> 32)) & m62;
621 #define a0 (((word32 *)(polyS+i*4))[2+NativeByteOrder::ToEnum()]) 622 #define a1 (*(((word32 *)(polyS+i*4))+3-NativeByteOrder::ToEnum())) // workaround for GCC 3.2 623 #define a2 (((word32 *)(polyS+i*4))[0+NativeByteOrder::ToEnum()]) 624 #define a3 (*(((word32 *)(polyS+i*4))+1-NativeByteOrder::ToEnum())) 625 #define aHi ((polyS+i*4)[0]) 626 #define k0 (((word32 *)(polyS+i*4+2))[2+NativeByteOrder::ToEnum()]) 627 #define k1 (*(((word32 *)(polyS+i*4+2))+3-NativeByteOrder::ToEnum())) 628 #define k2 (((word32 *)(polyS+i*4+2))[0+NativeByteOrder::ToEnum()]) 629 #define k3 (*(((word32 *)(polyS+i*4+2))+1-NativeByteOrder::ToEnum())) 630 #define kHi ((polyS+i*4+2)[0]) 634 isFirstBlock =
false;
638 for (i=0; i<=(size_t)T_128BitTag; i++)
642 t = (t >> 32) + nh1[i] +
k1;
644 aHi = (t >> 32) + nh2[i] +
kHi;
649 for (i=0; i<=(size_t)T_128BitTag; i++)
694 #else // #if VMAC_BOOL_32BIT 697 isFirstBlock =
false;
701 #if VMAC_BOOL_WORD128 702 #define first_poly_step(a, kh, kl, m) a = (m & m126) + ((word128(kh) << 64) | kl) 704 first_poly_step(a1, kh1, kl1, nhA);
706 first_poly_step(
a2, kh2, kl2, nhB);
708 #define first_poly_step(ah, al, kh, kl, mh, ml) {\ 710 ADD128(mh, ml, kh, kl); \ 713 first_poly_step(ah1, al1, kh1, kl1, nhA1, nhA0);
715 first_poly_step(ah2, al2, kh2, kl2, nhB1, nhB0);
721 #if VMAC_BOOL_WORD128 722 a1 = (word128((polyS+0*4)[0]) << 64) | (polyS+0*4)[1];
724 ah1=(polyS+0*4)[0]; al1=(polyS+0*4)[1];
728 #if VMAC_BOOL_WORD128 729 a2 = (word128((polyS+1*4)[0]) << 64) | (polyS+1*4)[1];
731 ah2=(polyS+1*4)[0]; al2=(polyS+1*4)[1];
737 #if VMAC_BOOL_WORD128 738 #define poly_step(a, kh, kl, m) \ 739 { word128 t1, t2, t3, t4;\ 740 Multiply128(t2, a>>64, kl);\ 741 Multiply128(t3, a, kh);\ 742 Multiply128(t1, a, kl);\ 743 Multiply128(t4, a>>64, 2*kh);\ 747 a = (word128(word64(t2)&m63) << 64) | word64(t4);\ 752 poly_step(a1, kh1, kl1, nhA);
754 poly_step(
a2, kh2, kl2, nhB);
756 #define poly_step(ah, al, kh, kl, mh, ml) \ 757 { word64 t1h, t1l, t2h, t2l, t3h, t3l, z=0; \ 759 MUL64(t2h,t2l,ah,kl); \ 760 MUL64(t3h,t3l,al,kh); \ 761 MUL64(t1h,t1l,ah,2*kh); \ 762 MUL64(ah,al,al,kl); \ 764 ADD128(t2h,t2l,t3h,t3l); \ 766 ADD128(ah,al,t1h,t1l); \ 769 ADD128(t2h,ah,z,t2l); \ 771 t2h += t2h + (ah >> 63); \ 775 ADD128(ah,al,mh,ml); \ 776 ADD128(ah,al,z,t2h); \ 779 poly_step(ah1, al1, kh1, kl1, nhA1, nhA0);
781 poly_step(ah2, al2, kh2, kl2, nhB1, nhB0);
783 #endif // #if VMAC_BOOL_32BIT 784 }
while (blocksRemainingInWord64);
786 #if VMAC_BOOL_WORD128 787 (polyS+0*4)[0]=
word64(a1>>64); (polyS+0*4)[1]=
word64(a1);
792 #elif !VMAC_BOOL_32BIT 793 (polyS+0*4)[0]=ah1; (polyS+0*4)[1]=al1;
796 (polyS+1*4)[0]=ah2; (polyS+1*4)[1]=al2;
803 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32) 815 VHASH_Update_Template<true>(
data, blocksRemainingInWord64);
817 VHASH_Update_Template<false>(
data, blocksRemainingInWord64);
831 word64 p1 = input[0], p2 = input[1];
839 t = (p1 > m63) + ((p1 == m63) & (p2 == m64));
846 t += (
word32)t > 0xfffffffeU;
852 p1 += (0 - (p1 <
k1)) & 257;
854 p2 += (0 - (p2 <
k2)) & 257;
857 MUL64(rh, rl, p1, p2);
864 rl += (0 - (rl < t)) & 257;
865 rl += (0 - (rl > p64-1)) & 257;
877 memset(m_data()+len, 0, (0-len)%16);
884 m_polyState()[0] = m_polyState()[2];
885 m_polyState()[1] = m_polyState()[3];
888 m_polyState()[4] = m_polyState()[6];
889 m_polyState()[5] = m_polyState()[7];
896 t[0] = L3Hash(m_polyState(), m_l3Key(), len) + GetWord<word64>(
true,
BIG_ENDIAN_ORDER, m_pad());
897 t[1] = L3Hash(m_polyState()+4, m_l3Key()+2, len) + GetWord<word64>(
true,
BIG_ENDIAN_ORDER, m_pad()+8);
900 PutWord(
false, BIG_ENDIAN_ORDER, mac, t[0]);
901 PutWord(
false, BIG_ENDIAN_ORDER, mac+8, t[1]);
912 word64 t = L3Hash(m_polyState(), m_l3Key(), len);
915 PutWord(
false, BIG_ENDIAN_ORDER, mac, t);
Standard names for retrieving values by name when working with NameValuePairs.
An invalid argument was detected.
virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms=g_nullNameValuePairs)
Sets or reset the key of this object.
const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size)
Retrieves and validates the IV.
T2 ModPowerOf2(const T1 &a, const T2 &b)
Reduces a value to a power of 2.
void CleanNew(size_type newSize)
Change size without preserving contents.
void VHASH_Update(const word64 *data, size_t blocksRemainingInWord128)
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
#define NAMESPACE_BEGIN(x)
void HashEndianCorrectedBlock(const word64 *data)
Library configuration file.
Interface for random number generators.
const BlockCipher & GetCipher() const
#define MUL64(rh, rl, i1, i2)
Interface for one direction (encryption or decryption) of a block cipher.
virtual BlockCipher & AccessCipher()=0
size_t ThrowIfInvalidIVLength(int length)
Validates the IV length.
unsigned int m_L1KeyLength
Classes and functions for secure memory allocations.
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Classes for the VMAC message authentication code.
A method was called which was not implemented.
CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
word64 GetBitCountLo() const
FascTransaction __attribute__
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
uint32_t shr(uint32_t x, std::size_t n)
void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms)
Sets the key for this object without performing parameter validation.
unsigned long long word64
#define CRYPTOPP_ASSERT(exp)
size_t HashMultipleBlocks(const word64 *input, size_t length)
Functions for CPU features and intrinsics.
void TruncatedFinal(byte *mac, size_t size)
Computes the hash of the current message.
void Restart()
Restart the hash.
#define INNER_LOOP_ITERATION(j)
unsigned int IVSize() const
Returns length of the IV accepted by this object.
uint8_t const size_t const size
void * memcpy(void *a, const void *b, size_t c)
#define CRYPTOPP_UNUSED(x)
unsigned int OptimalDataAlignment() const
Provides input and output data alignment for optimal performance.
#define ADD128(rh, rl, ih, il)
void VHASH_Update_SSE2(const word64 *data, size_t blocksRemainingInWord64, int tagPart)
virtual int DefaultDigestSize() const =0
void VHASH_Update_Template(const word64 *data, size_t blockRemainingInWord128)
void Resynchronize(const byte *nonce, int length=-1)
Resynchronize with an IV.
virtual void GetNextIV(RandomNumberGenerator &rng, byte *iv)
Retrieves a secure IV for the next message.
void GetNextIV(RandomNumberGenerator &rng, byte *IV)
Retrieves a secure IV for the next message.
bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Interface for retrieving values given their names.
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.