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 ZIP7_INC_CRYPTO_WZ_AES_H 13 #define ZIP7_INC_CRYPTO_WZ_AES_H 14 15 #include "../../Common/MyBuffer.h" 16 17 #include "../IPassword.h" 18 19 #include "HmacSha1.h" 20 #include "MyAes.h" 21 22 namespace NCrypto { 23 namespace NWzAes { 24 25 /* ICompressFilter::Init() does nothing for this filter. 26 27 Call to init: 28 Encoder: 29 CryptoSetPassword(); 30 WriteHeader(); 31 Decoder: 32 [CryptoSetPassword();] 33 ReadHeader(); 34 [CryptoSetPassword();] Init_and_CheckPassword(); 35 [CryptoSetPassword();] Init_and_CheckPassword(); 36 */ 37 38 const UInt32 kPasswordSizeMax = 99; // 128; 39 40 const unsigned kSaltSizeMax = 16; 41 const unsigned kPwdVerifSize = 2; 42 const unsigned kMacSize = 10; 43 44 enum EKeySizeMode 45 { 46 kKeySizeMode_AES128 = 1, 47 kKeySizeMode_AES192 = 2, 48 kKeySizeMode_AES256 = 3 49 }; 50 51 struct CKeyInfo 52 { 53 EKeySizeMode KeySizeMode; 54 Byte Salt[kSaltSizeMax]; 55 Byte PwdVerifComputed[kPwdVerifSize]; 56 57 CByteBuffer Password; 58 GetKeySizeCKeyInfo59 unsigned GetKeySize() const { return (8 * KeySizeMode + 8); } GetSaltSizeCKeyInfo60 unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); } GetNumSaltWordsCKeyInfo61 unsigned GetNumSaltWords() const { return (KeySizeMode + 1); } 62 CKeyInfoCKeyInfo63 CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {} 64 WipeCKeyInfo65 void Wipe() 66 { 67 Password.Wipe(); 68 Z7_memset_0_ARRAY(Salt); 69 Z7_memset_0_ARRAY(PwdVerifComputed); 70 } 71 ~CKeyInfoCKeyInfo72 ~CKeyInfo() { Wipe(); } 73 }; 74 75 /* 76 struct CAesCtr2 77 { 78 unsigned pos; 79 CAlignedBuffer aes; 80 UInt32 *Aes() { return (UInt32 *)(Byte *)aes; } 81 82 // unsigned offset; 83 // UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3]; 84 // UInt32 *Aes() { return aes + offset; } 85 CAesCtr2(); 86 }; 87 88 void AesCtr2_Init(CAesCtr2 *p); 89 void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size); 90 */ 91 92 class CBaseCoder: 93 public ICompressFilter, 94 public ICryptoSetPassword, 95 public CMyUnknownImp 96 { 97 Z7_COM_UNKNOWN_IMP_1(ICryptoSetPassword) 98 Z7_COM7F_IMP(Init()) 99 public: 100 Z7_IFACE_COM7_IMP(ICryptoSetPassword) 101 protected: 102 CKeyInfo _key; 103 104 // NSha1::CHmac _hmac; 105 // NSha1::CHmac *Hmac() { return &_hmac; } 106 CAlignedBuffer1 _hmacBuf; 107 UInt32 _hmacOverCalc; 108 Hmac()109 NSha1::CHmac *Hmac() { return (NSha1::CHmac *)(void *)(Byte *)_hmacBuf; } 110 111 // CAesCtr2 _aes; 112 CAesCoder *_aesCoderSpec; 113 CMyComPtr<ICompressFilter> _aesCoder; CBaseCoder()114 CBaseCoder(): 115 _hmacBuf(sizeof(NSha1::CHmac)) 116 { 117 _aesCoderSpec = new CAesCtrCoder(32); 118 _aesCoder = _aesCoderSpec; 119 } 120 121 void Init2(); 122 public: GetHeaderSize()123 unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; } GetAddPackSize()124 unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; } 125 SetKeyMode(unsigned mode)126 bool SetKeyMode(unsigned mode) 127 { 128 if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256) 129 return false; 130 _key.KeySizeMode = (EKeySizeMode)mode; 131 return true; 132 } 133 ~CBaseCoder()134 virtual ~CBaseCoder() {} 135 }; 136 137 class CEncoder Z7_final: 138 public CBaseCoder 139 { 140 Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) 141 public: 142 HRESULT WriteHeader(ISequentialOutStream *outStream); 143 HRESULT WriteFooter(ISequentialOutStream *outStream); 144 }; 145 146 class CDecoder Z7_final: 147 public CBaseCoder 148 // public ICompressSetDecoderProperties2 149 { 150 Byte _pwdVerifFromArchive[kPwdVerifSize]; 151 Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) 152 public: 153 // Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) 154 HRESULT ReadHeader(ISequentialInStream *inStream); 155 bool Init_and_CheckPassword(); 156 HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK); 157 }; 158 159 }} 160 161 #endif 162