/src/SymCrypt/lib/xtsaes.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // xtsaes.c code for XTS-AES implementation |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | #include "precomp.h" |
8 | | |
9 | | SYMCRYPT_ERROR |
10 | | SYMCRYPT_CALL |
11 | | SymCryptXtsAesExpandKey( |
12 | | _Out_ PSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
13 | | _In_reads_( cbKey ) PCBYTE pbKey, |
14 | | SIZE_T cbKey ) |
15 | 0 | { |
16 | 0 | SYMCRYPT_ERROR scError; |
17 | 0 | SIZE_T halfKeySize = cbKey / 2; |
18 | |
|
19 | 0 | scError = SymCryptAesExpandKey( &pExpandedKey->key1, pbKey, halfKeySize ); |
20 | 0 | if( scError != SYMCRYPT_NO_ERROR ) |
21 | 0 | { |
22 | 0 | goto cleanup; |
23 | 0 | } |
24 | | |
25 | | // |
26 | | // Pass the 'rest' of the key to the second one. This catches errors such as |
27 | | // an attempt to pass a 33 byte key. |
28 | | // halfKeySize = 16, which is valid, but this expansion gets a 17-byte key which will fail. |
29 | | // Key2 is only used for tweak encryption, so we can use the EncryptOnly key expansion. |
30 | | // |
31 | 0 | scError = SymCryptAesExpandKeyEncryptOnly( &pExpandedKey->key2, pbKey + halfKeySize, cbKey - halfKeySize ); |
32 | 0 | if( scError != SYMCRYPT_NO_ERROR ) |
33 | 0 | { |
34 | 0 | goto cleanup; |
35 | 0 | } |
36 | | |
37 | 0 | cleanup: |
38 | |
|
39 | 0 | return scError; |
40 | 0 | } |
41 | | |
42 | | SYMCRYPT_ERROR |
43 | | SYMCRYPT_CALL |
44 | | SymCryptXtsAesExpandKeyEx( |
45 | | _Out_ PSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
46 | | _In_reads_( cbKey ) PCBYTE pbKey, |
47 | | SIZE_T cbKey, |
48 | | UINT32 flags ) |
49 | 0 | { |
50 | 0 | if( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) |
51 | 0 | { |
52 | | // FIPS IG C.I enforces that the two AES keys internally used in XTS-AES are non-equal |
53 | 0 | if( cbKey > 64 ) |
54 | 0 | { |
55 | 0 | return SYMCRYPT_WRONG_KEY_SIZE; |
56 | 0 | } |
57 | 0 | if( SymCryptEqual( pbKey, pbKey+(cbKey/2), (cbKey/2) ) ) |
58 | 0 | { |
59 | 0 | return SYMCRYPT_FIPS_FAILURE; |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | 0 | return SymCryptXtsAesExpandKey( pExpandedKey, pbKey, cbKey ); |
64 | 0 | } |
65 | | |
66 | | |
67 | | VOID |
68 | | SYMCRYPT_CALL |
69 | | SymCryptXtsAesKeyCopy( |
70 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pSrc, |
71 | | _Out_ PSYMCRYPT_XTS_AES_EXPANDED_KEY pDst ) |
72 | 0 | { |
73 | 0 | SymCryptAesKeyCopy( &pSrc->key1, &pDst->key1 ); |
74 | 0 | SymCryptAesKeyCopy( &pSrc->key2, &pDst->key2 ); |
75 | 0 | } |
76 | | |
77 | 0 | #define N_PARALLEL_TWEAKS 16 |
78 | | |
79 | | #define SYMCRYPT_XTS_AES_LOCALSCRATCH_DEFN \ |
80 | 0 | SYMCRYPT_ALIGN BYTE localScratch[N_PARALLEL_TWEAKS * SYMCRYPT_AES_BLOCK_SIZE]; |
81 | | |
82 | 0 | #define SYMCRYPT_AesEcbEncryptXxx SymCryptAesEcbEncryptC |
83 | | |
84 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalC |
85 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
86 | 0 | SymCryptXtsAesEncryptDataUnitC( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
87 | | #include "xtsaes_pattern.c" |
88 | | #undef SYMCRYPT_XtsAesXxx |
89 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
90 | | |
91 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalC |
92 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
93 | 0 | SymCryptXtsAesDecryptDataUnitC( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
94 | | #include "xtsaes_pattern.c" |
95 | | #undef SYMCRYPT_XtsAesXxx |
96 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
97 | | |
98 | | #undef SYMCRYPT_AesEcbEncryptXxx |
99 | | |
100 | | |
101 | | #if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM |
102 | 0 | #define SYMCRYPT_AesEcbEncryptXxx SymCryptAesEcbEncryptAsm |
103 | | |
104 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalAsm |
105 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
106 | 0 | SymCryptXtsAesEncryptDataUnitAsm( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
107 | | #include "xtsaes_pattern.c" |
108 | | #undef SYMCRYPT_XtsAesXxx |
109 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
110 | | |
111 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalAsm |
112 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
113 | 0 | SymCryptXtsAesDecryptDataUnitAsm( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
114 | | #include "xtsaes_pattern.c" |
115 | | #undef SYMCRYPT_XtsAesXxx |
116 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
117 | | |
118 | | #undef SYMCRYPT_AesEcbEncryptXxx |
119 | | #endif |
120 | | |
121 | | #if SYMCRYPT_CPU_ARM64 |
122 | | #define SYMCRYPT_AesEcbEncryptXxx SymCryptAesEcbEncryptNeon |
123 | | |
124 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalNeon |
125 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
126 | | SymCryptXtsAesEncryptDataUnitNeon( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
127 | | #include "xtsaes_pattern.c" |
128 | | #undef SYMCRYPT_XtsAesXxx |
129 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
130 | | |
131 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalNeon |
132 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
133 | | SymCryptXtsAesDecryptDataUnitNeon( &pExpandedKey->key1, &tweakBuf[i], pbSrc, pbDst, cbDataUnit ); |
134 | | #include "xtsaes_pattern.c" |
135 | | #undef SYMCRYPT_XtsAesXxx |
136 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
137 | | |
138 | | #undef SYMCRYPT_AesEcbEncryptXxx |
139 | | #endif |
140 | | |
141 | | #undef SYMCRYPT_XTS_AES_LOCALSCRATCH_DEFN |
142 | | |
143 | | |
144 | | #if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 |
145 | | |
146 | | #define SYMCRYPT_XTS_AES_LOCALSCRATCH_DEFN \ |
147 | | /* Defining localScratch as a buffer of __m128is ensures there is required 16B alignment on x86 */ \ |
148 | 0 | __m128i localScratch[ N_PARALLEL_TWEAKS + 16 ]; |
149 | 0 | #define SYMCRYPT_AesEcbEncryptXxx SymCryptAesEcbEncryptXmm |
150 | | |
151 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalXmm |
152 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
153 | 0 | SymCryptXtsAesEncryptDataUnitXmm( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
154 | | #include "xtsaes_pattern.c" |
155 | | #undef SYMCRYPT_XtsAesXxx |
156 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
157 | | |
158 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalXmm |
159 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
160 | 0 | SymCryptXtsAesDecryptDataUnitXmm( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
161 | | #include "xtsaes_pattern.c" |
162 | | #undef SYMCRYPT_XtsAesXxx |
163 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
164 | | |
165 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalYmm |
166 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
167 | 0 | SymCryptXtsAesEncryptDataUnitYmm_2048( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
168 | | #include "xtsaes_pattern.c" |
169 | | #undef SYMCRYPT_XtsAesXxx |
170 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
171 | | |
172 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalYmm |
173 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
174 | 0 | SymCryptXtsAesDecryptDataUnitYmm_2048( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
175 | | #include "xtsaes_pattern.c" |
176 | | #undef SYMCRYPT_XtsAesXxx |
177 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
178 | | |
179 | | #if 0 //do not compile Zmm code for now |
180 | | |
181 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesEncryptInternalZmm |
182 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
183 | | SymCryptXtsAesEncryptDataUnitZmm_2048( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
184 | | #include "xtsaes_pattern.c" |
185 | | #undef SYMCRYPT_XtsAesXxx |
186 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
187 | | |
188 | | #define SYMCRYPT_XtsAesXxx SymCryptXtsAesDecryptInternalZmm |
189 | | #define SYMCRYPT_XTSAESDATAUNIT_INVOKE \ |
190 | | SymCryptXtsAesDecryptDataUnitZmm_2048( &pExpandedKey->key1, &tweakBuf[i], (PBYTE) &localScratch[N_PARALLEL_TWEAKS], pbSrc, pbDst, cbDataUnit ); |
191 | | #include "xtsaes_pattern.c" |
192 | | #undef SYMCRYPT_XtsAesXxx |
193 | | #undef SYMCRYPT_XTSAESDATAUNIT_INVOKE |
194 | | |
195 | | #endif |
196 | | |
197 | | #undef SYMCRYPT_XTS_AES_LOCALSCRATCH_DEFN |
198 | | #undef SYMCRYPT_AesEcbEncryptXxx |
199 | | |
200 | | #endif |
201 | | |
202 | | VOID |
203 | | SYMCRYPT_CALL |
204 | | SymCryptXtsAesEncryptInternal( |
205 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
206 | | SIZE_T cbDataUnit, |
207 | | _In_reads_( SYMCRYPT_AES_BLOCK_SIZE ) PCBYTE pbTweak, |
208 | | _In_reads_( cbData ) PCBYTE pbSrc, |
209 | | _Out_writes_( cbData ) PBYTE pbDst, |
210 | | SIZE_T cbData, |
211 | | BOOLEAN bOverflow ) |
212 | 0 | { |
213 | 0 | #if SYMCRYPT_CPU_AMD64 |
214 | 0 | SYMCRYPT_EXTENDED_SAVE_DATA SaveData; |
215 | | /* if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_512_CODE ) ) { |
216 | | SymCryptXtsAesEncryptInternalZmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
217 | | } else */ |
218 | 0 | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_256_CODE ) && |
219 | 0 | SymCryptSaveYmm( &SaveData ) == SYMCRYPT_NO_ERROR ) |
220 | 0 | { |
221 | 0 | SymCryptXtsAesEncryptInternalYmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
222 | 0 | SymCryptRestoreYmm( &SaveData ); |
223 | 0 | } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) ) { |
224 | 0 | SymCryptXtsAesEncryptInternalXmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
225 | 0 | } else { |
226 | 0 | SymCryptXtsAesEncryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
227 | 0 | } |
228 | | #elif SYMCRYPT_CPU_X86 |
229 | | SYMCRYPT_EXTENDED_SAVE_DATA SaveData; |
230 | | |
231 | | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) && |
232 | | SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR ) |
233 | | { |
234 | | SymCryptXtsAesEncryptInternalXmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
235 | | SymCryptRestoreXmm( &SaveData ); |
236 | | } else { |
237 | | SymCryptXtsAesEncryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
238 | | } |
239 | | #elif SYMCRYPT_CPU_ARM |
240 | | SymCryptXtsAesEncryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
241 | | #elif SYMCRYPT_CPU_ARM64 |
242 | | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) ) |
243 | | { |
244 | | SymCryptXtsAesEncryptInternalNeon( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
245 | | } else { |
246 | | SymCryptXtsAesEncryptInternalC( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
247 | | } |
248 | | #else |
249 | | SymCryptXtsAesEncryptInternalC( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
250 | | #endif |
251 | 0 | } |
252 | | |
253 | | VOID |
254 | | SYMCRYPT_CALL |
255 | | SymCryptXtsAesEncrypt( |
256 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
257 | | SIZE_T cbDataUnit, |
258 | | UINT64 tweak, |
259 | | _In_reads_( cbData ) PCBYTE pbSrc, |
260 | | _Out_writes_( cbData ) PBYTE pbDst, |
261 | | SIZE_T cbData ) |
262 | 0 | { |
263 | 0 | SYMCRYPT_ALIGN BYTE fullTweak[SYMCRYPT_AES_BLOCK_SIZE]; |
264 | |
|
265 | 0 | SYMCRYPT_ASSERT( cbData % cbDataUnit == 0 ); |
266 | | |
267 | 0 | if( cbDataUnit < SYMCRYPT_AES_BLOCK_SIZE ) |
268 | 0 | { |
269 | | // Invalid data unit size |
270 | | // Return early to avoid repeated checks deeper in the code |
271 | 0 | return; |
272 | 0 | } |
273 | | |
274 | 0 | SYMCRYPT_STORE_LSBFIRST64(&fullTweak[0], tweak); |
275 | 0 | SYMCRYPT_STORE_LSBFIRST64(&fullTweak[8], 0); |
276 | |
|
277 | 0 | SymCryptXtsAesEncryptInternal( pExpandedKey, cbDataUnit, &fullTweak[0], pbSrc, pbDst, cbData, FALSE ); |
278 | 0 | } |
279 | | |
280 | | VOID |
281 | | SYMCRYPT_CALL |
282 | | SymCryptXtsAesEncryptWith128bTweak( |
283 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
284 | | SIZE_T cbDataUnit, |
285 | | _In_reads_( SYMCRYPT_AES_BLOCK_SIZE ) PCBYTE pbTweak, |
286 | | _In_reads_( cbData ) PCBYTE pbSrc, |
287 | | _Out_writes_( cbData ) PBYTE pbDst, |
288 | | SIZE_T cbData ) |
289 | 0 | { |
290 | 0 | if( cbDataUnit < SYMCRYPT_AES_BLOCK_SIZE ) |
291 | 0 | { |
292 | | // Invalid data unit size |
293 | | // Return early to avoid repeated checks deeper in the code |
294 | 0 | return; |
295 | 0 | } |
296 | | |
297 | 0 | SymCryptXtsAesEncryptInternal( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, TRUE ); |
298 | 0 | } |
299 | | |
300 | | |
301 | | VOID |
302 | | SYMCRYPT_CALL |
303 | | SymCryptXtsAesDecryptInternal( |
304 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
305 | | SIZE_T cbDataUnit, |
306 | | _In_reads_( SYMCRYPT_AES_BLOCK_SIZE ) PCBYTE pbTweak, |
307 | | _In_reads_( cbData ) PCBYTE pbSrc, |
308 | | _Out_writes_( cbData ) PBYTE pbDst, |
309 | | SIZE_T cbData, |
310 | | BOOLEAN bOverflow ) |
311 | 0 | { |
312 | 0 | #if SYMCRYPT_CPU_AMD64 |
313 | 0 | SYMCRYPT_EXTENDED_SAVE_DATA SaveData; |
314 | | /* if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_512_CODE ) ) { |
315 | | SymCryptXtsAesDecryptInternalZmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
316 | | } else */ |
317 | 0 | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_256_CODE ) && |
318 | 0 | SymCryptSaveYmm( &SaveData ) == SYMCRYPT_NO_ERROR ) |
319 | 0 | { |
320 | 0 | SymCryptXtsAesDecryptInternalYmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
321 | 0 | SymCryptRestoreYmm( &SaveData ); |
322 | 0 | } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) ) { |
323 | 0 | SymCryptXtsAesDecryptInternalXmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
324 | 0 | } else { |
325 | 0 | SymCryptXtsAesDecryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
326 | 0 | } |
327 | | #elif SYMCRYPT_CPU_X86 |
328 | | SYMCRYPT_EXTENDED_SAVE_DATA SaveData; |
329 | | |
330 | | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) && |
331 | | SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR ) |
332 | | { |
333 | | SymCryptXtsAesDecryptInternalXmm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
334 | | SymCryptRestoreXmm( &SaveData ); |
335 | | } else { |
336 | | SymCryptXtsAesDecryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
337 | | } |
338 | | #elif SYMCRYPT_CPU_ARM |
339 | | SymCryptXtsAesDecryptInternalAsm( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
340 | | #elif SYMCRYPT_CPU_ARM64 |
341 | | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) ) |
342 | | { |
343 | | SymCryptXtsAesDecryptInternalNeon( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
344 | | } else { |
345 | | SymCryptXtsAesDecryptInternalC( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
346 | | } |
347 | | #else |
348 | | SymCryptXtsAesDecryptInternalC( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, bOverflow ); |
349 | | #endif |
350 | 0 | } |
351 | | |
352 | | VOID |
353 | | SYMCRYPT_CALL |
354 | | SymCryptXtsAesDecrypt( |
355 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
356 | | SIZE_T cbDataUnit, |
357 | | UINT64 tweak, |
358 | | _In_reads_( cbData ) PCBYTE pbSrc, |
359 | | _Out_writes_( cbData ) PBYTE pbDst, |
360 | | SIZE_T cbData ) |
361 | 0 | { |
362 | 0 | SYMCRYPT_ALIGN BYTE fullTweak[SYMCRYPT_AES_BLOCK_SIZE]; |
363 | |
|
364 | 0 | SYMCRYPT_ASSERT( cbData % cbDataUnit == 0 ); |
365 | |
|
366 | 0 | if( cbDataUnit < SYMCRYPT_AES_BLOCK_SIZE ) |
367 | 0 | { |
368 | | // Invalid data unit size |
369 | | // Return early to avoid repeated checks deeper in the code |
370 | 0 | return; |
371 | 0 | } |
372 | | |
373 | 0 | SYMCRYPT_STORE_LSBFIRST64(&fullTweak[0], tweak); |
374 | 0 | SYMCRYPT_STORE_LSBFIRST64(&fullTweak[8], 0); |
375 | |
|
376 | 0 | SymCryptXtsAesDecryptInternal( pExpandedKey, cbDataUnit, &fullTweak[0], pbSrc, pbDst, cbData, FALSE ); |
377 | 0 | } |
378 | | |
379 | | VOID |
380 | | SYMCRYPT_CALL |
381 | | SymCryptXtsAesDecryptWith128bTweak( |
382 | | _In_ PCSYMCRYPT_XTS_AES_EXPANDED_KEY pExpandedKey, |
383 | | SIZE_T cbDataUnit, |
384 | | _In_reads_( SYMCRYPT_AES_BLOCK_SIZE ) PCBYTE pbTweak, |
385 | | _In_reads_( cbData ) PCBYTE pbSrc, |
386 | | _Out_writes_( cbData ) PBYTE pbDst, |
387 | | SIZE_T cbData ) |
388 | 0 | { |
389 | 0 | if( cbDataUnit < SYMCRYPT_AES_BLOCK_SIZE ) |
390 | 0 | { |
391 | | // Invalid data unit size |
392 | | // Return early to avoid repeated checks deeper in the code |
393 | 0 | return; |
394 | 0 | } |
395 | | |
396 | 0 | SymCryptXtsAesDecryptInternal( pExpandedKey, cbDataUnit, pbTweak, pbSrc, pbDst, cbData, TRUE ); |
397 | 0 | } |
398 | | |
399 | | VOID |
400 | | SYMCRYPT_CALL |
401 | | SymCryptXtsUpdateTweak( |
402 | | _Inout_updates_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE buf ) |
403 | 0 | { |
404 | | /* |
405 | | UINT32 b0 = LOAD_LSBFIRST32( buf ); |
406 | | UINT32 b1 = LOAD_LSBFIRST32( buf + 4 ); |
407 | | UINT32 b2 = LOAD_LSBFIRST32( buf + 8 ); |
408 | | UINT32 b3 = LOAD_LSBFIRST32( buf + 12 ); |
409 | | UINT32 msbit = b3 >> 31; |
410 | | |
411 | | // |
412 | | // The STORE_* macros re-evaluate their arguments sometimes, so we |
413 | | // keep all computations in local variables. |
414 | | // |
415 | | UINT32 r0 = (b0 << 1) ^ (135 * msbit); |
416 | | UINT32 r1 = (b1 << 1) | (b0 >> 31); |
417 | | UINT32 r2 = (b2 << 1) | (b1 >> 31); |
418 | | UINT32 r3 = (b3 << 1) | (b2 >> 31); |
419 | | |
420 | | STORE_LSBFIRST32( buf , r0 ); |
421 | | STORE_LSBFIRST32( buf + 4, r1 ); |
422 | | STORE_LSBFIRST32( buf + 8, r2 ); |
423 | | STORE_LSBFIRST32( buf + 12, r3 ); |
424 | | */ |
425 | 0 | UINT64 b0 = SYMCRYPT_LOAD_LSBFIRST64( buf ); |
426 | 0 | UINT64 b1 = SYMCRYPT_LOAD_LSBFIRST64( buf + 8 ); |
427 | | |
428 | | /* |
429 | | UINT32 msbit = (UINT32)(b1 >> 63); |
430 | | //UINT32 feedback = 135 * msbit; |
431 | | UINT32 feedback = (msbit << 7) + (msbit << 3) - msbit; |
432 | | */ |
433 | 0 | UINT32 feedback = (((INT64)b1) >> 63) & 135; |
434 | |
|
435 | 0 | UINT64 r0 = (b0 << 1) ^ feedback; |
436 | 0 | UINT64 r1 = (b1 << 1) | (b0 >> 63); |
437 | |
|
438 | 0 | SYMCRYPT_STORE_LSBFIRST64( buf , r0 ); |
439 | 0 | SYMCRYPT_STORE_LSBFIRST64( buf + 8, r1 ); |
440 | 0 | } |
441 | | |
442 | | VOID |
443 | | SYMCRYPT_CALL |
444 | | SymCryptXtsEncryptDataUnit( |
445 | | _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, |
446 | | _In_ PCVOID pExpandedKey, |
447 | | _Inout_updates_( pBlockCipher->blockSize ) PBYTE pbTweakBlock, |
448 | | _In_reads_( cbData ) PCBYTE pbSrc, |
449 | | _Out_writes_( cbData ) PBYTE pbDst, |
450 | | SIZE_T cbData ) |
451 | 0 | { |
452 | 0 | BYTE buf[2*SYMCRYPT_AES_BLOCK_SIZE]; |
453 | |
|
454 | 0 | while( cbData >= 2*SYMCRYPT_AES_BLOCK_SIZE ) |
455 | 0 | { |
456 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
457 | 0 | (*pBlockCipher->encryptFunc)( pExpandedKey, buf, buf ); |
458 | 0 | SymCryptXorBytes( pbTweakBlock, buf, pbDst, SYMCRYPT_AES_BLOCK_SIZE ); |
459 | |
|
460 | 0 | SYMCRYPT_ASSERT( pBlockCipher->blockSize == SYMCRYPT_AES_BLOCK_SIZE ); |
461 | 0 | SymCryptXtsUpdateTweak( pbTweakBlock ); |
462 | |
|
463 | 0 | pbSrc += SYMCRYPT_AES_BLOCK_SIZE; |
464 | 0 | pbDst += SYMCRYPT_AES_BLOCK_SIZE; |
465 | 0 | cbData -= SYMCRYPT_AES_BLOCK_SIZE; |
466 | 0 | } |
467 | |
|
468 | 0 | if( cbData > SYMCRYPT_AES_BLOCK_SIZE ) |
469 | 0 | { |
470 | | // Ciphertext stealing encryption |
471 | | // |
472 | | // +--------------+ |
473 | | // | | |
474 | | // | V |
475 | | // +-----------------+ | +-----+-----------+ |
476 | | // | P_m-1 | | | P_m |++++CP+++++| |
477 | | // +-----------------+ | +-----+-----------+ |
478 | | // | | | |
479 | | // enc_m-1 | enc_m |
480 | | // | | | |
481 | | // V | V |
482 | | // +-----+-----------+ | +-----------------+ |
483 | | // | C_m |++++CP+++++|--+ | C_m-1 | |
484 | | // +-----+-----------+ +-----------------+ |
485 | | // | / |
486 | | // +---------------- / --+ |
487 | | // / | |
488 | | // | V |
489 | | // +-----------------+ | +-----+ |
490 | | // | C_m-1 |<-+ | C_m | |
491 | | // +-----------------+ +-----+ |
492 | | |
493 | | // Encrypt penultimate plaintext block into buf |
494 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
495 | 0 | (*pBlockCipher->encryptFunc)( pExpandedKey, buf, buf ); |
496 | 0 | SymCryptXorBytes( pbTweakBlock, buf, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
497 | |
|
498 | 0 | cbData -= SYMCRYPT_AES_BLOCK_SIZE; |
499 | | |
500 | | // Copy buf to buf[SYMCRYPT_AES_BLOCK_SIZE] |
501 | 0 | memcpy( &buf[SYMCRYPT_AES_BLOCK_SIZE], buf, SYMCRYPT_AES_BLOCK_SIZE ); |
502 | | // Copy final plaintext bytes to prefix of buf - we must read before writing to support in-place encryption |
503 | 0 | memcpy( buf, pbSrc + SYMCRYPT_AES_BLOCK_SIZE, cbData ); |
504 | | // Copy prefix of buf[SYMCRYPT_AES_BLOCK_SIZE] to the right place in the destination buffer |
505 | 0 | memcpy( pbDst + SYMCRYPT_AES_BLOCK_SIZE, &buf[SYMCRYPT_AES_BLOCK_SIZE], cbData ); |
506 | | |
507 | | // Do final tweak update |
508 | 0 | SymCryptXtsUpdateTweak( pbTweakBlock ); |
509 | | |
510 | | // Set pbSrc correctly to share code with non-ciphertext stealing case |
511 | 0 | pbSrc = &buf[0]; |
512 | 0 | } |
513 | | |
514 | | // Final full block encryption |
515 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
516 | 0 | (*pBlockCipher->encryptFunc)( pExpandedKey, buf, buf ); |
517 | 0 | SymCryptXorBytes( pbTweakBlock, buf, pbDst, SYMCRYPT_AES_BLOCK_SIZE ); |
518 | |
|
519 | 0 | SymCryptWipeKnownSize( buf, sizeof(buf) ); |
520 | 0 | } |
521 | | |
522 | | VOID |
523 | | SYMCRYPT_CALL |
524 | | SymCryptXtsDecryptDataUnit( |
525 | | _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, |
526 | | _In_ PCVOID pExpandedKey, |
527 | | _Inout_updates_( pBlockCipher->blockSize ) PBYTE pbTweakBlock, |
528 | | _In_reads_( cbData ) PCBYTE pbSrc, |
529 | | _Out_writes_( cbData ) PBYTE pbDst, |
530 | | SIZE_T cbData ) |
531 | 0 | { |
532 | 0 | BYTE buf[2*SYMCRYPT_AES_BLOCK_SIZE]; |
533 | 0 | BYTE tweakBuf[SYMCRYPT_AES_BLOCK_SIZE]; |
534 | |
|
535 | 0 | while( cbData >= 2*SYMCRYPT_AES_BLOCK_SIZE ) |
536 | 0 | { |
537 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
538 | 0 | (*pBlockCipher->decryptFunc)( pExpandedKey, buf, buf ); |
539 | 0 | SymCryptXorBytes( pbTweakBlock, buf, pbDst, SYMCRYPT_AES_BLOCK_SIZE ); |
540 | |
|
541 | 0 | SYMCRYPT_ASSERT( pBlockCipher->blockSize == SYMCRYPT_AES_BLOCK_SIZE ); |
542 | 0 | SymCryptXtsUpdateTweak( pbTweakBlock ); |
543 | |
|
544 | 0 | pbSrc += SYMCRYPT_AES_BLOCK_SIZE; |
545 | 0 | pbDst += SYMCRYPT_AES_BLOCK_SIZE; |
546 | 0 | cbData -= SYMCRYPT_AES_BLOCK_SIZE; |
547 | 0 | } |
548 | |
|
549 | 0 | if( cbData > SYMCRYPT_AES_BLOCK_SIZE ) |
550 | 0 | { |
551 | | // Ciphertext stealing decryption |
552 | | // |
553 | | // +--------------+ |
554 | | // | | |
555 | | // | V |
556 | | // +-----------------+ | +-----+-----------+ |
557 | | // | C_m-1 | | | C_m |++++CP+++++| |
558 | | // +-----------------+ | +-----+-----------+ |
559 | | // | | | |
560 | | // dec_m | dec_m-1 |
561 | | // | | | |
562 | | // V | V |
563 | | // +-----+-----------+ | +-----------------+ |
564 | | // | P_m |++++CP+++++|--+ | P_m-1 | |
565 | | // +-----+-----------+ +-----------------+ |
566 | | // | / |
567 | | // +---------------- / --+ |
568 | | // / | |
569 | | // | V |
570 | | // +-----------------+ | +-----+ |
571 | | // | P_m-1 |<-+ | P_m | |
572 | | // +-----------------+ +-----+ |
573 | | |
574 | | // Save penultimate value of tweak to tweakBuf |
575 | 0 | memcpy( tweakBuf, pbTweakBlock, SYMCRYPT_AES_BLOCK_SIZE ); |
576 | | |
577 | | // Do final tweak update |
578 | 0 | SymCryptXtsUpdateTweak( pbTweakBlock ); |
579 | | |
580 | | // Decrypt penultimate ciphertext block into buf |
581 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
582 | 0 | (*pBlockCipher->decryptFunc)( pExpandedKey, buf, buf ); |
583 | 0 | SymCryptXorBytes( pbTweakBlock, buf, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
584 | |
|
585 | 0 | cbData -= SYMCRYPT_AES_BLOCK_SIZE; |
586 | | |
587 | | // Copy buf to buf[SYMCRYPT_AES_BLOCK_SIZE] |
588 | 0 | memcpy( &buf[SYMCRYPT_AES_BLOCK_SIZE], buf, SYMCRYPT_AES_BLOCK_SIZE ); |
589 | | // Copy final ciphertext bytes to prefix of buf - we must read before writing to support in-place decryption |
590 | 0 | memcpy( buf, pbSrc + SYMCRYPT_AES_BLOCK_SIZE, cbData ); |
591 | | // Copy prefix of buf[SYMCRYPT_AES_BLOCK_SIZE] to the right place in the destination buffer |
592 | 0 | memcpy( pbDst + SYMCRYPT_AES_BLOCK_SIZE, &buf[SYMCRYPT_AES_BLOCK_SIZE], cbData ); |
593 | | |
594 | | // Set pbSrc and pbTweakBlock correctly to share code with non-ciphertext stealing case |
595 | 0 | pbSrc = &buf[0]; |
596 | 0 | pbTweakBlock = &tweakBuf[0]; |
597 | 0 | } |
598 | | |
599 | | // Final full block decryption |
600 | 0 | SymCryptXorBytes( pbTweakBlock, pbSrc, buf, SYMCRYPT_AES_BLOCK_SIZE ); |
601 | 0 | (*pBlockCipher->decryptFunc)( pExpandedKey, buf, buf ); |
602 | 0 | SymCryptXorBytes( pbTweakBlock, buf, pbDst, SYMCRYPT_AES_BLOCK_SIZE ); |
603 | |
|
604 | 0 | SymCryptWipeKnownSize( buf, sizeof(buf) ); |
605 | 0 | SymCryptWipeKnownSize( tweakBuf, sizeof(tweakBuf) ); |
606 | 0 | } |
607 | | |
608 | | VOID |
609 | | SYMCRYPT_CALL |
610 | | SymCryptXtsAesEncryptDataUnitAsm( |
611 | | _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, |
612 | | _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbTweakBlock, |
613 | | _In_reads_( cbData ) PCBYTE pbSrc, |
614 | | _Out_writes_( cbData ) PBYTE pbDst, |
615 | | SIZE_T cbData ) |
616 | 0 | { |
617 | 0 | SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy |
618 | 0 | SymCryptXtsEncryptDataUnit( |
619 | 0 | &SymCryptAesBlockCipherNoOpt, |
620 | 0 | pExpandedKey, |
621 | 0 | pbTweakBlock, |
622 | 0 | pbSrc, |
623 | 0 | pbDst, |
624 | 0 | cbData ); |
625 | 0 | } |
626 | | |
627 | | VOID |
628 | | SYMCRYPT_CALL |
629 | | SymCryptXtsAesDecryptDataUnitAsm( |
630 | | _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, |
631 | | _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbTweakBlock, |
632 | | _In_reads_( cbData ) PCBYTE pbSrc, |
633 | | _Out_writes_( cbData ) PBYTE pbDst, |
634 | | SIZE_T cbData ) |
635 | 0 | { |
636 | 0 | SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy |
637 | 0 | SymCryptXtsDecryptDataUnit( |
638 | 0 | &SymCryptAesBlockCipherNoOpt, |
639 | 0 | pExpandedKey, |
640 | 0 | pbTweakBlock, |
641 | 0 | pbSrc, |
642 | 0 | pbDst, |
643 | 0 | cbData ); |
644 | 0 | } |
645 | | |
646 | | VOID |
647 | | SYMCRYPT_CALL |
648 | | SymCryptXtsAesEncryptDataUnitC( |
649 | | _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, |
650 | | _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbTweakBlock, |
651 | | _In_reads_( cbData ) PCBYTE pbSrc, |
652 | | _Out_writes_( cbData ) PBYTE pbDst, |
653 | | SIZE_T cbData ) |
654 | 0 | { |
655 | | // No special optimizations... |
656 | 0 | SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy |
657 | 0 | SymCryptXtsEncryptDataUnit( |
658 | 0 | &SymCryptAesBlockCipherNoOpt, |
659 | 0 | pExpandedKey, |
660 | 0 | pbTweakBlock, |
661 | 0 | pbSrc, |
662 | 0 | pbDst, |
663 | 0 | cbData ); |
664 | 0 | } |
665 | | |
666 | | VOID |
667 | | SYMCRYPT_CALL |
668 | | SymCryptXtsAesDecryptDataUnitC( |
669 | | _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, |
670 | | _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbTweakBlock, |
671 | | _In_reads_( cbData ) PCBYTE pbSrc, |
672 | | _Out_writes_( cbData ) PBYTE pbDst, |
673 | | SIZE_T cbData ) |
674 | 0 | { |
675 | 0 | SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy |
676 | 0 | SymCryptXtsDecryptDataUnit( |
677 | 0 | &SymCryptAesBlockCipherNoOpt, |
678 | 0 | pExpandedKey, |
679 | 0 | pbTweakBlock, |
680 | 0 | pbSrc, |
681 | 0 | pbDst, |
682 | 0 | cbData ); |
683 | |
|
684 | 0 | } |
685 | | |
686 | | static const BYTE SymCryptXtsAesCiphertext[32] = { |
687 | | 0xef, 0xe5, 0x8b, 0x1a, 0x0b, 0xaf, 0xc1, 0x08, |
688 | | 0xe9, 0xb7, 0x74, 0x1c, 0xcb, 0xdc, 0xf8, 0x53, |
689 | | 0x4f, 0x90, 0x55, 0x32, 0x53, 0xf6, 0x18, 0xd2, |
690 | | 0x34, 0xd5, 0xf2, 0x29, 0xf6, 0x4f, 0xd3, 0x8c, |
691 | | }; |
692 | | |
693 | | VOID |
694 | | SYMCRYPT_CALL |
695 | | SymCryptXtsAesSelftest(void) |
696 | 0 | { |
697 | 0 | SYMCRYPT_XTS_AES_EXPANDED_KEY key; |
698 | 0 | BYTE buf[32]; |
699 | 0 | BYTE plaintext[sizeof( buf )]; |
700 | |
|
701 | 0 | SymCryptWipeKnownSize( buf, sizeof( buf ) ); |
702 | 0 | buf[0] = 1; |
703 | |
|
704 | 0 | if( SymCryptXtsAesExpandKeyEx( &key, buf, sizeof( buf ), 0 ) != SYMCRYPT_NO_ERROR ) |
705 | 0 | { |
706 | 0 | SymCryptFatal( 'xtsa' ); |
707 | 0 | } |
708 | |
|
709 | 0 | SymCryptXtsAesEncrypt( &key, sizeof( buf ), 0, buf, buf, sizeof( buf ) ); |
710 | |
|
711 | 0 | SymCryptInjectError( buf, sizeof( buf ) ); |
712 | 0 | if( memcmp( buf, SymCryptXtsAesCiphertext, sizeof( buf ) ) != 0 ) |
713 | 0 | { |
714 | 0 | SymCryptFatal( 'xtsa' ); |
715 | 0 | } |
716 | |
|
717 | 0 | SymCryptXtsAesDecrypt( &key, sizeof( buf ), 0, buf, buf, sizeof( buf ) ); |
718 | |
|
719 | 0 | SymCryptInjectError( buf, sizeof( buf ) ); |
720 | |
|
721 | 0 | SymCryptWipeKnownSize( plaintext, sizeof( plaintext ) ); |
722 | 0 | plaintext[0] = 1; |
723 | 0 | if( memcmp( buf, plaintext, sizeof( buf ) ) != 0 ) |
724 | 0 | { |
725 | 0 | SymCryptFatal( 'xtsa' ); |
726 | 0 | } |
727 | 0 | } |