ReactOS 0.4.17-dev-1005-g171e1de
chacha20.c
Go to the documentation of this file.
1//
2// ChaCha20.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
15 SIZE_T cbData );
16// Encrypt Src to Dst using whole blocks, starting at block floor(pState->offset/64).
17// # blocks processed is floor( cbData / 64 )
18// pState->offset point is updated by 64 for each block encrypted
19
20
21
22#define OFFSET_MASK (((UINT64)1 << 38) - 1)
23
30 _In_reads_( cbNonce ) PCBYTE pbNonce,
33{
34 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
35
36 if (cbKey != 32)
37 {
38 scError = SYMCRYPT_WRONG_KEY_SIZE;
39 goto cleanup;
40 }
41
42 if (cbNonce != 12)
43 {
44 scError = SYMCRYPT_WRONG_NONCE_SIZE;
45 goto cleanup;
46 }
47
49 SymCryptLsbFirstToUint32( pbNonce, &pState->nonce[0], 3 );
50
52
54 return scError;
55}
56
57VOID
62{
63 pState->offset = offset;
64 pState->keystreamBufferValid = FALSE;
65}
66
67VOID
74{
75 UINT32 blockOffset;
76 SIZE_T nBytes;
77
78 blockOffset = pState->offset & 0x3f;
79
80 // If the offset is in the middle of the block, we first crypt until the end
81 // of the block
82 if( blockOffset != 0 )
83 {
84 if( !pState->keystreamBufferValid )
85 {
86 // Generate a block of key stream
87 SymCryptWipe( &pState->keystream[0], 64 );
89 &pState->keystream[0],
90 &pState->keystream[0],
91 64 );
92 pState->offset -= 64; // Don't update the offset yet
93 }
94
95 nBytes = 64 - blockOffset; // # bytes in buffer starting at offset
96 if( cbData < nBytes )
97 {
98 // We don't use the generated block to the end. The buffer will be valid
99 // at the end as the offset won't advance beyond the block.
100 nBytes = cbData;
101 pState->keystreamBufferValid = TRUE;
102 } else {
103 // We'll use the rest of the generated block. After that the key stream
104 // buffer won't be valid as the offset will advance beyond it.
105 pState->keystreamBufferValid = FALSE;
106 }
107
108 SymCryptXorBytes( pbSrc, &pState->keystream[ blockOffset ], pbDst, nBytes );
109 pbSrc += nBytes;
110 pbDst += nBytes;
111 cbData -= nBytes;
112 pState->offset += nBytes;
113 }
114
115 // Here: pbSrc, pbDst, cbData, and pState->offset all in sync
116 // and either cbData == 0 or offset is at a block boundary
117
118 if( cbData >= 64 )
119 {
120 nBytes = cbData & ~0x3f;
122 pbSrc += nBytes;
123 pbDst += nBytes;
124 cbData -= nBytes;
125 }
126
127 if( cbData > 0 )
128 {
129 // Generate a block of key stream
130 SymCryptWipe( &pState->keystream[0], 64 );
132 &pState->keystream[0],
133 &pState->keystream[0],
134 64 );
135 pState->offset -= 64; // Don't update the offset yet
136 pState->keystreamBufferValid = TRUE;
137
138 SymCryptXorBytes( pbSrc, &pState->keystream[0], pbDst, cbData );
139 pState->offset += cbData;
140 // The following updates are correct but not needed
141 // pbSrc += cbData;
142 // pbDst += cbData;
143 // cbData -= cbData;
144 }
145}
146
147#define CHACHA_QUARTERROUND( a, b, c, d ) { \
148 a += b; d ^= a; d = ROL32( d, 16 ); \
149 c += d; b ^= c; b = ROL32( b, 12 ); \
150 a += b; d ^= a; d = ROL32( d, 8 ); \
151 c += d; b ^= c; b = ROL32( b, 7 ); \
152}
153
154VOID
160 SIZE_T cbData )
161{
163 UINT32 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15;
164 int i;
165
166 counter = (UINT32)(pState->offset >> 6);
167
168 while( cbData >= 64 )
169 {
170 // Initialize the state
171 s0 = 0x61707865;
172 s1 = 0x3320646e;
173 s2 = 0x79622d32;
174 s3 = 0x6b206574;
175 s4 = pState->key[0];
176 s5 = pState->key[1];
177 s6 = pState->key[2];
178 s7 = pState->key[3];
179 s8 = pState->key[4];
180 s9 = pState->key[5];
181 s10 = pState->key[6];
182 s11 = pState->key[7];
183 s12 = counter;
184 s13 = pState->nonce[0];
185 s14 = pState->nonce[1];
186 s15 = pState->nonce[2];
187
188 for( i=0; i<10; i++ )
189 {
190 CHACHA_QUARTERROUND( s0 , s4 , s8 , s12 );
191 CHACHA_QUARTERROUND( s1 , s5 , s9 , s13 );
192 CHACHA_QUARTERROUND( s2 , s6 , s10, s14 );
193 CHACHA_QUARTERROUND( s3 , s7 , s11, s15 );
194
195 CHACHA_QUARTERROUND( s0 , s5 , s10, s15 );
196 CHACHA_QUARTERROUND( s1 , s6 , s11, s12 );
197 CHACHA_QUARTERROUND( s2 , s7 , s8 , s13 );
198 CHACHA_QUARTERROUND( s3 , s4 , s9 , s14 );
199 }
200
201 s0 += 0x61707865;
202 s1 += 0x3320646e;
203 s2 += 0x79622d32;
204 s3 += 0x6b206574;
205 s4 += pState->key[0];
206 s5 += pState->key[1];
207 s6 += pState->key[2];
208 s7 += pState->key[3];
209 s8 += pState->key[4];
210 s9 += pState->key[5];
211 s10 += pState->key[6];
212 s11 += pState->key[7];
213 s12 += counter;
214 s13 += pState->nonce[0];
215 s14 += pState->nonce[1];
216 s15 += pState->nonce[2];
217
234
235 counter ++;
236 // If counter overflows then the caller has encrypted more than 256GB of data with a single stream, which is
237 // called out as being insecure. It is the caller's responsibility to avoid this!
238 pbSrc += 64;
239 pbDst += 64;
240 cbData -= 64;
241 pState->offset += 64;
242 }
243}
244
245static const BYTE chacha20KatAnswer[ 3 ] = { 0xb5, 0xe0, 0x54 };
246
247VOID
250{
251 BYTE buf[3];
253
257 0 );
258
260
261 SymCryptInjectError( buf, sizeof( buf ) );
262
263 if( memcmp( buf, chacha20KatAnswer, sizeof( buf )) != 0 )
264 {
265 SymCryptFatal( 'Cha2' );
266 }
267}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static int state
Definition: maze.c:121
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
signed char s8
Definition: linux.h:51
GLintptr offset
Definition: glext.h:5920
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
struct S1 s1
#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
const BYTE SymCryptTestMsg16[16]
Definition: selftest.c:15
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
FORCEINLINE VOID SYMCRYPT_CALL SymCryptLsbFirstToUint32(_In_reads_(4 *cuResult) PCBYTE pbData, _Out_writes_(cuResult) PUINT32 puResult, SIZE_T cuResult)
Definition: sc_lib.h:487
const BYTE SymCryptTestKey32[32]
Definition: selftest.c:10
const BYTE SymCryptTestMsg3[3]
Definition: selftest.c:8
static const BYTE chacha20KatAnswer[3]
Definition: chacha20.c:245
VOID SYMCRYPT_CALL SymCryptChaCha20CryptBlocks(_Inout_ PSYMCRYPT_CHACHA20_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: chacha20.c:156
#define CHACHA_QUARTERROUND(a, b, c, d)
Definition: chacha20.c:147
VOID SYMCRYPT_CALL SymCryptChaCha20Crypt(_Inout_ PSYMCRYPT_CHACHA20_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: chacha20.c:69
VOID SYMCRYPT_CALL SymCryptChaCha20SetOffset(_Inout_ PSYMCRYPT_CHACHA20_STATE pState, UINT64 offset)
Definition: chacha20.c:59
VOID SYMCRYPT_CALL SymCryptChaCha20Selftest(void)
Definition: chacha20.c:249
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Init(_Out_ PSYMCRYPT_CHACHA20_STATE pState, _In_reads_(cbKey) PCBYTE pbKey, _In_ SIZE_T cbKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, UINT64 offset)
Definition: chacha20.c:26
PCWSTR s2
Definition: shell32_main.h:38
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)
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_LOAD_LSBFIRST32(p)
Definition: symcrypt.h:299
#define SYMCRYPT_STORE_LSBFIRST32(p, v)
Definition: symcrypt.h:307
SYMCRYPT_ERROR
Definition: symcrypt.h:227
PCBYTE pbSrc
#define SYMCRYPT_CALL
PCBYTE pbKey
PCBYTE SIZE_T cbKey
PCBYTE PBYTE SIZE_T cbData
PCBYTE PBYTE pbDst
SIZE_T cbNonce
* PSYMCRYPT_CHACHA20_STATE
SYMCRYPT_CHACHA20_STATE
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193