Coverage Report

Created: 2024-11-21 07:03

/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
}