zipCryptStream.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "io/zip/zipCryptStream.h"
  23. #include "algorithm/crctab.h"
  24. #include "console/console.h"
  25. //////////////////////////////////////////////////////////////////////////
  26. // Constructor/Destructor
  27. //////////////////////////////////////////////////////////////////////////
  28. ZipCryptRStream::ZipCryptRStream() : mStream(NULL), mFileEndPos(0), mPassword(NULL)
  29. {
  30. }
  31. ZipCryptRStream::~ZipCryptRStream()
  32. {
  33. }
  34. //////////////////////////////////////////////////////////////////////////
  35. // Private Methods
  36. //////////////////////////////////////////////////////////////////////////
  37. U32 ZipCryptRStream::fillBuffer(const U32 in_attemptSize, void *pBuffer)
  38. {
  39. AssertFatal(mStream != NULL, "No stream to fill from?");
  40. AssertFatal(mStream->getStatus() != Stream::Closed,
  41. "Fill from a closed stream?");
  42. U32 currPos = mStream->getPosition();
  43. U32 actualReadSize;
  44. if (in_attemptSize + currPos > (U32)mFileEndPos) {
  45. actualReadSize = mFileEndPos - currPos;
  46. } else {
  47. actualReadSize = in_attemptSize;
  48. }
  49. if (mStream->read(actualReadSize, pBuffer) == true) {
  50. return actualReadSize;
  51. } else {
  52. AssertWarn(false, "Read failed while trying to fill buffer");
  53. return 0;
  54. }
  55. }
  56. //////////////////////////////////////////////////////////////////////////
  57. // Public Methods
  58. //////////////////////////////////////////////////////////////////////////
  59. void ZipCryptRStream::setPassword(const char *password)
  60. {
  61. mKeys[0] = 305419896;
  62. mKeys[1] = 591751049;
  63. mKeys[2] = 878082192;
  64. mPassword = password;
  65. const char *pPtr = password;
  66. while(*pPtr)
  67. {
  68. updateKeys(*pPtr);
  69. pPtr++;
  70. }
  71. }
  72. bool ZipCryptRStream::attachStream(Stream* io_pSlaveStream)
  73. {
  74. mStream = io_pSlaveStream;
  75. mStreamStartPos = mStream->getPosition();
  76. // [tom, 12/20/2005] Encrypted zip files have an extra 12 bytes
  77. // of entropy before the file data.
  78. U8 buffer[12];
  79. if(mStream->read(sizeof(buffer), &buffer))
  80. {
  81. // Initialize keys
  82. for(S32 i = 0;i < sizeof(buffer);i++)
  83. {
  84. updateKeys(buffer[i] ^= decryptByte());
  85. }
  86. // if(buffer[11] !)
  87. mFileStartPos = mStream->getPosition();
  88. setStatus(Ok);
  89. return true;
  90. }
  91. return false;
  92. }
  93. void ZipCryptRStream::detachStream()
  94. {
  95. mStream = NULL;
  96. // Clear keys, just in case
  97. dMemset(&mKeys, 0, sizeof(mKeys));
  98. setStatus(Closed);
  99. }
  100. U32 ZipCryptRStream::getPosition() const
  101. {
  102. return mStream->getPosition();
  103. }
  104. bool ZipCryptRStream::setPosition(const U32 in_newPosition)
  105. {
  106. if(in_newPosition > (U32)mFileEndPos)
  107. return false;
  108. U32 curPos = getPosition();
  109. U32 readSize = in_newPosition - mFileStartPos;
  110. bool ret = true;
  111. if(in_newPosition < curPos)
  112. {
  113. // Reposition to start of stream
  114. Stream *stream = getStream();
  115. U32 startPos = mStreamStartPos;
  116. const char *password = mPassword;
  117. detachStream();
  118. setPassword(password);
  119. stream->setPosition(startPos);
  120. ret = attachStream(stream);
  121. if(in_newPosition == mFileStartPos)
  122. return ret;
  123. }
  124. // Read until we reach the new position
  125. U8 *buffer = new U8 [1024];
  126. while(readSize >= 1024)
  127. {
  128. readSize -= 1024;
  129. ret = _read(1024, buffer);
  130. if(! ret)
  131. break;
  132. }
  133. if(readSize > 0 && ret)
  134. {
  135. ret = _read(readSize, buffer);
  136. }
  137. delete [] buffer;
  138. return ret;
  139. }
  140. //////////////////////////////////////////////////////////////////////////
  141. // Protected Methods
  142. //////////////////////////////////////////////////////////////////////////
  143. void ZipCryptRStream::updateKeys(const U8 c)
  144. {
  145. mKeys[0] = ZC_CRC32(mKeys[0], c);
  146. mKeys[1] += mKeys[0] & 0x000000ff;
  147. mKeys[1] = mKeys[1] * 134775813 + 1;
  148. U32 k = mKeys[1] >> 24;
  149. mKeys[2] = ZC_CRC32(mKeys[2], k);
  150. }
  151. U8 ZipCryptRStream::decryptByte()
  152. {
  153. U16 temp;
  154. temp = (mKeys[2] & 0xffff) | 2;
  155. return (temp * (temp ^ 1)) >> 8;
  156. }
  157. bool ZipCryptRStream::_read(const U32 in_numBytes, void* out_pBuffer)
  158. {
  159. U32 numRead = fillBuffer(in_numBytes, out_pBuffer);
  160. if(numRead > 0)
  161. {
  162. // Decrypt
  163. U8 *pBytes = (U8 *)out_pBuffer;
  164. for(U32 i = 0;i < numRead;i++)
  165. {
  166. updateKeys(pBytes[i] ^= decryptByte());
  167. }
  168. return true;
  169. }
  170. return false;
  171. }