ReactOS 0.4.17-dev-1005-g171e1de
marvin32.c
Go to the documentation of this file.
1//
2// Marvin32.c
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7//
8// This module contains the routines to implement the Marvin32 checksum function
9//
10//
11
12#include "precomp.h"
13
14//
15// See the symcrypt.h file for documentation on what the various functions do.
16//
17
18
19//
20// Default initial seed, first 8 bytes of SHA256( "Marvin32" );
21//
23 {0xcd0893b7, 0xd53cd9ce},
24#if defined( SYMCRYPT_MAGIC_ENABLED )
25 SYMCRYPT_MAGIC_VALUE( &SymCryptMarvin32DefaultSeedStruct ),
26#endif
27 };
28
30
31//
32// Round rotation amounts. This array is optimized away by the compiler
33// as we inline all our rotations.
34//
35static const int rotate[4] = {
36 20, 9, 27, 19,
37};
38
39
46{
47 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
48
50 {
51 scError = SYMCRYPT_WRONG_KEY_SIZE;
52 goto cleanup;
53 }
54 pExpandedSeed->s[0] = SYMCRYPT_LOAD_LSBFIRST32( pbSeed );
55 pExpandedSeed->s[1] = SYMCRYPT_LOAD_LSBFIRST32( pbSeed + 4 );
56
57 SYMCRYPT_SET_MAGIC( pExpandedSeed );
58
60 return scError;
61}
62
63VOID
67{
69 *pDst = *pSrc;
70 SYMCRYPT_SET_MAGIC( pDst );
71}
72
73
74VOID
80{
82 *pDst = *pSrc;
83
84 if( pExpandedSeed == NULL )
85 {
86 SYMCRYPT_CHECK_MAGIC( pSrc->pSeed );
87 pDst->pSeed = pSrc->pSeed;
88 }
89 else
90 {
91 SYMCRYPT_CHECK_MAGIC( pExpandedSeed );
92 pDst->pSeed = pExpandedSeed;
93 }
94
95 SYMCRYPT_SET_MAGIC( pDst );
96}
97
98
99VOID
103{
104 pState->chain = *pExpandedSeed;
105 pState->dataLength = 0;
106 pState->pSeed = pExpandedSeed;
107
108 *(UINT32 *) &pState->buffer[4] = 0; // wipe the last 4 bytes of the buffer.
109
111}
112
113
114//
115// SymCryptMarvin32Append
116//
117
118VOID
122 SIZE_T cbData )
123{
124 UINT32 bytesInBuffer = state->dataLength;
125
127
128 state->dataLength += (UINT32) cbData; // We only keep track of the last 2 bits...
129
130#define ALG MARVIN32
131#define Alg Marvin32
132#include "hash_buffer_pattern.c"
133#undef ALG
134#undef Alg
135
136}
137
138
139//
140// SymCryptMarvin32Result
141//
142VOID
147{
148 SIZE_T bytesInBuffer = ( pState->dataLength) & 0x3;
149
151
152 //
153 // Wipe four bytes in the buffer.
154 // Doing this first ensures that this write is aligned when the input was of
155 // length 0 mod 4.
156 // The buffer is 8 bytes long, so we never overwrite anything else.
157 //
158 *(UINT32 *) &pState->buffer[bytesInBuffer] = 0;
159
160 //
161 // The buffer is never completely full, so we can always put the first
162 // padding byte in.
163 //
164 pState->buffer[bytesInBuffer++] = 0x80;
165
166 //
167 // Process the final block
168 //
169 SymCryptMarvin32AppendBlocks( &pState->chain, pState->buffer, 8 );
170
172 SYMCRYPT_STORE_LSBFIRST32( pbResult + 4, pState->chain.s[1] );
173
174 //
175 // Wipe only those things that we need to wipe.
176 //
177
178 *(UINT32 *) &pState->buffer[0] = 0;
179 pState->dataLength = 0;
180
181 pState->chain = *pState->pSeed;
182}
183
184#define BLOCK( a, b ) \
185{\
186 b ^= a; a = ROL32( a, rotate[0] );\
187 a += b; b = ROL32( b, rotate[1] );\
188 b ^= a; a = ROL32( a, rotate[2] );\
189 a += b; b = ROL32( b, rotate[3] );\
190}
191
192VOID
197 SIZE_T cbData )
198{
199 UINT32 s0 = pChain->s[0];
200 UINT32 s1 = pChain->s[1];
201
202 SIZE_T bytesInFirstBlock = cbData & 0xc; // 0, 4, 8, or 12
203
204 SYMCRYPT_ASSERT( (cbData & 3) == 0 );
205
206
207 pbData += bytesInFirstBlock;
208 cbData -= bytesInFirstBlock;
209
210 switch( bytesInFirstBlock )
211 {
212 case 0: // This handles the cbData == 0 case too
213 while( cbData > 0 )
214 {
215 pbData += 16;
216 cbData -= 16;
217
218 s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData - 16 );
219 BLOCK( s0, s1 );
220 case 12:
221 s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData - 12 );
222 BLOCK( s0, s1 );
223 case 8:
224 s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData - 8 );
225 BLOCK( s0, s1 );
226 case 4:
227 s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData - 4 );
228 BLOCK( s0, s1 );
229 }
230 }
231
232 pChain->s[0] = s0;
233 pChain->s[1] = s1;
234}
235
236
237VOID
244//
245// To reduce the per-computation overhead, we have a dedicated code here instead of the whole Init/Append/Result stuff.
246//
247{
248 UINT32 tmp;
249
250 UINT32 s0 = pExpandedSeed->s[0];
251 UINT32 s1 = pExpandedSeed->s[1];
252
253 while( cbData > 7 )
254 {
256 BLOCK( s0, s1 );
257 s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData + 4 );
258 BLOCK( s0, s1 );
259 pbData += 8;
260 cbData -= 8;
261 }
262
263 /*
264 switch( cbData )
265 {
266 case 3:
267 buf[2] = pbData[2];
268 case 2:
269 *(UINT16 *) &buf[0] = *(UINT16 *) pbData;
270 break;
271 case 1:
272 buf[0] = pbData[0];
273 case 0:
274 ;
275 }
276
277 buf[ cbData ] = 0x80;
278
279 s0 += LOAD_LSBFIRST32( buf );
280 */
281
282
283 switch( cbData )
284 {
285 default:
286 case 4: s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
287 case 0: tmp = 0x80; break;
288
289 case 5: s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
290 case 1: tmp = 0x8000 | pbData[0]; break;
291
292 case 6: s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
293 case 2: tmp = 0x800000 | SYMCRYPT_LOAD_LSBFIRST16( pbData ); break;
294
295 case 7: s0 += SYMCRYPT_LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
296 case 3: tmp = SYMCRYPT_LOAD_LSBFIRST16( pbData ) | (pbData[2] << 16) | 0x80000000; break;
297 }
298 s0 += tmp;
299
300
301 BLOCK( s0, s1 );
302 BLOCK( s0, s1 );
303
306}
307
308
309
310//
311// Simple test vector
312//
313
314static const BYTE marvin32KATAnswer[ 8 ] = {
315 0xbf, 0x69, 0x27, 0x49, 0x39, 0x43, 0xc7, 0x22,
316} ;
317
318VOID
321{
323
325
326 SymCryptInjectError( res, sizeof( res ) );
327 if( memcmp( res, marvin32KATAnswer, sizeof( res ) ) != 0 )
328 {
329 SymCryptFatal( 'marv' );
330 }
331}
static int state
Definition: maze.c:121
#define NULL
Definition: types.h:112
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
GLuint res
Definition: glext.h:9613
VOID SYMCRYPT_CALL SymCryptMarvin32Result(_Inout_ PSYMCRYPT_MARVIN32_STATE pState, _Out_writes_(SYMCRYPT_MARVIN32_RESULT_SIZE) PBYTE pbResult)
Definition: marvin32.c:144
VOID SYMCRYPT_CALL SymCryptMarvin32(_In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_MARVIN32_RESULT_SIZE) PBYTE pbResult)
Definition: marvin32.c:239
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMarvin32ExpandSeed(_Out_ PSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed, _In_reads_(cbSeed) PCBYTE pbSeed, SIZE_T cbSeed)
Definition: marvin32.c:42
VOID SYMCRYPT_CALL SymCryptMarvin32Selftest(void)
Definition: marvin32.c:320
#define BLOCK(a, b)
Definition: marvin32.c:184
VOID SYMCRYPT_CALL SymCryptMarvin32SeedCopy(_In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pSrc, _Out_ PSYMCRYPT_MARVIN32_EXPANDED_SEED pDst)
Definition: marvin32.c:65
static const BYTE marvin32KATAnswer[8]
Definition: marvin32.c:314
PCSYMCRYPT_MARVIN32_EXPANDED_SEED const SymCryptMarvin32DefaultSeed
Definition: marvin32.c:29
VOID SYMCRYPT_CALL SymCryptMarvin32AppendBlocks(_Inout_ PSYMCRYPT_MARVIN32_CHAINING_STATE pChain, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: marvin32.c:194
VOID SYMCRYPT_CALL SymCryptMarvin32StateCopy(_In_ PCSYMCRYPT_MARVIN32_STATE pSrc, _In_opt_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed, _Out_ PSYMCRYPT_MARVIN32_STATE pDst)
Definition: marvin32.c:76
static const SYMCRYPT_MARVIN32_EXPANDED_SEED SymCryptMarvin32DefaultSeedStruct
Definition: marvin32.c:22
VOID SYMCRYPT_CALL SymCryptMarvin32Init(_Out_ PSYMCRYPT_MARVIN32_STATE pState, _In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed)
Definition: marvin32.c:101
static const int rotate[4]
Definition: marvin32.c:35
VOID SYMCRYPT_CALL SymCryptMarvin32Append(_Inout_ PSYMCRYPT_MARVIN32_STATE state, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: marvin32.c:120
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
#define _In_opt_
Definition: no_sal2.h:212
BYTE * PBYTE
Definition: pedump.c:66
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
const BYTE SymCryptTestMsg3[3]
Definition: selftest.c:8
static const BYTE pbResult[]
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
#define SYMCRYPT_MARVIN32_SEED_SIZE
Definition: symcrypt.h:3989
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
#define SYMCRYPT_MARVIN32_RESULT_SIZE
Definition: symcrypt.h:3988
#define SYMCRYPT_LOAD_LSBFIRST16(p)
Definition: symcrypt.h:298
#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
#define SYMCRYPT_CALL
const SYMCRYPT_MARVIN32_EXPANDED_SEED * PCSYMCRYPT_MARVIN32_EXPANDED_SEED
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_MARVIN32_STATE
SIZE_T bytesInBuffer
PCBYTE PBYTE SIZE_T cbData
#define SYMCRYPT_SET_MAGIC(p)
UINT32 cbSeed
const SYMCRYPT_MARVIN32_STATE * PCSYMCRYPT_MARVIN32_STATE
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
PCBYTE pbData
#define SYMCRYPT_CHECK_MAGIC(p)
SYMCRYPT_MARVIN32_EXPANDED_SEED * PSYMCRYPT_MARVIN32_CHAINING_STATE
PBYTE pbSeed
SYMCRYPT_MAGIC_FIELD SYMCRYPT_MARVIN32_EXPANDED_SEED
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_MARVIN32_EXPANDED_SEED
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193