/src/ibmswtpm2/src/CryptHash.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Implementation of cryptographic functions for hashing. */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: CryptHash.c 1311 2018-08-23 21:39:29Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 10.2.14 CryptHash.c */ |
63 | | /* 10.2.14.1 Description */ |
64 | | /* This file contains implementation of cryptographic functions for hashing. */ |
65 | | /* 10.2.14.2 Includes, Defines, and Types */ |
66 | | #define _CRYPT_HASH_C_ |
67 | | #include "Tpm.h" |
68 | | #define HASH_TABLE_SIZE (HASH_COUNT + 1) |
69 | | extern const HASH_INFO g_hashData[HASH_COUNT + 1]; |
70 | | #if ALG_SHA1 |
71 | | HASH_DEF_TEMPLATE(SHA1); |
72 | | #endif |
73 | | #if ALG_SHA256 |
74 | | HASH_DEF_TEMPLATE(SHA256); |
75 | | #endif |
76 | | #if ALG_SHA384 |
77 | | HASH_DEF_TEMPLATE(SHA384); |
78 | | #endif |
79 | | #if ALG_SHA512 |
80 | | HASH_DEF_TEMPLATE(SHA512); |
81 | | #endif |
82 | | HASH_DEF nullDef = {{0}}; |
83 | | /* 10.2.14.3 Obligatory Initialization Functions */ |
84 | | /* This function is called by _TPM_Init() do perform the initialization operations for the |
85 | | library. */ |
86 | | BOOL |
87 | | CryptHashInit( |
88 | | void |
89 | | ) |
90 | 361 | { |
91 | 361 | LibHashInit(); |
92 | 361 | return TRUE; |
93 | 361 | } |
94 | | /* 10.2.13.3.2 CryptHashStartup() */ |
95 | | /* This function is called by TPM2_Startup() in case there is work to do at startup. Currently, this |
96 | | is a placeholder. */ |
97 | | BOOL |
98 | | CryptHashStartup( |
99 | | void |
100 | | ) |
101 | 360 | { |
102 | 360 | return TRUE; |
103 | 360 | } |
104 | | /* 10.2.14.4 Hash Information Access Functions */ |
105 | | /* 10.2.14.4.1 Introduction */ |
106 | | /* These functions provide access to the hash algorithm description information. */ |
107 | | /* 10.2.14.4.2 CryptGetHashDef() */ |
108 | | /* This function accesses the hash descriptor associated with a hash a algorithm. The function |
109 | | returns NULL for TPM_ALG_NULL and fails if hashAlg is not a hash algorithm. */ |
110 | | PHASH_DEF |
111 | | CryptGetHashDef( |
112 | | TPM_ALG_ID hashAlg |
113 | | ) |
114 | 78.4k | { |
115 | 78.4k | PHASH_DEF retVal; |
116 | 78.4k | switch(hashAlg) |
117 | 78.4k | { |
118 | 0 | #if ALG_SHA1 |
119 | 19.6k | case ALG_SHA1_VALUE: |
120 | 19.6k | return &SHA1_Def; |
121 | 0 | break; |
122 | 0 | #endif |
123 | 0 | #if ALG_SHA256 |
124 | 19.6k | case ALG_SHA256_VALUE: |
125 | 19.6k | retVal = &SHA256_Def; |
126 | 19.6k | break; |
127 | 0 | #endif |
128 | 0 | #if ALG_SHA384 |
129 | 19.6k | case ALG_SHA384_VALUE: |
130 | 19.6k | retVal = &SHA384_Def; |
131 | 19.6k | break; |
132 | 0 | #endif |
133 | 0 | #if ALG_SHA512 |
134 | 19.6k | case ALG_SHA512_VALUE: |
135 | 19.6k | retVal = &SHA512_Def; |
136 | 19.6k | break; |
137 | 0 | #endif |
138 | 0 | default: |
139 | 0 | retVal = &nullDef; |
140 | 0 | break; |
141 | 78.4k | } |
142 | 58.8k | return retVal; |
143 | 78.4k | } |
144 | | /* 10.2.13.4.3 CryptHashIsValidAlg() */ |
145 | | /* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then |
146 | | TPM_ALG_NULL is a valid hash. */ |
147 | | /* Return Value Meaning */ |
148 | | /* TRUE hashAlg is a valid, implemented hash on this TPM. */ |
149 | | /* FALSE not valid */ |
150 | | BOOL |
151 | | CryptHashIsValidAlg( |
152 | | TPM_ALG_ID hashAlg, |
153 | | BOOL flag |
154 | | ) |
155 | 0 | { |
156 | 0 | switch(hashAlg) |
157 | 0 | { |
158 | 0 | #if ALG_SHA1 |
159 | 0 | case ALG_SHA1_VALUE: |
160 | 0 | #endif |
161 | 0 | #if ALG_SHA256 |
162 | 0 | case ALG_SHA256_VALUE: |
163 | 0 | #endif |
164 | 0 | #if ALG_SHA384 |
165 | 0 | case ALG_SHA384_VALUE: |
166 | 0 | #endif |
167 | 0 | #if ALG_SHA512 |
168 | 0 | case ALG_SHA512_VALUE: |
169 | 0 | #endif |
170 | | #if ALG_SM3_256 |
171 | | case ALG_SM3_256_VALUE: |
172 | | #endif |
173 | 0 | return TRUE; |
174 | 0 | break; |
175 | 0 | case ALG_NULL_VALUE: |
176 | 0 | return flag; |
177 | 0 | break; |
178 | 0 | default: |
179 | 0 | break; |
180 | 0 | } |
181 | 0 | return FALSE; |
182 | 0 | } |
183 | | /* 10.2.14.4.4 GetHashInfoPointer() */ |
184 | | /* This function returns a pointer to the hash info for the algorithm. If the algorithm is not |
185 | | supported, function returns a pointer to the data block associated with TPM_ALG_NULL. */ |
186 | | /* NOTE: The data structure must have a digest size of 0 for TPM_ALG_NULL. */ |
187 | | static |
188 | | const HASH_INFO * |
189 | | GetHashInfoPointer( |
190 | | TPM_ALG_ID hashAlg |
191 | | ) |
192 | 0 | { |
193 | 0 | UINT32 i; |
194 | | // |
195 | | // TPM_ALG_NULL is the stop value so search up to it |
196 | 0 | for(i = 0; i < HASH_COUNT; i++) |
197 | 0 | { |
198 | 0 | if(g_hashData[i].alg == hashAlg) |
199 | 0 | return &g_hashData[i]; |
200 | 0 | } |
201 | | // either the input was TPM_ALG_NUL or we didn't find the requested algorithm |
202 | | // in either case return a pointer to the TPM_ALG_NULL "hash" descriptor |
203 | 0 | return &g_hashData[HASH_COUNT]; |
204 | 0 | } |
205 | | /* 10.2.14.4.5 CryptHashGetAlgByIndex() */ |
206 | | /* This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes |
207 | | that are not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return |
208 | | the first implemented hash and an index of 2 will return the last. All other index values will |
209 | | return TPM_ALG_NULL. */ |
210 | | /* Return Values Meaning */ |
211 | | /* TPM_ALG_xxx() a hash algorithm */ |
212 | | /* TPM_ALG_NULL this can be used as a stop value */ |
213 | | LIB_EXPORT TPM_ALG_ID |
214 | | CryptHashGetAlgByIndex( |
215 | | UINT32 index // IN: the index |
216 | | ) |
217 | 35.1k | { |
218 | 35.1k | if(index >= HASH_COUNT) |
219 | 4.29k | return TPM_ALG_NULL; |
220 | 30.8k | return g_hashData[index].alg; |
221 | 35.1k | } |
222 | | /* 10.2.14.4.6 CryptHashGetDigestSize() */ |
223 | | /* This function returns the size of the digest produced by the hash. If hashAlg is not a hash |
224 | | algorithm, the TPM will FAIL. */ |
225 | | /* Return Values Meaning */ |
226 | | /* 0 TPM_ALG_NULL */ |
227 | | /* > 0 the digest size */ |
228 | | LIB_EXPORT UINT16 |
229 | | CryptHashGetDigestSize( |
230 | | TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
231 | | ) |
232 | 24.5k | { |
233 | 24.5k | return CryptGetHashDef(hashAlg)->digestSize; |
234 | 24.5k | } |
235 | | /* 10.2.14.4.7 CryptHashGetBlockSize() */ |
236 | | /* Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will |
237 | | FAIL. */ |
238 | | /* Return Values Meaning */ |
239 | | /* 0 TPM_ALG_NULL */ |
240 | | /* > 0 the digest size */ |
241 | | LIB_EXPORT UINT16 |
242 | | CryptHashGetBlockSize( |
243 | | TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
244 | | ) |
245 | 112 | { |
246 | 112 | return CryptGetHashDef(hashAlg)->blockSize; |
247 | 112 | } |
248 | | /* 10.2.14.4.8 CryptHashGetDer */ |
249 | | /* This function returns a pointer to the DER string for the algorithm and indicates its size. */ |
250 | | LIB_EXPORT UINT16 |
251 | | CryptHashGetDer( |
252 | | TPM_ALG_ID hashAlg, // IN: the algorithm to look up |
253 | | const BYTE **p |
254 | | ) |
255 | 0 | { |
256 | 0 | const HASH_INFO *q; |
257 | 0 | q = GetHashInfoPointer(hashAlg); |
258 | 0 | *p = &q->der[0]; |
259 | 0 | return q->derSize; |
260 | 0 | } |
261 | | /* 10.2.14.4.9 CryptHashGetContextAlg() */ |
262 | | /* This function returns the hash algorithm associated with a hash context. */ |
263 | | TPM_ALG_ID |
264 | | CryptHashGetContextAlg( |
265 | | PHASH_STATE state // IN: the context to check |
266 | | ) |
267 | 0 | { |
268 | 0 | return state->hashAlg; |
269 | 0 | } |
270 | | /* 10.2.14.5 State Import and Export */ |
271 | | /* 10.2.14.5.1 CryptHashCopyState */ |
272 | | /* This function is used to clone a HASH_STATE. */ |
273 | | LIB_EXPORT void |
274 | | CryptHashCopyState( |
275 | | HASH_STATE *out, // OUT: destination of the state |
276 | | const HASH_STATE *in // IN: source of the state |
277 | | ) |
278 | 0 | { |
279 | 0 | pAssert(out->type == in->type); |
280 | 0 | out->hashAlg = in->hashAlg; |
281 | 0 | out->def = in->def; |
282 | 0 | if(in->hashAlg != TPM_ALG_NULL) |
283 | 0 | { |
284 | | // Just verify that the hashAlg makes sense (is implemented) |
285 | 0 | CryptGetHashDef(in->hashAlg); |
286 | | // ... and copy. |
287 | 0 | HASH_STATE_COPY(out, in); |
288 | 0 | } |
289 | 0 | if(in->type == HASH_STATE_HMAC) |
290 | 0 | { |
291 | 0 | const HMAC_STATE *hIn = (HMAC_STATE *)in; |
292 | 0 | HMAC_STATE *hOut = (HMAC_STATE *)out; |
293 | 0 | hOut->hmacKey = hIn->hmacKey; |
294 | 0 | } |
295 | 0 | return; |
296 | 0 | } |
297 | | /* 10.2.14.5.2 CryptHashExportState() */ |
298 | | /* This function is used to export a hash or HMAC hash state. This function would be called when |
299 | | preparing to context save a sequence object. */ |
300 | | void |
301 | | CryptHashExportState( |
302 | | PCHASH_STATE internalFmt, // IN: the hash state formatted for use by |
303 | | // library |
304 | | PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state |
305 | | ) |
306 | 0 | { |
307 | 0 | BYTE *outBuf = (BYTE *)externalFmt; |
308 | | // |
309 | 0 | cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE)); |
310 | | // the following #define is used to move data from an aligned internal data |
311 | | // structure to a byte buffer (external format data. |
312 | 0 | #define CopyToOffset(value) \ |
313 | 0 | memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value, \ |
314 | 0 | sizeof(internalFmt->value)) |
315 | | // Copy the hashAlg |
316 | 0 | CopyToOffset(hashAlg); |
317 | 0 | CopyToOffset(type); |
318 | 0 | #ifdef HASH_STATE_SMAC |
319 | 0 | if(internalFmt->type == HASH_STATE_SMAC) |
320 | 0 | { |
321 | 0 | memcpy(outBuf, internalFmt, sizeof(HASH_STATE)); |
322 | 0 | return; |
323 | 0 | } |
324 | 0 | #endif |
325 | 0 | if(internalFmt->type == HASH_STATE_HMAC) |
326 | 0 | { |
327 | 0 | HMAC_STATE *from = (HMAC_STATE *)internalFmt; |
328 | 0 | memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey, |
329 | 0 | sizeof(from->hmacKey)); |
330 | 0 | } |
331 | 0 | if(internalFmt->hashAlg != TPM_ALG_NULL) |
332 | 0 | HASH_STATE_EXPORT(externalFmt, internalFmt); |
333 | 0 | } |
334 | | /* 10.2.14.5.3 CryptHashImportState() */ |
335 | | /* This function is used to import the hash state. This function would be called to import a hash |
336 | | state when the context of a sequence object was being loaded. */ |
337 | | void |
338 | | CryptHashImportState( |
339 | | PHASH_STATE internalFmt, // OUT: the hash state formatted for use by |
340 | | // the library |
341 | | PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state |
342 | | ) |
343 | 0 | { |
344 | 0 | BYTE *inBuf = (BYTE *)externalFmt; |
345 | | // |
346 | 0 | #define CopyFromOffset(value) \ |
347 | 0 | memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)], \ |
348 | 0 | sizeof(internalFmt->value)) |
349 | | // Copy the hashAlg of the byte-aligned input structure to the structure-aligned |
350 | | // internal structure. |
351 | 0 | CopyFromOffset(hashAlg); |
352 | 0 | CopyFromOffset(type); |
353 | 0 | if(internalFmt->hashAlg != TPM_ALG_NULL) |
354 | 0 | { |
355 | 0 | #ifdef HASH_STATE_SMAC |
356 | 0 | if(internalFmt->type == HASH_STATE_SMAC) |
357 | 0 | { |
358 | 0 | memcpy(internalFmt, inBuf, sizeof(HASH_STATE)); |
359 | 0 | return; |
360 | 0 | } |
361 | 0 | #endif |
362 | 0 | internalFmt->def = CryptGetHashDef(internalFmt->hashAlg); |
363 | 0 | HASH_STATE_IMPORT(internalFmt, inBuf); |
364 | 0 | if(internalFmt->type == HASH_STATE_HMAC) |
365 | 0 | { |
366 | 0 | HMAC_STATE *to = (HMAC_STATE *)internalFmt; |
367 | 0 | memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)], |
368 | 0 | sizeof(to->hmacKey)); |
369 | 0 | } |
370 | 0 | } |
371 | 0 | } |
372 | | /* 10.2.14.6 State Modification Functions */ |
373 | | /* 10.2.14.6.1 HashEnd() */ |
374 | | /* Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function |
375 | | is used to complete the hash and only return a partial digest. The return value is the size of |
376 | | the data copied. */ |
377 | | static UINT16 |
378 | | HashEnd( |
379 | | PHASH_STATE hashState, // IN: the hash state |
380 | | UINT32 dOutSize, // IN: the size of receive buffer |
381 | | PBYTE dOut // OUT: the receive buffer |
382 | | ) |
383 | 25.3k | { |
384 | 25.3k | BYTE temp[MAX_DIGEST_SIZE]; |
385 | 25.3k | if((hashState->hashAlg == TPM_ALG_NULL) |
386 | 25.3k | || (hashState->type != HASH_STATE_HASH)) |
387 | 0 | dOutSize = 0; |
388 | 25.3k | if(dOutSize > 0) |
389 | 24.6k | { |
390 | 24.6k | hashState->def = CryptGetHashDef(hashState->hashAlg); |
391 | | // Set the final size |
392 | 24.6k | dOutSize = MIN(dOutSize, hashState->def->digestSize); |
393 | | // Complete into the temp buffer and then copy |
394 | 24.6k | HASH_END(hashState, temp); |
395 | | // Don't want any other functions calling the HASH_END method |
396 | | // directly. |
397 | 24.6k | #undef HASH_END |
398 | 24.6k | memcpy(dOut, &temp, dOutSize); |
399 | 24.6k | } |
400 | 25.3k | hashState->type = HASH_STATE_EMPTY; |
401 | 25.3k | return (UINT16)dOutSize; |
402 | 25.3k | } |
403 | | /* 10.2.14.6.2 CryptHashStart() */ |
404 | | /* Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, |
405 | | the value of stateSize in hashState is updated to indicate the number of bytes of state that were |
406 | | saved. This function calls GetHashServer() and that function will put the TPM into failure mode |
407 | | if the hash algorithm is not supported. */ |
408 | | /* This function does not use the sequence parameter. If it is necessary to import or export |
409 | | context, this will start the sequence in a local state and export the state to the input |
410 | | buffer. Will need to add a flag to the state structure to indicate that it needs to be imported |
411 | | before it can be used. (BLEH). */ |
412 | | /* Return Values Meaning */ |
413 | | /* 0 hash is TPM_ALG_NULL */ |
414 | | /* >0 digest size */ |
415 | | LIB_EXPORT UINT16 |
416 | | CryptHashStart( |
417 | | PHASH_STATE hashState, // OUT: the running hash state |
418 | | TPM_ALG_ID hashAlg // IN: hash algorithm |
419 | | ) |
420 | 28.9k | { |
421 | 28.9k | UINT16 retVal; |
422 | 28.9k | TEST(hashAlg); |
423 | 28.9k | hashState->hashAlg = hashAlg; |
424 | 28.9k | if(hashAlg == TPM_ALG_NULL) |
425 | 0 | { |
426 | 0 | retVal = 0; |
427 | 0 | } |
428 | 28.9k | else |
429 | 28.9k | { |
430 | 28.9k | hashState->def = CryptGetHashDef(hashAlg); |
431 | 28.9k | HASH_START(hashState); |
432 | 28.9k | retVal = hashState->def->digestSize; |
433 | 28.9k | } |
434 | 28.9k | #undef HASH_START |
435 | 28.9k | hashState->type = HASH_STATE_HASH; |
436 | 28.9k | return retVal; |
437 | 28.9k | } |
438 | | |
439 | | /* 10.2.14.6.3 CryptDigestUpdate() */ |
440 | | /* Add data to a hash or HMAC, SMAC stack. */ |
441 | | void |
442 | | CryptDigestUpdate( |
443 | | PHASH_STATE hashState, // IN: the hash context information |
444 | | UINT32 dataSize, // IN: the size of data to be added |
445 | | const BYTE *data // IN: data to be hashed |
446 | | ) |
447 | 25.5k | { |
448 | 25.5k | if(hashState->hashAlg != TPM_ALG_NULL) |
449 | 25.5k | { |
450 | 25.5k | if((hashState->type == HASH_STATE_HASH) |
451 | 25.5k | || (hashState->type == HASH_STATE_HMAC)) |
452 | 25.5k | HASH_DATA(hashState, dataSize, (BYTE *)data); |
453 | 0 | #if SMAC_IMPLEMENTED |
454 | 0 | else if(hashState->type == HASH_STATE_SMAC) |
455 | 0 | (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state, |
456 | 0 | dataSize, data); |
457 | 0 | #endif // SMAC_IMPLEMENTED |
458 | 0 | else |
459 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
460 | 25.5k | } |
461 | 25.5k | return; |
462 | 25.5k | } |
463 | | |
464 | | /* 10.2.14.6.4 CryptHashEnd() */ |
465 | | /* Complete a hash or HMAC computation. This function will place the smaller of digestSize or the |
466 | | size of the digest in dOut. The number of bytes in the placed in the buffer is returned. If there |
467 | | is a failure, the returned value is <= 0. */ |
468 | | /* Return Values Meaning */ |
469 | | /* 0 no data returned */ |
470 | | /* > 0 the number of bytes in the digest or dOutSize, whichever is smaller */ |
471 | | LIB_EXPORT UINT16 |
472 | | CryptHashEnd( |
473 | | PHASH_STATE hashState, // IN: the state of hash stack |
474 | | UINT32 dOutSize, // IN: size of digest buffer |
475 | | BYTE *dOut // OUT: hash digest |
476 | | ) |
477 | 25.1k | { |
478 | 25.1k | pAssert(hashState->type == HASH_STATE_HASH); |
479 | 25.1k | return HashEnd(hashState, dOutSize, dOut); |
480 | 25.1k | } |
481 | | /* 10.2.14.6.5 CryptHashBlock() */ |
482 | | /* Start a hash, hash a single block, update digest and return the size of the results. */ |
483 | | /* The digestSize parameter can be smaller than the digest. If so, only the more significant bytes |
484 | | are returned. */ |
485 | | /* Return Values Meaning */ |
486 | | /* >= 0 number of bytes placed in dOut */ |
487 | | LIB_EXPORT UINT16 |
488 | | CryptHashBlock( |
489 | | TPM_ALG_ID hashAlg, // IN: The hash algorithm |
490 | | UINT32 dataSize, // IN: size of buffer to hash |
491 | | const BYTE *data, // IN: the buffer to hash |
492 | | UINT32 dOutSize, // IN: size of the digest buffer |
493 | | BYTE *dOut // OUT: digest buffer |
494 | | ) |
495 | 0 | { |
496 | 0 | HASH_STATE state; |
497 | 0 | CryptHashStart(&state, hashAlg); |
498 | 0 | CryptDigestUpdate(&state, dataSize, data); |
499 | 0 | return HashEnd(&state, dOutSize, dOut); |
500 | 0 | } |
501 | | /* 10.2.14.6.6 CryptDigestUpdate2B() */ |
502 | | /* This function updates a digest (hash or HMAC) with a TPM2B. */ |
503 | | /* This function can be used for both HMAC and hash functions so the digestState is void so that |
504 | | either state type can be passed. */ |
505 | | LIB_EXPORT void |
506 | | CryptDigestUpdate2B( |
507 | | PHASH_STATE state, // IN: the digest state |
508 | | const TPM2B *bIn // IN: 2B containing the data |
509 | | ) |
510 | 0 | { |
511 | | // Only compute the digest if a pointer to the 2B is provided. |
512 | | // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change |
513 | | // to the digest occurs. This function should not provide a buffer if bIn is |
514 | | // not provided. |
515 | 0 | pAssert(bIn != NULL); |
516 | 0 | CryptDigestUpdate(state, bIn->size, bIn->buffer); |
517 | 0 | return; |
518 | 0 | } |
519 | | /* 10.2.14.6.7 CryptHashEnd2B() */ |
520 | | /* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the |
521 | | most common use and this is provided for specification clarity. 'digest.size' should be set to |
522 | | indicate the number of bytes to place in the buffer */ |
523 | | /* Return Values Meaning */ |
524 | | /* >=0 the number of bytes placed in 'digest.buffer' */ |
525 | | LIB_EXPORT UINT16 |
526 | | CryptHashEnd2B( |
527 | | PHASH_STATE state, // IN: the hash state |
528 | | P2B digest // IN: the size of the buffer Out: requested |
529 | | // number of bytes |
530 | | ) |
531 | 12.2k | { |
532 | 12.2k | return CryptHashEnd(state, digest->size, digest->buffer); |
533 | 12.2k | } |
534 | | /* 10.2.14.6.8 CryptDigestUpdateInt() */ |
535 | | /* This function is used to include an integer value to a hash stack. The function marshals the |
536 | | integer into its canonical form before calling CryptDigestUpdate(). */ |
537 | | LIB_EXPORT void |
538 | | CryptDigestUpdateInt( |
539 | | void *state, // IN: the state of hash stack |
540 | | UINT32 intSize, // IN: the size of 'intValue' in bytes |
541 | | UINT64 intValue // IN: integer value to be hashed |
542 | | ) |
543 | 0 | { |
544 | 0 | #if LITTLE_ENDIAN_TPM |
545 | 0 | intValue = REVERSE_ENDIAN_64(intValue); |
546 | 0 | #endif |
547 | 0 | CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]); |
548 | 0 | } |
549 | | /* 10.2.14.7 HMAC Functions */ |
550 | | /* 10.2.14.7.1 CryptHmacStart */ |
551 | | /* This function is used to start an HMAC using a temp hash context. The function does the |
552 | | initialization of the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. */ |
553 | | /* The function returns the number of bytes in a digest produced by hashAlg. */ |
554 | | /* Return Values Meaning */ |
555 | | /* >= 0 number of bytes in digest produced by hashAlg (may be zero) */ |
556 | | LIB_EXPORT UINT16 |
557 | | CryptHmacStart( |
558 | | PHMAC_STATE state, // IN/OUT: the state buffer |
559 | | TPM_ALG_ID hashAlg, // IN: the algorithm to use |
560 | | UINT16 keySize, // IN: the size of the HMAC key |
561 | | const BYTE *key // IN: the HMAC key |
562 | | ) |
563 | 112 | { |
564 | 112 | PHASH_DEF hashDef; |
565 | 112 | BYTE * pb; |
566 | 112 | UINT32 i; |
567 | | // |
568 | 112 | hashDef = CryptGetHashDef(hashAlg); |
569 | 112 | if(hashDef->digestSize != 0) |
570 | 112 | { |
571 | | // If the HMAC key is larger than the hash block size, it has to be reduced |
572 | | // to fit. The reduction is a digest of the hashKey. |
573 | 112 | if(keySize > hashDef->blockSize) |
574 | 0 | { |
575 | | // if the key is too big, reduce it to a digest of itself |
576 | 0 | state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key, |
577 | 0 | hashDef->digestSize, |
578 | 0 | state->hmacKey.t.buffer); |
579 | 0 | } |
580 | 112 | else |
581 | 112 | { |
582 | 112 | memcpy(state->hmacKey.t.buffer, key, keySize); |
583 | 112 | state->hmacKey.t.size = keySize; |
584 | 112 | } |
585 | | // XOR the key with iPad (0x36) |
586 | 112 | pb = state->hmacKey.t.buffer; |
587 | 9.29k | for(i = state->hmacKey.t.size; i > 0; i--) |
588 | 9.18k | *pb++ ^= 0x36; |
589 | | // if the keySize is smaller than a block, fill the rest with 0x36 |
590 | 1.68k | for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--) |
591 | 1.56k | *pb++ = 0x36; |
592 | | // Increase the oPadSize to a full block |
593 | 112 | state->hmacKey.t.size = hashDef->blockSize; |
594 | | // Start a new hash with the HMAC key |
595 | | // This will go in the caller's state structure and may be a sequence or not |
596 | 112 | CryptHashStart((PHASH_STATE)state, hashAlg); |
597 | 112 | CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size, |
598 | 112 | state->hmacKey.t.buffer); |
599 | | // XOR the key block with 0x5c ^ 0x36 |
600 | 10.8k | for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--) |
601 | 10.7k | *pb++ ^= (0x5c ^ 0x36); |
602 | 112 | } |
603 | | // Set the hash algorithm |
604 | 112 | state->hashState.hashAlg = hashAlg; |
605 | | // Set the hash state type |
606 | 112 | state->hashState.type = HASH_STATE_HMAC; |
607 | 112 | return hashDef->digestSize; |
608 | 112 | } |
609 | | /* 10.2.14.7.2 CryptHmacEnd() */ |
610 | | /* This function is called to complete an HMAC. It will finish the current digest, and start a new |
611 | | digest. It will then add the oPadKey and the completed digest and return the results in dOut. It |
612 | | will not return more than dOutSize bytes. */ |
613 | | /* Return Values Meaning */ |
614 | | /* >= 0 number of bytes in dOut (may be zero) */ |
615 | | LIB_EXPORT UINT16 |
616 | | CryptHmacEnd( |
617 | | PHMAC_STATE state, // IN: the hash state buffer |
618 | | UINT32 dOutSize, // IN: size of digest buffer |
619 | | BYTE *dOut // OUT: hash digest |
620 | | ) |
621 | 112 | { |
622 | 112 | BYTE temp[MAX_DIGEST_SIZE]; |
623 | 112 | PHASH_STATE hState = (PHASH_STATE)&state->hashState; |
624 | 112 | #if SMAC_IMPLEMENTED |
625 | 112 | if(hState->type == HASH_STATE_SMAC) |
626 | 0 | return (state->hashState.state.smac.smacMethods.end) |
627 | 0 | (&state->hashState.state.smac.state, |
628 | 0 | dOutSize, |
629 | 0 | dOut); |
630 | 112 | #endif |
631 | 112 | pAssert(hState->type == HASH_STATE_HMAC); |
632 | 112 | hState->def = CryptGetHashDef(hState->hashAlg); |
633 | | // Change the state type for completion processing |
634 | 112 | hState->type = HASH_STATE_HASH; |
635 | 112 | if(hState->hashAlg == TPM_ALG_NULL) |
636 | 0 | dOutSize = 0; |
637 | 112 | else |
638 | 112 | { |
639 | | // Complete the current hash |
640 | 112 | HashEnd(hState, hState->def->digestSize, temp); |
641 | | // Do another hash starting with the oPad |
642 | 112 | CryptHashStart(hState, hState->hashAlg); |
643 | 112 | CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer); |
644 | 112 | CryptDigestUpdate(hState, hState->def->digestSize, temp); |
645 | 112 | } |
646 | 112 | return HashEnd(hState, dOutSize, dOut); |
647 | 112 | } |
648 | | /* 10.2.14.7.3 CryptHmacStart2B() */ |
649 | | /* This function starts an HMAC and returns the size of the digest that will be produced. */ |
650 | | /* This function is provided to support the most common use of starting an HMAC with a TPM2B key. */ |
651 | | /* The caller must provide a block of memory in which the hash sequence state is kept. The caller |
652 | | should not alter the contents of this buffer until the hash sequence is completed or |
653 | | abandoned. */ |
654 | | /* Return Values Meaning */ |
655 | | /* > 0 the digest size of the algorithm */ |
656 | | /* = 0 the hashAlg was TPM_ALG_NULL */ |
657 | | LIB_EXPORT UINT16 |
658 | | CryptHmacStart2B( |
659 | | PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used |
660 | | // in HMAC update and completion |
661 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
662 | | P2B key // IN: HMAC key |
663 | | ) |
664 | 0 | { |
665 | 0 | return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer); |
666 | 0 | } |
667 | | /* 10.2.14.7.4 CryptHmacEnd2B() */ |
668 | | /* This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is |
669 | | the most common use. */ |
670 | | /* Return Values Meaning */ |
671 | | /* >=0 the number of bytes placed in digest */ |
672 | | LIB_EXPORT UINT16 |
673 | | CryptHmacEnd2B( |
674 | | PHMAC_STATE hmacState, // IN: the state of HMAC stack |
675 | | P2B digest // OUT: HMAC |
676 | | ) |
677 | 0 | { |
678 | 0 | return CryptHmacEnd(hmacState, digest->size, digest->buffer); |
679 | 0 | } |
680 | | /* 10.2.14.8 Mask and Key Generation Functions */ |
681 | | /* 10.2.14.8.1 _crypi_MGF1() */ |
682 | | /* This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || |
683 | | counter). This function returns the length of the mask produced which could be zero if the digest |
684 | | algorithm is not supported */ |
685 | | /* Return Values Meaning */ |
686 | | /* 0 hash algorithm was TPM_ALG_NULL */ |
687 | | /* > 0 should be the same as mSize */ |
688 | | LIB_EXPORT UINT16 |
689 | | CryptMGF1( |
690 | | UINT32 mSize, // IN: length of the mask to be produced |
691 | | BYTE *mask, // OUT: buffer to receive the mask |
692 | | TPM_ALG_ID hashAlg, // IN: hash to use |
693 | | UINT32 seedSize, // IN: size of the seed |
694 | | BYTE *seed // IN: seed size |
695 | | ) |
696 | 0 | { |
697 | 0 | HASH_STATE hashState; |
698 | 0 | PHASH_DEF hDef = CryptGetHashDef(hashAlg); |
699 | 0 | UINT32 remaining; |
700 | 0 | UINT32 counter = 0; |
701 | 0 | BYTE swappedCounter[4]; |
702 | | // If there is no digest to compute return |
703 | 0 | if((hashAlg == TPM_ALG_NULL) || (mSize == 0)) |
704 | 0 | return 0; |
705 | 0 | for(remaining = mSize; ; remaining -= hDef->digestSize) |
706 | 0 | { |
707 | | // Because the system may be either Endian... |
708 | 0 | UINT32_TO_BYTE_ARRAY(counter, swappedCounter); |
709 | | // Start the hash and include the seed and counter |
710 | 0 | CryptHashStart(&hashState, hashAlg); |
711 | 0 | CryptDigestUpdate(&hashState, seedSize, seed); |
712 | 0 | CryptDigestUpdate(&hashState, 4, swappedCounter); |
713 | | // Handling the completion depends on how much space remains in the mask |
714 | | // buffer. If it can hold the entire digest, put it there. If not |
715 | | // put the digest in a temp buffer and only copy the amount that |
716 | | // will fit into the mask buffer. |
717 | 0 | HashEnd(&hashState, remaining, mask); |
718 | 0 | if(remaining <= hDef->digestSize) |
719 | 0 | break; |
720 | 0 | mask = &mask[hDef->digestSize]; |
721 | 0 | counter++; |
722 | 0 | } |
723 | 0 | return (UINT16)mSize; |
724 | 0 | } |
725 | | /* 10.2.14.8.2 CryptKDFa() */ |
726 | | /* This function performs the key generation according to Part 1 of the TPM specification. */ |
727 | | /* This function returns the number of bytes generated which may be zero. */ |
728 | | /* The key and keyStream pointers are not allowed to be NULL. The other pointer values may be |
729 | | NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). */ |
730 | | /* The once parameter is set to allow incremental generation of a large value. If this flag is TRUE, |
731 | | sizeInBits will be used in the HMAC computation but only one iteration of the KDF is |
732 | | performed. This would be used for XOR obfuscation so that the mask value can be generated in |
733 | | digest-sized chunks rather than having to be generated all at once in an arbitrarily large buffer |
734 | | and then XORed() into the result. If once is TRUE, then sizeInBits must be a multiple of 8. */ |
735 | | /* Any error in the processing of this command is considered fatal. */ |
736 | | /* Return Values Meaning */ |
737 | | /* 0 hash algorithm is not supported or is TPM_ALG_NULL */ |
738 | | /* > 0 the number of bytes in the keyStream buffer */ |
739 | | LIB_EXPORT UINT16 |
740 | | CryptKDFa( |
741 | | TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
742 | | const TPM2B *key, // IN: HMAC key |
743 | | const TPM2B *label, // IN: a label for the KDF |
744 | | const TPM2B *contextU, // IN: context U |
745 | | const TPM2B *contextV, // IN: context V |
746 | | UINT32 sizeInBits, // IN: size of generated key in bits |
747 | | BYTE *keyStream, // OUT: key buffer |
748 | | UINT32 *counterInOut, // IN/OUT: caller may provide the iteration |
749 | | // counter for incremental operations to |
750 | | // avoid large intermediate buffers. |
751 | | UINT16 blocks // IN: If non-zero, this is the maximum number |
752 | | // of blocks to be returned, regardless of sizeInBits |
753 | | ) |
754 | 0 | { |
755 | 0 | UINT32 counter = 0; // counter value |
756 | 0 | INT16 bytes; // number of bytes to produce |
757 | 0 | UINT16 generated; // number of bytes generated |
758 | 0 | BYTE *stream = keyStream; |
759 | 0 | HMAC_STATE hState; |
760 | 0 | UINT16 digestSize = CryptHashGetDigestSize(hashAlg); |
761 | 0 | pAssert(key != NULL && keyStream != NULL); |
762 | 0 | TEST(TPM_ALG_KDF1_SP800_108); |
763 | 0 | if(digestSize == 0) |
764 | 0 | return 0; |
765 | 0 | if(counterInOut != NULL) |
766 | 0 | counter = *counterInOut; |
767 | | // If the size of the request is larger than the numbers will handle, |
768 | | // it is a fatal error. |
769 | 0 | pAssert(((sizeInBits + 7) / 8) <= INT16_MAX); |
770 | | // The number of bytes to be generated is the smaller of the sizeInBits bytes or |
771 | | // the number of requested blocks. The number of blocks is the smaller of the |
772 | | // number requested or the number allowed by sizeInBits. A partial block is |
773 | | // a full block. |
774 | 0 | bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits); |
775 | 0 | generated = bytes; |
776 | | // Generate required bytes |
777 | 0 | for(; bytes > 0; bytes -= digestSize) |
778 | 0 | { |
779 | 0 | counter++; |
780 | | // Start HMAC |
781 | 0 | if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0) |
782 | 0 | return 0; |
783 | | // Adding counter |
784 | 0 | CryptDigestUpdateInt(&hState.hashState, 4, counter); |
785 | | // Adding label |
786 | 0 | if(label != NULL) |
787 | 0 | HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer); |
788 | | // Add a null. SP108 is not very clear about when the 0 is needed but to |
789 | | // make this like the previous version that did not add an 0x00 after |
790 | | // a null-terminated string, this version will only add a null byte |
791 | | // if the label parameter did not end in a null byte, or if no label |
792 | | // is present. |
793 | 0 | if((label == NULL) |
794 | 0 | || (label->size == 0) |
795 | 0 | || (label->buffer[label->size - 1] != 0)) |
796 | 0 | CryptDigestUpdateInt(&hState.hashState, 1, 0); |
797 | | // Adding contextU |
798 | 0 | if(contextU != NULL) |
799 | 0 | HASH_DATA(&hState.hashState, contextU->size, contextU->buffer); |
800 | | // Adding contextV |
801 | 0 | if(contextV != NULL) |
802 | 0 | HASH_DATA(&hState.hashState, contextV->size, contextV->buffer); |
803 | | // Adding size in bits |
804 | 0 | CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits); |
805 | | // Complete and put the data in the buffer |
806 | 0 | CryptHmacEnd(&hState, bytes, stream); |
807 | 0 | stream = &stream[digestSize]; |
808 | 0 | } |
809 | | // Masking in the KDF is disabled. If the calling function wants something |
810 | | // less than even number of bytes, then the caller should do the masking |
811 | | // because there is no universal way to do it here |
812 | 0 | if(counterInOut != NULL) |
813 | 0 | *counterInOut = counter; |
814 | 0 | return generated; |
815 | 0 | } |
816 | | /* 10.2.14.8.3 CryptKDFe() */ |
817 | | /* KDFe() as defined in TPM specification part 1. */ |
818 | | /* This function returns the number of bytes generated which may be zero. */ |
819 | | /* The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be |
820 | | NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any |
821 | | error in the processing of this command is considered fatal. */ |
822 | | /* Return Values Meaning */ |
823 | | /* 0 hash algorithm is not supported or is TPM_ALG_NULL */ |
824 | | /* > 0 the number of bytes in the keyStream buffer */ |
825 | | LIB_EXPORT UINT16 |
826 | | CryptKDFe( |
827 | | TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
828 | | TPM2B *Z, // IN: Z |
829 | | const TPM2B *label, // IN: a label value for the KDF |
830 | | TPM2B *partyUInfo, // IN: PartyUInfo |
831 | | TPM2B *partyVInfo, // IN: PartyVInfo |
832 | | UINT32 sizeInBits, // IN: size of generated key in bits |
833 | | BYTE *keyStream // OUT: key buffer |
834 | | ) |
835 | 0 | { |
836 | 0 | HASH_STATE hashState; |
837 | 0 | PHASH_DEF hashDef = CryptGetHashDef(hashAlg); |
838 | 0 | UINT32 counter = 0; // counter value |
839 | 0 | UINT16 hLen; |
840 | 0 | BYTE *stream = keyStream; |
841 | 0 | INT16 bytes; // number of bytes to generate |
842 | 0 | pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX); |
843 | | // |
844 | 0 | hLen = hashDef->digestSize; |
845 | 0 | bytes = (INT16)((sizeInBits + 7) / 8); |
846 | 0 | if(hashAlg == TPM_ALG_NULL || bytes == 0) |
847 | 0 | return 0; |
848 | | // Generate required bytes |
849 | | //The inner loop of that KDF uses: |
850 | | // Hash[i] := H(counter | Z | OtherInfo) (5) |
851 | | // Where: |
852 | | // Hash[i] the hash generated on the i-th iteration of the loop. |
853 | | // H() an approved hash function |
854 | | // counter a 32-bit counter that is initialized to 1 and incremented |
855 | | // on each iteration |
856 | | // Z the X coordinate of the product of a public ECC key and a |
857 | | // different private ECC key. |
858 | | // OtherInfo a collection of qualifying data for the KDF defined below. |
859 | | // In this specification, OtherInfo will be constructed by: |
860 | | // OtherInfo := Use | PartyUInfo | PartyVInfo |
861 | 0 | for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) |
862 | 0 | { |
863 | 0 | if(bytes < hLen) |
864 | 0 | hLen = bytes; |
865 | 0 | counter++; |
866 | | // Do the hash |
867 | 0 | CryptHashStart(&hashState, hashAlg); |
868 | | // Add counter |
869 | 0 | CryptDigestUpdateInt(&hashState, 4, counter); |
870 | | // Add Z |
871 | 0 | if(Z != NULL) |
872 | 0 | CryptDigestUpdate2B(&hashState, Z); |
873 | | // Add label |
874 | 0 | if(label != NULL) |
875 | 0 | CryptDigestUpdate2B(&hashState, label); |
876 | | // Add a null. SP108 is not very clear about when the 0 is needed but to |
877 | | // make this like the previous version that did not add an 0x00 after |
878 | | // a null-terminated string, this version will only add a null byte |
879 | | // if the label parameter did not end in a null byte, or if no label |
880 | | // is present. |
881 | 0 | if((label == NULL) |
882 | 0 | || (label->size == 0) |
883 | 0 | || (label->buffer[label->size - 1] != 0)) |
884 | 0 | CryptDigestUpdateInt(&hashState, 1, 0); |
885 | | // Add PartyUInfo |
886 | 0 | if(partyUInfo != NULL) |
887 | 0 | CryptDigestUpdate2B(&hashState, partyUInfo); |
888 | | // Add PartyVInfo |
889 | 0 | if(partyVInfo != NULL) |
890 | 0 | CryptDigestUpdate2B(&hashState, partyVInfo); |
891 | | // Compute Hash. hLen was changed to be the smaller of bytes or hLen |
892 | | // at the start of each iteration. |
893 | 0 | CryptHashEnd(&hashState, hLen, stream); |
894 | 0 | } |
895 | | // Mask off bits if the required bits is not a multiple of byte size |
896 | 0 | if((sizeInBits % 8) != 0) |
897 | 0 | keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); |
898 | 0 | return (UINT16)((sizeInBits + 7) / 8); |
899 | 0 | } |