ReactOS 0.4.17-dev-1005-g171e1de
chacha20_poly1305.c File Reference
#include "precomp.h"
Include dependency graph for chacha20_poly1305.c:

Go to the source code of this file.

Macros

#define CHACHA20_POLY1305_MAX_DATA_SIZE   (((1ull << 32) - 1) * 64)
 

Functions

VOID SYMCRYPT_CALL SymCryptChaCha20Poly1305ComputeTag (_Inout_ PSYMCRYPT_POLY1305_STATE pState, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_POLY1305_RESULT_SIZE) PBYTE pbTag)
 
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Encrypt (_In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
 
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Decrypt (_In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
 
VOID SYMCRYPT_CALL SymCryptChaCha20Poly1305Selftest (void)
 

Variables

const BOOL fcbDataLteMaxDataSizeStatic = SIZE_T_MAX <= CHACHA20_POLY1305_MAX_DATA_SIZE
 
static const BYTE SymCryptChaCha20Poly1305Result [3+SYMCRYPT_POLY1305_RESULT_SIZE]
 

Macro Definition Documentation

◆ CHACHA20_POLY1305_MAX_DATA_SIZE

#define CHACHA20_POLY1305_MAX_DATA_SIZE   (((1ull << 32) - 1) * 64)

Definition at line 9 of file chacha20_poly1305.c.

Function Documentation

◆ SymCryptChaCha20Poly1305ComputeTag()

VOID SYMCRYPT_CALL SymCryptChaCha20Poly1305ComputeTag ( _Inout_ PSYMCRYPT_POLY1305_STATE  pState,
_In_reads_opt_(cbAuthData) PCBYTE  pbAuthData,
SIZE_T  cbAuthData,
_In_reads_(cbData) PCBYTE  pbData,
SIZE_T  cbData,
_Out_writes_(SYMCRYPT_POLY1305_RESULT_SIZE) PBYTE  pbTag 
)

Definition at line 17 of file chacha20_poly1305.c.

24{
26 BYTE partialBlockSize;
27
29
30 // Add additional authentication data if needed.
31 if ( cbAuthData > 0 )
32 {
34
35 // Append zeros to make a complete Poly1305 block.
36 partialBlockSize = cbAuthData % SYMCRYPT_POLY1305_BLOCK_SIZE;
37 if ( partialBlockSize > 0 )
38 {
40 }
41 }
42
43 // Add ciphertext if needed.
44 if ( cbData > 0 )
45 {
47
48 // Append zeros to make a complete Poly1305 block.
49 partialBlockSize = cbData % SYMCRYPT_POLY1305_BLOCK_SIZE;
50 if ( partialBlockSize > 0 )
51 {
53 }
54 }
55
56 // Add length of additional authentication data and ciphertext.
61
63}
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
VOID SYMCRYPT_CALL SymCryptPoly1305Result(_Inout_ PSYMCRYPT_POLY1305_STATE pState, _Out_writes_(SYMCRYPT_POLY1305_RESULT_SIZE) PBYTE pbResult)
Definition: poly1305.c:109
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
#define SYMCRYPT_POLY1305_BLOCK_SIZE
Definition: symcrypt.h:3857
VOID SYMCRYPT_CALL SymCryptPoly1305Append(_Inout_ PSYMCRYPT_POLY1305_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: poly1305.c:55
#define SYMCRYPT_STORE_LSBFIRST64(p, v)
Definition: symcrypt.h:308
#define SYMCRYPT_ALIGN
UINT64 cbAuthData
PCBYTE PBYTE SIZE_T cbData
PSYMCRYPT_COMMON_HASH_STATE pState
PCBYTE pbData
unsigned char BYTE
Definition: xxhash.c:193

Referenced by SymCryptChaCha20Poly1305Decrypt(), and SymCryptChaCha20Poly1305Encrypt().

◆ SymCryptChaCha20Poly1305Decrypt()

SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Decrypt ( _In_reads_(cbKey) PCBYTE  pbKey,
SIZE_T  cbKey,
_In_reads_(cbNonce) PCBYTE  pbNonce,
SIZE_T  cbNonce,
_In_reads_opt_(cbAuthData) PCBYTE  pbAuthData,
SIZE_T  cbAuthData,
_In_reads_(cbData) PCBYTE  pbSrc,
_Out_writes_(cbData) PBYTE  pbDst,
SIZE_T  cbData,
_In_reads_(cbTag) PCBYTE  pbTag,
SIZE_T  cbTag 
)

Definition at line 138 of file chacha20_poly1305.c.

150{
151 SYMCRYPT_ERROR status = SYMCRYPT_NO_ERROR;
152 SYMCRYPT_CHACHA20_STATE ChaCha20State;
153 SYMCRYPT_POLY1305_STATE Poly1305State;
156
158 {
159 status = SYMCRYPT_WRONG_DATA_SIZE;
160 goto cleanup;
161 }
162
164 {
165 status = SYMCRYPT_WRONG_TAG_SIZE;
166 goto cleanup;
167 }
168
169 status = SymCryptChaCha20Init( &ChaCha20State, pbKey, cbKey, pbNonce, cbNonce, 0 );
170 if ( status != SYMCRYPT_NO_ERROR )
171 {
172 goto cleanup;
173 }
174
175 // Generate the first 32 bytes of keystream.
176 SymCryptWipeKnownSize( key, sizeof( key ) );
177 SymCryptChaCha20Crypt( &ChaCha20State, key, key, sizeof( key ) );
178
179 // Create the Poly1305 key using the first 32 bytes of the ChaCha20 keystream.
180 SymCryptPoly1305Init( &Poly1305State, key );
181 SymCryptWipeKnownSize( key, sizeof( key ) );
182
183 // We read the ciphertext back, violating the general rule not to rely on I/O buffers
184 // as they can reside in a different security domain. For ChaCha20Poly1305, like GCM,
185 // this read-back of data is not a problem. An attacker with access to the buffer
186 // will get the ChaCha20 key stream plus the Poly1305 authenticator of a single value.
187 // As Poly1305 is strong even with attacker-controlled data, this is harmless.
188 SymCryptChaCha20Poly1305ComputeTag( &Poly1305State, pbAuthData, cbAuthData,
189 pbSrc, cbData, buf );
190
191 // Validate tag.
192 if (!SymCryptEqual(pbTag, buf, cbTag))
193 {
194 status = SYMCRYPT_AUTHENTICATION_FAILURE;
195 goto cleanup;
196 }
197
198 // Decrypt data if needed.
199 if ( cbData > 0)
200 {
201 // Advance the keystream to counter 1 (offset 64) for data decryption.
202 SymCryptChaCha20SetOffset( &ChaCha20State, 64 );
203 SymCryptChaCha20Crypt( &ChaCha20State, pbSrc, pbDst, cbData );
204 }
205
206cleanup:
207
208 SymCryptWipeKnownSize( &ChaCha20State, sizeof( ChaCha20State ) );
209 SymCryptWipeKnownSize( &Poly1305State, sizeof( Poly1305State ) );
210
211 return status;
212}
#define CHACHA20_POLY1305_MAX_DATA_SIZE
const BOOL fcbDataLteMaxDataSizeStatic
VOID SYMCRYPT_CALL SymCryptChaCha20Poly1305ComputeTag(_Inout_ PSYMCRYPT_POLY1305_STATE pState, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_POLY1305_RESULT_SIZE) PBYTE pbTag)
static void cleanup(void)
Definition: main.c:1335
Definition: copy.c:22
Definition: ps.c:97
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 SymCryptPoly1305Init(_Out_ PSYMCRYPT_POLY1305_STATE pState, _In_reads_(SYMCRYPT_POLY1305_KEY_SIZE) PCBYTE pbKey)
Definition: poly1305.c:33
#define SYMCRYPT_POLY1305_KEY_SIZE
Definition: symcrypt.h:3858
VOID SYMCRYPT_CALL SymCryptChaCha20SetOffset(_Inout_ PSYMCRYPT_CHACHA20_STATE pState, UINT64 offset)
Definition: chacha20.c:59
#define SYMCRYPT_POLY1305_RESULT_SIZE
Definition: symcrypt.h:3856
BOOLEAN SYMCRYPT_CALL SymCryptEqual(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, SIZE_T cbBytes)
Definition: equal.c:11
SYMCRYPT_ERROR
Definition: symcrypt.h:227
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
SIZE_T cbTag
PCBYTE pbSrc
PCBYTE pbKey
PCBYTE SIZE_T cbKey
PCBYTE PBYTE pbDst
SIZE_T cbNonce
SYMCRYPT_CHACHA20_STATE
SYMCRYPT_MAGIC_FIELD SYMCRYPT_POLY1305_STATE

Referenced by SymCryptChaCha20Poly1305Selftest().

◆ SymCryptChaCha20Poly1305Encrypt()

SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Encrypt ( _In_reads_(cbKey) PCBYTE  pbKey,
SIZE_T  cbKey,
_In_reads_(cbNonce) PCBYTE  pbNonce,
SIZE_T  cbNonce,
_In_reads_opt_(cbAuthData) PCBYTE  pbAuthData,
SIZE_T  cbAuthData,
_In_reads_(cbData) PCBYTE  pbSrc,
_Out_writes_(cbData) PBYTE  pbDst,
SIZE_T  cbData,
_Out_writes_(cbTag) PBYTE  pbTag,
SIZE_T  cbTag 
)

Definition at line 68 of file chacha20_poly1305.c.

80{
81 SYMCRYPT_ERROR status = SYMCRYPT_NO_ERROR;
82 SYMCRYPT_CHACHA20_STATE ChaCha20State;
83 SYMCRYPT_POLY1305_STATE Poly1305State;
85
87 {
88 status = SYMCRYPT_WRONG_DATA_SIZE;
89 goto cleanup;
90 }
91
93 {
94 status = SYMCRYPT_WRONG_TAG_SIZE;
95 goto cleanup;
96 }
97
98 status = SymCryptChaCha20Init( &ChaCha20State, pbKey, cbKey, pbNonce, cbNonce, 0 );
99 if ( status != SYMCRYPT_NO_ERROR )
100 {
101 goto cleanup;
102 }
103
104 // Generate the first 32 bytes of keystream.
105 SymCryptWipeKnownSize( key, sizeof( key ) );
106 SymCryptChaCha20Crypt( &ChaCha20State, key, key, sizeof ( key ) );
107
108 // Create the Poly1305 key using the first 32 bytes of the ChaCha20 keystream.
109 SymCryptPoly1305Init( &Poly1305State, key );
110 SymCryptWipeKnownSize( key, sizeof( key ) );
111
112 // Encrypt data if needed.
113 if ( cbData > 0 )
114 {
115 // Advance the keystream to counter 1 (offset 64) for data encryption.
116 SymCryptChaCha20SetOffset( &ChaCha20State, 64 );
117 SymCryptChaCha20Crypt( &ChaCha20State, pbSrc, pbDst, cbData );
118 }
119
120 // We read the ciphertext back, violating the general rule not to rely on I/O buffers
121 // as they can reside in a different security domain. For ChaCha20Poly1305, like GCM,
122 // this read-back of data is not a problem. An attacker with access to the buffer
123 // will get the ChaCha20 key stream plus the Poly1305 authenticator of a single value.
124 // As Poly1305 is strong even with attacker-controlled data, this is harmless.
125 SymCryptChaCha20Poly1305ComputeTag( &Poly1305State, pbAuthData, cbAuthData,
126 pbDst, cbData, pbTag );
127cleanup:
128
129 SymCryptWipeKnownSize( &ChaCha20State, sizeof( ChaCha20State ) );
130 SymCryptWipeKnownSize( &Poly1305State, sizeof( Poly1305State ) );
131
132 return status;
133}

Referenced by SymCryptChaCha20Poly1305Selftest().

◆ SymCryptChaCha20Poly1305Selftest()

VOID SYMCRYPT_CALL SymCryptChaCha20Poly1305Selftest ( void  )

Definition at line 223 of file chacha20_poly1305.c.

224{
227
231 &SymCryptTestMsg3[0], buf, 3,
232 &buf[3], SYMCRYPT_POLY1305_RESULT_SIZE ) != SYMCRYPT_NO_ERROR )
233 {
234 SymCryptFatal( 'ccp0' );
235 }
236
237 SymCryptInjectError( buf, sizeof( buf ) );
238 if ( memcmp( buf, SymCryptChaCha20Poly1305Result, sizeof( buf ) ) != 0 )
239 {
240 SymCryptFatal( 'ccp1' );
241 }
242
243 // Inject error into the ciphertext or tag.
244 SymCryptInjectError( buf, sizeof( buf ) );
245
249 buf, buf, 3,
252
253 if ( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
254 {
255 SymCryptFatal( 'ccp2' );
256 }
257}
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Encrypt(_In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
static const BYTE SymCryptChaCha20Poly1305Result[3+SYMCRYPT_POLY1305_RESULT_SIZE]
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptChaCha20Poly1305Decrypt(_In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define err(...)
const BYTE SymCryptTestMsg16[16]
Definition: selftest.c:15
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
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)

Variable Documentation

◆ fcbDataLteMaxDataSizeStatic

◆ SymCryptChaCha20Poly1305Result

const BYTE SymCryptChaCha20Poly1305Result[3+SYMCRYPT_POLY1305_RESULT_SIZE]
static
Initial value:
=
{
0x5d, 0xba, 0x7b,
0x80, 0x10, 0xd2, 0x05, 0x4a, 0xad, 0x53, 0x1f, 0xa2, 0xce, 0x83, 0xc1, 0x66, 0x12, 0x85, 0x21
}

Definition at line 215 of file chacha20_poly1305.c.

Referenced by SymCryptChaCha20Poly1305Selftest().