00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "TigerTree.h"
00025
00026 #ifdef _DEBUG
00027 #undef THIS_FILE
00028 static char THIS_FILE[]=__FILE__;
00029 #define new DEBUG_NEW
00030 #endif
00031
00032 #define BLOCK_SIZE 1024
00033 #define STACK_SIZE 64
00034 #define TIGER_SIZE 24
00035
00036 #define NEW_TIGER_ALG // New "more secure" padded node combination
00037
00038
00040
00041 extern "C" void TigerTree_Tiger_p5(WORD64* str, WORD64* state);
00042 extern "C" void TigerTree_Tiger_MMX(WORD64* str, WORD64* state);
00043 extern "C" void TigerTree_Tiger_SSE2(WORD64* str, WORD64* state);
00044 void (*pTiger)(WORD64*, WORD64*);
00045
00046 inline int GetCPUIDFlags()
00047 {
00048 _asm
00049 {
00050 mov eax, 1
00051 cpuid
00052 mov eax, edx
00053 }
00054 }
00055
00056 CTigerTree::CTigerTree()
00057 {
00058 m_nHeight = 0;
00059 m_pNode = NULL;
00060 m_nNodeCount = 0;
00061
00062 m_pStackBase = NULL;
00063 m_pStackTop = NULL;
00064
00065 pTiger = &TigerTree_Tiger_p5;
00066
00067 if (GetCPUIDFlags() & 0x04000000) pTiger = &TigerTree_Tiger_SSE2;
00068 }
00069
00070 CTigerTree::~CTigerTree()
00071 {
00072 Clear();
00073
00074 if ( m_pStackBase != NULL ) delete [] m_pStackBase;
00075 }
00076
00078
00079
00080 void CTigerTree::SetupAndAllocate(DWORD nHeight, QWORD nLength)
00081 {
00082 Clear();
00083
00084 QWORD nCount = (DWORD)( nLength / BLOCK_SIZE );
00085 if ( nLength % BLOCK_SIZE ) nCount++;
00086
00087 DWORD nActualHeight = 1;
00088
00089 for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
00090
00091 m_nHeight = min( nActualHeight, nHeight );
00092
00093 m_nBlockCount = 1;
00094 m_nBlockPos = 0;
00095
00096 if ( nActualHeight > nHeight )
00097 {
00098 for ( DWORD nStep = nActualHeight - nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
00099 }
00100
00101 m_nNodeCount = 1;
00102
00103 for ( DWORD nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00104
00105 m_nNodeBase = ( m_nNodeCount / 2 );
00106 m_nBaseUsed = (DWORD)( nCount / m_nBlockCount );
00107 if ( nCount % m_nBlockCount ) m_nBaseUsed++;
00108
00109 m_pNode = new CTigerNode[ --m_nNodeCount ];
00110 m_nNodePos = 0;
00111 }
00112
00113 void CTigerTree::SetupParameters(QWORD nLength)
00114 {
00115 QWORD nCount = nLength / BLOCK_SIZE;
00116 if ( nLength % BLOCK_SIZE ) nCount++;
00117
00118 DWORD nActualHeight = 1;
00119 for ( DWORD nStep = 1 ; nStep < nCount ; nStep *= 2 ) nActualHeight++;
00120
00121 m_nBlockCount = 1;
00122 m_nBlockPos = 0;
00123
00124 if ( nActualHeight > m_nHeight )
00125 {
00126 for ( DWORD nStep = nActualHeight - m_nHeight ; nStep ; nStep-- ) m_nBlockCount *= 2;
00127 }
00128
00129 m_nNodeCount = 1;
00130 for ( DWORD nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00131
00132 m_nNodeBase = ( m_nNodeCount-- / 2 );
00133
00134 m_nBaseUsed = (DWORD)( nCount / m_nBlockCount );
00135 if ( nCount % m_nBlockCount ) m_nBaseUsed++;
00136 }
00137
00139
00140
00141 void CTigerTree::Clear()
00142 {
00143 if ( m_pNode != NULL ) delete [] m_pNode;
00144
00145 m_nHeight = 0;
00146 m_pNode = NULL;
00147 m_nNodeCount = 0;
00148 }
00149
00151
00152
00153 void CTigerTree::Serialize(CArchive& ar)
00154 {
00155 CTigerNode* pNode;
00156 DWORD nStep;
00157
00158 if ( ar.IsStoring() )
00159 {
00160 ar << m_nHeight;
00161
00162 if ( m_nHeight == 0 ) return;
00163 ASSERT( m_pNode != NULL );
00164
00165 pNode = m_pNode;
00166
00167 for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
00168 {
00169 ar.Write( pNode->value, TIGER_SIZE );
00170 ar << pNode->bValid;
00171 }
00172 }
00173 else
00174 {
00175 Clear();
00176
00177 ar >> m_nHeight;
00178 if ( m_nHeight == 0 ) return;
00179
00180 m_nNodeCount = 1;
00181 for ( nStep = m_nHeight ; nStep ; nStep-- ) m_nNodeCount *= 2;
00182 m_nNodeCount --;
00183
00184 m_pNode = pNode = new CTigerNode[ m_nNodeCount ];
00185
00186 for ( nStep = m_nNodeCount ; nStep ; nStep--, pNode++ )
00187 {
00188 ar.Read( pNode->value, TIGER_SIZE );
00189 ar >> pNode->bValid;
00190 }
00191 }
00192 }
00193
00194 DWORD CTigerTree::GetSerialSize() const
00195 {
00196 return 4 + m_nNodeCount * ( TIGER_SIZE + 1 );
00197 }
00198
00200
00201
00202 BOOL CTigerTree::GetRoot(TIGEROOT* pTiger) const
00203 {
00204 if ( m_pNode == NULL ) return FALSE;
00205 ASSERT( sizeof(TIGEROOT) == TIGER_SIZE );
00206 CopyMemory( pTiger, &m_pNode->value, TIGER_SIZE );
00207 return TRUE;
00208 }
00209
00211
00212
00213 CString CTigerTree::RootToString() const
00214 {
00215 CString str;
00216 if ( m_pNode != NULL ) str = m_pNode->ToString();
00217 return str;
00218 }
00219
00221
00222
00223 void CTigerTree::Assume(CTigerTree* pSource)
00224 {
00225 Clear();
00226 if ( pSource->m_pNode == NULL ) return;
00227
00228 m_nHeight = pSource->m_nHeight;
00229 m_nNodeCount = pSource->m_nNodeCount;
00230 m_pNode = pSource->m_pNode;
00231
00232 pSource->m_nHeight = 0;
00233 pSource->m_nNodeCount = 0;
00234 pSource->m_pNode = NULL;
00235 }
00236
00238
00239
00240 void CTigerTree::BeginFile(DWORD nHeight, QWORD nLength)
00241 {
00242 ASSERT( ! IsAvailable() );
00243
00244 SetupAndAllocate( nHeight, nLength );
00245
00246 if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
00247 m_pStackTop = m_pStackBase;
00248 m_nBlockPos = 0;
00249 }
00250
00252
00253
00254 void CTigerTree::AddToFile(LPCVOID pInput, DWORD nLength)
00255 {
00256 ASSERT( m_pNode != NULL );
00257
00258 LPBYTE pBlock = (LPBYTE)pInput;
00259
00260 while ( nLength > 0 )
00261 {
00262 DWORD nBlock = min( nLength, DWORD(BLOCK_SIZE) );
00263
00264 Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
00265 m_pStackTop ++;
00266
00267 DWORD nCollapse = ++m_nBlockPos;
00268
00269 while ( ! ( nCollapse & 1 ) )
00270 {
00271 Collapse();
00272 nCollapse >>= 1;
00273 }
00274
00275 if ( m_nBlockPos >= m_nBlockCount )
00276 {
00277 BlocksToNode();
00278 }
00279
00280 pBlock += nBlock;
00281 nLength -= nBlock;
00282 }
00283 }
00284
00286
00287
00288 BOOL CTigerTree::FinishFile()
00289 {
00290 if ( m_pStackTop == NULL ) return FALSE;
00291 if ( m_nBaseUsed == 0 )
00292 {
00293 Tiger( this, 0, (m_pStackTop++)->value );
00294 m_nBlockPos++;
00295 }
00296
00297 BlocksToNode();
00298
00299 if ( m_nNodePos > m_nNodeBase ) return FALSE;
00300
00301 if ( m_pStackBase != NULL ) delete [] m_pStackBase;
00302
00303 m_pStackBase = NULL;
00304 m_pStackTop = NULL;
00305
00306 CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00307
00308 for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00309 {
00310 CTigerNode* pIn = pBase;
00311 CTigerNode* pOut = pBase - nCombine / 2;
00312
00313 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00314 {
00315 if ( pIn[0].bValid && pIn[1].bValid )
00316 {
00317 Tiger( NULL, TIGER_SIZE * 2, pOut->value, pIn[0].value, pIn[1].value );
00318 pOut->bValid = TRUE;
00319 }
00320 else if ( pIn[0].bValid )
00321 {
00322 *pOut = *pIn;
00323 }
00324 }
00325
00326 pBase -= nCombine / 2;
00327 }
00328
00329 return TRUE;
00330 }
00331
00333
00334
00335 void CTigerTree::BeginBlockTest()
00336 {
00337 ASSERT( m_pNode != NULL );
00338
00339 if ( m_pStackBase == NULL ) m_pStackBase = new CTigerNode[ STACK_SIZE ];
00340 m_pStackTop = m_pStackBase;
00341 m_nBlockPos = 0;
00342 }
00343
00345
00346
00347 void CTigerTree::AddToTest(LPCVOID pInput, DWORD nLength)
00348 {
00349 ASSERT( m_pNode != NULL );
00350
00351 LPBYTE pBlock = (LPBYTE)pInput;
00352
00353 while ( nLength > 0 )
00354 {
00355 DWORD nBlock = min( nLength, DWORD(BLOCK_SIZE) );
00356
00357 Tiger( pBlock, (WORD64)nBlock, m_pStackTop->value );
00358 m_pStackTop ++;
00359
00360 ASSERT( m_nBlockPos < m_nBlockCount );
00361
00362 DWORD nCollapse = ++m_nBlockPos;
00363
00364 while ( ! ( nCollapse & 1 ) )
00365 {
00366 Collapse();
00367 nCollapse >>= 1;
00368 }
00369
00370 pBlock += nBlock;
00371 nLength -= nBlock;
00372 }
00373 }
00374
00376
00377
00378 BOOL CTigerTree::FinishBlockTest(DWORD nBlock)
00379 {
00380 ASSERT( nBlock < m_nBaseUsed );
00381 if ( nBlock >= m_nBaseUsed ) return FALSE;
00382
00383 while ( m_pStackTop - 1 > m_pStackBase ) Collapse();
00384
00385 CTigerNode* pNode = m_pNode + m_nNodeCount - m_nNodeBase + nBlock;
00386
00387 if ( pNode->v1 != m_pStackBase->v1 ) return FALSE;
00388 if ( pNode->v2 != m_pStackBase->v2 ) return FALSE;
00389 if ( pNode->v3 != m_pStackBase->v3 ) return FALSE;
00390
00391 return TRUE;
00392 }
00393
00395
00396
00397 BOOL CTigerTree::ToBytes(BYTE** pOutput, DWORD* pnOutput, DWORD nHeight)
00398 {
00399 if ( m_pNode == NULL ) return FALSE;
00400
00401 if ( nHeight < 1 || nHeight > m_nHeight ) nHeight = m_nHeight;
00402
00403 DWORD nNodeCount = 1;
00404 while ( nHeight-- ) nNodeCount *= 2;
00405 nNodeCount --;
00406
00407 nNodeCount = min( nNodeCount, m_nNodeCount );
00408 *pnOutput = nNodeCount * TIGER_SIZE;
00409 *pOutput = new BYTE[ *pnOutput ];
00410
00411 CTigerNode* pNode = m_pNode;
00412 BYTE* pOut = *pOutput;
00413
00414 for ( DWORD nNode = 0 ; nNode < nNodeCount ; nNode++, pNode++ )
00415 {
00416 if ( pNode->bValid )
00417 {
00418 CopyMemory( pOut, pNode->value, TIGER_SIZE );
00419 pOut += TIGER_SIZE;
00420 }
00421 else
00422 {
00423 *pnOutput -= TIGER_SIZE;
00424 }
00425 }
00426
00427 return TRUE;
00428 }
00429
00431
00432
00433 BOOL CTigerTree::FromBytes(BYTE* pInput, DWORD nInput, DWORD nHeight, QWORD nLength)
00434 {
00435 SetupAndAllocate( nHeight, nLength );
00436
00437 CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00438
00439 for ( DWORD nStep = m_nBaseUsed ; nStep ; nStep-- )
00440 {
00441 pBase[ nStep - 1 ].bValid = TRUE;
00442 }
00443
00444 for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00445 {
00446 CTigerNode* pIn = pBase;
00447 CTigerNode* pOut = pBase - nCombine / 2;
00448
00449 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00450 {
00451 if ( pIn[0].bValid ) pOut->bValid = TRUE;
00452 }
00453
00454 pBase -= nCombine / 2;
00455 }
00456
00457 TIGEROOT* pTiger = (TIGEROOT*)pInput;
00458 nInput /= TIGER_SIZE;
00459
00460 DWORD nRowPos = 0, nRowCount = 1;
00461 m_nHeight = 0;
00462
00463 for ( DWORD nStep = 0 ; nStep < m_nNodeCount && nInput > 0 ; nStep++ )
00464 {
00465 if ( m_pNode[ nStep ].bValid )
00466 {
00467 CopyMemory( m_pNode[ nStep ].value, pTiger->w, TIGER_SIZE );
00468 pTiger ++; nInput --;
00469 }
00470
00471 if ( nRowPos == 0 ) m_nHeight ++;
00472
00473 if ( ++nRowPos == nRowCount )
00474 {
00475 nRowCount *= 2;
00476 nRowPos = 0;
00477 }
00478 }
00479
00480 if ( m_nHeight == 0 || m_nHeight > nHeight )
00481 {
00482 Clear();
00483 return FALSE;
00484 }
00485
00486 SetupParameters( nLength );
00487
00488 if ( ! CheckIntegrity() )
00489 {
00490 Clear();
00491 return FALSE;
00492 }
00493
00494 return TRUE;
00495 }
00496
00498
00499
00500 BOOL CTigerTree::CheckIntegrity()
00501 {
00502 if ( m_pNode == NULL ) return FALSE;
00503
00504 m_nNodeBase = ( m_nNodeCount + 1 ) / 2;
00505 CTigerNode* pBase = m_pNode + m_nNodeCount - m_nNodeBase;
00506
00507 for ( DWORD nCombine = m_nNodeBase ; nCombine > 1 ; nCombine /= 2 )
00508 {
00509 CTigerNode* pIn = pBase;
00510 CTigerNode* pOut = pBase - nCombine / 2;
00511
00512 if ( nCombine == 2 && pOut->bValid == FALSE ) return FALSE;
00513
00514 for ( DWORD nIterate = nCombine / 2 ; nIterate ; nIterate--, pIn += 2, pOut++ )
00515 {
00516 if ( pIn[0].bValid && pIn[1].bValid )
00517 {
00518 TIGEROOT pTemp;
00519 Tiger( NULL, TIGER_SIZE * 2, pTemp.w, pIn[0].value, pIn[1].value );
00520 if ( memcmp( pTemp.w, pOut->value, TIGER_SIZE ) ) return FALSE;
00521 }
00522 else if ( pIn[0].bValid )
00523 {
00524 if ( memcmp( pIn[0].value, pOut->value, TIGER_SIZE ) ) return FALSE;
00525 }
00526 else
00527 {
00528
00529 }
00530 }
00531
00532 pBase -= nCombine / 2;
00533 }
00534
00535 return TRUE;
00536 }
00537
00539
00540
00541 void CTigerTree::Dump()
00542 {
00543 #ifdef _DEBUG
00544 CString strOutput, strLine;
00545
00546 DWORD nRowPos = 0, nRowCount = 1;
00547 m_nHeight = 0;
00548
00549 for ( DWORD nStep = 0 ; nStep < m_nNodeCount ; nStep++ )
00550 {
00551 if ( m_pNode[ nStep ].bValid )
00552 strLine += CTigerNode::HashToString( (TIGEROOT*)m_pNode[ nStep ].value );
00553 else
00554 strLine += _T("_______________________________________");
00555 strLine += ' ';
00556
00557 if ( ++nRowPos == nRowCount )
00558 {
00559 strOutput += strLine;
00560 strOutput += _T("\r\n");
00561 strLine.Empty();
00562
00563 m_nHeight ++;
00564 nRowCount *= 2;
00565 nRowPos = 0;
00566 }
00567 }
00568
00569 theApp.LogMessage( strOutput );
00570
00571 #endif
00572 }
00573
00574
00576
00577
00578 CString CTigerNode::ToString()
00579 {
00580 return HashToString( (TIGEROOT*)&value );
00581 }
00582
00583 CString CTigerNode::HashToString(const TIGEROOT* pInHash, BOOL bURN)
00584 {
00585 static LPCTSTR pszBase64 = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567");
00586
00587 CString strHash;
00588 LPTSTR pszHash = strHash.GetBuffer( bURN ? 16 + 39 : 39 );
00589
00590 if ( bURN )
00591 {
00592 *pszHash++ = 'u'; *pszHash++ = 'r'; *pszHash++ = 'n'; *pszHash++ = ':';
00593 *pszHash++ = 't'; *pszHash++ = 'r'; *pszHash++ = 'e'; *pszHash++ = 'e'; *pszHash++ = ':';
00594 *pszHash++ = 't'; *pszHash++ = 'i'; *pszHash++ = 'g'; *pszHash++ = 'e'; *pszHash++ = 'r'; *pszHash++ = '/'; *pszHash++ = ':';
00595 }
00596
00597 LPBYTE pHash = (LPBYTE)pInHash;
00598 BYTE pZero = 0;
00599 int nShift = 7;
00600 int nHash = 0;
00601
00602 for ( int nChar = 39 ; nChar ; nChar-- )
00603 {
00604 BYTE nBits = 0;
00605
00606 for ( int nBit = 0 ; nBit < 5 ; nBit++ )
00607 {
00608 if ( nBit ) nBits <<= 1;
00609 nBits |= ( *pHash >> nShift ) & 1;
00610
00611 if ( ! nShift-- )
00612 {
00613 nShift = 7;
00614 if ( ++nHash < TIGER_SIZE )
00615 pHash++;
00616 else
00617 pHash = &pZero;
00618 }
00619 }
00620
00621 *pszHash++ = pszBase64[ nBits ];
00622 }
00623
00624 strHash.ReleaseBuffer( bURN ? 16 + 39 : 39 );
00625
00626 return strHash;
00627 }
00628
00630
00631
00632 BOOL CTigerNode::HashFromString(LPCTSTR pszHash, TIGEROOT* pTiger)
00633 {
00634 if ( ! pszHash || _tcslen( pszHash ) < 39 ) return FALSE;
00635
00636 if ( _tcsnicmp(pszHash, _T("BVBCHUUIDO4TRQL3C2QL3RIA3KB3TDWJDZ7AHCQ"), 39 ) == 0 ) return FALSE;
00637
00638 LPBYTE pHash = (LPBYTE)pTiger;
00639 DWORD nBits = 0;
00640 int nCount = 0;
00641
00642 for ( int nChars = 39 ; nChars-- ; pszHash++ )
00643 {
00644 if ( *pszHash >= 'A' && *pszHash <= 'Z' )
00645 nBits |= ( *pszHash - 'A' );
00646 else if ( *pszHash >= 'a' && *pszHash <= 'z' )
00647 nBits |= ( *pszHash - 'a' );
00648 else if ( *pszHash >= '2' && *pszHash <= '7' )
00649 nBits |= ( *pszHash - '2' + 26 );
00650 else
00651 return FALSE;
00652
00653 nCount += 5;
00654
00655 if ( nCount >= 8 )
00656 {
00657 *pHash++ = (BYTE)( nBits >> ( nCount - 8 ) );
00658 nCount -= 8;
00659 }
00660
00661 nBits <<= 5;
00662 }
00663
00664 return TRUE;
00665 }
00666
00667 BOOL CTigerNode::HashFromURN(LPCTSTR pszHash, TIGEROOT* pTiger)
00668 {
00669 if ( pszHash == NULL ) return FALSE;
00670
00671 int nLen = _tcslen( pszHash );
00672
00673 if ( nLen >= 16+39 && _tcsnicmp( pszHash, _T("urn:tree:tiger/:"), 16 ) == 0 )
00674 {
00675 return HashFromString( pszHash + 16, pTiger );
00676 }
00677 else if ( nLen >= 12+39 && _tcsnicmp( pszHash, _T("tree:tiger/:"), 12 ) == 0 )
00678 {
00679 return HashFromString( pszHash + 12, pTiger );
00680 }
00681 else if ( nLen >= 15+39 && _tcsnicmp( pszHash, _T("urn:tree:tiger:"), 15 ) == 0 )
00682 {
00683 return HashFromString( pszHash + 15, pTiger );
00684 }
00685 else if ( nLen >= 11+39 && _tcsnicmp( pszHash, _T("tree:tiger:"), 11 ) == 0 )
00686 {
00687 return HashFromString( pszHash + 11, pTiger );
00688 }
00689 else if ( nLen >= 85 && _tcsnicmp( pszHash, _T("urn:bitprint:"), 13 ) == 0 )
00690 {
00691 return HashFromString( pszHash + 46, pTiger );
00692 }
00693 else if ( nLen >= 81 && _tcsnicmp( pszHash, _T("bitprint:"), 9 ) == 0 )
00694 {
00695 return HashFromString( pszHash + 42, pTiger );
00696 }
00697
00698 return FALSE;
00699 }
00700
00701 BOOL CTigerNode::IsNull(TIGEROOT* pTiger)
00702 {
00703 if ( _tcsnicmp( HashToString(pTiger) , _T("BVBCHUUIDO4TRQL3C2QL3RIA3KB3TDWJDZ7AHCQ"), 39 ) == 0 ) return TRUE;
00704
00705 return FALSE;
00706 }
00707
00708
00710
00711
00712
00713
00714
00715 void CTigerTree::Tiger(LPCVOID pInput, WORD64 nInput, WORD64* pOutput, WORD64* pInput1, WORD64* pInput2)
00716 {
00717 register WORD64 i, j;
00718 BYTE pTemp[64];
00719
00720 pOutput[0] = 0x0123456789ABCDEF;
00721 pOutput[1] = 0xFEDCBA9876543210;
00722 pOutput[2] = 0xF096A5B4C3B2E187;
00723
00724 if ( pInput != NULL )
00725 {
00726 #ifdef NEW_TIGER_ALG
00727 if ( nInput < 63 )
00728 {
00729 pTemp[0] = 0x00;
00730 const BYTE* pBytes = (const BYTE*)pInput;
00731 for ( j = 1 ; j < nInput + 1 ; j++ ) pTemp[j] = *pBytes++;
00732 }
00733 else
00734 {
00735 pTemp[0] = 0x00;
00736 CopyMemory( pTemp + 1, pInput, 63 );
00737 pTiger( (WORD64*)pTemp, pOutput );
00738
00739 const WORD64* pWords = (const WORD64*)( (const BYTE*)pInput + 63 );
00740
00741 for ( i = nInput - 63 ; i >= 64 ; i -= 64 )
00742 {
00743 pTiger( (WORD64*) pWords, pOutput );
00744 pWords += 8;
00745 }
00746
00747 for ( j = 0 ; j < i ; j++ ) pTemp[j] = ((BYTE*)pWords)[j];
00748 }
00749 nInput++;
00750 #else
00751 const WORD64* pWords = (const WORD64*)pInput;
00752
00753 for ( i = nInput ; i >= 64 ; i -= 64 )
00754 {
00755 pTiger( pWords, pOutput );
00756 pWords += 8;
00757 }
00758
00759 for ( j = 0 ; j < i ; j++ ) pTemp[j] = ((BYTE*)pWords)[j];
00760 #endif
00761 }
00762 else if ( pInput1 != NULL && pInput2 != NULL )
00763 {
00764 #ifdef NEW_TIGER_ALG
00765 pTemp[0] = 0x01;
00766 CopyMemory( pTemp + 1, pInput1, TIGER_SIZE );
00767 CopyMemory( pTemp + TIGER_SIZE + 1, pInput2, TIGER_SIZE );
00768 j = TIGER_SIZE * 2 + 1;
00769 nInput = j;
00770 #else
00771 CopyMemory( pTemp, pInput1, TIGER_SIZE );
00772 CopyMemory( pTemp + TIGER_SIZE, pInput2, TIGER_SIZE );
00773 nInput = j = TIGER_SIZE * 2;
00774 #endif
00775 }
00776 else
00777 {
00778 ASSERT( FALSE );
00779 }
00780
00781 pTemp[j++] = 0x01;
00782
00783 for ( ; j & 7 ; j++ ) pTemp[j] = 0;
00784
00785 if ( j > 56 )
00786 {
00787 for ( ; j < 64 ; j++ ) pTemp[j] = 0;
00788 pTiger( ((WORD64*)pTemp), pOutput );
00789 j = 0;
00790 }
00791
00792 for ( ; j < 56 ; j++ ) pTemp[j] = 0;
00793
00794 ((WORD64*)(&(pTemp[56])))[0] = ((WORD64)nInput) << 3;
00795
00796 pTiger( ((WORD64*)pTemp), pOutput );
00797 }
00798
00799 #define PASSES 3
00800
00801 #define t1 (m_pTable)
00802 #define t2 (m_pTable+256)
00803 #define t3 (m_pTable+256*2)
00804 #define t4 (m_pTable+256*3)
00805
00806 #define save_abc \
00807 aa = a; \
00808 bb = b; \
00809 cc = c;
00810
00811 #define round(a,b,c,x,mul) \
00812 c ^= x; \
00813 a -= t1[(BYTE)(c)] ^ \
00814 t2[(BYTE)(((DWORD)(c))>>(2*8))] ^ \
00815 t3[(BYTE)((c)>>(4*8))] ^ \
00816 t4[(BYTE)(((DWORD)((c)>>(4*8)))>>(2*8))] ; \
00817 b += t4[(BYTE)(((DWORD)(c))>>(1*8))] ^ \
00818 t3[(BYTE)(((DWORD)(c))>>(3*8))] ^ \
00819 t2[(BYTE)(((DWORD)((c)>>(4*8)))>>(1*8))] ^ \
00820 t1[(BYTE)(((DWORD)((c)>>(4*8)))>>(3*8))]; \
00821 b *= mul;
00822
00823 #define pass(a,b,c,mul) \
00824 round(a,b,c,x0,mul) \
00825 round(b,c,a,x1,mul) \
00826 round(c,a,b,x2,mul) \
00827 round(a,b,c,x3,mul) \
00828 round(b,c,a,x4,mul) \
00829 round(c,a,b,x5,mul) \
00830 round(a,b,c,x6,mul) \
00831 round(b,c,a,x7,mul)
00832
00833 #define key_schedule \
00834 x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5; \
00835 x1 ^= x0; \
00836 x2 += x1; \
00837 x3 -= x2 ^ ((~x1)<<19); \
00838 x4 ^= x3; \
00839 x5 += x4; \
00840 x6 -= x5 ^ ((~x4)>>23); \
00841 x7 ^= x6; \
00842 x0 += x7; \
00843 x1 -= x0 ^ ((~x7)<<19); \
00844 x2 ^= x1; \
00845 x3 += x2; \
00846 x4 -= x3 ^ ((~x2)>>23); \
00847 x5 ^= x4; \
00848 x6 += x5; \
00849 x7 -= x6 ^ 0x0123456789ABCDEF;
00850
00851 #define feedforward \
00852 a ^= aa; \
00853 b -= bb; \
00854 c += cc;
00855
00856 #define compress \
00857 save_abc \
00858 for(pass_no=0; pass_no<PASSES; pass_no++) { \
00859 if(pass_no != 0) {key_schedule} \
00860 pass(a,b,c,(pass_no==0?5:pass_no==1?7:9)); \
00861 tmpa=a; a=c; c=b; b=tmpa;} \
00862 feedforward
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00888
00889
00890 void CTigerTree::Collapse()
00891 {
00892 ASSERT( m_pStackTop - m_pStackBase >= 2 );
00893
00894 Tiger( NULL, TIGER_SIZE * 2, m_pStackTop->value, m_pStackTop[-2].value, m_pStackTop[-1].value );
00895
00896 m_pStackTop -= 2;
00897 m_pStackTop[0] = m_pStackTop[2];
00898 m_pStackTop ++;
00899 }
00900
00902
00903
00904 void CTigerTree::BlocksToNode()
00905 {
00906 if ( m_pStackTop == m_pStackBase ) return;
00907
00908 while ( m_pStackTop - 1 > m_pStackBase ) Collapse();
00909
00910 CTigerNode* pNode = m_pNode + m_nNodeCount - m_nNodeBase + m_nNodePos++;
00911
00912 pNode->v1 = m_pStackBase->v1;
00913 pNode->v2 = m_pStackBase->v2;
00914 pNode->v3 = m_pStackBase->v3;
00915 pNode->bValid = TRUE;
00916
00917 m_nBlockPos = 0;
00918 m_pStackTop = m_pStackBase;
00919 }