diff src/win32/7zip/7z/CPP/7zip/Crypto/RarAes.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Crypto/RarAes.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,139 @@
     1.4 +// Crypto/RarAes.cpp
     1.5 +// Note: you must include MyAes.cpp to project to initialize AES tables
     1.6 +
     1.7 +#include "StdAfx.h"
     1.8 +
     1.9 +#include "RarAes.h"
    1.10 +#include "Sha1.h"
    1.11 +
    1.12 +namespace NCrypto {
    1.13 +namespace NRar29 {
    1.14 +
    1.15 +CDecoder::CDecoder():
    1.16 +  _thereIsSalt(false),
    1.17 +  _needCalculate(true),
    1.18 +  _rar350Mode(false)
    1.19 +{
    1.20 +  for (int i = 0; i < sizeof(_salt); i++)
    1.21 +    _salt[i] = 0;
    1.22 +}
    1.23 +
    1.24 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
    1.25 +{
    1.26 +  bool thereIsSaltPrev = _thereIsSalt;
    1.27 +  _thereIsSalt = false;
    1.28 +  if (size == 0)
    1.29 +    return S_OK;
    1.30 +  if (size < 8)
    1.31 +    return E_INVALIDARG;
    1.32 +  _thereIsSalt = true;
    1.33 +  bool same = false;
    1.34 +  if (_thereIsSalt == thereIsSaltPrev)
    1.35 +  {
    1.36 +    same = true;
    1.37 +    if (_thereIsSalt)
    1.38 +    {
    1.39 +      for (int i = 0; i < sizeof(_salt); i++)
    1.40 +        if (_salt[i] != data[i])
    1.41 +        {
    1.42 +          same = false;
    1.43 +          break;
    1.44 +        }
    1.45 +    }
    1.46 +  }
    1.47 +  for (int i = 0; i < sizeof(_salt); i++)
    1.48 +    _salt[i] = data[i];
    1.49 +  if (!_needCalculate && !same)
    1.50 +    _needCalculate = true;
    1.51 +  return S_OK;
    1.52 +}
    1.53 +
    1.54 +static const int kMaxPasswordLength = 127 * 2;
    1.55 +
    1.56 +STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
    1.57 +{
    1.58 +  if (size > kMaxPasswordLength)
    1.59 +    size = kMaxPasswordLength;
    1.60 +  bool same = false;
    1.61 +  if (size == buffer.GetCapacity())
    1.62 +  {
    1.63 +    same = true;
    1.64 +    for (UInt32 i = 0; i < size; i++)
    1.65 +      if (data[i] != buffer[i])
    1.66 +      {
    1.67 +        same = false;
    1.68 +        break;
    1.69 +      }
    1.70 +  }
    1.71 +  if (!_needCalculate && !same)
    1.72 +    _needCalculate = true;
    1.73 +  buffer.SetCapacity(size);
    1.74 +  memcpy(buffer, data, size);
    1.75 +  return S_OK;
    1.76 +}
    1.77 +
    1.78 +STDMETHODIMP CDecoder::Init()
    1.79 +{
    1.80 +  Calculate();
    1.81 +  Aes_SetKeyDecode(&Aes.aes, aesKey, kRarAesKeySize);
    1.82 +  AesCbc_Init(&Aes, aesInit);
    1.83 +  return S_OK;
    1.84 +}
    1.85 +
    1.86 +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
    1.87 +{
    1.88 +  return (UInt32)AesCbc_Decode(&Aes, data, size);
    1.89 +}
    1.90 +
    1.91 +void CDecoder::Calculate()
    1.92 +{
    1.93 +  if (_needCalculate)
    1.94 +  {
    1.95 +    const int kSaltSize = 8;
    1.96 +    
    1.97 +    Byte rawPassword[kMaxPasswordLength + kSaltSize];
    1.98 +    
    1.99 +    memcpy(rawPassword, buffer, buffer.GetCapacity());
   1.100 +    
   1.101 +    size_t rawLength = buffer.GetCapacity();
   1.102 +    
   1.103 +    if (_thereIsSalt)
   1.104 +    {
   1.105 +      memcpy(rawPassword + rawLength, _salt, kSaltSize);
   1.106 +      rawLength += kSaltSize;
   1.107 +    }
   1.108 +    
   1.109 +    NSha1::CContext sha;
   1.110 +    sha.Init();
   1.111 +
   1.112 +    // seems rar reverts hash for sha.
   1.113 +    const int hashRounds = 0x40000;
   1.114 +    int i;
   1.115 +    for (i = 0; i < hashRounds; i++)
   1.116 +    {
   1.117 +      sha.Update(rawPassword, rawLength, _rar350Mode);
   1.118 +      Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
   1.119 +      sha.Update(pswNum, 3, _rar350Mode);
   1.120 +      if (i % (hashRounds / 16) == 0)
   1.121 +      {
   1.122 +        NSha1::CContext shaTemp = sha;
   1.123 +        Byte digest[NSha1::kDigestSize];
   1.124 +        shaTemp.Final(digest);
   1.125 +        aesInit[i / (hashRounds / 16)] = (Byte)digest[4 * 4 + 3];
   1.126 +      }
   1.127 +    }
   1.128 +    /*
   1.129 +    // it's test message for sha
   1.130 +    const char *message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
   1.131 +    sha.Update((const Byte *)message, strlen(message));
   1.132 +    */
   1.133 +    Byte digest[20];
   1.134 +    sha.Final(digest);
   1.135 +    for (i = 0; i < 4; i++)
   1.136 +      for (int j = 0; j < 4; j++)
   1.137 +        aesKey[i * 4 + j] = (digest[i * 4 + 3 - j]);
   1.138 +  }
   1.139 +  _needCalculate = false;
   1.140 +}
   1.141 +
   1.142 +}}