xref: /aosp_15_r20/external/lzma/CPP/7zip/Crypto/MyAes.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Crypto/MyAes.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/CpuArch.h"
6 
7 #include "MyAes.h"
8 
9 namespace NCrypto {
10 
CAesTabInitNCrypto::CAesTabInit11 static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;
12 
CAesCoder(unsigned keySize)13 CAesCoder::CAesCoder(
14       // bool encodeMode,
15       unsigned keySize
16       // , bool ctrMode
17       ):
18   _keyIsSet(false),
19   // _encodeMode(encodeMode),
20   // _ctrMode(ctrMode),
21   _keySize(keySize),
22   // _ctrPos(0), // _ctrPos =0 will be set in Init()
23   _aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2)
24 {
25   // _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);
26   memset(_iv, 0, AES_BLOCK_SIZE);
27   /*
28   // we can use the following code to test 32-bit overflow case for AES-CTR
29   for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1);
30   _iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF;
31   */
32 }
33 
Z7_COM7F_IMF(CAesCoder::Init ())34 Z7_COM7F_IMF(CAesCoder::Init())
35 {
36   _ctrPos = 0;
37   AesCbc_Init(Aes(), _iv);
38   return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL
39 }
40 
Z7_COM7F_IMF2(UInt32,CAesCoder::Filter (Byte * data,UInt32 size))41 Z7_COM7F_IMF2(UInt32, CAesCoder::Filter(Byte *data, UInt32 size))
42 {
43   if (!_keyIsSet)
44     return 0;
45   if (size < AES_BLOCK_SIZE)
46   {
47     if (size == 0)
48       return 0;
49     return AES_BLOCK_SIZE;
50   }
51   size >>= 4;
52   // (data) must be aligned for 16-bytes here
53   _codeFunc(Aes(), data, size);
54   return size << 4;
55 }
56 
57 
Z7_COM7F_IMF(CAesCoder::SetKey (const Byte * data,UInt32 size))58 Z7_COM7F_IMF(CAesCoder::SetKey(const Byte *data, UInt32 size))
59 {
60   if ((size & 0x7) != 0 || size < 16 || size > 32)
61     return E_INVALIDARG;
62   if (_keySize != 0 && size != _keySize)
63     return E_INVALIDARG;
64   _setKeyFunc(Aes() + 4, data, size);
65   _keyIsSet = true;
66   return S_OK;
67 }
68 
Z7_COM7F_IMF(CAesCoder::SetInitVector (const Byte * data,UInt32 size))69 Z7_COM7F_IMF(CAesCoder::SetInitVector(const Byte *data, UInt32 size))
70 {
71   if (size != AES_BLOCK_SIZE)
72     return E_INVALIDARG;
73   memcpy(_iv, data, size);
74   /* we allow SetInitVector() call before SetKey() call.
75      so we ignore possible error in Init() here */
76   CAesCoder::Init(); // don't call virtual function here !!!
77   return S_OK;
78 }
79 
80 
81 #ifndef Z7_SFX
82 
83 /*
84 Z7_COM7F_IMF(CAesCtrCoder::Init())
85 {
86   _ctrPos = 0;
87   return CAesCoder::Init();
88 }
89 */
90 
Z7_COM7F_IMF2(UInt32,CAesCtrCoder::Filter (Byte * data,UInt32 size))91 Z7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size))
92 {
93   if (!_keyIsSet)
94     return 0;
95   if (size == 0)
96     return 0;
97 
98   if (_ctrPos != 0)
99   {
100     /* Optimized caller will not call here */
101     const Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS);
102     unsigned num = 0;
103     for (unsigned i = _ctrPos; i != AES_BLOCK_SIZE; i++)
104     {
105       if (num == size)
106       {
107         _ctrPos = i;
108         return num;
109       }
110       data[num++] ^= ctr[i];
111     }
112     _ctrPos = 0;
113     /* if (num < size) {
114        we can filter more data with _codeFunc().
115        But it's supposed that the caller can work correctly,
116        even if we do only partial filtering here.
117        So we filter data only for current 16-byte block. }
118     */
119     /*
120     size -= num;
121     size >>= 4;
122     // (data) must be aligned for 16-bytes here
123     _codeFunc(Aes(), data + num, size);
124     return num + (size << 4);
125     */
126     return num;
127   }
128 
129   if (size < AES_BLOCK_SIZE)
130   {
131     /* The good optimized caller can call here only in last Filter() call.
132        But we support also non-optimized callers,
133        where another Filter() calls are allowed after this call.
134     */
135     Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS);
136     memset(ctr, 0, AES_BLOCK_SIZE);
137     memcpy(ctr, data, size);
138     _codeFunc(Aes(), ctr, 1);
139     memcpy(data, ctr, size);
140     _ctrPos = size;
141     return size;
142   }
143 
144   size >>= 4;
145   // (data) must be aligned for 16-bytes here
146   _codeFunc(Aes(), data, size);
147   return size << 4;
148 }
149 
150 #endif // Z7_SFX
151 
152 
153 #ifndef Z7_EXTRACT_ONLY
154 
155 #ifdef MY_CPU_X86_OR_AMD64
156   #define USE_HW_AES
157 #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
158 
159   #if   defined(__ARM_FEATURE_AES) \
160      || defined(__ARM_FEATURE_CRYPTO)
161     #define USE_HW_AES
162   #else
163     #if  defined(MY_CPU_ARM64) \
164       || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
165       || defined(Z7_MSC_VER_ORIGINAL)
166     #if  defined(__ARM_FP) && \
167           (   defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
168            || defined(__GNUC__) && (__GNUC__ >= 6) \
169           ) \
170       || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
171     #if  defined(MY_CPU_ARM64) \
172       || !defined(Z7_CLANG_VERSION) \
173       || defined(__ARM_NEON) && \
174           (Z7_CLANG_VERSION < 170000 || \
175            Z7_CLANG_VERSION > 170001)
176       #define USE_HW_AES
177     #endif
178     #endif
179     #endif
180   #endif
181 #endif
182 
183 #ifdef USE_HW_AES
184 // #pragma message("=== MyAES.c USE_HW_AES === ")
185 
186     #define SET_AES_FUNC_2(f2) \
187       if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \
188       { f = f2; }
189   #ifdef MY_CPU_X86_OR_AMD64
190     #define SET_AES_FUNC_23(f2, f3) \
191       SET_AES_FUNC_2(f2) \
192       if (algo == 3) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) \
193       { f = f3; }
194   #else  // MY_CPU_X86_OR_AMD64
195     #define SET_AES_FUNC_23(f2, f3) \
196       SET_AES_FUNC_2(f2)
197   #endif // MY_CPU_X86_OR_AMD64
198 #else  // USE_HW_AES
199     #define SET_AES_FUNC_23(f2, f3)
200 #endif // USE_HW_AES
201 
202 #define SET_AES_FUNCS(c, f0, f1, f2, f3) \
203   bool c::SetFunctions(UInt32 algo) { \
204   _codeFunc = f0; if (algo < 1) return true; \
205   AES_CODE_FUNC f = NULL; \
206   if (algo == 1) { f = f1; } \
207   SET_AES_FUNC_23(f2, f3) \
208   if (f) { _codeFunc = f; return true; } \
209   return false; }
210 
211 
212 
213 #ifndef Z7_SFX
SET_AES_FUNCS(CAesCtrCoder,g_AesCtr_Code,AesCtr_Code,AesCtr_Code_HW,AesCtr_Code_HW_256)214 SET_AES_FUNCS(
215     CAesCtrCoder,
216   g_AesCtr_Code,
217     AesCtr_Code,
218     AesCtr_Code_HW,
219     AesCtr_Code_HW_256)
220 #endif
221 
222 SET_AES_FUNCS(
223     CAesCbcEncoder,
224   g_AesCbc_Encode,
225     AesCbc_Encode,
226     AesCbc_Encode_HW,
227     AesCbc_Encode_HW)
228 
229 SET_AES_FUNCS(
230     CAesCbcDecoder,
231   g_AesCbc_Decode,
232     AesCbc_Decode,
233     AesCbc_Decode_HW,
234     AesCbc_Decode_HW_256)
235 
236 Z7_COM7F_IMF(CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
237 {
238   UInt32 algo = 0;
239   for (UInt32 i = 0; i < numProps; i++)
240   {
241     if (propIDs[i] == NCoderPropID::kDefaultProp)
242     {
243       const PROPVARIANT &prop = coderProps[i];
244       if (prop.vt != VT_UI4)
245         return E_INVALIDARG;
246       if (prop.ulVal > 3)
247         return E_NOTIMPL;
248       algo = prop.ulVal;
249     }
250   }
251   if (!SetFunctions(algo))
252     return E_NOTIMPL;
253   return S_OK;
254 }
255 
256 #endif // Z7_EXTRACT_ONLY
257 
258 }
259