ReactOS 0.4.17-dev-1005-g171e1de
rc4.c
Go to the documentation of this file.
1//
2// Rc4.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6// This is a new implementation, NOT based on the existing ones in RSA32.lib.
7// The algorithm specification is taken from "ARCFOUR Algorithm" internet
8// draft dated July 1999, and from memory.
9//
10
11#include "precomp.h"
12
19{
20 SIZE_T i;
21 SIZE_T j;
22 BYTE keyBuf[256];
23 SIZE_T keyIdx;
24
26
27 if( cbKey > 256 || cbKey == 0 )
28 {
29 return SYMCRYPT_WRONG_KEY_SIZE;
30 }
31
32 //
33 // Make a copy of the key to obey the read-once rule.
34 // This is a case where it looks safe to break the read-once
35 // rule, but it isn't. RC4 with very long keys (e.g. 256 bytes)
36 // is actually very vulnerable against related-key attacks.
37 // One obvious precaution is to limit the length of the RC4 key,
38 // which one of the layers above us might do.
39 // Allowing the key bytes to change as we read them negates
40 // this countermeasure.
41 //
42 memcpy( keyBuf, pbKey, cbKey );
43
44 for( i=0; i<256; i++ )
45 {
47 }
48
49 j = 0;
50 keyIdx = 0;
51 for( i=0; i<256; i++ )
52 {
53
54 T = pState->S[i];
55 j = (j + T + keyBuf[keyIdx]) & 0xff;
56 pState->S[i] = pState->S[j];
57 pState->S[j] = T;
58 keyIdx++;
59 if( keyIdx == cbKey )
60 {
61 keyIdx = 0;
62 }
63 }
64
65 //
66 // We store the i value already incremented for the next byte.
67 // This seems to allow better instruction sequencing interleaving in the actual en/decrypt loop
68 //
69 pState->i = 1;
70 pState->j = 0;
71
73
74 SymCryptWipe( keyBuf, cbKey );
75
76 return SYMCRYPT_NO_ERROR;
77}
78
79
80VOID
87{
88 SIZE_T i;
89 SIZE_T j;
92 PCBYTE pbSrcEnd = pbSrc + cbData;
93
95
96 i = pState->i;
97 j = pState->j;
98
99 //
100 // I tried to unroll this loop 4x and use a single 32-bit operation to XOR the key
101 // stream with the data. This actually makes the code slower by 1 c/B on a Core 2.
102 // I suspect that that is because the instruction decoders are the bottleneck, and
103 // a small loop can be run out of the uop queue which bypasses the instruction decoders.
104 // A larger loop has to be decoded every time, and that slows things down.
105 // The theoretical gain of unrolling the loop is less than 1 c/B,
106 // and as Core 2 and derived CPUs are the most commonly used CPUs by our customers,
107 // it is not worthwhile to persue this further.
108 //
109 // - Niels Ferguson (niels) 2010-10-11
110 //
111
112 while( pbSrc < pbSrcEnd )
113 {
114 //
115 // Our i value is already incremented
116 //
117 Ti = pState->S[i];
118 j = (j + Ti ) & 0xff;
119 Tj = pState->S[j];
120 pState->S[i] = Tj;
121 pState->S[j] = Ti;
122 *pbDst = (BYTE) (*pbSrc ^ pState->S[(Ti + Tj) & 0xff]);
123
124 i = (i + 1) & 0xff;
125
126 pbSrc++;
127 pbDst++;
128 }
129
130 pState->i = (BYTE) i;
131 pState->j = (BYTE) j;
132}
133
134
135static const BYTE rc4KatAnswer[ 3 ] = { 0x71, 0x46, 0x92 };
136
137
138VOID
141{
142 BYTE buf[3];
144
146
148
149 SymCryptInjectError( buf, sizeof( buf ) );
150
151 if( memcmp( buf, rc4KatAnswer, sizeof( buf )) != 0 )
152 {
153 SymCryptFatal( 'rc4 ' );
154 }
155
156}
VOID SYMCRYPT_CALL SymCryptRc4Crypt(_Inout_ PSYMCRYPT_RC4_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, _In_ SIZE_T cbData)
Definition: rc4.c:82
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptRc4Init(_Out_ PSYMCRYPT_RC4_STATE pState, _In_reads_(cbKey) PCBYTE pbKey, _In_ SIZE_T cbKey)
Definition: rc4.c:15
VOID SYMCRYPT_CALL SymCryptRc4Selftest(void)
Definition: rc4.c:140
static const BYTE rc4KatAnswer[3]
Definition: rc4.c:135
static int state
Definition: maze.c:121
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
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
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 GLint GLint j
Definition: glfuncs.h:250
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#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
#define T(num)
Definition: thunks.c:311
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
const BYTE SymCryptTestKey32[32]
Definition: selftest.c:10
const BYTE SymCryptTestMsg3[3]
Definition: selftest.c:8
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
SYMCRYPT_ERROR
Definition: symcrypt.h:227
PCBYTE pbSrc
#define SYMCRYPT_CALL
PCBYTE pbKey
SYMCRYPT_MAGIC_FIELD SYMCRYPT_RC4_STATE
PCBYTE SIZE_T cbKey
BYTE SYMCRYPT_RC4_S_TYPE
PCBYTE PBYTE SIZE_T cbData
#define SYMCRYPT_SET_MAGIC(p)
PCBYTE PBYTE pbDst
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_RC4_STATE
#define SYMCRYPT_CHECK_MAGIC(p)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
unsigned char BYTE
Definition: xxhash.c:193