Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // hash.c generic code used in many hash implementations. |
3 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
4 | | // |
5 | | |
6 | | #include "precomp.h" |
7 | | |
8 | | VOID |
9 | | SYMCRYPT_CALL |
10 | | SymCryptHashAppendInternal( |
11 | | _In_ PCSYMCRYPT_HASH pHash, |
12 | | _Inout_ PSYMCRYPT_COMMON_HASH_STATE pState, |
13 | | _In_reads_bytes_( cbData ) PCBYTE pbData, |
14 | | SIZE_T cbData ) |
15 | 156k | { |
16 | 156k | UINT32 bytesInBuffer; |
17 | 156k | UINT32 freeInBuffer; |
18 | 156k | SIZE_T tmp; |
19 | | |
20 | 156k | SYMCRYPT_CHECK_MAGIC( pState ); |
21 | | |
22 | 156k | pState->dataLengthL += cbData; |
23 | 156k | if( pState->dataLengthL < cbData ) { |
24 | 0 | pState->dataLengthH ++; // This is almost-unreachable code as it requires 2^64 bytes to be hashed. |
25 | 0 | } |
26 | | |
27 | 156k | bytesInBuffer = pState->bytesInBuffer; |
28 | | |
29 | | // |
30 | | // If previous data in buffer, buffer new input and transform if possible. |
31 | | // |
32 | 156k | if( bytesInBuffer > 0 ) |
33 | 131k | { |
34 | 131k | SYMCRYPT_ASSERT( pHash->inputBlockSize > bytesInBuffer ); |
35 | | |
36 | 131k | freeInBuffer = pHash->inputBlockSize - bytesInBuffer; |
37 | 131k | if( cbData < freeInBuffer ) |
38 | 111k | { |
39 | | // |
40 | | // All the data will fit in the buffer. |
41 | | // We don't do anything here. |
42 | | // As cbData < inputBlockSize the bulk data processing is skipped, |
43 | | // and the data will be copied to the buffer at the end |
44 | | // of this code. |
45 | 111k | } else { |
46 | | // |
47 | | // Enough data to fill the whole buffer & process it |
48 | | // |
49 | 19.7k | memcpy(&pState->buffer[bytesInBuffer], pbData, freeInBuffer); |
50 | 19.7k | pbData += freeInBuffer; |
51 | 19.7k | cbData -= freeInBuffer; |
52 | 19.7k | (*pHash->appendBlockFunc)( (PBYTE)pState + pHash->chainOffset, &pState->buffer[0], pHash->inputBlockSize, &tmp ); |
53 | | |
54 | 19.7k | bytesInBuffer = 0; |
55 | 19.7k | } |
56 | 131k | } |
57 | | |
58 | | // |
59 | | // Internal buffer is empty; process all remaining whole blocks in the input |
60 | | // |
61 | 156k | if( cbData >= pHash->inputBlockSize ) |
62 | 21.6k | { |
63 | 21.6k | (*pHash->appendBlockFunc)( (PBYTE)pState + pHash->chainOffset, pbData, cbData, &tmp ); |
64 | 21.6k | SYMCRYPT_ASSERT( tmp < pHash->inputBlockSize ); |
65 | 21.6k | pbData += cbData - tmp; |
66 | 21.6k | cbData = tmp; |
67 | 21.6k | } |
68 | | |
69 | 156k | SYMCRYPT_ASSERT( cbData < pHash->inputBlockSize ); |
70 | | |
71 | | // |
72 | | // buffer remaining input if necessary. |
73 | | // |
74 | 156k | if( cbData > 0 ) |
75 | 69.1k | { |
76 | 69.1k | memcpy( &pState->buffer[bytesInBuffer], pbData, cbData ); |
77 | 69.1k | bytesInBuffer += (UINT32) cbData; |
78 | 69.1k | } |
79 | | |
80 | 156k | pState->bytesInBuffer = bytesInBuffer; |
81 | 156k | } |
82 | | |
83 | | VOID |
84 | | SYMCRYPT_CALL |
85 | | SymCryptHashCommonPaddingMd4Style( |
86 | | _In_ PCSYMCRYPT_HASH pHash, |
87 | | _Inout_ PSYMCRYPT_COMMON_HASH_STATE pState ) |
88 | 23.0k | { |
89 | 23.0k | SIZE_T tmp; |
90 | 23.0k | SIZE_T bytesInBuffer = pState->bytesInBuffer; |
91 | | |
92 | 23.0k | SYMCRYPT_CHECK_MAGIC( pState ); |
93 | 23.0k | SYMCRYPT_ASSERT( pHash->inputBlockSize == 64 ); |
94 | 23.0k | SYMCRYPT_ASSERT( bytesInBuffer == (pState->dataLengthL & 0x3f) ); |
95 | | |
96 | | // |
97 | | // The buffer is never completely full, so we can always put the first |
98 | | // padding byte in. |
99 | | // |
100 | 23.0k | pState->buffer[bytesInBuffer++] = 0x80; |
101 | | |
102 | 23.0k | if( bytesInBuffer > 64-8 ) { |
103 | | // |
104 | | // No room for the rest of the padding. Pad with zeroes & process block |
105 | | // bytesInBuffer is at most 64, so we do not have an integer underflow |
106 | | // |
107 | 1.76k | SymCryptWipe( &pState->buffer[bytesInBuffer], 64-bytesInBuffer ); |
108 | 1.76k | (*pHash->appendBlockFunc)( (PBYTE)pState + pHash->chainOffset, pState->buffer, 64, &tmp ); |
109 | 1.76k | SYMCRYPT_ASSERT( tmp == 0 ); |
110 | 1.76k | bytesInBuffer = 0; |
111 | 1.76k | } |
112 | | |
113 | | // |
114 | | // Set rest of padding |
115 | | // At this point bytesInBuffer <= 64-8, so we don't have an underflow |
116 | | // We wipe to the end of the buffer as it is 16-aligned, |
117 | | // and it is faster to wipe to an aligned point |
118 | | // |
119 | 23.0k | SymCryptWipe( &pState->buffer[bytesInBuffer], 64-bytesInBuffer ); |
120 | 23.0k | SYMCRYPT_STORE_LSBFIRST64( &pState->buffer[64-8], pState->dataLengthL * 8 ); |
121 | | |
122 | | // |
123 | | // Process the final block |
124 | | // |
125 | 23.0k | (*pHash->appendBlockFunc)( (PBYTE)pState + pHash->chainOffset, pState->buffer, 64, &tmp ); |
126 | 23.0k | } |
127 | | |
128 | | |
129 | | |
130 | | SIZE_T |
131 | | SYMCRYPT_CALL |
132 | | SymCryptHashResultSize( _In_ PCSYMCRYPT_HASH pHash ) |
133 | 0 | { |
134 | 0 | return pHash->resultSize; |
135 | 0 | } |
136 | | |
137 | | |
138 | | SIZE_T |
139 | | SYMCRYPT_CALL |
140 | | SymCryptHashInputBlockSize( _In_ PCSYMCRYPT_HASH pHash ) |
141 | 0 | { |
142 | 0 | return pHash->inputBlockSize; |
143 | 0 | } |
144 | | |
145 | | SIZE_T |
146 | | SYMCRYPT_CALL |
147 | | SymCryptHashStateSize( _In_ PCSYMCRYPT_HASH pHash ) |
148 | 0 | { |
149 | 0 | return pHash->stateSize; |
150 | 0 | } |
151 | | |
152 | | |
153 | | VOID |
154 | | SYMCRYPT_CALL |
155 | | SymCryptHash( |
156 | | _In_ PCSYMCRYPT_HASH pHash, |
157 | | _In_reads_( cbData ) PCBYTE pbData, |
158 | | SIZE_T cbData, |
159 | | _Out_writes_( SYMCRYPT_MIN( cbResult, pHash->resultSize ) ) PBYTE pbResult, |
160 | | SIZE_T cbResult ) |
161 | 0 | { |
162 | 0 | SYMCRYPT_HASH_STATE hash; |
163 | |
|
164 | 0 | _Analysis_assume_( pHash->stateSize <= sizeof( hash ) ); |
165 | 0 | SymCryptHashInit( pHash, &hash ); |
166 | 0 | SymCryptHashAppend( pHash, &hash, pbData, cbData ); |
167 | 0 | SymCryptHashResult( pHash, &hash, pbResult, cbResult ); |
168 | 0 | SymCryptWipe( &hash, pHash->stateSize ); |
169 | 0 | } |
170 | | |
171 | | VOID |
172 | | SYMCRYPT_CALL |
173 | | SymCryptHashInit( |
174 | | _In_ PCSYMCRYPT_HASH pHash, |
175 | | _Out_writes_bytes_( pHash->stateSize ) PVOID pState ) |
176 | 0 | { |
177 | 0 | (*pHash->initFunc)( pState ); |
178 | 0 | } |
179 | | |
180 | | VOID |
181 | | SYMCRYPT_CALL |
182 | | SymCryptHashAppend( |
183 | | _In_ PCSYMCRYPT_HASH pHash, |
184 | | _Inout_updates_bytes_( pHash->stateSize ) PVOID pState, |
185 | | _In_reads_( cbData ) PCBYTE pbData, |
186 | | SIZE_T cbData ) |
187 | 0 | { |
188 | 0 | (*pHash->appendFunc)( pState, pbData, cbData ); |
189 | 0 | } |
190 | | |
191 | | VOID |
192 | | SYMCRYPT_CALL |
193 | | SymCryptHashResult( |
194 | | _In_ PCSYMCRYPT_HASH pHash, |
195 | | _Inout_updates_bytes_( pHash->stateSize ) PVOID pState, |
196 | | _Out_writes_( SYMCRYPT_MIN( cbResult, pHash->resultSize ) ) PBYTE pbResult, |
197 | | SIZE_T cbResult ) |
198 | 0 | { |
199 | 0 | BYTE buf[SYMCRYPT_HASH_MAX_RESULT_SIZE]; |
200 | |
|
201 | 0 | _Analysis_assume_( pHash->resultSize <= SYMCRYPT_HASH_MAX_RESULT_SIZE ); |
202 | |
|
203 | 0 | (*pHash->resultFunc)( pState, buf ); |
204 | 0 | memcpy( pbResult, buf, SYMCRYPT_MIN( cbResult, pHash->resultSize )); |
205 | 0 | SymCryptWipe( buf, pHash->resultSize ); |
206 | 0 | } |
207 | | |
208 | | VOID |
209 | | SYMCRYPT_CALL |
210 | | SymCryptHashStateCopy( |
211 | | _In_ PCSYMCRYPT_HASH pHash, |
212 | | _In_reads_( pHash->stateSize ) PCVOID pSrc, |
213 | | _Out_writes_( pHash->stateSize ) PVOID pDst) |
214 | 0 | { |
215 | 0 | (*pHash->stateCopyFunc)( pSrc, pDst ); |
216 | 0 | } |
217 | | |