1 // Crypto/WzAes.h 2 /* 3 This code implements Brian Gladman's scheme 4 specified in "A Password Based File Encryption Utility": 5 - AES encryption (128,192,256-bit) in Counter (CTR) mode. 6 - HMAC-SHA1 authentication for encrypted data (10 bytes) 7 - Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and 8 Salt (saltSize = aesKeySize / 2). 9 - 2 bytes contain Password Verifier's Code 10 */ 11 12 #ifndef __CRYPTO_WZ_AES_H 13 #define __CRYPTO_WZ_AES_H 14 15 #include "../../../C/Aes.h" 16 17 #include "../../Common/MyBuffer.h" 18 #include "../../Common/MyCom.h" 19 20 #include "../ICoder.h" 21 #include "../IPassword.h" 22 23 #include "HmacSha1.h" 24 25 namespace NCrypto { 26 namespace NWzAes { 27 28 /* ICompressFilter::Init() does nothing for this filter. 29 30 Call to init: 31 Encoder: 32 CryptoSetPassword(); 33 WriteHeader(); 34 Decoder: 35 [CryptoSetPassword();] 36 ReadHeader(); 37 [CryptoSetPassword();] Init_and_CheckPassword(); 38 [CryptoSetPassword();] Init_and_CheckPassword(); 39 */ 40 41 const UInt32 kPasswordSizeMax = 99; // 128; 42 43 const unsigned kSaltSizeMax = 16; 44 const unsigned kPwdVerifSize = 2; 45 const unsigned kMacSize = 10; 46 47 enum EKeySizeMode 48 { 49 kKeySizeMode_AES128 = 1, 50 kKeySizeMode_AES192 = 2, 51 kKeySizeMode_AES256 = 3 52 }; 53 54 struct CKeyInfo 55 { 56 EKeySizeMode KeySizeMode; 57 Byte Salt[kSaltSizeMax]; 58 Byte PwdVerifComputed[kPwdVerifSize]; 59 60 CByteBuffer Password; 61 GetKeySizeCKeyInfo62 unsigned GetKeySize() const { return (8 * KeySizeMode + 8); } GetSaltSizeCKeyInfo63 unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); } GetNumSaltWordsCKeyInfo64 unsigned GetNumSaltWords() const { return (KeySizeMode + 1); } 65 CKeyInfoCKeyInfo66 CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {} 67 }; 68 69 struct CAesCtr2 70 { 71 unsigned pos; 72 unsigned offset; 73 UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3]; 74 CAesCtr2(); 75 }; 76 77 void AesCtr2_Init(CAesCtr2 *p); 78 void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size); 79 80 class CBaseCoder: 81 public ICompressFilter, 82 public ICryptoSetPassword, 83 public CMyUnknownImp 84 { 85 protected: 86 CKeyInfo _key; 87 NSha1::CHmac _hmac; 88 CAesCtr2 _aes; 89 90 void Init2(); 91 public: 92 MY_UNKNOWN_IMP1(ICryptoSetPassword) 93 94 STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); 95 96 STDMETHOD(Init)(); 97 GetHeaderSize()98 unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; } GetAddPackSize()99 unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; } 100 SetKeyMode(unsigned mode)101 bool SetKeyMode(unsigned mode) 102 { 103 if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256) 104 return false; 105 _key.KeySizeMode = (EKeySizeMode)mode; 106 return true; 107 } 108 ~CBaseCoder()109 virtual ~CBaseCoder() {} 110 }; 111 112 class CEncoder: 113 public CBaseCoder 114 { 115 public: 116 STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); 117 HRESULT WriteHeader(ISequentialOutStream *outStream); 118 HRESULT WriteFooter(ISequentialOutStream *outStream); 119 }; 120 121 class CDecoder: 122 public CBaseCoder 123 // public ICompressSetDecoderProperties2 124 { 125 Byte _pwdVerifFromArchive[kPwdVerifSize]; 126 public: 127 // ICompressSetDecoderProperties2 128 // STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); 129 STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); 130 HRESULT ReadHeader(ISequentialInStream *inStream); 131 bool Init_and_CheckPassword(); 132 HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK); 133 }; 134 135 }} 136 137 #endif 138