ReactOS 0.4.17-dev-1190-g4c812f4
rc2.c
Go to the documentation of this file.
1//
2// Rc2.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7//
8// This module contains the routines to implement RC2 from RFC 2268
9//
10// This is a new implementation, based on the RFC specification
11// and NOT based on the existing one in RSA32.lib, which is the one from RSA data security.
12//
13
14
15#include "precomp.h"
16
18 SymCryptRc2ExpandKey, // PSYMCRYPT_BLOCKCIPHER_EXPAND_KEY expandKeyFunc;
19 SymCryptRc2Encrypt, // PSYMCRYPT_BLOCKCIPHER_CRYPT encryptFunc;
20 SymCryptRc2Decrypt, // PSYMCRYPT_BLOCKCIPHER_CRYPT decryptFunc;
21 NULL, // PSYMCRYPT_BLOCKCIPHER_CRYPT_ECB ecbEncryptFunc;
22 NULL, // PSYMCRYPT_BLOCKCIPHER_CRYPT_ECB ecbDecryptFunc;
23 NULL, // PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE cbcEncryptFunc;
24 NULL, // PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE cbcDecryptFunc;
25 NULL, // PSYMCRYPT_BLOCKCIPHER_MAC_MODE cbcMacFunc;
26 NULL, // PSYMCRYPT_BLOCKCIPHER_CRYPT_MODE ctrMsbFunc;
27 NULL, // PSYMCRYPT_BLOCKCIPHER_AEADPART_MODE gcmEncryptPartFunc;
28 NULL, // PSYMCRYPT_BLOCKCIPHER_AEADPART_MODE gcmDecryptPartFunc;
29 8, // SIZE_T blockSize;
30 sizeof( SYMCRYPT_RC2_EXPANDED_KEY ), // SIZE_T expandedKeySize; // = sizeof( SYMCRYPT_XXX_EXPANDED_KEY )
31};
32
34
35/*
36 *
37 * constants
38 *
39 */
40static const BYTE PITABLE[] =
41{
42 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
43 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
44 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
45 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
46 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
47 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
48 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
49 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
50 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
51 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
52 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
53 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
54 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
55 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
56 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
57 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
58};
59
60/*
61 *
62 * macros
63 *
64 */
65
66
67/*
68 * These are the original macros we derived directly from the RFC.
69 * To improve the perf we changed to using R0, R1, R2, R3 variables rather
70 * than an array.
71 */
72
73/*
74#define MIX(R, K, i, j, S) {\
75 R[i] = R[i] + K[j] + (R[(i-1)&3] & R[(i-2)&3]) + ((~R[(i-1)&3]) & R[(i-3)&3]);\
76 j = j + 1;\
77 R[i] = ROL16(R[i], S);\
78 }
79
80#define MIXROUND(R, K, j) {\
81 MIX(R, K, 0, j, 1);\
82 MIX(R, K, 1, j, 2);\
83 MIX(R, K, 2, j, 3);\
84 MIX(R, K, 3, j, 5);\
85 }
86
87#define MASH(R, K, i) \
88 R[i] = R[i] + K[R[(i-1)&3]&63];
89
90#define MASHROUND(R, K) {\
91 MASH(R, K, 0);\
92 MASH(R, K, 1);\
93 MASH(R, K, 2);\
94 MASH(R, K, 3);\
95 }
96
97//
98// decrypt macros
99//
100
101
102#define RMIX(R, K, i, j, S) {\
103 R[i] = ROR16( R[i], S );\
104 R[i] = R[i] - K[j] - (R[(i-1)&3] & R[(i-2)&3]) - ((~R[(i-1)&3]) & R[(i-3)&3]);\
105 j = j - 1;\
106 }
107
108#define RMIXROUND(R, K, j) {\
109 RMIX(R, K, 3, j, 5);\
110 RMIX(R, K, 2, j, 3);\
111 RMIX(R, K, 1, j, 2);\
112 RMIX(R, K, 0, j, 1);\
113 }
114
115#define RMASH(R, K, i) \
116 R[i] = R[i] - K[R[(i-1)&3] & 63];
117
118#define RMASHROUND(R, K) {\
119 RMASH(R, K, 3);\
120 RMASH(R, K, 2);\
121 RMASH(R, K, 1);\
122 RMASH(R, K, 0);\
123 }
124*/
125
126
133 UINT32 effectiveKeySizeInBits )
134{
135 SYMCRYPT_ALIGN BYTE L[128];
136 UINT32 T;
137 UINT32 T1;
138 UINT32 T8;
139 UINT32 TM;
140 int i;
141
143
144 //
145 // According to RFC 2268 any key size in 1..128 is allowed.
146 //
147 // The effective key size cannot be 0 as the RFC specs would lead to a buffer overflow
148 // in the key expansion.
149 //
150 // If the effective key size <= 8 then T8=1 and the key expansion backward recursion
151 // drops into a fixed point because L[i+1] xor L[i+T8] is zero.
152 // Therefore, we require an effective key size of at least 9.
153 //
154 if( cbKey < 1 || cbKey > 128 || effectiveKeySizeInBits < 9 || effectiveKeySizeInBits > 8*128 )
155 {
156 return SYMCRYPT_WRONG_KEY_SIZE;
157 }
158
159 T = (UINT32)cbKey; // 1 <= T1 <= 128
160
161 T1 = effectiveKeySizeInBits; // 9 <= T1 <= 1024
162 T8 = (T1+7)/8; // 2 <= T8 <= 128
163
164 TM = 255 & ((1 << (8 + (UINT32)T1 - 8*T8))-1);
165
166 //
167 // To be endian-agnostic our expanded key is stored as an array of UINT16s. We do the key
168 // expansion in a local buffer and copy the values into the expanded key using the proper conversion.
169 //
170 memcpy(L, pbKey, T);
171
172 for(i = T; i <= 127; i++)
173 {
174 L[i] = PITABLE[(L[i-1]+L[i-T]) & 0xff];
175 //
176 // If the key size T=1 then we lose one bit of key space in the key expansion because
177 // L[i-1] == L[i-T] which makes the index to PITABLE even. So L[1..128] depend only on
178 // 7 bits.
179 //
180 }
181
182 L[128-T8] = PITABLE[L[128-T8] & TM];
183
184 for( i = 127-T8; i >=0; i--)
185 {
186 L[i] = PITABLE[L[i+1] ^ L[i+T8]];
187 }
188
189 //
190 // Now we copy the result into the UINT16 array in our expanded key.
191 // This is a memcpy for little-endian platforms, but this code works on all CPUs.
192 //
193 for( i=0; i<64; i++ )
194 {
196 }
197
198 SymCryptWipeKnownSize( L, sizeof( L ) );
199
200 return SYMCRYPT_NO_ERROR;
201}
202
208 SIZE_T cbKey )
209{
211}
212
213
214#define MIXROUND( n ) {\
215 R0 = R0 + K[4*n] + (R3 & R2) + (~R3 & R1); \
216 R0 = ROL16( R0, 1 ); \
217 R1 = R1 + K[4*n+1] + (R0 & R3) + (~R0 & R2 ); \
218 R1 = ROL16( R1, 2 ); \
219 R2 = R2 + K[4*n+2] + (R1 & R0) + (~R1 & R3); \
220 R2 = ROL16( R2, 3 ); \
221 R3 = R3 + K[4*n+3] + (R2 & R1) + (~R2 & R0 ); \
222 R3 = ROL16( R3, 5 ); \
223 }
224
225#define MASHROUND() { \
226 R0 = R0 + K[R3 & 63]; \
227 R1 = R1 + K[R0 & 63]; \
228 R2 = R2 + K[R1 & 63]; \
229 R3 = R3 + K[R2 & 63]; \
230 }
231
232VOID
238{
239 UINT16 R0, R1, R2, R3;
240 PCUINT16 K;
241
243
244 //
245 // 1. Initialize words R[0], ..., R[3] to contain the 64-bit plaintext value.
246 //
251
252 //
253 // 2. Expand the key, so that words K[0], ..., K[63] become defined.
254 // (In our case the key was previously expanded, so we just grab the pointer to it.)
255 //
256 K = pExpandedKey->K;
257
258 //
259 // 3. Initialize j to zero.
260 //
261
262 //
263 // 4. Perform five mixing rounds.
264 //
265 MIXROUND(0);
266 MIXROUND(1);
267 MIXROUND(2);
268 MIXROUND(3);
269 MIXROUND(4);
270
271 //
272 // 5. Perform one mashing round.
273 //
274 MASHROUND();
275
276 //
277 // 6. Perform six mixing rounds.
278 //
279 MIXROUND(5);
280 MIXROUND(6);
281 MIXROUND(7);
282 MIXROUND(8);
283 MIXROUND(9);
284 MIXROUND(10);
285
286 //
287 // 7. Perform one mashing round.
288 //
289 MASHROUND();
290
291 //
292 // 8. Perform five mixing rounds.
293 //
294 MIXROUND(11);
295 MIXROUND(12);
296 MIXROUND(13);
297 MIXROUND(14);
298 MIXROUND(15);
299
304
305}
306
307
308#define RMIXROUND( n ) {\
309 R3 = ROR16( R3, 5 ); \
310 R3 = R3 - K[4*n+3] - (R2 & R1) - (~R2 & R0 ); \
311 R2 = ROR16( R2, 3 ); \
312 R2 = R2 - K[4*n+2] - (R1 & R0) - (~R1 & R3); \
313 R1 = ROR16( R1, 2 ); \
314 R1 = R1 - K[4*n+1] - (R0 & R3) - (~R0 & R2 ); \
315 R0 = ROR16( R0, 1 ); \
316 R0 = R0 - K[4*n ] - (R3 & R2) - (~R3 & R1); \
317 }
318
319#define RMASHROUND() { \
320 R3 = R3 - K[R2 & 63]; \
321 R2 = R2 - K[R1 & 63]; \
322 R1 = R1 - K[R0 & 63]; \
323 R0 = R0 - K[R3 & 63]; \
324 }
325
326
327
328VOID
334{
335 UINT16 R0, R1, R2, R3;
336 PCUINT16 K;
337
339
340 //
341 // 1. Initialize words R[0], ..., R[3] to contain the 64-bit plaintext value.
342 //
347
348 //
349 // 2. Expand the key, so that words K[0], ..., K[63] become defined.
350 // (In our case the key was previously expanded, so we just grab the pointer to it.)
351 //
352 K = pExpandedKey->K;
353
354 //
355 // 3. Initialize j to 63.
356 //
357
358 //
359 // 4. Perform five r-mixing rounds.
360 //
361 RMIXROUND(15);
362 RMIXROUND(14);
363 RMIXROUND(13);
364 RMIXROUND(12);
365 RMIXROUND(11);
366
367 //
368 // 5. Perform one r-mashing round.
369 //
370 RMASHROUND();
371
372 //
373 // 6. Perform six r-mixing rounds.
374 //
375 RMIXROUND(10);
376 RMIXROUND(9);
377 RMIXROUND(8);
378 RMIXROUND(7);
379 RMIXROUND(6);
380 RMIXROUND(5);
381
382 //
383 // 7. Perform one r-mashing round.
384 //
385 RMASHROUND();
386
387 //
388 // 8. Perform five r-mixing rounds.
389 //
390 RMIXROUND(4);
391 RMIXROUND(3);
392 RMIXROUND(2);
393 RMIXROUND(1);
394 RMIXROUND(0);
395
400
401}
402
403static const BYTE testPlaintext[8] = { 'P', 'l', 'a', 'i', 'n', 't', 'x', 't', };
404static const BYTE testCiphertext[8] = {
405 0x89, 0xe8, 0x5d, 0x1a, 0x98, 0xcd, 0xe5, 0x52,
406};
407
408VOID
411{
414
415 if( SymCryptRc2ExpandKeyEx( &key, SymCryptTestKey32, 16, 87) != SYMCRYPT_NO_ERROR )
416 {
417 SymCryptFatal( 'rc21' );
418 }
419
421
423
425 {
426 SymCryptFatal( 'rc22' );
427 }
428
430
432
434 {
435 SymCryptFatal( 'rc23' );
436 }
437
438}
unsigned short UINT16
Definition: actypes.h:129
#define NULL
Definition: types.h:112
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define L(x)
Definition: resources.c:13
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
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 _In_reads_(s)
Definition: no_sal2.h:168
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
BYTE * PBYTE
Definition: pedump.c:66
static const BYTE PITABLE[]
Definition: rc2.c:40
static const BYTE testCiphertext[8]
Definition: rc2.c:404
VOID SYMCRYPT_CALL SymCryptRc2Decrypt(_In_ PCSYMCRYPT_RC2_EXPANDED_KEY pExpandedKey, _In_reads_(SYMCRYPT_RC2_BLOCK_SIZE) PCBYTE pbSrc, _Out_writes_(SYMCRYPT_RC2_BLOCK_SIZE) PBYTE pbDst)
Definition: rc2.c:330
static const BYTE testPlaintext[8]
Definition: rc2.c:403
#define MIXROUND(n)
Definition: rc2.c:214
const SYMCRYPT_BLOCKCIPHER SymCryptRc2BlockCipher_default
Definition: rc2.c:17
#define MASHROUND()
Definition: rc2.c:225
VOID SYMCRYPT_CALL SymCryptRc2Encrypt(_In_ PCSYMCRYPT_RC2_EXPANDED_KEY pExpandedKey, _In_reads_(SYMCRYPT_RC2_BLOCK_SIZE) PCBYTE pbSrc, _Out_writes_(SYMCRYPT_RC2_BLOCK_SIZE) PBYTE pbDst)
Definition: rc2.c:234
#define RMIXROUND(n)
Definition: rc2.c:308
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptRc2ExpandKey(_Out_ PSYMCRYPT_RC2_EXPANDED_KEY pExpandedKey, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey)
Definition: rc2.c:205
const PCSYMCRYPT_BLOCKCIPHER SymCryptRc2BlockCipher
Definition: rc2.c:33
#define RMASHROUND()
Definition: rc2.c:319
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptRc2ExpandKeyEx(_Out_ PSYMCRYPT_RC2_EXPANDED_KEY pExpandedKey, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, UINT32 effectiveKeySizeInBits)
Definition: rc2.c:129
VOID SYMCRYPT_CALL SymCryptRc2Selftest(void)
Definition: rc2.c:410
#define T(num)
Definition: thunks.c:311
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
const BYTE SymCryptTestKey32[32]
Definition: selftest.c:10
#define R1(v, w, x, y, z, i)
Definition: sha1.c:36
#define R2(v, w, x, y, z, i)
Definition: sha1.c:37
#define R0(v, w, x, y, z, i)
Definition: sha1.c:35
#define R3(v, w, x, y, z, i)
Definition: sha1.c:38
Definition: copy.c:22
#define SYMCRYPT_RC2_BLOCK_SIZE
Definition: symcrypt.h:4543
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
#define SYMCRYPT_STORE_LSBFIRST16(p, v)
Definition: symcrypt.h:306
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
#define SYMCRYPT_LOAD_LSBFIRST16(p)
Definition: symcrypt.h:298
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_ALIGN
PCBYTE pbSrc
const SYMCRYPT_RC2_EXPANDED_KEY * PCSYMCRYPT_RC2_EXPANDED_KEY
#define SYMCRYPT_CALL
PCBYTE pbKey
PCBYTE SIZE_T cbKey
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_RC2_EXPANDED_KEY
#define SYMCRYPT_SET_MAGIC(p)
PCBYTE PBYTE pbDst
SYMCRYPT_MAGIC_FIELD SYMCRYPT_RC2_EXPANDED_KEY
const UINT16 * PCUINT16
const BYTE * PCBYTE
#define SYMCRYPT_CHECK_MAGIC(p)
PCVOID pExpandedKey
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193