Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Crypto/WzAes.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 source
1 // Crypto/WzAes.cpp2 /*3 This code implements Brian Gladman's scheme4 specified in password Based File Encryption Utility.6 Note: you must include MyAes.cpp to project to initialize AES tables7 */9 #include "StdAfx.h"11 #include "../Common/StreamObjects.h"12 #include "../Common/StreamUtils.h"14 #include "Pbkdf2HmacSha1.h"15 #include "RandGen.h"16 #include "WzAes.h"18 // define it if you don't want to use speed-optimized version of Pbkdf2HmacSha119 // #define _NO_WZAES_OPTIMIZATIONS21 namespace NCrypto {22 namespace NWzAes {24 const unsigned int kAesKeySizeMax = 32;26 static const UInt32 kNumKeyGenIterations = 1000;28 STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)29 {30 if(size > kPasswordSizeMax)31 return E_INVALIDARG;32 _key.Password.SetCapacity(size);33 memcpy(_key.Password, data, size);34 return S_OK;35 }37 #define SetUi32(p, d) { UInt32 x = (d); (p)[0] = (Byte)x; (p)[1] = (Byte)(x >> 8); \38 (p)[2] = (Byte)(x >> 16); (p)[3] = (Byte)(x >> 24); }40 void CBaseCoder::EncryptData(Byte *data, UInt32 size)41 {42 unsigned int pos = _blockPos;43 for (; size > 0; size--)44 {45 if (pos == AES_BLOCK_SIZE)46 {47 if (++_counter[0] == 0)48 _counter[1]++;49 UInt32 temp[4];50 Aes_Encode32(&Aes, temp, _counter);51 SetUi32(_buffer, temp[0]);52 SetUi32(_buffer + 4, temp[1]);53 SetUi32(_buffer + 8, temp[2]);54 SetUi32(_buffer + 12, temp[3]);55 pos = 0;56 }57 *data++ ^= _buffer[pos++];58 }59 _blockPos = pos;60 }62 #ifndef _NO_WZAES_OPTIMIZATIONS64 static void BytesToBeUInt32s(const Byte *src, UInt32 *dest, int destSize)65 {66 for (int i = 0 ; i < destSize; i++)67 dest[i] =68 ((UInt32)(src[i * 4 + 0]) << 24) |69 ((UInt32)(src[i * 4 + 1]) << 16) |70 ((UInt32)(src[i * 4 + 2]) << 8) |71 ((UInt32)(src[i * 4 + 3]));72 }74 #endif76 STDMETHODIMP CBaseCoder::Init()77 {78 UInt32 keySize = _key.GetKeySize();79 UInt32 keysTotalSize = 2 * keySize + kPwdVerifCodeSize;80 Byte buf[2 * kAesKeySizeMax + kPwdVerifCodeSize];82 // for (int ii = 0; ii < 1000; ii++)83 {84 #ifdef _NO_WZAES_OPTIMIZATIONS86 NSha1::Pbkdf2Hmac(87 _key.Password, _key.Password.GetCapacity(),88 _key.Salt, _key.GetSaltSize(),89 kNumKeyGenIterations,90 buf, keysTotalSize);92 #else94 UInt32 buf32[(2 * kAesKeySizeMax + kPwdVerifCodeSize + 3) / 4];95 UInt32 key32SizeTotal = (keysTotalSize + 3) / 4;96 UInt32 salt[kSaltSizeMax * 4];97 UInt32 saltSizeInWords = _key.GetSaltSize() / 4;98 BytesToBeUInt32s(_key.Salt, salt, saltSizeInWords);99 NSha1::Pbkdf2Hmac32(100 _key.Password, _key.Password.GetCapacity(),101 salt, saltSizeInWords,102 kNumKeyGenIterations,103 buf32, key32SizeTotal);104 for (UInt32 j = 0; j < keysTotalSize; j++)105 buf[j] = (Byte)(buf32[j / 4] >> (24 - 8 * (j & 3)));107 #endif108 }110 _hmac.SetKey(buf + keySize, keySize);111 memcpy(_key.PwdVerifComputed, buf + 2 * keySize, kPwdVerifCodeSize);113 _blockPos = AES_BLOCK_SIZE;114 for (int i = 0; i < 4; i++)115 _counter[i] = 0;117 Aes_SetKeyEncode(&Aes, buf, keySize);118 return S_OK;119 }121 /*122 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)123 {124 Byte keySizeMode = 3;125 return outStream->Write(&keySizeMode, 1, NULL);126 }127 */129 HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)130 {131 UInt32 saltSize = _key.GetSaltSize();132 g_RandomGenerator.Generate(_key.Salt, saltSize);133 Init();134 RINOK(WriteStream(outStream, _key.Salt, saltSize));135 return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifCodeSize);136 }138 HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)139 {140 Byte mac[kMacSize];141 _hmac.Final(mac, kMacSize);142 return WriteStream(outStream, mac, kMacSize);143 }145 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)146 {147 if (size != 1)148 return E_INVALIDARG;149 _key.Init();150 Byte keySizeMode = data[0];151 if (keySizeMode < 1 || keySizeMode > 3)152 return E_INVALIDARG;153 _key.KeySizeMode = keySizeMode;154 return S_OK;155 }157 HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)158 {159 UInt32 saltSize = _key.GetSaltSize();160 UInt32 extraSize = saltSize + kPwdVerifCodeSize;161 Byte temp[kSaltSizeMax + kPwdVerifCodeSize];162 RINOK(ReadStream_FAIL(inStream, temp, extraSize));163 UInt32 i;164 for (i = 0; i < saltSize; i++)165 _key.Salt[i] = temp[i];166 for (i = 0; i < kPwdVerifCodeSize; i++)167 _pwdVerifFromArchive[i] = temp[saltSize + i];168 return S_OK;169 }171 static bool CompareArrays(const Byte *p1, const Byte *p2, UInt32 size)172 {173 for (UInt32 i = 0; i < size; i++)174 if (p1[i] != p2[i])175 return false;176 return true;177 }179 bool CDecoder::CheckPasswordVerifyCode()180 {181 return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifCodeSize);182 }184 HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)185 {186 isOK = false;187 Byte mac1[kMacSize];188 RINOK(ReadStream_FAIL(inStream, mac1, kMacSize));189 Byte mac2[kMacSize];190 _hmac.Final(mac2, kMacSize);191 isOK = CompareArrays(mac1, mac2, kMacSize);192 return S_OK;193 }195 STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)196 {197 EncryptData(data, size);198 _hmac.Update(data, size);199 return size;200 }202 STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)203 {204 _hmac.Update(data, size);205 EncryptData(data, size);206 return size;207 }209 }}