ReactOS 0.4.17-dev-1005-g171e1de
blockciphermodes.c
Go to the documentation of this file.
1//
2// BlockCipherModes.c generic implementation of all block cipher modes
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
17{
18 SIZE_T i;
19 SIZE_T cbToDo = cbData & ~(pBlockCipher->blockSize - 1);
20
22 {
23 //
24 // Use optimized implementation if available
25 //
27 return;
28 }
29
30 //
31 // To avoid buffer overruns we truncate the work to an integral number of blocks.
32 //
33
34 for( i=0; i<cbToDo; i+= pBlockCipher->blockSize )
35 {
37 }
38}
39
40VOID
48{
49 SIZE_T i;
50 SIZE_T cbToDo = cbData & ~(pBlockCipher->blockSize - 1);
51
53 {
54 //
55 // Use optimized implementation if available
56 //
58 return;
59 }
60
61 for( i=0; i<cbToDo; i+= pBlockCipher->blockSize )
62 {
64 }
65}
66
67
68//
69// SymCryptCbcEncrypt
70//
71// Generic CBC encryption routine for block ciphers.
72// The following restrictions must be obeyed:
73// - blockSize <= 32 and must be a power of 2
74// - cbData must be a multiple of the block size
75//
76VOID
81 _Inout_updates_( pBlockCipher->blockSize )
86{
88 SIZE_T blockSize;
89 PCBYTE pbSrcEnd;
90 PCBYTE pSrc = pbSrc;
91 PBYTE pDst = pbDst;
92
94 {
95 //
96 // Use optimized implementation if available
97 //
99 return;
100 }
101
102 blockSize = pBlockCipher->blockSize;
103
105
106
107 //
108 // Compute the end of the data, rounding the size down to a multiple of the block size.
109 //
110 pbSrcEnd = &pbSrc[ cbData & ~(blockSize - 1) ];
111
112 //
113 // We keep the chaining state in a local buffer to enforce the read-once write-once rule.
114 //
115 memcpy( buf, pbChainingValue, blockSize );
116 while( pSrc < pbSrcEnd )
117 {
118 SYMCRYPT_ASSERT( pSrc <= pbSrc + cbData - blockSize ); // help PreFast
119 SYMCRYPT_ASSERT( pDst <= pbDst + cbData - blockSize ); // help PreFast
120 SYMCRYPT_ASSERT( blockSize <= cbData ); // help PreFast
121 SymCryptXorBytes( pSrc, buf, buf, blockSize );
123 memcpy( pDst, buf, blockSize );
124 pSrc += blockSize;
125 pDst += blockSize;
126 }
127
128 memcpy( pbChainingValue, buf, blockSize );
129
130 SymCryptWipeKnownSize( buf, sizeof( buf ));
131}
132
133//
134// SymCryptCbcDecrypt
135//
136// Generic CBC decryption routine for block ciphers.
137// The following restrictions must be obeyed:
138// - blockSize <= 32 and must be a power of 2
139// - cbData must be a multiple of the block size
140//
141VOID
146 _Inout_updates_( pBlockCipher->blockSize )
150 SIZE_T cbData )
151{
153 PBYTE chain = &buf[0];
154 PBYTE ciphertext = &buf[SYMCRYPT_MAX_BLOCK_SIZE];
156
157 SIZE_T blockSize;
158 PCBYTE pbSrcEnd;
159
161 {
163 return;
164 }
165
166 blockSize = pBlockCipher->blockSize;
168
169 //
170 // Compute the end of the data, rounding the size down to a multiple of the block size.
171 //
172 pbSrcEnd = &pbSrc[ cbData & ~(blockSize-1) ];
173
174#pragma warning(suppress: 22105)
175 memcpy( chain, pbChainingValue, blockSize );
176
177 //
178 // Loop structured to obey the read-once/write-once rule
179 //
180 while( pbSrc < pbSrcEnd )
181 {
182 SYMCRYPT_ASSERT( pbSrc <= pbSrcEnd - blockSize ); // help PreFast
183 memcpy( ciphertext, pbSrc, blockSize );
184 (*pBlockCipher->decryptFunc)( pExpandedKey, ciphertext, tmp );
185 SymCryptXorBytes( tmp, chain, pbDst, blockSize );
186 memcpy( chain, ciphertext, blockSize );
187 pbDst += blockSize;
188 pbSrc += blockSize;
189 }
190
191 memcpy( pbChainingValue, chain, blockSize );
192
193 SymCryptWipeKnownSize( buf, sizeof( buf ));
194}
195
196VOID
201 _Inout_updates_( pBlockCipher->blockSize )
204 SIZE_T cbData )
205{
207 SIZE_T blockSize;
208 PCBYTE pbSrcEnd;
209 PCBYTE p;
210
212 {
213 //
214 // Use optimized implementation if available
215 //
217 return;
218 }
219
220 blockSize = pBlockCipher->blockSize;
222
223 //
224 // Compute the end of the data, rounding the size down to a multiple of the block size.
225 //
226 pbSrcEnd = &pbSrc[ cbData & ~(blockSize - 1) ];
227
228 //
229 // We keep the chaining state in a local buffer to enforce the read-once write-once rule.
230 // It also improves memory locality.
231 //
232 memcpy( buf, pbChainingValue, blockSize );
233 p = pbSrc;
234 while( p < pbSrcEnd )
235 {
236 SYMCRYPT_ASSERT( p <= pbSrc + cbData - blockSize );
237 SymCryptXorBytes( p, buf, buf, blockSize );
239 p += blockSize;
240 }
241
242 memcpy( pbChainingValue, buf, blockSize );
243
244 SymCryptWipeKnownSize( buf, sizeof( buf ));
245}
246
247VOID
252 _Inout_updates_( pBlockCipher->blockSize )
256 SIZE_T cbData )
257{
259 PBYTE count = &buf[0];
261 SIZE_T blockSize;
262 PCBYTE pbSrcEnd;
263
264 blockSize = pBlockCipher->blockSize;
266
267 //
268 // Compute the end of the data, rounding the size down to a multiple of the block size.
269 //
270 pbSrcEnd = &pbSrc[ cbData & ~(blockSize - 1) ];
271
272 //
273 // We keep the chaining state in a local buffer to enforce the read-once write-once rule.
274 // It also improves memory locality.
275 //
276 #pragma warning(suppress: 22105)
277 memcpy( count, pbChainingValue, blockSize );
278 while( pbSrc < pbSrcEnd )
279 {
280 SYMCRYPT_ASSERT( pbSrc <= pbSrcEnd - blockSize ); // help PreFast
282 SymCryptXorBytes( keystream, pbSrc, pbDst, blockSize );
283
284 //
285 // We only need to increment the last 32 bits of the counter value.
286 //
287 SYMCRYPT_STORE_MSBFIRST32( &count[ blockSize-4 ], 1 + SYMCRYPT_LOAD_MSBFIRST32( &count[ blockSize-4 ] ) );
288
289 pbSrc += blockSize;
290 pbDst += blockSize;
291 }
292
293 memcpy( pbChainingValue, count, blockSize );
294
295 SymCryptWipeKnownSize( buf, sizeof( buf ));
296}
297
298VOID
303 _Inout_updates_( pBlockCipher->blockSize )
307 SIZE_T cbData )
308{
310 PBYTE count = &buf[0];
312 SIZE_T blockSize;
313 PCBYTE pbSrcEnd;
314
316 {
317 //
318 // Use optimized implementation if available
319 //
321 return;
322 }
323
324 blockSize = pBlockCipher->blockSize;
326
327 //
328 // Compute the end of the data, rounding the size down to a multiple of the block size.
329 //
330 pbSrcEnd = &pbSrc[ cbData & ~(blockSize - 1) ];
331
332 //
333 // We keep the chaining state in a local buffer to enforce the read-once write-once rule.
334 // It also improves memory locality.
335 //
336 #pragma warning(suppress: 22105)
337 memcpy( count, pbChainingValue, blockSize );
338 while( pbSrc < pbSrcEnd )
339 {
340 SYMCRYPT_ASSERT( pbSrc <= pbSrcEnd - blockSize ); // help PreFast
342 SymCryptXorBytes( keystream, pbSrc, pbDst, blockSize );
343
344 //
345 // We only need to increment the last 64 bits of the counter value.
346 //
347 SYMCRYPT_STORE_MSBFIRST64( &count[ blockSize-8 ], 1 + SYMCRYPT_LOAD_MSBFIRST64( &count[ blockSize-8 ] ) );
348
349 pbSrc += blockSize;
350 pbDst += blockSize;
351 }
352
353 memcpy( pbChainingValue, count, blockSize );
354
355 SymCryptWipeKnownSize( buf, sizeof( buf ));
356}
357
358VOID
362 SIZE_T cbShift,
364 _Inout_updates_( pBlockCipher->blockSize )
368 SIZE_T cbData )
369//
370// Encrypt a buffer using the CFB cipher mode.
371//
372// This implements the CFB mode using a 1-byte feedback shift.
373// This requires a block cipher encryption call for each byte, which is very slow.
374// Use of this cipher mode is not recommended.
375//
376// - pBlockCipher is a pointer to the block cipher description table.
377// Suitable description tables for all ciphers in this library have been pre-defined.
378// - pExpandedKey points to the expanded key to use. This generic function uses PVOID so there
379// is no type safety to ensure that the expanded key and the encryption function match.
380// - pbChainingValue points to the chaining value. On entry and exit it
381// contains the last blockSize ciphertext bytes.
382// - pbSrc is the input data buffer that will be encrypted/decrypted.
383// - cbData. Number of bytes to encrypt/decrypt. This must be a multiple of the block size.
384// - pbDst is the output buffer that receives the encrypted/decrypted data. The input and output
385// buffers may be the same or non-overlapping, but may not partially overlap.
386//
387{
389 PBYTE chain = &buf[0];
391 SIZE_T blockSize;
392
393 blockSize = pBlockCipher->blockSize;
395
396 // Force cbShift to either be 1 or blockSize
397 if(cbShift != 1)
398 {
399 cbShift = blockSize;
400 }
401
402 memcpy( chain, pbChainingValue, blockSize );
403 while( cbData >= cbShift )
404 {
406 SymCryptXorBytes( pbSrc, tmp, tmp, cbShift ); // tmp[0..cbShift-1] ^= pbSrc[0..cbShift-1]
407 memcpy( pbDst, tmp, cbShift );
408
409 memmove( chain, chain + cbShift, blockSize - cbShift );
410 memcpy( chain + blockSize - cbShift, tmp, cbShift );
411
412 pbDst += cbShift;
413 pbSrc += cbShift;
414 cbData -= cbShift;
415 }
416
417 memcpy( pbChainingValue, chain, blockSize );
418}
419
420
421VOID
425 SIZE_T cbShift,
427 _Inout_updates_( pBlockCipher->blockSize )
431 SIZE_T cbData )
432{
434 PBYTE chain = &buf[0];
436 SIZE_T blockSize;
437
438 blockSize = pBlockCipher->blockSize;
440
441 // Force cbShift to either be 1 or blockSize
442 if(cbShift != 1)
443 {
444 cbShift = blockSize;
445 }
446
447 memcpy( chain, pbChainingValue, blockSize );
448 while( cbData >= cbShift )
449 {
451
452 //
453 // First we update the chain block
454 //
455
456 memmove( chain, chain + cbShift, blockSize - cbShift );
457 memcpy( chain + blockSize - cbShift, pbSrc, cbShift );
458
459 //
460 // To obey the read-once rule, we take the ciphertext from the updated chain block.
461 //
462 SymCryptXorBytes( chain + blockSize - cbShift, tmp, pbDst, cbShift );
463
464 pbDst += cbShift;
465 pbSrc += cbShift;
466 cbData -= cbShift;
467 }
468
469 memcpy( pbChainingValue, chain, blockSize );
470}
VOID SYMCRYPT_CALL SymCryptEcbEncrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCfbDecrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, SIZE_T cbShift, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCbcEncrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptEcbDecrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCfbEncrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, SIZE_T cbShift, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCtrMsb32(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCtrMsb64(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCbcMac(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptCbcDecrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
CONST VOID * PCVOID
Definition: cfgmgr32.h:44
#define NULL
Definition: types.h:112
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_updates_(s)
Definition: no_sal2.h:182
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _In_
Definition: no_sal2.h:158
BYTE * PBYTE
Definition: pedump.c:66
PSYMCRYPT_BLOCKCIPHER_CRYPT_ECB ecbDecryptFunc
PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE cbcEncryptFunc
PSYMCRYPT_BLOCKCIPHER_CRYPT decryptFunc
PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE ctrMsb64Func
PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE cbcDecryptFunc
PSYMCRYPT_BLOCKCIPHER_CRYPT encryptFunc
PSYMCRYPT_BLOCKCIPHER_CRYPT_ECB ecbEncryptFunc
PSYMCRYPT_BLOCKCIPHER_MAC_MODE cbcMacFunc
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
#define SYMCRYPT_LOAD_MSBFIRST32(p)
Definition: symcrypt.h:303
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
#define SYMCRYPT_LOAD_MSBFIRST64(p)
Definition: symcrypt.h:304
VOID SYMCRYPT_CALL SymCryptXorBytes(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, _Out_writes_(cbBytes) PBYTE pbResult, SIZE_T cbBytes)
Definition: libmain.c:236
#define SYMCRYPT_STORE_MSBFIRST32(p, v)
Definition: symcrypt.h:311
#define SYMCRYPT_STORE_MSBFIRST64(p, v)
Definition: symcrypt.h:312
#define SYMCRYPT_ALIGN
PBYTE pbChainingValue
PCBYTE pbSrc
#define SYMCRYPT_CALL
#define SYMCRYPT_MAX_BLOCK_SIZE
PCSYMCRYPT_BLOCKCIPHER pBlockCipher
PCBYTE PBYTE SIZE_T cbData
PCBYTE PBYTE pbDst
const BYTE * PCBYTE
BYTE keystream[64]
PCVOID pExpandedKey
struct sock * chain
Definition: tcpcore.h:1
ULONG_PTR SIZE_T
Definition: typedefs.h:80
unsigned char BYTE
Definition: xxhash.c:193