Line | Count | Source (jump to first uncovered line) |
1 | | // This file was extracted from the TCG Published |
2 | | // Trusted Platform Module Library |
3 | | // Part 4: Supporting Routines |
4 | | // Family "2.0" |
5 | | // Level 00 Revision 01.16 |
6 | | // October 30, 2014 |
7 | | |
8 | | #include "TPM_Types.h" |
9 | | #include "CryptoEngine.h" // types shared by CryptUtil and CryptoEngine. |
10 | | // Includes the function prototypes for the |
11 | | // CryptoEngine functions. |
12 | | #include "Global.h" |
13 | | #include "InternalRoutines.h" |
14 | | #include "MemoryLib_fp.h" |
15 | | //#include "CryptSelfTest_fp.h" |
16 | | // |
17 | | // |
18 | | // 10.2.2 TranslateCryptErrors() |
19 | | // |
20 | | // This function converts errors from the cryptographic library into TPM_RC_VALUES. |
21 | | // |
22 | | // Error Returns Meaning |
23 | | // |
24 | | // TPM_RC_VALUE CRYPT_FAIL |
25 | | // TPM_RC_NO_RESULT CRYPT_NO_RESULT |
26 | | // TPM_RC_SCHEME CRYPT_SCHEME |
27 | | // TPM_RC_VALUE CRYPT_PARAMETER |
28 | | // TPM_RC_SIZE CRYPT_UNDERFLOW |
29 | | // TPM_RC_ECC_POINT CRYPT_POINT |
30 | | // TPM_RC_CANCELLED CRYPT_CANCEL |
31 | | // |
32 | | static TPM_RC |
33 | | TranslateCryptErrors ( |
34 | | CRYPT_RESULT retVal // IN: crypt error to evaluate |
35 | | ) |
36 | 6 | { |
37 | 6 | switch (retVal) |
38 | 6 | { |
39 | 5 | case CRYPT_SUCCESS: |
40 | 5 | return TPM_RC_SUCCESS; |
41 | 0 | case CRYPT_FAIL: |
42 | 0 | return TPM_RC_VALUE; |
43 | 1 | case CRYPT_NO_RESULT: |
44 | 1 | return TPM_RC_NO_RESULT; |
45 | 0 | case CRYPT_SCHEME: |
46 | 0 | return TPM_RC_SCHEME; |
47 | 0 | case CRYPT_PARAMETER: |
48 | 0 | return TPM_RC_RANGE; |
49 | 0 | case CRYPT_UNDERFLOW: |
50 | 0 | return TPM_RC_SIZE; |
51 | 0 | case CRYPT_POINT: |
52 | 0 | return TPM_RC_ECC_POINT; |
53 | 0 | case CRYPT_CANCEL: |
54 | 0 | return TPM_RC_CANCELED; |
55 | 0 | default: // CRYPT_HW_FAILURE and other unknown warnings |
56 | 0 | return TPM_RC_FAILURE; |
57 | 6 | } |
58 | 6 | } |
59 | | // |
60 | | // |
61 | | // 10.2.3 Random Number Generation Functions |
62 | | // |
63 | | #ifdef TPM_ALG_NULL //% |
64 | | #ifdef _DRBG_STATE_SAVE //% |
65 | | // |
66 | | // |
67 | | // 10.2.3.1 CryptDrbgGetPutState() |
68 | | // |
69 | | // Read or write the current state from the DRBG in the cryptoEngine. |
70 | | // |
71 | | void |
72 | | CryptDrbgGetPutState( |
73 | | GET_PUT direction // IN: Get from or put to DRBG |
74 | | ) |
75 | 462 | { |
76 | 462 | _cpri__DrbgGetPutState(direction, |
77 | 462 | sizeof(go.drbgState), |
78 | 462 | (BYTE *)&go.drbgState); |
79 | 462 | } |
80 | | #else //% 00 |
81 | | //%#define CryptDrbgGetPutState(ignored) // If not doing state save, turn this |
82 | | //% // into a null macro |
83 | | #endif //% |
84 | | // |
85 | | // |
86 | | // 10.2.3.2 CryptStirRandom() |
87 | | // |
88 | | // Stir random entropy |
89 | | // |
90 | | void |
91 | | CryptStirRandom( |
92 | | UINT32 entropySize, // IN: size of entropy buffer |
93 | | BYTE *buffer // IN: entropy buffer |
94 | | ) |
95 | 1 | { |
96 | | // RNG self testing code may be inserted here |
97 | | // Call crypto engine random number stirring function |
98 | 1 | _cpri__StirRandom(entropySize, buffer); |
99 | 1 | return; |
100 | 1 | } |
101 | | // |
102 | | // |
103 | | // 10.2.3.3 CryptGenerateRandom() |
104 | | // |
105 | | // This is the interface to _cpri__GenerateRandom(). |
106 | | // |
107 | | UINT16 |
108 | | CryptGenerateRandom( |
109 | | UINT16 randomSize, // IN: size of random number |
110 | | BYTE *buffer // OUT: buffer of random number |
111 | | ) |
112 | 1.84k | { |
113 | 1.84k | UINT16 result; |
114 | 1.84k | pAssert(randomSize <= MAX_RSA_KEY_BYTES || randomSize <= PRIMARY_SEED_SIZE); |
115 | 1.84k | if(randomSize == 0) |
116 | 0 | return 0; |
117 | | // Call crypto engine random number generation |
118 | 1.84k | result = _cpri__GenerateRandom(randomSize, buffer); |
119 | 1.84k | if(result != randomSize) |
120 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
121 | 1.84k | return result; |
122 | 1.84k | } |
123 | | #endif //TPM_ALG_NULL //% |
124 | | // |
125 | | // |
126 | | // 10.2.4 Hash/HMAC Functions |
127 | | // |
128 | | // 10.2.4.1 CryptGetContextAlg() |
129 | | // |
130 | | // This function returns the hash algorithm associated with a hash context. |
131 | | // |
132 | | #ifdef TPM_ALG_KEYEDHASH //% 1 |
133 | | TPM_ALG_ID |
134 | | CryptGetContextAlg( |
135 | | void *state // IN: the context to check |
136 | | ) |
137 | 0 | { |
138 | 0 | HASH_STATE *context = (HASH_STATE *)state; |
139 | 0 | return _cpri__GetContextAlg(&context->state); |
140 | 0 | } |
141 | | // |
142 | | // |
143 | | // 10.2.4.2 CryptStartHash() |
144 | | // |
145 | | // This function starts a hash and return the size, in bytes, of the digest. |
146 | | // |
147 | | // Return Value Meaning |
148 | | // |
149 | | // >0 the digest size of the algorithm |
150 | | // =0 the hashAlg was TPM_ALG_NULL |
151 | | // |
152 | | UINT16 |
153 | | CryptStartHash( |
154 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
155 | | HASH_STATE *hashState // OUT: the state of hash stack. It will be used |
156 | | // in hash update and completion |
157 | | ) |
158 | 78 | { |
159 | 78 | CRYPT_RESULT retVal = 0; |
160 | 78 | pAssert(hashState != NULL); |
161 | 78 | TEST_HASH(hashAlg); |
162 | 78 | hashState->type = HASH_STATE_EMPTY; |
163 | | // Call crypto engine start hash function |
164 | 78 | if((retVal = _cpri__StartHash(hashAlg, FALSE, &hashState->state)) > 0) |
165 | 78 | hashState->type = HASH_STATE_HASH; |
166 | 78 | return retVal; |
167 | 78 | } |
168 | | // |
169 | | // |
170 | | // |
171 | | // 10.2.4.3 CryptStartHashSequence() |
172 | | // |
173 | | // Start a hash stack for a sequence object and return the size, in bytes, of the digest. This call uses the |
174 | | // form of the hash state that requires context save and restored. |
175 | | // |
176 | | // Return Value Meaning |
177 | | // |
178 | | // >0 the digest size of the algorithm |
179 | | // =0 the hashAlg was TPM_ALG_NULL |
180 | | // |
181 | | UINT16 |
182 | | CryptStartHashSequence( |
183 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
184 | | HASH_STATE *hashState // OUT: the state of hash stack. It will be used |
185 | | // in hash update and completion |
186 | | ) |
187 | 0 | { |
188 | 0 | CRYPT_RESULT retVal = 0; |
189 | 0 | pAssert(hashState != NULL); |
190 | 0 | TEST_HASH(hashAlg); |
191 | 0 | hashState->type = HASH_STATE_EMPTY; |
192 | | // Call crypto engine start hash function |
193 | 0 | if((retVal = _cpri__StartHash(hashAlg, TRUE, &hashState->state)) > 0) |
194 | 0 | hashState->type = HASH_STATE_HASH; |
195 | 0 | return retVal; |
196 | 0 | } |
197 | | // |
198 | | // |
199 | | // 10.2.4.4 CryptStartHMAC() |
200 | | // |
201 | | // This function starts an HMAC sequence and returns the size of the digest that will be produced. |
202 | | // The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
203 | | // not alter the contents of this buffer until the hash sequence is completed or abandoned. |
204 | | // |
205 | | // Return Value Meaning |
206 | | // |
207 | | // >0 the digest size of the algorithm |
208 | | // =0 the hashAlg was TPM_ALG_NULL |
209 | | // |
210 | | UINT16 |
211 | | CryptStartHMAC( |
212 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
213 | | UINT16 keySize, // IN: the size of HMAC key in byte |
214 | | BYTE *key, // IN: HMAC key |
215 | | HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
216 | | // in HMAC update and completion |
217 | | ) |
218 | 3 | { |
219 | 3 | HASH_STATE *hashState = (HASH_STATE *)hmacState; |
220 | 3 | CRYPT_RESULT retVal; |
221 | | // This has to come before the pAssert in case we all calling this function |
222 | | // during testing. If so, the first instance will have no arguments but the |
223 | | // hash algorithm. The call from the test routine will have arguments. When |
224 | | // the second call is done, then we return to the test dispatcher. |
225 | 3 | TEST_HASH(hashAlg); |
226 | 3 | pAssert(hashState != NULL); |
227 | 3 | hashState->type = HASH_STATE_EMPTY; |
228 | 3 | if((retVal = _cpri__StartHMAC(hashAlg, FALSE, &hashState->state, keySize, key, |
229 | 3 | &hmacState->hmacKey.b)) > 0) |
230 | 3 | hashState->type = HASH_STATE_HMAC; |
231 | 3 | return retVal; |
232 | 3 | } |
233 | | // |
234 | | // |
235 | | // 10.2.4.5 CryptStartHMACSequence() |
236 | | // |
237 | | // This function starts an HMAC sequence and returns the size of the digest that will be produced. |
238 | | // The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
239 | | // not alter the contents of this buffer until the hash sequence is completed or abandoned. |
240 | | // This call is used to start a sequence HMAC that spans multiple TPM commands. |
241 | | // |
242 | | // Return Value Meaning |
243 | | // |
244 | | // >0 the digest size of the algorithm |
245 | | // =0 the hashAlg was TPM_ALG_NULL |
246 | | // |
247 | | UINT16 |
248 | | CryptStartHMACSequence( |
249 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
250 | | UINT16 keySize, // IN: the size of HMAC key in byte |
251 | | BYTE *key, // IN: HMAC key |
252 | | HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
253 | | // in HMAC update and completion |
254 | | ) |
255 | 0 | { |
256 | 0 | HASH_STATE *hashState = (HASH_STATE *)hmacState; |
257 | 0 | CRYPT_RESULT retVal; |
258 | 0 | TEST_HASH(hashAlg); |
259 | 0 | hashState->type = HASH_STATE_EMPTY; |
260 | 0 | if((retVal = _cpri__StartHMAC(hashAlg, TRUE, &hashState->state, |
261 | 0 | keySize, key, &hmacState->hmacKey.b)) > 0) |
262 | 0 | hashState->type = HASH_STATE_HMAC; |
263 | 0 | return retVal; |
264 | 0 | } |
265 | | // |
266 | | // |
267 | | // 10.2.4.6 CryptStartHMAC2B() |
268 | | // |
269 | | // This function starts an HMAC and returns the size of the digest that will be produced. |
270 | | // This function is provided to support the most common use of starting an HMAC with a TPM2B key. |
271 | | // The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
272 | | // not alter the contents of this buffer until the hash sequence is completed or abandoned. |
273 | | // |
274 | | // |
275 | | // |
276 | | // |
277 | | // Return Value Meaning |
278 | | // |
279 | | // >0 the digest size of the algorithm |
280 | | // =0 the hashAlg was TPM_ALG_NULL |
281 | | // |
282 | | LIB_EXPORT UINT16 |
283 | | CryptStartHMAC2B( |
284 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
285 | | TPM2B *key, // IN: HMAC key |
286 | | HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
287 | | // in HMAC update and completion |
288 | | ) |
289 | 3 | { |
290 | 3 | return CryptStartHMAC(hashAlg, key->size, key->buffer, hmacState); |
291 | 3 | } |
292 | | // |
293 | | // |
294 | | // 10.2.4.7 CryptStartHMACSequence2B() |
295 | | // |
296 | | // This function starts an HMAC sequence and returns the size of the digest that will be produced. |
297 | | // This function is provided to support the most common use of starting an HMAC with a TPM2B key. |
298 | | // The caller must provide a block of memory in which the hash sequence state is kept. The caller should |
299 | | // not alter the contents of this buffer until the hash sequence is completed or abandoned. |
300 | | // |
301 | | // Return Value Meaning |
302 | | // |
303 | | // >0 the digest size of the algorithm |
304 | | // =0 the hashAlg was TPM_ALG_NULL |
305 | | // |
306 | | UINT16 |
307 | | CryptStartHMACSequence2B( |
308 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm |
309 | | TPM2B *key, // IN: HMAC key |
310 | | HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used |
311 | | // in HMAC update and completion |
312 | | ) |
313 | 0 | { |
314 | 0 | return CryptStartHMACSequence(hashAlg, key->size, key->buffer, hmacState); |
315 | 0 | } |
316 | | // |
317 | | // |
318 | | // 10.2.4.8 CryptUpdateDigest() |
319 | | // |
320 | | // This function updates a digest (hash or HMAC) with an array of octets. |
321 | | // This function can be used for both HMAC and hash functions so the digestState is void so that either |
322 | | // state type can be passed. |
323 | | // |
324 | | LIB_EXPORT void |
325 | | CryptUpdateDigest( |
326 | | void *digestState, // IN: the state of hash stack |
327 | | UINT32 dataSize, // IN: the size of data |
328 | | BYTE *data // IN: data to be hashed |
329 | | ) |
330 | 110 | { |
331 | 110 | HASH_STATE *hashState = (HASH_STATE *)digestState; |
332 | 110 | pAssert(digestState != NULL); |
333 | 110 | if(hashState->type != HASH_STATE_EMPTY && data != NULL && dataSize != 0) |
334 | 110 | { |
335 | | // Call crypto engine update hash function |
336 | 110 | _cpri__UpdateHash(&hashState->state, dataSize, data); |
337 | 110 | } |
338 | 110 | return; |
339 | 110 | } |
340 | | // |
341 | | // |
342 | | // 10.2.4.9 CryptUpdateDigest2B() |
343 | | // |
344 | | // This function updates a digest (hash or HMAC) with a TPM2B. |
345 | | // This function can be used for both HMAC and hash functions so the digestState is void so that either |
346 | | // state type can be passed. |
347 | | // |
348 | | LIB_EXPORT void |
349 | | CryptUpdateDigest2B( |
350 | | void *digestState, // IN: the digest state |
351 | | TPM2B *bIn // IN: 2B containing the data |
352 | | ) |
353 | 60 | { |
354 | | // Only compute the digest if a pointer to the 2B is provided. |
355 | | // In CryptUpdateDigest(), if size is zero or buffer is NULL, then no change |
356 | | // to the digest occurs. This function should not provide a buffer if bIn is |
357 | | // not provided. |
358 | 60 | if(bIn != NULL) |
359 | 60 | CryptUpdateDigest(digestState, bIn->size, bIn->buffer); |
360 | 60 | return; |
361 | 60 | } |
362 | | // |
363 | | // |
364 | | // 10.2.4.10 CryptUpdateDigestInt() |
365 | | // |
366 | | // This function is used to include an integer value to a hash stack. The function marshals the integer into its |
367 | | // canonical form before calling CryptUpdateHash(). |
368 | | // |
369 | | LIB_EXPORT void |
370 | | CryptUpdateDigestInt( |
371 | | void *state, // IN: the state of hash stack |
372 | | UINT32 intSize, // IN: the size of 'intValue' in byte |
373 | | void *intValue // IN: integer value to be hashed |
374 | | ) |
375 | 3 | { |
376 | | #if BIG_ENDIAN_TPM == YES |
377 | | pAssert( intValue != NULL && (intSize == 1 || intSize == 2 |
378 | | || intSize == 4 || intSize == 8)); |
379 | | CryptUpdateHash(state, inSize, (BYTE *)intValue); |
380 | | #else |
381 | 3 | BYTE marshalBuffer[8]; |
382 | | // Point to the big end of an little-endian value |
383 | 3 | BYTE *p = &((BYTE *)intValue)[intSize - 1]; |
384 | | // Point to the big end of an big-endian value |
385 | 3 | BYTE *q = marshalBuffer; |
386 | 3 | pAssert(intValue != NULL); |
387 | 3 | switch (intSize) |
388 | 3 | { |
389 | 0 | case 8: |
390 | 0 | *q++ = *p--; |
391 | 0 | *q++ = *p--; |
392 | 0 | *q++ = *p--; |
393 | 0 | *q++ = *p--; |
394 | 0 | case 4: |
395 | 0 | *q++ = *p--; |
396 | 0 | *q++ = *p--; |
397 | 3 | case 2: |
398 | 3 | *q++ = *p--; |
399 | 3 | case 1: |
400 | 3 | *q = *p; |
401 | | // Call update the hash |
402 | 3 | CryptUpdateDigest(state, intSize, marshalBuffer); |
403 | 3 | break; |
404 | 0 | default: |
405 | 0 | FAIL(0); |
406 | 3 | } |
407 | 3 | #endif |
408 | 3 | return; |
409 | 3 | } |
410 | | // |
411 | | // |
412 | | // 10.2.4.11 CryptCompleteHash() |
413 | | // |
414 | | // This function completes a hash sequence and returns the digest. |
415 | | // This function can be called to complete either an HMAC or hash sequence. The state type determines if |
416 | | // the context type is a hash or HMAC. If an HMAC, then the call is forwarded to CryptCompleteHash(). |
417 | | // If digestSize is smaller than the digest size of hash/HMAC algorithm, the most significant bytes of |
418 | | // required size will be returned |
419 | | // |
420 | | // Return Value Meaning |
421 | | // |
422 | | // >=0 the number of bytes placed in digest |
423 | | // |
424 | | LIB_EXPORT UINT16 |
425 | | CryptCompleteHash( |
426 | | void *state, // IN: the state of hash stack |
427 | | UINT16 digestSize, // IN: size of digest buffer |
428 | | BYTE *digest // OUT: hash digest |
429 | | ) |
430 | 78 | { |
431 | 78 | HASH_STATE *hashState = (HASH_STATE *)state; // local value |
432 | | // If the session type is HMAC, then could forward this to |
433 | | // the HMAC processing and not cause an error. However, if no |
434 | | // function calls this routine to forward it, then we can't get |
435 | | // test coverage. The decision is to assert if this is called with |
436 | | // the type == HMAC and fix anything that makes the wrong call. |
437 | 78 | pAssert(hashState->type == HASH_STATE_HASH); |
438 | | // Set the state to empty so that it doesn't get used again |
439 | 78 | hashState->type = HASH_STATE_EMPTY; |
440 | | // Call crypto engine complete hash function |
441 | 78 | return _cpri__CompleteHash(&hashState->state, digestSize, digest); |
442 | 78 | } |
443 | | // |
444 | | // |
445 | | // 10.2.4.12 CryptCompleteHash2B() |
446 | | // |
447 | | // This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the most |
448 | | // common use and this is provided for specification clarity. 'digest.size' should be set to indicate the number |
449 | | // of bytes to place in the buffer |
450 | | // |
451 | | // |
452 | | // |
453 | | // |
454 | | // Return Value Meaning |
455 | | // |
456 | | // >=0 the number of bytes placed in 'digest.buffer' |
457 | | // |
458 | | LIB_EXPORT UINT16 |
459 | | CryptCompleteHash2B( |
460 | | void *state, // IN: the state of hash stack |
461 | | TPM2B *digest // IN: the size of the buffer Out: requested |
462 | | // number of byte |
463 | | ) |
464 | 6 | { |
465 | 6 | UINT16 retVal = 0; |
466 | 6 | if(digest != NULL) |
467 | 6 | retVal = CryptCompleteHash(state, digest->size, digest->buffer); |
468 | 6 | return retVal; |
469 | 6 | } |
470 | | // |
471 | | // |
472 | | // 10.2.4.13 CryptHashBlock() |
473 | | // |
474 | | // Hash a block of data and return the results. If the digest is larger than retSize, it is truncated and with the |
475 | | // least significant octets dropped. |
476 | | // |
477 | | // Return Value Meaning |
478 | | // |
479 | | // >=0 the number of bytes placed in ret |
480 | | // |
481 | | LIB_EXPORT UINT16 |
482 | | CryptHashBlock( |
483 | | TPM_ALG_ID algId, // IN: the hash algorithm to use |
484 | | UINT16 blockSize, // IN: size of the data block |
485 | | BYTE *block, // IN: address of the block to hash |
486 | | UINT16 retSize, // IN: size of the return buffer |
487 | | BYTE *ret // OUT: address of the buffer |
488 | | ) |
489 | 0 | { |
490 | 0 | TEST_HASH(algId); |
491 | 0 | return _cpri__HashBlock(algId, blockSize, block, retSize, ret); |
492 | 0 | } |
493 | | // |
494 | | // |
495 | | // 10.2.4.14 CryptCompleteHMAC() |
496 | | // |
497 | | // This function completes a HMAC sequence and returns the digest. If digestSize is smaller than the digest |
498 | | // size of the HMAC algorithm, the most significant bytes of required size will be returned. |
499 | | // |
500 | | // Return Value Meaning |
501 | | // |
502 | | // >=0 the number of bytes placed in digest |
503 | | // |
504 | | LIB_EXPORT UINT16 |
505 | | CryptCompleteHMAC( |
506 | | HMAC_STATE *hmacState, // IN: the state of HMAC stack |
507 | | UINT32 digestSize, // IN: size of digest buffer |
508 | | BYTE *digest // OUT: HMAC digest |
509 | | ) |
510 | 3 | { |
511 | 3 | HASH_STATE *hashState; |
512 | 3 | pAssert(hmacState != NULL); |
513 | 3 | hashState = &hmacState->hashState; |
514 | 3 | pAssert(hashState->type == HASH_STATE_HMAC); |
515 | 3 | hashState->type = HASH_STATE_EMPTY; |
516 | 3 | return _cpri__CompleteHMAC(&hashState->state, &hmacState->hmacKey.b, |
517 | 3 | digestSize, digest); |
518 | 3 | } |
519 | | // |
520 | | // |
521 | | // 10.2.4.15 CryptCompleteHMAC2B() |
522 | | // |
523 | | // This function is the same as CryptCompleteHMAC() but the HMAC result is returned in a TPM2B which is |
524 | | // the most common use. |
525 | | // |
526 | | // Return Value Meaning |
527 | | // |
528 | | // >=0 the number of bytes placed in digest |
529 | | // |
530 | | LIB_EXPORT UINT16 |
531 | | CryptCompleteHMAC2B( |
532 | | HMAC_STATE *hmacState, // IN: the state of HMAC stack |
533 | | TPM2B *digest // OUT: HMAC |
534 | | ) |
535 | 3 | { |
536 | 3 | UINT16 retVal = 0; |
537 | 3 | if(digest != NULL) |
538 | 3 | retVal = CryptCompleteHMAC(hmacState, digest->size, digest->buffer); |
539 | 3 | return retVal; |
540 | 3 | } |
541 | | // |
542 | | // |
543 | | // 10.2.4.16 CryptHashStateImportExport() |
544 | | // |
545 | | // This function is used to prepare a hash state context for LIB_EXPORT or to import it into the internal |
546 | | // format. It is used by TPM2_ContextSave() and TPM2_ContextLoad() via SequenceDataImportExport(). |
547 | | // This is just a pass-through function to the crypto library. |
548 | | // |
549 | | void |
550 | | CryptHashStateImportExport( |
551 | | HASH_STATE *internalFmt, // IN: state to LIB_EXPORT |
552 | | HASH_STATE *externalFmt, // OUT: exported state |
553 | | IMPORT_EXPORT direction |
554 | | ) |
555 | 0 | { |
556 | 0 | _cpri__ImportExportHashState(&internalFmt->state, |
557 | 0 | (EXPORT_HASH_STATE *)&externalFmt->state, |
558 | 0 | direction); |
559 | 0 | } |
560 | | // |
561 | | // |
562 | | // 10.2.4.17 CryptGetHashDigestSize() |
563 | | // |
564 | | // This function returns the digest size in bytes for a hash algorithm. |
565 | | // |
566 | | // Return Value Meaning |
567 | | // |
568 | | // 0 digest size for TPM_ALG_NULL |
569 | | // >0 digest size |
570 | | // |
571 | | LIB_EXPORT UINT16 |
572 | | CryptGetHashDigestSize( |
573 | | TPM_ALG_ID hashAlg // IN: hash algorithm |
574 | | ) |
575 | 22.2k | { |
576 | 22.2k | return _cpri__GetDigestSize(hashAlg); |
577 | 22.2k | } |
578 | | // |
579 | | // |
580 | | // 10.2.4.18 CryptGetHashBlockSize() |
581 | | // |
582 | | // Get the digest size in byte of a hash algorithm. |
583 | | // |
584 | | // Return Value Meaning |
585 | | // |
586 | | // 0 block size for TPM_ALG_NULL |
587 | | // >0 block size |
588 | | // |
589 | | LIB_EXPORT UINT16 |
590 | | CryptGetHashBlockSize( |
591 | | TPM_ALG_ID hash // IN: hash algorithm to look up |
592 | | ) |
593 | 0 | { |
594 | 0 | return _cpri__GetHashBlockSize(hash); |
595 | 0 | } |
596 | | // |
597 | | // |
598 | | // 10.2.4.19 CryptGetHashAlgByIndex() |
599 | | // |
600 | | // This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are |
601 | | // not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first |
602 | | // implemented hash and an index value of 2 will return the last implemented hash. All other index values |
603 | | // will return TPM_ALG_NULL. |
604 | | // |
605 | | // Return Value Meaning |
606 | | // |
607 | | // TPM_ALG_xxx() a hash algorithm |
608 | | // TPM_ALG_NULL this can be used as a stop value |
609 | | // |
610 | | LIB_EXPORT TPM_ALG_ID |
611 | | CryptGetHashAlgByIndex( |
612 | | UINT32 index // IN: the index |
613 | | ) |
614 | 924 | { |
615 | 924 | return _cpri__GetHashAlgByIndex(index); |
616 | 924 | } |
617 | | // |
618 | | // |
619 | | // 10.2.4.20 CryptSignHMAC() |
620 | | // |
621 | | // Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message. |
622 | | // |
623 | | // Error Returns Meaning |
624 | | // |
625 | | static TPM_RC |
626 | | CryptSignHMAC( |
627 | | OBJECT *signKey, // IN: HMAC key sign the hash |
628 | | TPMT_SIG_SCHEME *scheme, // IN: signing scheme |
629 | | TPM2B_DIGEST *hashData, // IN: hash to be signed |
630 | | TPMT_SIGNATURE *signature // OUT: signature |
631 | | ) |
632 | 0 | { |
633 | | // |
634 | 0 | HMAC_STATE hmacState; |
635 | 0 | UINT32 digestSize; |
636 | |
|
637 | 0 | if (signature->sigAlg != TPM_ALG_HMAC) |
638 | 0 | return TPM_RC_SCHEME; |
639 | | // HMAC algorithm self testing code may be inserted here |
640 | 0 | digestSize = CryptStartHMAC2B(scheme->details.hmac.hashAlg, |
641 | 0 | &signKey->sensitive.sensitive.bits.b, |
642 | 0 | &hmacState); |
643 | | // The hash algorithm must be a valid one. |
644 | 0 | pAssert(digestSize > 0); |
645 | 0 | CryptUpdateDigest2B(&hmacState, &hashData->b); |
646 | 0 | CryptCompleteHMAC(&hmacState, digestSize, |
647 | 0 | (BYTE *) &signature->signature.hmac.digest); |
648 | | // Set HMAC algorithm |
649 | 0 | signature->signature.hmac.hashAlg = scheme->details.hmac.hashAlg; |
650 | 0 | return TPM_RC_SUCCESS; |
651 | 0 | } |
652 | | // |
653 | | // |
654 | | // 10.2.4.21 CryptHMACVerifySignature() |
655 | | // |
656 | | // This function will verify a signature signed by a HMAC key. |
657 | | // |
658 | | // Error Returns Meaning |
659 | | // |
660 | | // TPM_RC_SIGNATURE if invalid input or signature is not genuine |
661 | | // |
662 | | static TPM_RC |
663 | | CryptHMACVerifySignature( |
664 | | OBJECT *signKey, // IN: HMAC key signed the hash |
665 | | TPM2B_DIGEST *hashData, // IN: digest being verified |
666 | | TPMT_SIGNATURE *signature // IN: signature to be verified |
667 | | ) |
668 | 0 | { |
669 | 0 | HMAC_STATE hmacState; |
670 | 0 | TPM2B_DIGEST digestToCompare; |
671 | 0 | digestToCompare.t.size = CryptStartHMAC2B(signature->signature.hmac.hashAlg, |
672 | 0 | &signKey->sensitive.sensitive.bits.b, &hmacState); |
673 | 0 | CryptUpdateDigest2B(&hmacState, &hashData->b); |
674 | 0 | CryptCompleteHMAC2B(&hmacState, &digestToCompare.b); |
675 | | // Compare digest |
676 | 0 | if(MemoryEqual(digestToCompare.t.buffer, |
677 | 0 | (BYTE *) &signature->signature.hmac.digest, |
678 | 0 | digestToCompare.t.size)) |
679 | 0 | return TPM_RC_SUCCESS; |
680 | 0 | else |
681 | 0 | return TPM_RC_SIGNATURE; |
682 | 0 | } |
683 | | // |
684 | | // |
685 | | // 10.2.4.22 CryptGenerateKeyedHash() |
686 | | // |
687 | | // This function creates a keyedHash object. |
688 | | // |
689 | | // |
690 | | // |
691 | | // Error Returns Meaning |
692 | | // |
693 | | // TPM_RC_SIZE sensitive data size is larger than allowed for the scheme |
694 | | // TPM_RC_VALUE the publicArea nameAlg is invalid |
695 | | // |
696 | | static TPM_RC |
697 | | CryptGenerateKeyedHash( |
698 | | TPMT_PUBLIC *publicArea, // IN/OUT: the public area template |
699 | | // for the new key. |
700 | | TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data |
701 | | TPMT_SENSITIVE *sensitive, // OUT: sensitive area |
702 | | TPM_ALG_ID kdfHashAlg, // IN: algorithm for the KDF |
703 | | TPM2B_SEED *seed, // IN: the seed |
704 | | TPM2B_NAME *name // IN: name of the object |
705 | | ) |
706 | 0 | { |
707 | 0 | TPMT_KEYEDHASH_SCHEME *scheme; |
708 | 0 | TPM_ALG_ID hashAlg; |
709 | 0 | UINT16 hashBlockSize; |
710 | | // Check parameter values |
711 | 0 | if(publicArea->nameAlg == TPM_ALG_NULL) |
712 | 0 | { |
713 | 0 | return TPM_RC_VALUE; |
714 | 0 | } |
715 | 0 | scheme = &publicArea->parameters.keyedHashDetail.scheme; |
716 | 0 | pAssert(publicArea->type == TPM_ALG_KEYEDHASH); |
717 | | // Pick the limiting hash algorithm |
718 | 0 | if(scheme->scheme == TPM_ALG_NULL) |
719 | 0 | hashAlg = publicArea->nameAlg; |
720 | 0 | else if(scheme->scheme == TPM_ALG_XOR) |
721 | 0 | hashAlg = scheme->details.xor_.hashAlg; |
722 | 0 | else |
723 | 0 | hashAlg = scheme->details.hmac.hashAlg; |
724 | 0 | hashBlockSize = CryptGetHashBlockSize(hashAlg); |
725 | | // if this is a signing or a decryption key, then then the limit |
726 | | // for the data size is the block size of the hash. This limit |
727 | | // is set because larger values have lower entropy because of the |
728 | | // HMAC function. |
729 | 0 | if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR) |
730 | 0 | { |
731 | 0 | if( ( publicArea->objectAttributes.decrypt |
732 | 0 | || publicArea->objectAttributes.sign) |
733 | 0 | && sensitiveCreate->data.t.size > hashBlockSize) |
734 | 0 | return TPM_RC_SIZE; |
735 | 0 | } |
736 | 0 | else |
737 | 0 | { |
738 | | // If the TPM is going to generate the data, then set the size to be the |
739 | | // size of the digest of the algorithm |
740 | 0 | sensitive->sensitive.sym.t.size = CryptGetHashDigestSize(hashAlg); |
741 | 0 | sensitiveCreate->data.t.size = 0; |
742 | 0 | } |
743 | | // Fill in the sensitive area |
744 | 0 | CryptGenerateNewSymmetric(sensitiveCreate, sensitive, kdfHashAlg, |
745 | 0 | seed, name); |
746 | | // Create unique area in public |
747 | 0 | CryptComputeSymmetricUnique(publicArea->nameAlg, |
748 | 0 | sensitive, &publicArea->unique.sym); |
749 | 0 | return TPM_RC_SUCCESS; |
750 | 0 | } |
751 | | // |
752 | | // |
753 | | // 10.2.4.25 KDFa() |
754 | | // |
755 | | // This function is used by functions outside of CryptUtil() to access _cpri_KDFa(). |
756 | | // |
757 | | void |
758 | | KDFa( |
759 | | TPM_ALG_ID hash, // IN: hash algorithm used in HMAC |
760 | | TPM2B *key, // IN: HMAC key |
761 | | const char *label, // IN: a null-terminated label for KDF |
762 | | TPM2B *contextU, // IN: context U |
763 | | TPM2B *contextV, // IN: context V |
764 | | UINT32 sizeInBits, // IN: size of generated key in bit |
765 | | BYTE *keyStream, // OUT: key buffer |
766 | | UINT32 *counterInOut // IN/OUT: caller may provide the iteration |
767 | | // counter for incremental operations to |
768 | | // avoid large intermediate buffers. |
769 | | ) |
770 | 0 | { |
771 | 0 | CryptKDFa(hash, key, label, contextU, contextV, sizeInBits, |
772 | 0 | keyStream, counterInOut); |
773 | 0 | } |
774 | | #endif //TPM_ALG_KEYEDHASH //% 1 |
775 | | // |
776 | | // |
777 | | // 10.2.5 RSA Functions |
778 | | // |
779 | | // 10.2.5.1 BuildRSA() |
780 | | // |
781 | | // Function to set the cryptographic elements of an RSA key into a structure to simplify the interface to |
782 | | // _cpri__ RSA function. This can/should be eliminated by building this structure into the object structure. |
783 | | // |
784 | | #ifdef TPM_ALG_RSA //% 2 |
785 | | static void |
786 | | BuildRSA( |
787 | | OBJECT *rsaKey, |
788 | | RSA_KEY *key |
789 | | ) |
790 | 0 | { |
791 | 0 | key->exponent = rsaKey->publicArea.parameters.rsaDetail.exponent; |
792 | 0 | if(key->exponent == 0) |
793 | 0 | key->exponent = RSA_DEFAULT_PUBLIC_EXPONENT; |
794 | 0 | key->publicKey = &rsaKey->publicArea.unique.rsa.b; |
795 | 0 | if(rsaKey->attributes.publicOnly || rsaKey->privateExponent.t.size == 0) |
796 | 0 | key->privateKey = NULL; |
797 | 0 | else |
798 | 0 | key->privateKey = &(rsaKey->privateExponent.b); |
799 | 0 | } |
800 | | // |
801 | | // |
802 | | // 10.2.5.2 CryptTestKeyRSA() |
803 | | // |
804 | | // This function provides the interface to _cpri__TestKeyRSA(). If both p and q are provided, n will be set to |
805 | | // p*q. |
806 | | // If only p is provided, q is computed by q = n/p. If n mod p != 0, TPM_RC_BINDING is returned. |
807 | | // The key is validated by checking that a d can be found such that e d mod ((p-1)*(q-1)) = 1. If d is found |
808 | | // that satisfies this requirement, it will be placed in d. |
809 | | // Page 286 TCG Published Family "2.0" |
810 | | // October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16 |
811 | | // Part 4: Supporting Routines Trusted Platform Module Library |
812 | | // |
813 | | // |
814 | | // Error Returns Meaning |
815 | | // |
816 | | // TPM_RC_BINDING the public and private portions of the key are not matched |
817 | | // |
818 | | TPM_RC |
819 | | CryptTestKeyRSA( |
820 | | TPM2B *d, // OUT: receives the private exponent |
821 | | UINT32 e, // IN: public exponent |
822 | | TPM2B *n, // IN/OUT: public modulu |
823 | | TPM2B *p, // IN: a first prime |
824 | | TPM2B *q // IN: an optional second prime |
825 | | ) |
826 | 32 | { |
827 | 32 | CRYPT_RESULT retVal; |
828 | 32 | TEST(ALG_NULL_VALUE); |
829 | 32 | pAssert(d != NULL && n != NULL && p != NULL); |
830 | | // Set the exponent |
831 | 32 | if(e == 0) |
832 | 1 | e = RSA_DEFAULT_PUBLIC_EXPONENT; |
833 | | // CRYPT_PARAMETER |
834 | 32 | retVal =_cpri__TestKeyRSA(d, e, n, p, q); |
835 | 32 | if(retVal == CRYPT_SUCCESS) |
836 | 1 | return TPM_RC_SUCCESS; |
837 | 31 | else |
838 | 31 | return TPM_RC_BINDING; // convert CRYPT_PARAMETER |
839 | 32 | } |
840 | | // |
841 | | // |
842 | | // 10.2.5.3 CryptGenerateKeyRSA() |
843 | | // |
844 | | // This function is called to generate an RSA key from a provided seed. It calls _cpri__GenerateKeyRSA() |
845 | | // to perform the computations. The implementation is vendor specific. |
846 | | // |
847 | | // Error Returns Meaning |
848 | | // |
849 | | // TPM_RC_RANGE the exponent value is not supported |
850 | | // TPM_RC_CANCELLED key generation has been canceled |
851 | | // TPM_RC_VALUE exponent is not prime or is less than 3; or could not find a prime using |
852 | | // the provided parameters |
853 | | // |
854 | | static TPM_RC |
855 | | CryptGenerateKeyRSA( |
856 | | TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for |
857 | | // the new key. The public key |
858 | | // area will be replaced by the |
859 | | // product of two primes found by |
860 | | // this function |
861 | | TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be |
862 | | // updated to contain the first |
863 | | // prime and the symmetric |
864 | | // encryption key |
865 | | TPM_ALG_ID hashAlg, // IN: the hash algorithm for the KDF |
866 | | TPM2B_SEED *seed, // IN: Seed for the creation |
867 | | TPM2B_NAME *name, // IN: Object name |
868 | | UINT32 *counter // OUT: last iteration of the counter |
869 | | ) |
870 | 3 | { |
871 | 3 | CRYPT_RESULT retVal; |
872 | 3 | UINT32 exponent = publicArea->parameters.rsaDetail.exponent; |
873 | 3 | TEST_HASH(hashAlg); |
874 | 3 | TEST(ALG_NULL_VALUE); |
875 | | // In this implementation, only the default exponent is allowed |
876 | 3 | if(exponent != 0 && exponent != RSA_DEFAULT_PUBLIC_EXPONENT) |
877 | 0 | return TPM_RC_RANGE; |
878 | 3 | exponent = RSA_DEFAULT_PUBLIC_EXPONENT; |
879 | 3 | *counter = 0; |
880 | | // _cpri_GenerateKeyRSA can return CRYPT_CANCEL or CRYPT_FAIL |
881 | 3 | retVal = _cpri__GenerateKeyRSA(&publicArea->unique.rsa.b, |
882 | 3 | &sensitive->sensitive.rsa.b, |
883 | 3 | publicArea->parameters.rsaDetail.keyBits, |
884 | 3 | exponent, |
885 | 3 | hashAlg, |
886 | 3 | &seed->b, |
887 | 3 | "RSA key by vendor", |
888 | 3 | &name->b, |
889 | 3 | counter); |
890 | | // CRYPT_CANCEL -> TPM_RC_CANCELLED; CRYPT_FAIL -> TPM_RC_VALUE |
891 | 3 | return TranslateCryptErrors(retVal); |
892 | 3 | } |
893 | | // |
894 | | // |
895 | | // 10.2.5.4 CryptLoadPrivateRSA() |
896 | | // |
897 | | // This function is called to generate the private exponent of an RSA key. It uses CryptTestKeyRSA(). |
898 | | // |
899 | | // Error Returns Meaning |
900 | | // |
901 | | // TPM_RC_BINDING public and private parts of rsaKey are not matched |
902 | | // |
903 | | TPM_RC |
904 | | CryptLoadPrivateRSA( |
905 | | OBJECT *rsaKey // IN: the RSA key object |
906 | | ) |
907 | 32 | { |
908 | 32 | TPM_RC result; |
909 | 32 | TPMT_PUBLIC *publicArea = &rsaKey->publicArea; |
910 | 32 | TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; |
911 | | // Load key by computing the private exponent |
912 | | // TPM_RC_BINDING |
913 | 32 | result = CryptTestKeyRSA(&(rsaKey->privateExponent.b), |
914 | 32 | publicArea->parameters.rsaDetail.exponent, |
915 | 32 | &(publicArea->unique.rsa.b), |
916 | 32 | &(sensitive->sensitive.rsa.b), |
917 | 32 | NULL); |
918 | 32 | if(result == TPM_RC_SUCCESS) |
919 | 1 | rsaKey->attributes.privateExp = SET; |
920 | 32 | return result; |
921 | 32 | } |
922 | | // |
923 | | // |
924 | | // 10.2.5.5 CryptSelectRSAScheme() |
925 | | // |
926 | | // This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a |
927 | | // scheme between input and object default. This function assume the RSA object is loaded. If a default |
928 | | // scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should |
929 | | // be chosen. In the case that both the object and scheme are not TPM_ALG_NULL, then if the schemes |
930 | | // |
931 | | // |
932 | | // are the same, the input scheme will be chosen. if the scheme are not compatible, a NULL pointer will be |
933 | | // returned. |
934 | | // The return pointer may point to a TPM_ALG_NULL scheme. |
935 | | // |
936 | | TPMT_RSA_DECRYPT* |
937 | | CryptSelectRSAScheme( |
938 | | TPMI_DH_OBJECT rsaHandle, // IN: handle of sign key |
939 | | TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme |
940 | | ) |
941 | 0 | { |
942 | 0 | OBJECT *rsaObject; |
943 | 0 | TPMT_ASYM_SCHEME *keyScheme; |
944 | 0 | TPMT_RSA_DECRYPT *retVal = NULL; |
945 | | // Get sign object pointer |
946 | 0 | rsaObject = ObjectGet(rsaHandle); |
947 | 0 | keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme; |
948 | | // if the default scheme of the object is TPM_ALG_NULL, then select the |
949 | | // input scheme |
950 | 0 | if(keyScheme->scheme == TPM_ALG_NULL) |
951 | 0 | { |
952 | 0 | retVal = scheme; |
953 | 0 | } |
954 | | // if the object scheme is not TPM_ALG_NULL and the input scheme is |
955 | | // TPM_ALG_NULL, then select the default scheme of the object. |
956 | 0 | else if(scheme->scheme == TPM_ALG_NULL) |
957 | 0 | { |
958 | | // if input scheme is NULL |
959 | 0 | retVal = (TPMT_RSA_DECRYPT *)keyScheme; |
960 | 0 | } |
961 | | // get here if both the object scheme and the input scheme are |
962 | | // not TPM_ALG_NULL. Need to insure that they are the same. |
963 | | // The hash algorithm match has to be verified for OAEP. |
964 | | // IMPLEMENTATION NOTE: This could cause problems if future versions have |
965 | | // schemes that have more values than just a hash algorithm. A new function |
966 | | // (IsSchemeSame()) might be needed then. |
967 | 0 | else if (keyScheme->scheme == scheme->scheme |
968 | 0 | && ((keyScheme->scheme != TPM_ALG_OAEP) || |
969 | 0 | (keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg))) |
970 | 0 | { |
971 | 0 | retVal = scheme; |
972 | 0 | } |
973 | | // two different, incompatible schemes specified will return NULL |
974 | 0 | return retVal; |
975 | 0 | } |
976 | | // |
977 | | // |
978 | | // 10.2.5.6 CryptDecryptRSA() |
979 | | // |
980 | | // This function is the interface to _cpri__DecryptRSA(). It handles the return codes from that function and |
981 | | // converts them from CRYPT_RESULT to TPM_RC values. The rsaKey parameter must reference an RSA |
982 | | // decryption key |
983 | | // |
984 | | // Error Returns Meaning |
985 | | // |
986 | | // TPM_RC_BINDING Public and private parts of the key are not cryptographically bound. |
987 | | // TPM_RC_SIZE Size of data to decrypt is not the same as the key size. |
988 | | // TPM_RC_VALUE Numeric value of the encrypted data is greater than the public |
989 | | // exponent, or output buffer is too small for the decrypted message. |
990 | | // |
991 | | TPM_RC |
992 | | CryptDecryptRSA( |
993 | | UINT16 *dataOutSize, // OUT: size of plain text in byte |
994 | | BYTE *dataOut, // OUT: plain text |
995 | | OBJECT *rsaKey, // IN: internal RSA key |
996 | | TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme |
997 | | UINT16 cipherInSize, // IN: size of cipher text in byte |
998 | | BYTE *cipherIn, // IN: cipher text |
999 | | const char *label // IN: a label, when needed |
1000 | | ) |
1001 | 0 | { |
1002 | 0 | RSA_KEY key; |
1003 | 0 | CRYPT_RESULT retVal = CRYPT_SUCCESS; |
1004 | 0 | UINT32 dSize; // Place to put temporary value for the |
1005 | | // returned data size |
1006 | 0 | TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in the selected |
1007 | | // padding scheme |
1008 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
1009 | | // pointer checks |
1010 | 0 | pAssert( (dataOutSize != NULL) && (dataOut != NULL) |
1011 | 0 | && (rsaKey != NULL) && (cipherIn != NULL)); |
1012 | | // The public type is a RSA decrypt key |
1013 | 0 | pAssert( (rsaKey->publicArea.type == TPM_ALG_RSA |
1014 | 0 | && rsaKey->publicArea.objectAttributes.decrypt == SET)); |
1015 | | // Must have the private portion loaded. This check is made before this |
1016 | | // function is called. |
1017 | 0 | pAssert(rsaKey->attributes.publicOnly == CLEAR); |
1018 | | // decryption requires that the private modulus be present |
1019 | 0 | if(rsaKey->attributes.privateExp == CLEAR) |
1020 | 0 | { |
1021 | | // Load key by computing the private exponent |
1022 | | // CryptLoadPrivateRSA may return TPM_RC_BINDING |
1023 | 0 | result = CryptLoadPrivateRSA(rsaKey); |
1024 | 0 | } |
1025 | | // the input buffer must be the size of the key |
1026 | 0 | if(result == TPM_RC_SUCCESS) |
1027 | 0 | { |
1028 | 0 | if(cipherInSize != rsaKey->publicArea.unique.rsa.t.size) |
1029 | 0 | result = TPM_RC_SIZE; |
1030 | 0 | else |
1031 | 0 | { |
1032 | 0 | BuildRSA(rsaKey, &key); |
1033 | | // Initialize the dOutSize parameter |
1034 | 0 | dSize = *dataOutSize; |
1035 | | // For OAEP scheme, initialize the hash algorithm for padding |
1036 | 0 | if(scheme->scheme == TPM_ALG_OAEP) |
1037 | 0 | { |
1038 | 0 | hashAlg = scheme->details.oaep.hashAlg; |
1039 | 0 | TEST_HASH(hashAlg); |
1040 | 0 | } |
1041 | | // See if the padding mode needs to be tested |
1042 | 0 | TEST(scheme->scheme); |
1043 | | // _cpri__DecryptRSA may return CRYPT_PARAMETER CRYPT_FAIL CRYPT_SCHEME |
1044 | 0 | retVal = _cpri__DecryptRSA(&dSize, dataOut, &key, scheme->scheme, |
1045 | 0 | cipherInSize, cipherIn, hashAlg, label); |
1046 | | // Scheme must have been validated when the key was loaded/imported |
1047 | 0 | pAssert(retVal != CRYPT_SCHEME); |
1048 | | // Set the return size |
1049 | 0 | pAssert(dSize <= UINT16_MAX); |
1050 | 0 | *dataOutSize = (UINT16)dSize; |
1051 | | // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_FAIL -> TPM_RC_VALUE |
1052 | 0 | result = TranslateCryptErrors(retVal); |
1053 | 0 | } |
1054 | 0 | } |
1055 | 0 | return result; |
1056 | 0 | } |
1057 | | // |
1058 | | // |
1059 | | // 10.2.5.7 CryptEncryptRSA() |
1060 | | // |
1061 | | // This function provides the interface to _cpri__EncryptRSA(). The object referenced by rsaKey is required |
1062 | | // to be an RSA decryption key. |
1063 | | // |
1064 | | // Error Returns Meaning |
1065 | | // |
1066 | | // TPM_RC_SCHEME scheme is not supported |
1067 | | // TPM_RC_VALUE numeric value of dataIn is greater than the key modulus |
1068 | | // |
1069 | | TPM_RC |
1070 | | CryptEncryptRSA( |
1071 | | UINT16 *cipherOutSize, // OUT: size of cipher text in byte |
1072 | | BYTE *cipherOut, // OUT: cipher text |
1073 | | OBJECT *rsaKey, // IN: internal RSA key |
1074 | | TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme |
1075 | | UINT16 dataInSize, // IN: size of plain text in byte |
1076 | | BYTE *dataIn, // IN: plain text |
1077 | | const char *label // IN: an optional label |
1078 | | ) |
1079 | 0 | { |
1080 | 0 | RSA_KEY key; |
1081 | 0 | CRYPT_RESULT retVal; |
1082 | 0 | UINT32 cOutSize; // Conversion variable |
1083 | 0 | TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in selected |
1084 | | // padding scheme |
1085 | | // must have a pointer to a key and some data to encrypt |
1086 | 0 | pAssert(rsaKey != NULL && dataIn != NULL); |
1087 | | // The public type is a RSA decryption key |
1088 | 0 | pAssert( rsaKey->publicArea.type == TPM_ALG_RSA |
1089 | 0 | && rsaKey->publicArea.objectAttributes.decrypt == SET); |
1090 | | // If the cipher buffer must be provided and it must be large enough |
1091 | | // for the result |
1092 | 0 | pAssert( cipherOut != NULL |
1093 | 0 | && cipherOutSize != NULL |
1094 | 0 | && *cipherOutSize >= rsaKey->publicArea.unique.rsa.t.size); |
1095 | | // Only need the public key and exponent for encryption |
1096 | 0 | BuildRSA(rsaKey, &key); |
1097 | | // Copy the size to the conversion buffer |
1098 | 0 | cOutSize = *cipherOutSize; |
1099 | | // For OAEP scheme, initialize the hash algorithm for padding |
1100 | 0 | if(scheme->scheme == TPM_ALG_OAEP) |
1101 | 0 | { |
1102 | 0 | hashAlg = scheme->details.oaep.hashAlg; |
1103 | 0 | TEST_HASH(hashAlg); |
1104 | 0 | } |
1105 | | // This is a public key operation and does not require that the private key |
1106 | | // be loaded. To verify this, need to do the full algorithm |
1107 | 0 | TEST(scheme->scheme); |
1108 | | // Encrypt the data with the public exponent |
1109 | | // _cpri__EncryptRSA may return CRYPT_PARAMETER or CRYPT_SCHEME |
1110 | 0 | retVal = _cpri__EncryptRSA(&cOutSize,cipherOut, &key, scheme->scheme, |
1111 | 0 | dataInSize, dataIn, hashAlg, label); |
1112 | 0 | pAssert (cOutSize <= UINT16_MAX); |
1113 | 0 | *cipherOutSize = (UINT16)cOutSize; |
1114 | | // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_SCHEME -> TPM_RC_SCHEME |
1115 | 0 | return TranslateCryptErrors(retVal); |
1116 | 0 | } |
1117 | | // |
1118 | | // |
1119 | | // 10.2.5.8 CryptSignRSA() |
1120 | | // |
1121 | | // This function is used to sign a digest with an RSA signing key. |
1122 | | // |
1123 | | // Error Returns Meaning |
1124 | | // |
1125 | | // TPM_RC_BINDING public and private part of signKey are not properly bound |
1126 | | // TPM_RC_SCHEME scheme is not supported |
1127 | | // TPM_RC_VALUE hashData is larger than the modulus of signKey, or the size of |
1128 | | // hashData does not match hash algorithm in scheme |
1129 | | // |
1130 | | static TPM_RC |
1131 | | CryptSignRSA( |
1132 | | OBJECT *signKey, // IN: RSA key signs the hash |
1133 | | TPMT_SIG_SCHEME *scheme, // IN: sign scheme |
1134 | | TPM2B_DIGEST *hashData, // IN: hash to be signed |
1135 | | TPMT_SIGNATURE *sig // OUT: signature |
1136 | | ) |
1137 | 0 | { |
1138 | 0 | UINT32 signSize; |
1139 | 0 | RSA_KEY key; |
1140 | 0 | CRYPT_RESULT retVal; |
1141 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
1142 | 0 | pAssert( (signKey != NULL) && (scheme != NULL) |
1143 | 0 | && (hashData != NULL) && (sig != NULL)); |
1144 | | // assume that the key has private part loaded and that it is a signing key. |
1145 | 0 | pAssert( (signKey->attributes.publicOnly == CLEAR) |
1146 | 0 | && (signKey->publicArea.objectAttributes.sign == SET)); |
1147 | | // check if the private exponent has been computed |
1148 | 0 | if(signKey->attributes.privateExp == CLEAR) |
1149 | | // May return TPM_RC_BINDING |
1150 | 0 | result = CryptLoadPrivateRSA(signKey); |
1151 | 0 | if(result == TPM_RC_SUCCESS) |
1152 | 0 | { |
1153 | 0 | BuildRSA(signKey, &key); |
1154 | | // Make sure that the hash is tested |
1155 | 0 | TEST_HASH(sig->signature.any.hashAlg); |
1156 | | // Run a test of the RSA sign |
1157 | 0 | TEST(scheme->scheme); |
1158 | | // _crypi__SignRSA can return CRYPT_SCHEME and CRYPT_PARAMETER |
1159 | 0 | retVal = _cpri__SignRSA(&signSize, |
1160 | 0 | sig->signature.rsassa.sig.t.buffer, |
1161 | 0 | &key, |
1162 | 0 | sig->sigAlg, |
1163 | 0 | sig->signature.any.hashAlg, |
1164 | 0 | hashData->t.size, hashData->t.buffer); |
1165 | 0 | pAssert(signSize <= UINT16_MAX); |
1166 | 0 | sig->signature.rsassa.sig.t.size = (UINT16)signSize; |
1167 | | // CRYPT_SCHEME -> TPM_RC_SCHEME; CRYPT_PARAMTER -> TPM_RC_VALUE |
1168 | 0 | result = TranslateCryptErrors(retVal); |
1169 | 0 | } |
1170 | 0 | return result; |
1171 | 0 | } |
1172 | | // |
1173 | | // |
1174 | | // 10.2.5.9 CryptRSAVerifySignature() |
1175 | | // |
1176 | | // This function is used to verify signature signed by a RSA key. |
1177 | | // |
1178 | | // Error Returns Meaning |
1179 | | // |
1180 | | // TPM_RC_SIGNATURE if signature is not genuine |
1181 | | // TPM_RC_SCHEME signature scheme not supported |
1182 | | // |
1183 | | static TPM_RC |
1184 | | CryptRSAVerifySignature( |
1185 | | OBJECT *signKey, // IN: RSA key signed the hash |
1186 | | TPM2B_DIGEST *digestData, // IN: digest being signed |
1187 | | TPMT_SIGNATURE *sig // IN: signature to be verified |
1188 | | ) |
1189 | 0 | { |
1190 | 0 | RSA_KEY key; |
1191 | 0 | CRYPT_RESULT retVal; |
1192 | 0 | TPM_RC result; |
1193 | | // Validate parameter assumptions |
1194 | 0 | pAssert((signKey != NULL) && (digestData != NULL) && (sig != NULL)); |
1195 | 0 | TEST_HASH(sig->signature.any.hashAlg); |
1196 | 0 | TEST(sig->sigAlg); |
1197 | | // This is a public-key-only operation |
1198 | 0 | BuildRSA(signKey, &key); |
1199 | | // Call crypto engine to verify signature |
1200 | | // _cpri_ValidateSignaturRSA may return CRYPT_FAIL or CRYPT_SCHEME |
1201 | 0 | retVal = _cpri__ValidateSignatureRSA(&key, |
1202 | 0 | sig->sigAlg, |
1203 | 0 | sig->signature.any.hashAlg, |
1204 | 0 | digestData->t.size, |
1205 | 0 | digestData->t.buffer, |
1206 | 0 | sig->signature.rsassa.sig.t.size, |
1207 | 0 | sig->signature.rsassa.sig.t.buffer, |
1208 | 0 | 0); |
1209 | | // _cpri__ValidateSignatureRSA can return CRYPT_SUCCESS, CRYPT_FAIL, or |
1210 | | // CRYPT_SCHEME. Translate CRYPT_FAIL to TPM_RC_SIGNATURE |
1211 | 0 | if(retVal == CRYPT_FAIL) |
1212 | 0 | result = TPM_RC_SIGNATURE; |
1213 | 0 | else |
1214 | | // CRYPT_SCHEME -> TPM_RC_SCHEME |
1215 | 0 | result = TranslateCryptErrors(retVal); |
1216 | 0 | return result; |
1217 | 0 | } |
1218 | | // |
1219 | | #endif //TPM_ALG_RSA //% 2 |
1220 | | // |
1221 | | // |
1222 | | // 10.2.6 ECC Functions |
1223 | | // |
1224 | | // 10.2.6.1 CryptEccGetCurveDataPointer() |
1225 | | // |
1226 | | // This function returns a pointer to an ECC_CURVE_VALUES structure that contains the parameters for |
1227 | | // the key size and schemes for a given curve. |
1228 | | // |
1229 | | #ifdef TPM_ALG_ECC //% 3 |
1230 | | static const ECC_CURVE * |
1231 | | CryptEccGetCurveDataPointer( |
1232 | | TPM_ECC_CURVE curveID // IN: id of the curve |
1233 | | ) |
1234 | 19 | { |
1235 | 19 | return _cpri__EccGetParametersByCurveId(curveID); |
1236 | 19 | } |
1237 | | // |
1238 | | // |
1239 | | // 10.2.6.2 CryptEccGetKeySizeInBits() |
1240 | | // |
1241 | | // This function returns the size in bits of the key associated with a curve. |
1242 | | // |
1243 | | UINT16 |
1244 | | CryptEccGetKeySizeInBits( |
1245 | | TPM_ECC_CURVE curveID // IN: id of the curve |
1246 | | ) |
1247 | 13 | { |
1248 | 13 | const ECC_CURVE *curve = CryptEccGetCurveDataPointer(curveID); |
1249 | 13 | UINT16 keySizeInBits = 0; |
1250 | 13 | if(curve != NULL) |
1251 | 13 | keySizeInBits = curve->keySizeBits; |
1252 | 13 | return keySizeInBits; |
1253 | 13 | } |
1254 | | // |
1255 | | // |
1256 | | // 10.2.6.4 CryptEccGetParameter() |
1257 | | // |
1258 | | // This function returns a pointer to an ECC curve parameter. The parameter is selected by a single |
1259 | | // character designator from the set of {pnabxyh}. |
1260 | | // |
1261 | | LIB_EXPORT const TPM2B * |
1262 | | CryptEccGetParameter( |
1263 | | char p, // IN: the parameter selector |
1264 | | TPM_ECC_CURVE curveId // IN: the curve id |
1265 | | ) |
1266 | 0 | { |
1267 | 0 | const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
1268 | 0 | const TPM2B *parameter = NULL; |
1269 | 0 | if(curve != NULL) |
1270 | 0 | { |
1271 | 0 | switch (p) |
1272 | 0 | { |
1273 | 0 | case 'p': |
1274 | 0 | parameter = curve->curveData->p; |
1275 | 0 | break; |
1276 | 0 | case 'n': |
1277 | 0 | parameter = curve->curveData->n; |
1278 | 0 | break; |
1279 | 0 | case 'a': |
1280 | 0 | parameter = curve->curveData->a; |
1281 | 0 | break; |
1282 | 0 | case 'b': |
1283 | 0 | parameter = curve->curveData->b; |
1284 | 0 | break; |
1285 | 0 | case 'x': |
1286 | 0 | parameter = curve->curveData->x; |
1287 | 0 | break; |
1288 | 0 | case 'y': |
1289 | 0 | parameter = curve->curveData->y; |
1290 | 0 | break; |
1291 | 0 | case 'h': |
1292 | 0 | parameter = curve->curveData->h; |
1293 | 0 | break; |
1294 | 0 | default: |
1295 | 0 | break; |
1296 | 0 | } |
1297 | 0 | } |
1298 | 0 | return parameter; |
1299 | 0 | } |
1300 | | // |
1301 | | // |
1302 | | // 10.2.6.5 CryptGetCurveSignScheme() |
1303 | | // |
1304 | | // This function will return a pointer to the scheme of the curve. |
1305 | | // |
1306 | | const TPMT_ECC_SCHEME * |
1307 | | CryptGetCurveSignScheme( |
1308 | | TPM_ECC_CURVE curveId // IN: The curve selector |
1309 | | ) |
1310 | 7 | { |
1311 | 7 | const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
1312 | 7 | const TPMT_ECC_SCHEME *scheme = NULL; |
1313 | 7 | if(curve != NULL) |
1314 | 7 | scheme = &(curve->sign); |
1315 | 7 | return scheme; |
1316 | 7 | } |
1317 | | // |
1318 | | // |
1319 | | // 10.2.6.6 CryptEccIsPointOnCurve() |
1320 | | // |
1321 | | // This function will validate that an ECC point is on the curve of given curveID. |
1322 | | // |
1323 | | // Return Value Meaning |
1324 | | // |
1325 | | // TRUE if the point is on curve |
1326 | | // FALSE if the point is not on curve |
1327 | | // |
1328 | | BOOL |
1329 | | CryptEccIsPointOnCurve( |
1330 | | TPM_ECC_CURVE curveID, // IN: ECC curve ID |
1331 | | TPMS_ECC_POINT *Q // IN: ECC point |
1332 | | ) |
1333 | 7 | { |
1334 | | // Make sure that point multiply is working |
1335 | 7 | TEST(TPM_ALG_ECC); |
1336 | | // Check point on curve logic by seeing if the test key is on the curve |
1337 | | // Call crypto engine function to check if a ECC public point is on the |
1338 | | // given curve |
1339 | 7 | if(_cpri__EccIsPointOnCurve(curveID, Q)) |
1340 | 6 | return TRUE; |
1341 | 1 | else |
1342 | 1 | return FALSE; |
1343 | 7 | } |
1344 | | // |
1345 | | // |
1346 | | // 10.2.6.7 CryptNewEccKey() |
1347 | | // |
1348 | | // This function creates a random ECC key that is not derived from other parameters as is a Primary Key. |
1349 | | // |
1350 | | TPM_RC |
1351 | | CryptNewEccKey( |
1352 | | TPM_ECC_CURVE curveID, // IN: ECC curve |
1353 | | TPMS_ECC_POINT *publicPoint, // OUT: public point |
1354 | | TPM2B_ECC_PARAMETER *sensitive // OUT: private area |
1355 | | ) |
1356 | 0 | { |
1357 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
1358 | | // _cpri__GetEphemeralECC may return CRYPT_PARAMETER |
1359 | 0 | if(_cpri__GetEphemeralEcc(publicPoint, sensitive, curveID) != CRYPT_SUCCESS) |
1360 | | // Something is wrong with the key. |
1361 | 0 | result = TPM_RC_KEY; |
1362 | 0 | return result; |
1363 | 0 | } |
1364 | | // |
1365 | | // |
1366 | | // 10.2.6.8 CryptEccPointMultiply() |
1367 | | // |
1368 | | // This function is used to perform a point multiply R = [d]Q. If Q is not provided, the multiplication is |
1369 | | // performed using the generator point of the curve. |
1370 | | // |
1371 | | // Error Returns Meaning |
1372 | | // |
1373 | | // TPM_RC_ECC_POINT invalid optional ECC point pIn |
1374 | | // TPM_RC_NO_RESULT multiplication resulted in a point at infinity |
1375 | | // TPM_RC_CANCELED if a self-test was done, it might have been aborted |
1376 | | // |
1377 | | TPM_RC |
1378 | | CryptEccPointMultiply( |
1379 | | TPMS_ECC_POINT *pOut, // OUT: output point |
1380 | | TPM_ECC_CURVE curveId, // IN: curve selector |
1381 | | TPM2B_ECC_PARAMETER *dIn, // IN: public scalar |
1382 | | TPMS_ECC_POINT *pIn // IN: optional point |
1383 | | ) |
1384 | 3 | { |
1385 | 3 | TPM2B_ECC_PARAMETER *n = NULL; |
1386 | 3 | CRYPT_RESULT retVal; |
1387 | 3 | pAssert(pOut != NULL && dIn != NULL); |
1388 | 3 | if(pIn != NULL) |
1389 | 0 | { |
1390 | 0 | n = dIn; |
1391 | 0 | dIn = NULL; |
1392 | 0 | } |
1393 | | // Do a test of point multiply |
1394 | 3 | TEST(TPM_ALG_ECC); |
1395 | | // _cpri__EccPointMultiply may return CRYPT_POINT or CRYPT_NO_RESULT |
1396 | 3 | retVal = _cpri__EccPointMultiply(pOut, curveId, dIn, pIn, n); |
1397 | | // CRYPT_POINT->TPM_RC_ECC_POINT and CRYPT_NO_RESULT->TPM_RC_NO_RESULT |
1398 | 3 | return TranslateCryptErrors(retVal); |
1399 | 3 | } |
1400 | | // |
1401 | | // |
1402 | | // 10.2.6.9 CryptGenerateKeyECC() |
1403 | | // |
1404 | | // This function generates an ECC key from a seed value. |
1405 | | // The method here may not work for objects that have an order (G) that with a different size than a private |
1406 | | // key. |
1407 | | // |
1408 | | // Error Returns Meaning |
1409 | | // |
1410 | | // TPM_RC_VALUE hash algorithm is not supported |
1411 | | // |
1412 | | static TPM_RC |
1413 | | CryptGenerateKeyECC( |
1414 | | TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for the new |
1415 | | // key. |
1416 | | TPMT_SENSITIVE *sensitive, // IN/OUT: the sensitive area |
1417 | | TPM_ALG_ID hashAlg, // IN: algorithm for the KDF |
1418 | | TPM2B_SEED *seed, // IN: the seed value |
1419 | | TPM2B_NAME *name, // IN: the name of the object |
1420 | | UINT32 *counter // OUT: the iteration counter |
1421 | | ) |
1422 | 0 | { |
1423 | 0 | CRYPT_RESULT retVal; |
1424 | 0 | TEST_HASH(hashAlg); |
1425 | 0 | TEST(ALG_ECDSA_VALUE); // ECDSA is used to verify each key |
1426 | | // The iteration counter has no meaning for ECC key generation. The parameter |
1427 | | // will be overloaded for those implementations that have a requirement for |
1428 | | // doing pair-wise consistency checks on signing keys. If the counter parameter |
1429 | | // is 0 or NULL, then no consistency check is done. If it is other than 0, then |
1430 | | // a consistency check is run. This modification allow this code to work with |
1431 | | // the existing versions of the CrytpoEngine and with FIPS-compliant versions |
1432 | | // as well. |
1433 | 0 | *counter = (UINT32)(publicArea->objectAttributes.sign == SET); |
1434 | | // _cpri__GenerateKeyEcc only has one error return (CRYPT_PARAMETER) which means |
1435 | | // that the hash algorithm is not supported. This should not be possible |
1436 | 0 | retVal = _cpri__GenerateKeyEcc(&publicArea->unique.ecc, |
1437 | 0 | &sensitive->sensitive.ecc, |
1438 | 0 | publicArea->parameters.eccDetail.curveID, |
1439 | 0 | hashAlg, &seed->b, "ECC key by vendor", |
1440 | 0 | &name->b, counter); |
1441 | | // This will only be useful if _cpri__GenerateKeyEcc return CRYPT_CANCEL |
1442 | 0 | return TranslateCryptErrors(retVal); |
1443 | 0 | } |
1444 | | // |
1445 | | // |
1446 | | // 10.2.6.10 CryptSignECC() |
1447 | | // |
1448 | | // This function is used for ECC signing operations. If the signing scheme is a split scheme, and the signing |
1449 | | // operation is successful, the commit value is retired. |
1450 | | // |
1451 | | // |
1452 | | // Error Returns Meaning |
1453 | | // |
1454 | | // TPM_RC_SCHEME unsupported scheme |
1455 | | // TPM_RC_VALUE invalid commit status (in case of a split scheme) or failed to generate |
1456 | | // r value. |
1457 | | // |
1458 | | static TPM_RC |
1459 | | CryptSignECC( |
1460 | | OBJECT *signKey, // IN: ECC key to sign the hash |
1461 | | TPMT_SIG_SCHEME *scheme, // IN: sign scheme |
1462 | | TPM2B_DIGEST *hashData, // IN: hash to be signed |
1463 | | TPMT_SIGNATURE *signature // OUT: signature |
1464 | | ) |
1465 | 0 | { |
1466 | 0 | TPM2B_ECC_PARAMETER r; |
1467 | 0 | TPM2B_ECC_PARAMETER *pr = NULL; |
1468 | 0 | CRYPT_RESULT retVal; |
1469 | | // Run a test of the ECC sign and verify if it has not already been run |
1470 | 0 | TEST_HASH(scheme->details.any.hashAlg); |
1471 | 0 | TEST(scheme->scheme); |
1472 | 0 | if(CryptIsSplitSign(scheme->scheme)) |
1473 | 0 | { |
1474 | | // When this code was written, the only split scheme was ECDAA |
1475 | | // (which can also be used for U-Prove). |
1476 | 0 | if(!CryptGenerateR(&r, |
1477 | 0 | &scheme->details.ecdaa.count, |
1478 | 0 | signKey->publicArea.parameters.eccDetail.curveID, |
1479 | 0 | &signKey->name)) |
1480 | 0 | return TPM_RC_VALUE; |
1481 | 0 | pr = &r; |
1482 | 0 | } |
1483 | | // Call crypto engine function to sign |
1484 | | // _cpri__SignEcc may return CRYPT_SCHEME |
1485 | 0 | retVal = _cpri__SignEcc(&signature->signature.ecdsa.signatureR, |
1486 | 0 | &signature->signature.ecdsa.signatureS, |
1487 | 0 | scheme->scheme, |
1488 | 0 | scheme->details.any.hashAlg, |
1489 | 0 | signKey->publicArea.parameters.eccDetail.curveID, |
1490 | 0 | &signKey->sensitive.sensitive.ecc, |
1491 | 0 | &hashData->b, |
1492 | 0 | pr |
1493 | 0 | ); |
1494 | 0 | if(CryptIsSplitSign(scheme->scheme) && retVal == CRYPT_SUCCESS) |
1495 | 0 | CryptEndCommit(scheme->details.ecdaa.count); |
1496 | | // CRYPT_SCHEME->TPM_RC_SCHEME |
1497 | 0 | return TranslateCryptErrors(retVal); |
1498 | 0 | } |
1499 | | // |
1500 | | // |
1501 | | // 10.2.6.11 CryptECCVerifySignature() |
1502 | | // |
1503 | | // This function is used to verify a signature created with an ECC key. |
1504 | | // |
1505 | | // Error Returns Meaning |
1506 | | // |
1507 | | // TPM_RC_SIGNATURE if signature is not valid |
1508 | | // TPM_RC_SCHEME the signing scheme or hashAlg is not supported |
1509 | | // |
1510 | | static TPM_RC |
1511 | | CryptECCVerifySignature( |
1512 | | OBJECT *signKey, // IN: ECC key signed the hash |
1513 | | TPM2B_DIGEST *digestData, // IN: digest being signed |
1514 | | TPMT_SIGNATURE *signature // IN: signature to be verified |
1515 | | ) |
1516 | 0 | { |
1517 | 0 | CRYPT_RESULT retVal; |
1518 | 0 | TEST_HASH(signature->signature.any.hashAlg); |
1519 | 0 | TEST(signature->sigAlg); |
1520 | | // This implementation uses the fact that all the defined ECC signing |
1521 | | // schemes have the hash as the first parameter. |
1522 | | // _cpriValidateSignatureEcc may return CRYPT_FAIL or CRYP_SCHEME |
1523 | 0 | retVal = _cpri__ValidateSignatureEcc(&signature->signature.ecdsa.signatureR, |
1524 | 0 | &signature->signature.ecdsa.signatureS, |
1525 | 0 | signature->sigAlg, |
1526 | 0 | signature->signature.any.hashAlg, |
1527 | 0 | signKey->publicArea.parameters.eccDetail.curveID, |
1528 | 0 | &signKey->publicArea.unique.ecc, |
1529 | 0 | &digestData->b); |
1530 | 0 | if(retVal == CRYPT_FAIL) |
1531 | 0 | return TPM_RC_SIGNATURE; |
1532 | | // CRYPT_SCHEME->TPM_RC_SCHEME |
1533 | 0 | return TranslateCryptErrors(retVal); |
1534 | 0 | } |
1535 | | // |
1536 | | // |
1537 | | // 10.2.6.12 CryptGenerateR() |
1538 | | // |
1539 | | // This function computes the commit random value for a split signing scheme. |
1540 | | // If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will |
1541 | | // validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns |
1542 | | // FALSE and no r value is generated. |
1543 | | // |
1544 | | // Return Value Meaning |
1545 | | // |
1546 | | // TRUE r value computed |
1547 | | // FALSE no r value computed |
1548 | | // |
1549 | | BOOL |
1550 | | CryptGenerateR( |
1551 | | TPM2B_ECC_PARAMETER *r, // OUT: the generated random value |
1552 | | UINT16 *c, // IN/OUT: count value. |
1553 | | TPMI_ECC_CURVE curveID, // IN: the curve for the value |
1554 | | TPM2B_NAME *name // IN: optional name of a key to |
1555 | | // associate with 'r' |
1556 | | ) |
1557 | 0 | { |
1558 | | // This holds the marshaled g_commitCounter. |
1559 | 0 | TPM2B_TYPE(8B, 8); |
1560 | 0 | TPM2B_8B cntr = {.b.size = 8}; |
1561 | 0 | UINT32 iterations; |
1562 | 0 | const TPM2B *n; |
1563 | 0 | UINT64 currentCount = gr.commitCounter; |
1564 | | // This is just to suppress a compiler warning about a conditional expression |
1565 | | // being a constant. This is because of the macro expansion of ryptKDFa |
1566 | 0 | TPMI_ALG_HASH hashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
1567 | 0 | n = CryptEccGetParameter('n', curveID); |
1568 | 0 | pAssert(r != NULL && n != NULL); |
1569 | | // If this is the commit phase, use the current value of the commit counter |
1570 | 0 | if(c != NULL) |
1571 | | // |
1572 | 0 | { |
1573 | 0 | UINT16 t1; |
1574 | | // if the array bit is not set, can't use the value. |
1575 | 0 | if(!BitIsSet((*c & COMMIT_INDEX_MASK), gr.commitArray, |
1576 | 0 | sizeof(gr.commitArray))) |
1577 | 0 | return FALSE; |
1578 | | // If it is the sign phase, figure out what the counter value was |
1579 | | // when the commitment was made. |
1580 | | // |
1581 | | // When gr.commitArray has less than 64K bits, the extra |
1582 | | // bits of 'c' are used as a check to make sure that the |
1583 | | // signing operation is not using an out of range count value |
1584 | 0 | t1 = (UINT16)currentCount; |
1585 | | // If the lower bits of c are greater or equal to the lower bits of t1 |
1586 | | // then the upper bits of t1 must be one more than the upper bits |
1587 | | // of c |
1588 | 0 | if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK)) |
1589 | | // Since the counter is behind, reduce the current count |
1590 | 0 | currentCount = currentCount - (COMMIT_INDEX_MASK + 1); |
1591 | 0 | t1 = (UINT16)currentCount; |
1592 | 0 | if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK)) |
1593 | 0 | return FALSE; |
1594 | | // set the counter to the value that was |
1595 | | // present when the commitment was made |
1596 | 0 | currentCount = (currentCount & 0xffffffffffff0000) | *c; |
1597 | 0 | } |
1598 | | // Marshal the count value to a TPM2B buffer for the KDF |
1599 | 0 | cntr.t.size = sizeof(currentCount); |
1600 | 0 | UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer); |
1601 | | // Now can do the KDF to create the random value for the signing operation |
1602 | | // During the creation process, we may generate an r that does not meet the |
1603 | | // requirements of the random value. |
1604 | | // want to generate a new r. |
1605 | 0 | r->t.size = n->size; |
1606 | | // Arbitrary upper limit on the number of times that we can look for |
1607 | | // a suitable random value. The normally number of tries will be 1. |
1608 | 0 | for(iterations = 1; iterations < 1000000;) |
1609 | 0 | { |
1610 | 0 | BYTE *pr = &r->b.buffer[0]; |
1611 | 0 | int i; |
1612 | 0 | CryptKDFa(hashAlg, &gr.commitNonce.b, "ECDAA Commit", |
1613 | 0 | name, &cntr.b, n->size * 8, r->t.buffer, &iterations); |
1614 | | // random value must be less than the prime |
1615 | 0 | if(CryptCompare(r->b.size, r->b.buffer, n->size, n->buffer) >= 0) |
1616 | 0 | continue; |
1617 | | // in this implementation it is required that at least bit |
1618 | | // in the upper half of the number be set |
1619 | 0 | for(i = n->size/2; i > 0; i--) |
1620 | 0 | if(*pr++ != 0) |
1621 | 0 | return TRUE; |
1622 | 0 | } |
1623 | 0 | return FALSE; |
1624 | 0 | } |
1625 | | // |
1626 | | // |
1627 | | // |
1628 | | // 10.2.6.13 CryptCommit() |
1629 | | // |
1630 | | // This function is called when the count value is committed. The gr.commitArray value associated with the |
1631 | | // current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the |
1632 | | // counter is returned. |
1633 | | // |
1634 | | UINT16 |
1635 | | CryptCommit( |
1636 | | void |
1637 | | ) |
1638 | 0 | { |
1639 | 0 | UINT16 oldCount = (UINT16)gr.commitCounter; |
1640 | 0 | gr.commitCounter++; |
1641 | 0 | BitSet(oldCount & COMMIT_INDEX_MASK, gr.commitArray, sizeof(gr.commitArray)); |
1642 | 0 | return oldCount; |
1643 | 0 | } |
1644 | | // |
1645 | | // |
1646 | | // 10.2.6.14 CryptEndCommit() |
1647 | | // |
1648 | | // This function is called when the signing operation using the committed value is completed. It clears the |
1649 | | // gr.commitArray bit associated with the count value so that it can't be used again. |
1650 | | // |
1651 | | void |
1652 | | CryptEndCommit( |
1653 | | UINT16 c // IN: the counter value of the commitment |
1654 | | ) |
1655 | 0 | { |
1656 | 0 | BitClear((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray)); |
1657 | 0 | } |
1658 | | // |
1659 | | // |
1660 | | // 10.2.6.15 CryptCommitCompute() |
1661 | | // |
1662 | | // This function performs the computations for the TPM2_Commit() command. This could be a macro. |
1663 | | // |
1664 | | // Error Returns Meaning |
1665 | | // |
1666 | | // TPM_RC_NO_RESULT K, L, or E is the point at infinity |
1667 | | // TPM_RC_CANCELLED command was canceled |
1668 | | // |
1669 | | TPM_RC |
1670 | | CryptCommitCompute( |
1671 | | TPMS_ECC_POINT *K, // OUT: [d]B |
1672 | | TPMS_ECC_POINT *L, // OUT: [r]B |
1673 | | TPMS_ECC_POINT *E, // OUT: [r]M |
1674 | | TPM_ECC_CURVE curveID, // IN: The curve for the computation |
1675 | | TPMS_ECC_POINT *M, // IN: M (P1) |
1676 | | TPMS_ECC_POINT *B, // IN: B (x2, y2) |
1677 | | TPM2B_ECC_PARAMETER *d, // IN: the private scalar |
1678 | | TPM2B_ECC_PARAMETER *r // IN: the computed r value |
1679 | | ) |
1680 | 0 | { |
1681 | 0 | TEST(ALG_ECDH_VALUE); |
1682 | | // CRYPT_NO_RESULT->TPM_RC_NO_RESULT CRYPT_CANCEL->TPM_RC_CANCELLED |
1683 | 0 | return TranslateCryptErrors( |
1684 | 0 | _cpri__EccCommitCompute(K, L , E, curveID, M, B, d, r)); |
1685 | 0 | } |
1686 | | // |
1687 | | // |
1688 | | // |
1689 | | // 10.2.6.16 CryptEccGetParameters() |
1690 | | // |
1691 | | // This function returns the ECC parameter details of the given curve |
1692 | | // |
1693 | | // Return Value Meaning |
1694 | | // |
1695 | | // TRUE Get parameters success |
1696 | | // FALSE Unsupported ECC curve ID |
1697 | | // |
1698 | | BOOL |
1699 | | CryptEccGetParameters( |
1700 | | TPM_ECC_CURVE curveId, // IN: ECC curve ID |
1701 | | TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameter |
1702 | | ) |
1703 | 0 | { |
1704 | 0 | const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId); |
1705 | 0 | const ECC_CURVE_DATA *data; |
1706 | 0 | BOOL found = curve != NULL; |
1707 | 0 | if(found) |
1708 | 0 | { |
1709 | 0 | data = curve->curveData; |
1710 | 0 | parameters->curveID = curve->curveId; |
1711 | | // Key size in bit |
1712 | 0 | parameters->keySize = curve->keySizeBits; |
1713 | | // KDF |
1714 | 0 | parameters->kdf = curve->kdf; |
1715 | | // Sign |
1716 | 0 | parameters->sign = curve->sign; |
1717 | | // Copy p value |
1718 | 0 | MemoryCopy2B(¶meters->p.b, data->p, sizeof(parameters->p.t.buffer)); |
1719 | | // Copy a value |
1720 | 0 | MemoryCopy2B(¶meters->a.b, data->a, sizeof(parameters->a.t.buffer)); |
1721 | | // Copy b value |
1722 | 0 | MemoryCopy2B(¶meters->b.b, data->b, sizeof(parameters->b.t.buffer)); |
1723 | | // Copy Gx value |
1724 | 0 | MemoryCopy2B(¶meters->gX.b, data->x, sizeof(parameters->gX.t.buffer)); |
1725 | | // Copy Gy value |
1726 | 0 | MemoryCopy2B(¶meters->gY.b, data->y, sizeof(parameters->gY.t.buffer)); |
1727 | | // Copy n value |
1728 | 0 | MemoryCopy2B(¶meters->n.b, data->n, sizeof(parameters->n.t.buffer)); |
1729 | | // Copy h value |
1730 | 0 | MemoryCopy2B(¶meters->h.b, data->h, sizeof(parameters->h.t.buffer)); |
1731 | 0 | } |
1732 | 0 | return found; |
1733 | 0 | } |
1734 | | #if IS_CC_ENABLED(ZGen_2Phase) |
1735 | | // |
1736 | | // CryptEcc2PhaseKeyExchange() This is the interface to the key exchange function. |
1737 | | // |
1738 | | TPM_RC |
1739 | | CryptEcc2PhaseKeyExchange( |
1740 | | TPMS_ECC_POINT *outZ1, // OUT: the computed point |
1741 | | TPMS_ECC_POINT *outZ2, // OUT: optional second point |
1742 | | TPM_ALG_ID scheme, // IN: the key exchange scheme |
1743 | | TPM_ECC_CURVE curveId, // IN: the curve for the computation |
1744 | | TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key |
1745 | | TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key |
1746 | | TPMS_ECC_POINT *QsB, // IN: static public party B key |
1747 | | TPMS_ECC_POINT *QeB // IN: ephemeral public party B key |
1748 | | ) |
1749 | | { |
1750 | | return (TranslateCryptErrors(_cpri__C_2_2_KeyExchange(outZ1, |
1751 | | outZ2, |
1752 | | scheme, |
1753 | | curveId, |
1754 | | dsA, |
1755 | | deA, |
1756 | | QsB, |
1757 | | QeB))); |
1758 | | } |
1759 | | #endif // CC_ZGen_2Phase |
1760 | | #endif //TPM_ALG_ECC //% 3 |
1761 | | // |
1762 | | // |
1763 | | // 10.2.6.17 CryptIsSchemeAnonymous() |
1764 | | // |
1765 | | // This function is used to test a scheme to see if it is an anonymous scheme The only anonymous scheme |
1766 | | // is ECDAA. ECDAA can be used to do things like U-Prove. |
1767 | | // |
1768 | | BOOL |
1769 | | CryptIsSchemeAnonymous( |
1770 | | TPM_ALG_ID scheme // IN: the scheme algorithm to test |
1771 | | ) |
1772 | 0 | { |
1773 | 0 | #ifdef TPM_ALG_ECDAA |
1774 | 0 | return (scheme == TPM_ALG_ECDAA); |
1775 | | #else |
1776 | | UNREFERENCED(scheme); |
1777 | | return 0; |
1778 | | #endif |
1779 | 0 | } |
1780 | | // |
1781 | | // |
1782 | | // 10.2.7 Symmetric Functions |
1783 | | // |
1784 | | // 10.2.7.1 ParmDecryptSym() |
1785 | | // |
1786 | | // This function performs parameter decryption using symmetric block cipher. |
1787 | | // |
1788 | | void |
1789 | | ParmDecryptSym( |
1790 | | TPM_ALG_ID symAlg, // IN: the symmetric algorithm |
1791 | | TPM_ALG_ID hash, // IN: hash algorithm for KDFa |
1792 | | UINT16 keySizeInBits, // IN: key key size in bit |
1793 | | TPM2B *key, // IN: KDF HMAC key |
1794 | | TPM2B *nonceCaller, // IN: nonce caller |
1795 | | TPM2B *nonceTpm, // IN: nonce TPM |
1796 | | UINT32 dataSize, // IN: size of parameter buffer |
1797 | | BYTE *data // OUT: buffer to be decrypted |
1798 | | ) |
1799 | 0 | { |
1800 | | // KDF output buffer |
1801 | | // It contains parameters for the CFB encryption |
1802 | | // From MSB to LSB, they are the key and iv |
1803 | 0 | BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; |
1804 | | // Symmetric key size in byte |
1805 | 0 | UINT16 keySize = (keySizeInBits + 7) / 8; |
1806 | 0 | TPM2B_IV iv; |
1807 | 0 | iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); |
1808 | | // If there is decryption to do... |
1809 | 0 | if(iv.t.size > 0) |
1810 | 0 | { |
1811 | | // Generate key and iv |
1812 | 0 | CryptKDFa(hash, key, "CFB", nonceCaller, nonceTpm, |
1813 | 0 | keySizeInBits + (iv.t.size * 8), symParmString, NULL); |
1814 | 0 | MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size, |
1815 | 0 | sizeof(iv.t.buffer)); |
1816 | 0 | CryptSymmetricDecrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB, |
1817 | 0 | symParmString, &iv, dataSize, data); |
1818 | 0 | } |
1819 | 0 | return; |
1820 | 0 | } |
1821 | | // |
1822 | | // |
1823 | | // 10.2.7.2 ParmEncryptSym() |
1824 | | // |
1825 | | // This function performs parameter encryption using symmetric block cipher. |
1826 | | // |
1827 | | void |
1828 | | ParmEncryptSym( |
1829 | | TPM_ALG_ID symAlg, // IN: symmetric algorithm |
1830 | | TPM_ALG_ID hash, // IN: hash algorithm for KDFa |
1831 | | UINT16 keySizeInBits, // IN: AES key size in bit |
1832 | | TPM2B *key, // IN: KDF HMAC key |
1833 | | TPM2B *nonceCaller, // IN: nonce caller |
1834 | | TPM2B *nonceTpm, // IN: nonce TPM |
1835 | | UINT32 dataSize, // IN: size of parameter buffer |
1836 | | BYTE *data // OUT: buffer to be encrypted |
1837 | | ) |
1838 | 0 | { |
1839 | | // KDF output buffer |
1840 | | // It contains parameters for the CFB encryption |
1841 | 0 | BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; |
1842 | | // Symmetric key size in bytes |
1843 | 0 | UINT16 keySize = (keySizeInBits + 7) / 8; |
1844 | 0 | TPM2B_IV iv; |
1845 | 0 | iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); |
1846 | | // See if there is any encryption to do |
1847 | 0 | if(iv.t.size > 0) |
1848 | 0 | { |
1849 | | // Generate key and iv |
1850 | 0 | CryptKDFa(hash, key, "CFB", nonceTpm, nonceCaller, |
1851 | 0 | keySizeInBits + (iv.t.size * 8), symParmString, NULL); |
1852 | 0 | MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size, |
1853 | 0 | sizeof(iv.t.buffer)); |
1854 | 0 | CryptSymmetricEncrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB, |
1855 | 0 | symParmString, &iv, dataSize, data); |
1856 | 0 | } |
1857 | 0 | return; |
1858 | 0 | } |
1859 | | // |
1860 | | // |
1861 | | // |
1862 | | // 10.2.7.3 CryptGenerateNewSymmetric() |
1863 | | // |
1864 | | // This function creates the sensitive symmetric values for an HMAC or symmetric key. If the sensitive area |
1865 | | // is zero, then the sensitive creation key data is copied. If it is not zero, then the TPM will generate a |
1866 | | // random value of the selected size. |
1867 | | // |
1868 | | void |
1869 | | CryptGenerateNewSymmetric( |
1870 | | TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data |
1871 | | TPMT_SENSITIVE *sensitive, // OUT: sensitive area |
1872 | | TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF |
1873 | | TPM2B_SEED *seed, // IN: seed used in creation |
1874 | | TPM2B_NAME *name // IN: name of the object |
1875 | | ) |
1876 | 0 | { |
1877 | | // This function is called to create a key and obfuscation value for a |
1878 | | // symmetric key that can either be a block cipher or an XOR key. The buffer |
1879 | | // in sensitive->sensitive will hold either. When we call the function |
1880 | | // to copy the input value or generated value to the sensitive->sensitive |
1881 | | // buffer we will need to have a size for the output buffer. This define |
1882 | | // computes the maximum that it might need to be and uses that. It will always |
1883 | | // be smaller than the largest value that will fit. |
1884 | 0 | #define MAX_SENSITIVE_SIZE \ |
1885 | 0 | (MAX(sizeof(sensitive->sensitive.bits.t.buffer), \ |
1886 | 0 | sizeof(sensitive->sensitive.sym.t.buffer))) |
1887 | | // set the size of the obfuscation value |
1888 | 0 | sensitive->seedValue.t.size = CryptGetHashDigestSize(hashAlg); |
1889 | | // If the input sensitive size is zero, then create both the sensitive data |
1890 | | // and the obfuscation value |
1891 | 0 | if(sensitiveCreate->data.t.size == 0) |
1892 | 0 | { |
1893 | 0 | BYTE symValues[MAX(MAX_DIGEST_SIZE, MAX_SYM_KEY_BYTES) |
1894 | 0 | + MAX_DIGEST_SIZE]; |
1895 | 0 | UINT16 requestSize; |
1896 | | // Set the size of the request to be the size of the key and the |
1897 | | // obfuscation value |
1898 | 0 | requestSize = sensitive->sensitive.sym.t.size |
1899 | 0 | + sensitive->seedValue.t.size; |
1900 | 0 | pAssert(requestSize <= sizeof(symValues)); |
1901 | 0 | requestSize = _cpri__GenerateSeededRandom(requestSize, symValues, hashAlg, |
1902 | 0 | &seed->b, |
1903 | 0 | "symmetric sensitive", &name->b, |
1904 | 0 | NULL); |
1905 | 0 | pAssert(requestSize != 0); |
1906 | | // Copy the new key |
1907 | 0 | MemoryCopy(sensitive->sensitive.sym.t.buffer, |
1908 | 0 | symValues, sensitive->sensitive.sym.t.size, |
1909 | 0 | MAX_SENSITIVE_SIZE); |
1910 | | // copy the obfuscation value |
1911 | 0 | MemoryCopy(sensitive->seedValue.t.buffer, |
1912 | 0 | &symValues[sensitive->sensitive.sym.t.size], |
1913 | 0 | sensitive->seedValue.t.size, |
1914 | 0 | sizeof(sensitive->seedValue.t.buffer)); |
1915 | 0 | } |
1916 | 0 | else |
1917 | 0 | { |
1918 | | // Copy input symmetric key to sensitive area as long as it will fit |
1919 | 0 | MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b, |
1920 | 0 | MAX_SENSITIVE_SIZE); |
1921 | | // Create the obfuscation value |
1922 | 0 | _cpri__GenerateSeededRandom(sensitive->seedValue.t.size, |
1923 | 0 | sensitive->seedValue.t.buffer, |
1924 | 0 | hashAlg, &seed->b, |
1925 | 0 | "symmetric obfuscation", &name->b, NULL); |
1926 | 0 | } |
1927 | 0 | return; |
1928 | 0 | } |
1929 | | // |
1930 | | // |
1931 | | // 10.2.7.4 CryptGenerateKeySymmetric() |
1932 | | // |
1933 | | // This function derives a symmetric cipher key from the provided seed. |
1934 | | // |
1935 | | // Error Returns Meaning |
1936 | | // |
1937 | | // TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive |
1938 | | // creation area |
1939 | | // TPM_RC_VALUE the publicArea nameAlg is invalid |
1940 | | // |
1941 | | static TPM_RC |
1942 | | CryptGenerateKeySymmetric( |
1943 | | TPMT_PUBLIC *publicArea, // IN/OUT: The public area template |
1944 | | // for the new key. |
1945 | | TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data |
1946 | | TPMT_SENSITIVE *sensitive, // OUT: sensitive area |
1947 | | TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF |
1948 | | TPM2B_SEED *seed, // IN: seed used in creation |
1949 | | TPM2B_NAME *name // IN: name of the object |
1950 | | ) |
1951 | 0 | { |
1952 | | // Check parameter values |
1953 | 0 | if(publicArea->nameAlg == TPM_ALG_NULL) |
1954 | 0 | { |
1955 | 0 | return TPM_RC_VALUE; |
1956 | 0 | } |
1957 | | // If this is not a new key, then the provided key data must be the right size |
1958 | 0 | if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR) |
1959 | 0 | { |
1960 | 0 | if( (sensitiveCreate->data.t.size * 8) |
1961 | 0 | != publicArea->parameters.symDetail.sym.keyBits.sym) |
1962 | 0 | return TPM_RC_KEY_SIZE; |
1963 | | // Make sure that the key size is OK. |
1964 | | // This implementation only supports symmetric key sizes that are |
1965 | | // multiples of 8 |
1966 | 0 | if(publicArea->parameters.symDetail.sym.keyBits.sym % 8 != 0) |
1967 | 0 | return TPM_RC_KEY_SIZE; |
1968 | 0 | } |
1969 | 0 | else |
1970 | 0 | { |
1971 | | // TPM is going to generate the key so set the size |
1972 | 0 | sensitive->sensitive.sym.t.size |
1973 | 0 | = publicArea->parameters.symDetail.sym.keyBits.sym / 8; |
1974 | 0 | sensitiveCreate->data.t.size = 0; |
1975 | 0 | } |
1976 | | // Fill in the sensitive area |
1977 | 0 | CryptGenerateNewSymmetric(sensitiveCreate, sensitive, hashAlg, |
1978 | 0 | seed, name); |
1979 | | // Create unique area in public |
1980 | 0 | CryptComputeSymmetricUnique(publicArea->nameAlg, |
1981 | 0 | sensitive, &publicArea->unique.sym); |
1982 | 0 | return TPM_RC_SUCCESS; |
1983 | 0 | } |
1984 | | // |
1985 | | // |
1986 | | // |
1987 | | // 10.2.7.5 CryptXORObfuscation() |
1988 | | // |
1989 | | // This function implements XOR obfuscation. It should not be called if the hash algorithm is not |
1990 | | // implemented. The only return value from this function is TPM_RC_SUCCESS. |
1991 | | // |
1992 | | #ifdef TPM_ALG_KEYEDHASH //% 5 |
1993 | | void |
1994 | | CryptXORObfuscation( |
1995 | | TPM_ALG_ID hash, // IN: hash algorithm for KDF |
1996 | | TPM2B *key, // IN: KDF key |
1997 | | TPM2B *contextU, // IN: contextU |
1998 | | TPM2B *contextV, // IN: contextV |
1999 | | UINT32 dataSize, // IN: size of data buffer |
2000 | | BYTE *data // IN/OUT: data to be XORed in place |
2001 | | ) |
2002 | 0 | { |
2003 | 0 | BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer |
2004 | 0 | BYTE *pm; |
2005 | 0 | UINT32 i; |
2006 | 0 | UINT32 counter = 0; |
2007 | 0 | UINT16 hLen = CryptGetHashDigestSize(hash); |
2008 | 0 | UINT32 requestSize = dataSize * 8; |
2009 | 0 | INT32 remainBytes = (INT32) dataSize; |
2010 | 0 | pAssert((key != NULL) && (data != NULL) && (hLen != 0)); |
2011 | | // Call KDFa to generate XOR mask |
2012 | 0 | for(; remainBytes > 0; remainBytes -= hLen) |
2013 | 0 | { |
2014 | | // Make a call to KDFa to get next iteration |
2015 | 0 | CryptKDFaOnce(hash, key, "XOR", contextU, contextV, |
2016 | 0 | requestSize, mask, &counter); |
2017 | | // XOR next piece of the data |
2018 | 0 | pm = mask; |
2019 | 0 | for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--) |
2020 | 0 | *data++ ^= *pm++; |
2021 | 0 | } |
2022 | 0 | return; |
2023 | 0 | } |
2024 | | #endif //TPM_ALG_KEYED_HASH //%5 |
2025 | | // |
2026 | | // |
2027 | | // 10.2.8 Initialization and shut down |
2028 | | // |
2029 | | // 10.2.8.1 CryptInitUnits() |
2030 | | // |
2031 | | // This function is called when the TPM receives a _TPM_Init() indication. After function returns, the hash |
2032 | | // algorithms should be available. |
2033 | | // |
2034 | | // NOTE: The hash algorithms do not have to be tested, they just need to be available. They have to be tested before the |
2035 | | // TPM can accept HMAC authorization or return any result that relies on a hash algorithm. |
2036 | | // |
2037 | | void |
2038 | | CryptInitUnits( |
2039 | | void |
2040 | | ) |
2041 | 231 | { |
2042 | | // Initialize the vector of implemented algorithms |
2043 | 231 | AlgorithmGetImplementedVector(&g_implementedAlgorithms); |
2044 | | // Indicate that all test are necessary |
2045 | 231 | CryptInitializeToTest(); |
2046 | | // |
2047 | | // Call crypto engine unit initialization |
2048 | | // It is assumed that crypt engine initialization should always succeed. |
2049 | | // Otherwise, TPM should go to failure mode. |
2050 | 231 | if(_cpri__InitCryptoUnits(&TpmFail) != CRYPT_SUCCESS) |
2051 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
2052 | 231 | return; |
2053 | 231 | } |
2054 | | // |
2055 | | // |
2056 | | // 10.2.8.2 CryptStopUnits() |
2057 | | // |
2058 | | // This function is only used in a simulated environment. There should be no reason to shut down the |
2059 | | // cryptography on an actual TPM other than loss of power. After receiving TPM2_Startup(), the TPM should |
2060 | | // be able to accept commands until it loses power and, unless the TPM is in Failure Mode, the |
2061 | | // cryptographic algorithms should be available. |
2062 | | // |
2063 | | void |
2064 | | CryptStopUnits( |
2065 | | void |
2066 | | ) |
2067 | 0 | { |
2068 | | // Call crypto engine unit stopping |
2069 | 0 | _cpri__StopCryptoUnits(); |
2070 | 0 | return; |
2071 | 0 | } |
2072 | | // |
2073 | | // |
2074 | | // 10.2.8.3 CryptUtilStartup() |
2075 | | // |
2076 | | // This function is called by TPM2_Startup() to initialize the functions in this crypto library and in the |
2077 | | // provided CryptoEngine(). In this implementation, the only initialization required in this library is |
2078 | | // initialization of the Commit nonce on TPM Reset. |
2079 | | // This function returns false if some problem prevents the functions from starting correctly. The TPM should |
2080 | | // go into failure mode. |
2081 | | // |
2082 | | BOOL |
2083 | | CryptUtilStartup( |
2084 | | STARTUP_TYPE type // IN: the startup type |
2085 | | ) |
2086 | 231 | { |
2087 | | // Make sure that the crypto library functions are ready. |
2088 | | // NOTE: need to initialize the crypto before loading |
2089 | | // the RND state may trigger a self-test which |
2090 | | // uses the |
2091 | 231 | if( !_cpri__Startup()) |
2092 | 0 | return FALSE; |
2093 | | // Initialize the state of the RNG. |
2094 | 231 | CryptDrbgGetPutState(PUT_STATE); |
2095 | 231 | if(type == SU_RESET) |
2096 | 231 | { |
2097 | 231 | #ifdef TPM_ALG_ECC |
2098 | | // Get a new random commit nonce |
2099 | 231 | gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer); |
2100 | 231 | _cpri__GenerateRandom(gr.commitNonce.t.size, gr.commitNonce.t.buffer); |
2101 | | // Reset the counter and commit array |
2102 | 231 | gr.commitCounter = 0; |
2103 | 231 | MemorySet(gr.commitArray, 0, sizeof(gr.commitArray)); |
2104 | 231 | #endif // TPM_ALG_ECC |
2105 | 231 | } |
2106 | | // If the shutdown was orderly, then the values recovered from NV will |
2107 | | // be OK to use. If the shutdown was not orderly, then a TPM Reset was required |
2108 | | // and we would have initialized in the code above. |
2109 | 231 | return TRUE; |
2110 | 231 | } |
2111 | | // |
2112 | | // |
2113 | | // 10.2.9 Algorithm-Independent Functions |
2114 | | // |
2115 | | // 10.2.9.1 Introduction |
2116 | | // |
2117 | | // These functions are used generically when a function of a general type (e.g., symmetric encryption) is |
2118 | | // required. The functions will modify the parameters as required to interface to the indicated algorithms. |
2119 | | // |
2120 | | // 10.2.9.2 CryptIsAsymAlgorithm() |
2121 | | // |
2122 | | // This function indicates if an algorithm is an asymmetric algorithm. |
2123 | | // |
2124 | | // Return Value Meaning |
2125 | | // |
2126 | | // TRUE if it is an asymmetric algorithm |
2127 | | // FALSE if it is not an asymmetric algorithm |
2128 | | // |
2129 | | BOOL |
2130 | | CryptIsAsymAlgorithm( |
2131 | | TPM_ALG_ID algID // IN: algorithm ID |
2132 | | ) |
2133 | 44 | { |
2134 | 44 | return ( |
2135 | 44 | #ifdef TPM_ALG_RSA |
2136 | 44 | algID == TPM_ALG_RSA |
2137 | 44 | #endif |
2138 | 44 | #if defined TPM_ALG_RSA && defined TPM_ALG_ECC |
2139 | 44 | || |
2140 | 44 | #endif |
2141 | 44 | #ifdef TPM_ALG_ECC |
2142 | 44 | algID == TPM_ALG_ECC |
2143 | 44 | #endif |
2144 | 44 | ); |
2145 | 44 | } |
2146 | | // |
2147 | | // |
2148 | | // 10.2.9.3 CryptGetSymmetricBlockSize() |
2149 | | // |
2150 | | // This function returns the size in octets of the symmetric encryption block used by an algorithm and key |
2151 | | // size combination. |
2152 | | // |
2153 | | INT16 |
2154 | | CryptGetSymmetricBlockSize( |
2155 | | TPMI_ALG_SYM algorithm, // IN: symmetric algorithm |
2156 | | UINT16 keySize // IN: key size in bit |
2157 | | ) |
2158 | 0 | { |
2159 | 0 | return _cpri__GetSymmetricBlockSize(algorithm, keySize); |
2160 | 0 | } |
2161 | | // |
2162 | | // |
2163 | | // |
2164 | | // 10.2.9.4 CryptSymmetricEncrypt() |
2165 | | // |
2166 | | // This function does in-place encryption of a buffer using the indicated symmetric algorithm, key, IV, and |
2167 | | // mode. If the symmetric algorithm and mode are not defined, the TPM will fail. |
2168 | | // |
2169 | | void |
2170 | | CryptSymmetricEncrypt( |
2171 | | BYTE *encrypted, // OUT: the encrypted data |
2172 | | TPM_ALG_ID algorithm, // IN: algorithm for encryption |
2173 | | UINT16 keySizeInBits, // IN: key size in bit |
2174 | | TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode |
2175 | | BYTE *key, // IN: encryption key |
2176 | | TPM2B_IV *ivIn, // IN/OUT: Input IV and output chaining |
2177 | | // value for the next block |
2178 | | UINT32 dataSize, // IN: data size in byte |
2179 | | BYTE *data // IN/OUT: data buffer |
2180 | | ) |
2181 | 0 | { |
2182 | 0 | TPM2B_IV defaultIv = {}; |
2183 | 0 | TPM2B_IV *iv = (ivIn != NULL) ? ivIn : &defaultIv; |
2184 | 0 | TEST(algorithm); |
2185 | 0 | pAssert(encrypted != NULL && key != NULL); |
2186 | | // this check can pass but the case below can fail. ALG_xx_VALUE values are |
2187 | | // defined for all algorithms but the TPM_ALG_xx might not be. |
2188 | 0 | if(algorithm == ALG_AES_VALUE || algorithm == ALG_SM4_VALUE) |
2189 | 0 | { |
2190 | 0 | if(mode != TPM_ALG_ECB) |
2191 | 0 | defaultIv.t.size = 16; |
2192 | | // A provided IV has to be the right size |
2193 | 0 | pAssert(mode == TPM_ALG_ECB || iv->t.size == 16); |
2194 | 0 | } |
2195 | 0 | switch(algorithm) |
2196 | 0 | { |
2197 | 0 | #ifdef TPM_ALG_AES |
2198 | 0 | case TPM_ALG_AES: |
2199 | 0 | { |
2200 | 0 | switch (mode) |
2201 | 0 | { |
2202 | 0 | case TPM_ALG_CTR: |
2203 | 0 | _cpri__AESEncryptCTR(encrypted, keySizeInBits, key, |
2204 | 0 | iv->t.buffer, dataSize, data); |
2205 | 0 | break; |
2206 | 0 | case TPM_ALG_OFB: |
2207 | 0 | _cpri__AESEncryptOFB(encrypted, keySizeInBits, key, |
2208 | 0 | iv->t.buffer, dataSize, data); |
2209 | 0 | break; |
2210 | 0 | case TPM_ALG_CBC: |
2211 | 0 | _cpri__AESEncryptCBC(encrypted, keySizeInBits, key, |
2212 | 0 | iv->t.buffer, dataSize, data); |
2213 | 0 | break; |
2214 | 0 | case TPM_ALG_CFB: |
2215 | 0 | _cpri__AESEncryptCFB(encrypted, keySizeInBits, key, |
2216 | 0 | iv->t.buffer, dataSize, data); |
2217 | 0 | break; |
2218 | 0 | case TPM_ALG_ECB: |
2219 | 0 | _cpri__AESEncryptECB(encrypted, keySizeInBits, key, |
2220 | 0 | dataSize, data); |
2221 | 0 | break; |
2222 | 0 | default: |
2223 | 0 | pAssert(0); |
2224 | 0 | } |
2225 | 0 | } |
2226 | 0 | break; |
2227 | 0 | #endif |
2228 | | #ifdef TPM_ALG_SM4 |
2229 | | case TPM_ALG_SM4: |
2230 | | { |
2231 | | switch (mode) |
2232 | | { |
2233 | | case TPM_ALG_CTR: |
2234 | | _cpri__SM4EncryptCTR(encrypted, keySizeInBits, key, |
2235 | | iv->t.buffer, dataSize, data); |
2236 | | break; |
2237 | | case TPM_ALG_OFB: |
2238 | | _cpri__SM4EncryptOFB(encrypted, keySizeInBits, key, |
2239 | | iv->t.buffer, dataSize, data); |
2240 | | break; |
2241 | | case TPM_ALG_CBC: |
2242 | | _cpri__SM4EncryptCBC(encrypted, keySizeInBits, key, |
2243 | | iv->t.buffer, dataSize, data); |
2244 | | break; |
2245 | | case TPM_ALG_CFB: |
2246 | | _cpri__SM4EncryptCFB(encrypted, keySizeInBits, key, |
2247 | | iv->t.buffer, dataSize, data); |
2248 | | break; |
2249 | | case TPM_ALG_ECB: |
2250 | | _cpri__SM4EncryptECB(encrypted, keySizeInBits, key, |
2251 | | dataSize, data); |
2252 | | break; |
2253 | | default: |
2254 | | pAssert(0); |
2255 | | } |
2256 | | } |
2257 | | break; |
2258 | | #endif |
2259 | 0 | default: |
2260 | 0 | pAssert(FALSE); |
2261 | 0 | break; |
2262 | 0 | } |
2263 | 0 | return; |
2264 | 0 | } |
2265 | | // |
2266 | | // |
2267 | | // 10.2.9.5 CryptSymmetricDecrypt() |
2268 | | // |
2269 | | // This function does in-place decryption of a buffer using the indicated symmetric algorithm, key, IV, and |
2270 | | // mode. If the symmetric algorithm and mode are not defined, the TPM will fail. |
2271 | | // |
2272 | | void |
2273 | | CryptSymmetricDecrypt( |
2274 | | BYTE *decrypted, |
2275 | | TPM_ALG_ID algorithm, // IN: algorithm for encryption |
2276 | | UINT16 keySizeInBits, // IN: key size in bit |
2277 | | TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode |
2278 | | BYTE *key, // IN: encryption key |
2279 | | TPM2B_IV *ivIn, // IN/OUT: IV for next block |
2280 | | UINT32 dataSize, // IN: data size in byte |
2281 | | BYTE *data // IN/OUT: data buffer |
2282 | | ) |
2283 | 0 | { |
2284 | 0 | BYTE *iv = NULL; |
2285 | 0 | BYTE defaultIV[sizeof(TPMT_HA)]; |
2286 | 0 | TEST(algorithm); |
2287 | 0 | if( |
2288 | 0 | #ifdef TPM_ALG_AES |
2289 | 0 | algorithm == TPM_ALG_AES |
2290 | 0 | #endif |
2291 | | #if defined TPM_ALG_AES && defined TPM_ALG_SM4 |
2292 | | || |
2293 | | #endif |
2294 | | #ifdef TPM_ALG_SM4 |
2295 | | algorithm == TPM_ALG_SM4 |
2296 | | #endif |
2297 | 0 | ) |
2298 | 0 | { |
2299 | | // Both SM4 and AES have block size of 128 bits |
2300 | | // If the iv is not provided, create a default of 0 |
2301 | 0 | if(ivIn == NULL) |
2302 | 0 | { |
2303 | | // Initialize the default IV |
2304 | 0 | iv = defaultIV; |
2305 | 0 | MemorySet(defaultIV, 0, 16); |
2306 | 0 | } |
2307 | 0 | else |
2308 | 0 | { |
2309 | | // A provided IV has to be the right size |
2310 | 0 | pAssert(mode == TPM_ALG_ECB || ivIn->t.size == 16); |
2311 | 0 | iv = &(ivIn->t.buffer[0]); |
2312 | 0 | } |
2313 | 0 | } |
2314 | 0 | switch(algorithm) |
2315 | 0 | { |
2316 | 0 | #ifdef TPM_ALG_AES |
2317 | 0 | case TPM_ALG_AES: |
2318 | 0 | { |
2319 | 0 | switch (mode) |
2320 | 0 | { |
2321 | 0 | case TPM_ALG_CTR: |
2322 | 0 | _cpri__AESDecryptCTR(decrypted, keySizeInBits, key, iv, |
2323 | 0 | dataSize, data); |
2324 | 0 | break; |
2325 | 0 | case TPM_ALG_OFB: |
2326 | 0 | _cpri__AESDecryptOFB(decrypted, keySizeInBits, key, iv, |
2327 | 0 | dataSize, data); |
2328 | 0 | break; |
2329 | 0 | case TPM_ALG_CBC: |
2330 | 0 | _cpri__AESDecryptCBC(decrypted, keySizeInBits, key, iv, |
2331 | 0 | dataSize, data); |
2332 | 0 | break; |
2333 | 0 | case TPM_ALG_CFB: |
2334 | 0 | _cpri__AESDecryptCFB(decrypted, keySizeInBits, key, iv, |
2335 | 0 | dataSize, data); |
2336 | 0 | break; |
2337 | 0 | case TPM_ALG_ECB: |
2338 | 0 | _cpri__AESDecryptECB(decrypted, keySizeInBits, key, |
2339 | 0 | dataSize, data); |
2340 | 0 | break; |
2341 | 0 | default: |
2342 | 0 | pAssert(0); |
2343 | 0 | } |
2344 | 0 | break; |
2345 | 0 | } |
2346 | 0 | #endif //TPM_ALG_AES |
2347 | | #ifdef TPM_ALG_SM4 |
2348 | | case TPM_ALG_SM4 : |
2349 | | switch (mode) |
2350 | | { |
2351 | | case TPM_ALG_CTR: |
2352 | | _cpri__SM4DecryptCTR(decrypted, keySizeInBits, key, iv, |
2353 | | dataSize, data); |
2354 | | break; |
2355 | | case TPM_ALG_OFB: |
2356 | | _cpri__SM4DecryptOFB(decrypted, keySizeInBits, key, iv, |
2357 | | dataSize, data); |
2358 | | break; |
2359 | | case TPM_ALG_CBC: |
2360 | | _cpri__SM4DecryptCBC(decrypted, keySizeInBits, key, iv, |
2361 | | dataSize, data); |
2362 | | break; |
2363 | | case TPM_ALG_CFB: |
2364 | | _cpri__SM4DecryptCFB(decrypted, keySizeInBits, key, iv, |
2365 | | dataSize, data); |
2366 | | break; |
2367 | | case TPM_ALG_ECB: |
2368 | | _cpri__SM4DecryptECB(decrypted, keySizeInBits, key, |
2369 | | dataSize, data); |
2370 | | break; |
2371 | | default: |
2372 | | pAssert(0); |
2373 | | } |
2374 | | break; |
2375 | | #endif //TPM_ALG_SM4 |
2376 | 0 | default: |
2377 | 0 | pAssert(FALSE); |
2378 | 0 | break; |
2379 | 0 | } |
2380 | 0 | return; |
2381 | 0 | } |
2382 | | // |
2383 | | // |
2384 | | // 10.2.9.6 CryptSecretEncrypt() |
2385 | | // |
2386 | | // This function creates a secret value and its associated secret structure using an asymmetric algorithm. |
2387 | | // This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate(). |
2388 | | // |
2389 | | // Error Returns Meaning |
2390 | | // |
2391 | | // TPM_RC_ATTRIBUTES keyHandle does not reference a valid decryption key |
2392 | | // TPM_RC_KEY invalid ECC key (public point is not on the curve) |
2393 | | // TPM_RC_SCHEME RSA key with an unsupported padding scheme |
2394 | | // TPM_RC_VALUE numeric value of the data to be decrypted is greater than the RSA |
2395 | | // key modulus |
2396 | | // |
2397 | | TPM_RC |
2398 | | CryptSecretEncrypt( |
2399 | | TPMI_DH_OBJECT keyHandle, // IN: encryption key handle |
2400 | | const char *label, // IN: a null-terminated string as L |
2401 | | TPM2B_DATA *data, // OUT: secret value |
2402 | | TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure |
2403 | | ) |
2404 | 0 | { |
2405 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
2406 | 0 | OBJECT *encryptKey = ObjectGet(keyHandle); // TPM key used for encrypt |
2407 | 0 | pAssert(data != NULL && secret != NULL); |
2408 | | // The output secret value has the size of the digest produced by the nameAlg. |
2409 | 0 | data->t.size = CryptGetHashDigestSize(encryptKey->publicArea.nameAlg); |
2410 | 0 | pAssert(encryptKey->publicArea.objectAttributes.decrypt == SET); |
2411 | 0 | switch(encryptKey->publicArea.type) |
2412 | 0 | { |
2413 | 0 | #ifdef TPM_ALG_RSA |
2414 | 0 | case TPM_ALG_RSA: |
2415 | 0 | { |
2416 | 0 | TPMT_RSA_DECRYPT scheme; |
2417 | | // Use OAEP scheme |
2418 | 0 | scheme.scheme = TPM_ALG_OAEP; |
2419 | 0 | scheme.details.oaep.hashAlg = encryptKey->publicArea.nameAlg; |
2420 | | // Create secret data from RNG |
2421 | 0 | CryptGenerateRandom(data->t.size, data->t.buffer); |
2422 | | // Encrypt the data by RSA OAEP into encrypted secret |
2423 | 0 | result = CryptEncryptRSA(&secret->t.size, secret->t.secret, |
2424 | 0 | encryptKey, &scheme, |
2425 | 0 | data->t.size, data->t.buffer, label); |
2426 | 0 | } |
2427 | 0 | break; |
2428 | 0 | #endif //TPM_ALG_RSA |
2429 | 0 | #ifdef TPM_ALG_ECC |
2430 | 0 | case TPM_ALG_ECC: |
2431 | 0 | { |
2432 | 0 | TPMS_ECC_POINT eccPublic; |
2433 | 0 | TPM2B_ECC_PARAMETER eccPrivate; |
2434 | 0 | TPMS_ECC_POINT eccSecret; |
2435 | 0 | BYTE *buffer = secret->t.secret; |
2436 | 0 | INT32 bufferSize = sizeof(TPMS_ECC_POINT); |
2437 | | // Need to make sure that the public point of the key is on the |
2438 | | // curve defined by the key. |
2439 | 0 | if(!_cpri__EccIsPointOnCurve( |
2440 | 0 | encryptKey->publicArea.parameters.eccDetail.curveID, |
2441 | 0 | &encryptKey->publicArea.unique.ecc)) |
2442 | 0 | result = TPM_RC_KEY; |
2443 | 0 | else |
2444 | 0 | { |
2445 | | // Call crypto engine to create an auxiliary ECC key |
2446 | | // We assume crypt engine initialization should always success. |
2447 | | // Otherwise, TPM should go to failure mode. |
2448 | 0 | CryptNewEccKey(encryptKey->publicArea.parameters.eccDetail.curveID, |
2449 | 0 | &eccPublic, &eccPrivate); |
2450 | | // Marshal ECC public to secret structure. This will be used by the |
2451 | | // recipient to decrypt the secret with their private key. |
2452 | 0 | secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, &bufferSize); |
2453 | | // Compute ECDH shared secret which is R = [d]Q where d is the |
2454 | | // private part of the ephemeral key and Q is the public part of a |
2455 | | // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret |
2456 | | // because the auxiliary ECC key is just created according to the |
2457 | | // parameters of input ECC encrypt key. |
2458 | 0 | if( CryptEccPointMultiply(&eccSecret, |
2459 | 0 | encryptKey->publicArea.parameters.eccDetail.curveID, |
2460 | 0 | &eccPrivate, |
2461 | 0 | &encryptKey->publicArea.unique.ecc) |
2462 | 0 | != CRYPT_SUCCESS) |
2463 | 0 | result = TPM_RC_KEY; |
2464 | 0 | else |
2465 | | // The secret value is computed from Z using KDFe as: |
2466 | | // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) |
2467 | | // Where: |
2468 | | // HashID the nameAlg of the decrypt key |
2469 | | // Z the x coordinate (Px) of the product (P) of the point |
2470 | | // (Q) of the secret and the private x coordinate (de,V) |
2471 | | // of the decryption key |
2472 | | // Use a null-terminated string containing "SECRET" |
2473 | | // PartyUInfo the x coordinate of the point in the secret |
2474 | | // (Qe,U ) |
2475 | | // PartyVInfo the x coordinate of the public key (Qs,V ) |
2476 | | // bits the number of bits in the digest of HashID |
2477 | | // Retrieve seed from KDFe |
2478 | 0 | CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b, |
2479 | 0 | label, &eccPublic.x.b, |
2480 | 0 | &encryptKey->publicArea.unique.ecc.x.b, |
2481 | 0 | data->t.size * 8, data->t.buffer); |
2482 | 0 | } |
2483 | 0 | } |
2484 | 0 | break; |
2485 | 0 | #endif //TPM_ALG_ECC |
2486 | 0 | default: |
2487 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
2488 | 0 | break; |
2489 | 0 | } |
2490 | 0 | return result; |
2491 | 0 | } |
2492 | | // |
2493 | | // |
2494 | | // 10.2.9.7 CryptSecretDecrypt() |
2495 | | // |
2496 | | // Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for |
2497 | | // ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both asymmetric |
2498 | | // and symmetric decryption process |
2499 | | // |
2500 | | // Error Returns Meaning |
2501 | | // |
2502 | | // TPM_RC_ATTRIBUTES RSA key is not a decryption key |
2503 | | // TPM_RC_BINDING Invalid RSA key (public and private parts are not cryptographically |
2504 | | // bound. |
2505 | | // TPM_RC_ECC_POINT ECC point in the secret is not on the curve |
2506 | | // TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret |
2507 | | // TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity |
2508 | | // TPM_RC_SIZE data to decrypt is not of the same size as RSA key |
2509 | | // TPM_RC_VALUE For RSA key, numeric value of the encrypted data is greater than the |
2510 | | // modulus, or the recovered data is larger than the output buffer. For |
2511 | | // keyedHash or symmetric key, the secret is larger than the size of the |
2512 | | // digest produced by the name algorithm. |
2513 | | // TPM_RC_FAILURE internal error |
2514 | | // |
2515 | | TPM_RC |
2516 | | CryptSecretDecrypt( |
2517 | | TPM_HANDLE tpmKey, // IN: decrypt key |
2518 | | TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for |
2519 | | // symmetric decryption. For |
2520 | | // asymmetric decryption, this |
2521 | | // parameter is NULL |
2522 | | const char *label, // IN: a null-terminated string as L |
2523 | | TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret |
2524 | | TPM2B_DATA *data // OUT: decrypted secret value |
2525 | | ) |
2526 | 0 | { |
2527 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
2528 | 0 | OBJECT *decryptKey = ObjectGet(tpmKey); //TPM key used for decrypting |
2529 | | // Decryption for secret |
2530 | 0 | switch(decryptKey->publicArea.type) |
2531 | 0 | { |
2532 | 0 | #ifdef TPM_ALG_RSA |
2533 | 0 | case TPM_ALG_RSA: |
2534 | 0 | { |
2535 | 0 | TPMT_RSA_DECRYPT scheme; |
2536 | | // Use OAEP scheme |
2537 | 0 | scheme.scheme = TPM_ALG_OAEP; |
2538 | 0 | scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg; |
2539 | | // Set the output buffer capacity |
2540 | 0 | data->t.size = sizeof(data->t.buffer); |
2541 | | // Decrypt seed by RSA OAEP |
2542 | 0 | result = CryptDecryptRSA(&data->t.size, data->t.buffer, decryptKey, |
2543 | 0 | &scheme, |
2544 | 0 | secret->t.size, secret->t.secret,label); |
2545 | 0 | if( (result == TPM_RC_SUCCESS) |
2546 | 0 | && (data->t.size |
2547 | 0 | > CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))) |
2548 | 0 | result = TPM_RC_VALUE; |
2549 | 0 | } |
2550 | 0 | break; |
2551 | 0 | #endif //TPM_ALG_RSA |
2552 | 0 | #ifdef TPM_ALG_ECC |
2553 | 0 | case TPM_ALG_ECC: |
2554 | 0 | { |
2555 | 0 | TPMS_ECC_POINT eccPublic; |
2556 | 0 | TPMS_ECC_POINT eccSecret; |
2557 | 0 | BYTE *buffer = secret->t.secret; |
2558 | 0 | INT32 size = secret->t.size; |
2559 | | // Retrieve ECC point from secret buffer |
2560 | 0 | result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size); |
2561 | 0 | if(result == TPM_RC_SUCCESS) |
2562 | 0 | { |
2563 | 0 | result = CryptEccPointMultiply(&eccSecret, |
2564 | 0 | decryptKey->publicArea.parameters.eccDetail.curveID, |
2565 | 0 | &decryptKey->sensitive.sensitive.ecc, |
2566 | 0 | &eccPublic); |
2567 | 0 | if(result == TPM_RC_SUCCESS) |
2568 | 0 | { |
2569 | | // Set the size of the "recovered" secret value to be the size |
2570 | | // of the digest produced by the nameAlg. |
2571 | 0 | data->t.size = |
2572 | 0 | CryptGetHashDigestSize(decryptKey->publicArea.nameAlg); |
2573 | | // The secret value is computed from Z using KDFe as: |
2574 | | // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) |
2575 | | // Where: |
2576 | | // HashID -- the nameAlg of the decrypt key |
2577 | | // Z -- the x coordinate (Px) of the product (P) of the point |
2578 | | // (Q) of the secret and the private x coordinate (de,V) |
2579 | | // of the decryption key |
2580 | | // Use -- a null-terminated string containing "SECRET" |
2581 | | // PartyUInfo -- the x coordinate of the point in the secret |
2582 | | // (Qe,U ) |
2583 | | // PartyVInfo -- the x coordinate of the public key (Qs,V ) |
2584 | | // bits -- the number of bits in the digest of HashID |
2585 | | // Retrieve seed from KDFe |
2586 | 0 | CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label, |
2587 | 0 | &eccPublic.x.b, |
2588 | 0 | &decryptKey->publicArea.unique.ecc.x.b, |
2589 | 0 | data->t.size * 8, data->t.buffer); |
2590 | 0 | } |
2591 | 0 | } |
2592 | 0 | } |
2593 | 0 | break; |
2594 | 0 | #endif //TPM_ALG_ECC |
2595 | 0 | case TPM_ALG_KEYEDHASH: |
2596 | | // The seed size can not be bigger than the digest size of nameAlg |
2597 | 0 | if(secret->t.size > |
2598 | 0 | CryptGetHashDigestSize(decryptKey->publicArea.nameAlg)) |
2599 | 0 | result = TPM_RC_VALUE; |
2600 | 0 | else |
2601 | 0 | { |
2602 | | // Retrieve seed by XOR Obfuscation: |
2603 | | // seed = XOR(secret, hash, key, nonceCaller, nullNonce) |
2604 | | // where: |
2605 | | // secret the secret parameter from the TPM2_StartAuthHMAC |
2606 | | // command |
2607 | | // which contains the seed value |
2608 | | // hash nameAlg of tpmKey |
2609 | | // key the key or data value in the object referenced by |
2610 | | // entityHandle in the TPM2_StartAuthHMAC command |
2611 | | // nonceCaller the parameter from the TPM2_StartAuthHMAC command |
2612 | | // nullNonce a zero-length nonce |
2613 | | // XOR Obfuscation in place |
2614 | 0 | CryptXORObfuscation(decryptKey->publicArea.nameAlg, |
2615 | 0 | &decryptKey->sensitive.sensitive.bits.b, |
2616 | 0 | &nonceCaller->b, NULL, |
2617 | 0 | secret->t.size, secret->t.secret); |
2618 | | // Copy decrypted seed |
2619 | 0 | MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer)); |
2620 | 0 | } |
2621 | 0 | break; |
2622 | 0 | case TPM_ALG_SYMCIPHER: |
2623 | 0 | { |
2624 | 0 | TPM2B_IV iv = {}; |
2625 | 0 | TPMT_SYM_DEF_OBJECT *symDef; |
2626 | | // The seed size can not be bigger than the digest size of nameAlg |
2627 | 0 | if(secret->t.size > |
2628 | 0 | CryptGetHashDigestSize(decryptKey->publicArea.nameAlg)) |
2629 | 0 | result = TPM_RC_VALUE; |
2630 | 0 | else |
2631 | 0 | { |
2632 | 0 | symDef = &decryptKey->publicArea.parameters.symDetail.sym; |
2633 | 0 | iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm, |
2634 | 0 | symDef->keyBits.sym); |
2635 | 0 | pAssert(iv.t.size != 0); |
2636 | 0 | if(nonceCaller->t.size >= iv.t.size) |
2637 | 0 | MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size, |
2638 | 0 | sizeof(iv.t.buffer)); |
2639 | 0 | else |
2640 | 0 | MemoryCopy(iv.b.buffer, nonceCaller->t.buffer, |
2641 | 0 | nonceCaller->t.size, sizeof(iv.t.buffer)); |
2642 | | // CFB decrypt in place, using nonceCaller as iv |
2643 | 0 | CryptSymmetricDecrypt(secret->t.secret, symDef->algorithm, |
2644 | 0 | symDef->keyBits.sym, TPM_ALG_CFB, |
2645 | 0 | decryptKey->sensitive.sensitive.sym.t.buffer, |
2646 | 0 | &iv, secret->t.size, secret->t.secret); |
2647 | | // Copy decrypted seed |
2648 | 0 | MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer)); |
2649 | 0 | } |
2650 | 0 | } |
2651 | 0 | break; |
2652 | 0 | default: |
2653 | 0 | pAssert(0); |
2654 | 0 | break; |
2655 | 0 | } |
2656 | 0 | return result; |
2657 | 0 | } |
2658 | | // |
2659 | | // |
2660 | | // 10.2.9.8 CryptParameterEncryption() |
2661 | | // |
2662 | | // This function does in-place encryption of a response parameter. |
2663 | | // |
2664 | | void |
2665 | | CryptParameterEncryption( |
2666 | | TPM_HANDLE handle, // IN: encrypt session handle |
2667 | | TPM2B *nonceCaller, // IN: nonce caller |
2668 | | UINT32 bufferSize, // IN: size of parameter buffer |
2669 | | UINT16 leadingSizeInByte, // IN: the size of the leading size field in |
2670 | | // byte |
2671 | | TPM2B_AUTH *extraKey, // IN: additional key material other than |
2672 | | // session auth |
2673 | | BYTE *buffer // IN/OUT: parameter buffer to be encrypted |
2674 | | ) |
2675 | 0 | { |
2676 | 0 | SESSION *session = SessionGet(handle); // encrypt session |
2677 | 0 | TPM2B_TYPE(SYM_KEY, ( sizeof(extraKey->t.buffer) |
2678 | 0 | + sizeof(session->sessionKey.t.buffer))); |
2679 | 0 | TPM2B_SYM_KEY key; // encryption key |
2680 | 0 | UINT32 cipherSize = 0; // size of cipher text |
2681 | 0 | pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer)); |
2682 | |
|
2683 | 0 | if (bufferSize < leadingSizeInByte) |
2684 | 0 | return; |
2685 | | // Retrieve encrypted data size. |
2686 | 0 | if(leadingSizeInByte == 2) |
2687 | 0 | { |
2688 | | // Extract the first two bytes as the size field as the data size |
2689 | | // encrypt |
2690 | 0 | cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); |
2691 | | // advance the buffer |
2692 | 0 | buffer = &buffer[2]; |
2693 | 0 | bufferSize -= 2; |
2694 | 0 | } |
2695 | | #ifdef TPM4B |
2696 | | else if(leadingSizeInByte == 4) |
2697 | | { |
2698 | | // use the first four bytes to indicate the number of bytes to encrypt |
2699 | | cipherSize = BYTE_ARRAY_TO_UINT32(buffer); |
2700 | | //advance pointer |
2701 | | buffer = &buffer[4]; |
2702 | | bufferSize -= 4; |
2703 | | } |
2704 | | #endif |
2705 | 0 | else |
2706 | 0 | { |
2707 | 0 | pAssert(FALSE); |
2708 | 0 | } |
2709 | 0 | if (cipherSize > bufferSize) |
2710 | 0 | cipherSize = bufferSize; |
2711 | | // |
2712 | | // Compute encryption key by concatenating sessionAuth with extra key |
2713 | 0 | MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); |
2714 | 0 | MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); |
2715 | 0 | if (session->symmetric.algorithm == TPM_ALG_XOR) |
2716 | | // XOR parameter encryption formulation: |
2717 | | // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) |
2718 | 0 | CryptXORObfuscation(session->authHashAlg, &(key.b), |
2719 | 0 | &(session->nonceTPM.b), |
2720 | 0 | nonceCaller, cipherSize, buffer); |
2721 | 0 | else |
2722 | 0 | ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg, |
2723 | 0 | session->symmetric.keyBits.aes, &(key.b), |
2724 | 0 | nonceCaller, &(session->nonceTPM.b), |
2725 | 0 | cipherSize, buffer); |
2726 | 0 | return; |
2727 | 0 | } |
2728 | | // |
2729 | | // |
2730 | | // 10.2.9.9 CryptParameterDecryption() |
2731 | | // |
2732 | | // This function does in-place decryption of a command parameter. |
2733 | | // |
2734 | | // Error Returns Meaning |
2735 | | // |
2736 | | // TPM_RC_SIZE The number of bytes in the input buffer is less than the number of |
2737 | | // bytes to be decrypted. |
2738 | | // |
2739 | | TPM_RC |
2740 | | CryptParameterDecryption( |
2741 | | TPM_HANDLE handle, // IN: encrypted session handle |
2742 | | TPM2B *nonceCaller, // IN: nonce caller |
2743 | | UINT32 bufferSize, // IN: size of parameter buffer |
2744 | | UINT16 leadingSizeInByte, // IN: the size of the leading size field in |
2745 | | // byte |
2746 | | TPM2B_AUTH *extraKey, // IN: the authValue |
2747 | | BYTE *buffer // IN/OUT: parameter buffer to be decrypted |
2748 | | ) |
2749 | 0 | { |
2750 | 0 | SESSION *session = SessionGet(handle); // encrypt session |
2751 | | // The HMAC key is going to be the concatenation of the session key and any |
2752 | | // additional key material (like the authValue). The size of both of these |
2753 | | // is the size of the buffer which can contain a TPMT_HA. |
2754 | 0 | TPM2B_TYPE(HMAC_KEY, ( sizeof(extraKey->t.buffer) |
2755 | 0 | + sizeof(session->sessionKey.t.buffer))); |
2756 | 0 | TPM2B_HMAC_KEY key; // decryption key |
2757 | 0 | UINT32 cipherSize = 0; // size of cipher text |
2758 | 0 | pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer)); |
2759 | |
|
2760 | 0 | if (bufferSize < leadingSizeInByte) |
2761 | 0 | return TPM_RC_INSUFFICIENT; |
2762 | | |
2763 | | // Retrieve encrypted data size. |
2764 | 0 | if(leadingSizeInByte == 2) |
2765 | 0 | { |
2766 | | // The first two bytes of the buffer are the size of the |
2767 | | // data to be decrypted |
2768 | 0 | cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); |
2769 | 0 | buffer = &buffer[2]; // advance the buffer |
2770 | 0 | bufferSize -= 2; |
2771 | 0 | } |
2772 | | #ifdef TPM4B |
2773 | | else if(leadingSizeInByte == 4) |
2774 | | { |
2775 | | // the leading size is four bytes so get the four byte size field |
2776 | | cipherSize = BYTE_ARRAY_TO_UINT32(buffer); |
2777 | | buffer = &buffer[4]; //advance pointer |
2778 | | bufferSize -= 4; |
2779 | | } |
2780 | | #endif |
2781 | 0 | else |
2782 | 0 | { |
2783 | 0 | pAssert(FALSE); |
2784 | 0 | } |
2785 | 0 | if(cipherSize > bufferSize) |
2786 | 0 | return TPM_RC_SIZE; |
2787 | | // Compute decryption key by concatenating sessionAuth with extra input key |
2788 | 0 | MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); |
2789 | 0 | MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); |
2790 | 0 | if(session->symmetric.algorithm == TPM_ALG_XOR) |
2791 | | // XOR parameter decryption formulation: |
2792 | | // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) |
2793 | | // Call XOR obfuscation function |
2794 | 0 | CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller, |
2795 | 0 | &(session->nonceTPM.b), cipherSize, buffer); |
2796 | 0 | else |
2797 | | // Assume that it is one of the symmetric block ciphers. |
2798 | 0 | ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg, |
2799 | 0 | session->symmetric.keyBits.sym, |
2800 | 0 | &key.b, nonceCaller, &session->nonceTPM.b, |
2801 | 0 | cipherSize, buffer); |
2802 | 0 | return TPM_RC_SUCCESS; |
2803 | 0 | } |
2804 | | // |
2805 | | // |
2806 | | // 10.2.9.10 CryptComputeSymmetricUnique() |
2807 | | // |
2808 | | // This function computes the unique field in public area for symmetric objects. |
2809 | | // |
2810 | | void |
2811 | | CryptComputeSymmetricUnique( |
2812 | | TPMI_ALG_HASH nameAlg, // IN: object name algorithm |
2813 | | TPMT_SENSITIVE *sensitive, // IN: sensitive area |
2814 | | TPM2B_DIGEST *unique // OUT: unique buffer |
2815 | | ) |
2816 | 0 | { |
2817 | 0 | HASH_STATE hashState; |
2818 | 0 | pAssert(sensitive != NULL && unique != NULL); |
2819 | | // Compute the public value as the hash of sensitive.symkey || unique.buffer |
2820 | 0 | unique->t.size = CryptGetHashDigestSize(nameAlg); |
2821 | 0 | CryptStartHash(nameAlg, &hashState); |
2822 | | // Add obfuscation value |
2823 | 0 | CryptUpdateDigest2B(&hashState, &sensitive->seedValue.b); |
2824 | | // Add sensitive value |
2825 | 0 | CryptUpdateDigest2B(&hashState, &sensitive->sensitive.any.b); |
2826 | 0 | CryptCompleteHash2B(&hashState, &unique->b); |
2827 | 0 | return; |
2828 | 0 | } |
2829 | | #if 0 //% |
2830 | | // |
2831 | | // |
2832 | | // |
2833 | | // 10.2.9.11 CryptComputeSymValue() |
2834 | | // |
2835 | | // This function computes the seedValue field in asymmetric sensitive areas. |
2836 | | // |
2837 | | void |
2838 | | CryptComputeSymValue( |
2839 | | TPM_HANDLE parentHandle, // IN: parent handle of the object to be created |
2840 | | TPMT_PUBLIC *publicArea, // IN/OUT: the public area template |
2841 | | TPMT_SENSITIVE *sensitive, // IN: sensitive area |
2842 | | TPM2B_SEED *seed, // IN: the seed |
2843 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm for KDFa |
2844 | | TPM2B_NAME *name // IN: object name |
2845 | | ) |
2846 | | { |
2847 | | TPM2B_AUTH *proof = NULL; |
2848 | | if(CryptIsAsymAlgorithm(publicArea->type)) |
2849 | | { |
2850 | | // Generate seedValue only when an asymmetric key is a storage key |
2851 | | if(publicArea->objectAttributes.decrypt == SET |
2852 | | && publicArea->objectAttributes.restricted == SET) |
2853 | | { |
2854 | | // If this is a primary object in the endorsement hierarchy, use |
2855 | | // ehProof in the creation of the symmetric seed so that child |
2856 | | // objects in the endorsement hierarchy are voided on TPM2_Clear() |
2857 | | // or TPM2_ChangeEPS() |
2858 | | if( parentHandle == TPM_RH_ENDORSEMENT |
2859 | | && publicArea->objectAttributes.fixedTPM == SET) |
2860 | | proof = &gp.ehProof; |
2861 | | } |
2862 | | else |
2863 | | { |
2864 | | sensitive->seedValue.t.size = 0; |
2865 | | return; |
2866 | | } |
2867 | | } |
2868 | | // For all object types, the size of seedValue is the digest size of nameAlg |
2869 | | sensitive->seedValue.t.size = CryptGetHashDigestSize(publicArea->nameAlg); |
2870 | | // Compute seedValue using implementation-dependent method |
2871 | | _cpri__GenerateSeededRandom(sensitive->seedValue.t.size, |
2872 | | sensitive->seedValue.t.buffer, |
2873 | | hashAlg, |
2874 | | &seed->b, |
2875 | | "seedValue", |
2876 | | &name->b, |
2877 | | (TPM2B *)proof); |
2878 | | return; |
2879 | | } |
2880 | | #endif //% |
2881 | | // |
2882 | | // |
2883 | | // 10.2.9.12 CryptCreateObject() |
2884 | | // |
2885 | | // This function creates an object. It: |
2886 | | // a) fills in the created key in public and sensitive area; |
2887 | | // b) creates a random number in sensitive area for symmetric keys; and |
2888 | | // c) compute the unique id in public area for symmetric keys. |
2889 | | // |
2890 | | // |
2891 | | // |
2892 | | // |
2893 | | // Error Returns Meaning |
2894 | | // |
2895 | | // TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive |
2896 | | // creation area for a symmetric key |
2897 | | // TPM_RC_RANGE for an RSA key, the exponent is not supported |
2898 | | // TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed |
2899 | | // hash object |
2900 | | // TPM_RC_VALUE exponent is not prime or could not find a prime using the provided |
2901 | | // parameters for an RSA key; unsupported name algorithm for an ECC |
2902 | | // key; unsupported name algorithm for symmetric algorithms |
2903 | | // |
2904 | | TPM_RC |
2905 | | CryptCreateObject( |
2906 | | TPM_HANDLE parentHandle, // IN/OUT: indication of the seed |
2907 | | // source |
2908 | | TPMT_PUBLIC *publicArea, // IN/OUT: public area |
2909 | | TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation |
2910 | | TPMT_SENSITIVE *sensitive // OUT: sensitive area |
2911 | | ) |
2912 | 3 | { |
2913 | | // Next value is a placeholder for a random seed that is used in |
2914 | | // key creation when the parent is not a primary seed. It has the same |
2915 | | // size as the primary seed. |
2916 | 3 | TPM2B_SEED localSeed; // data to seed key creation if this |
2917 | | // is not a primary seed |
2918 | 3 | TPM2B_SEED *seed = NULL; |
2919 | 3 | TPM_RC result = TPM_RC_SUCCESS; |
2920 | 3 | TPM2B_NAME name; |
2921 | 3 | TPM_ALG_ID hashAlg = CONTEXT_INTEGRITY_HASH_ALG; |
2922 | 3 | OBJECT *parent; |
2923 | 3 | UINT32 counter; |
2924 | | // Set the sensitive type for the object |
2925 | 3 | sensitive->sensitiveType = publicArea->type; |
2926 | 3 | ObjectComputeName(publicArea, &name); |
2927 | | // For all objects, copy the initial auth data |
2928 | 3 | sensitive->authValue = sensitiveCreate->userAuth; |
2929 | | // If this is a permanent handle assume that it is a hierarchy |
2930 | 3 | if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) |
2931 | 3 | { |
2932 | 3 | seed = HierarchyGetPrimarySeed(parentHandle); |
2933 | 3 | } |
2934 | 0 | else |
2935 | 0 | { |
2936 | | // If not hierarchy handle, get parent |
2937 | 0 | parent = ObjectGet(parentHandle); |
2938 | 0 | hashAlg = parent->publicArea.nameAlg; |
2939 | | // Use random value as seed for non-primary objects |
2940 | 0 | localSeed.t.size = PRIMARY_SEED_SIZE; |
2941 | 0 | CryptGenerateRandom(PRIMARY_SEED_SIZE, localSeed.t.buffer); |
2942 | 0 | seed = &localSeed; |
2943 | 0 | } |
2944 | 3 | switch(publicArea->type) |
2945 | 3 | { |
2946 | 0 | #ifdef TPM_ALG_RSA |
2947 | | // Create RSA key |
2948 | 3 | case TPM_ALG_RSA: |
2949 | 3 | result = CryptGenerateKeyRSA(publicArea, sensitive, |
2950 | 3 | hashAlg, seed, &name, &counter); |
2951 | 3 | break; |
2952 | 0 | #endif // TPM_ALG_RSA |
2953 | 0 | #ifdef TPM_ALG_ECC |
2954 | | // Create ECC key |
2955 | 0 | case TPM_ALG_ECC: |
2956 | 0 | result = CryptGenerateKeyECC(publicArea, sensitive, |
2957 | 0 | hashAlg, seed, &name, &counter); |
2958 | 0 | break; |
2959 | 0 | #endif // TPM_ALG_ECC |
2960 | | // Collect symmetric key information |
2961 | 0 | case TPM_ALG_SYMCIPHER: |
2962 | 0 | return CryptGenerateKeySymmetric(publicArea, sensitiveCreate, |
2963 | 0 | sensitive, hashAlg, seed, &name); |
2964 | 0 | break; |
2965 | 0 | case TPM_ALG_KEYEDHASH: |
2966 | 0 | return CryptGenerateKeyedHash(publicArea, sensitiveCreate, |
2967 | 0 | sensitive, hashAlg, seed, &name); |
2968 | 0 | break; |
2969 | 0 | default: |
2970 | 0 | pAssert(0); |
2971 | 0 | break; |
2972 | 3 | } |
2973 | 3 | if(result == TPM_RC_SUCCESS) |
2974 | 3 | { |
2975 | 3 | TPM2B_AUTH *proof = NULL; |
2976 | 3 | if(publicArea->objectAttributes.decrypt == SET |
2977 | 3 | && publicArea->objectAttributes.restricted == SET) |
2978 | 0 | { |
2979 | | // If this is a primary object in the endorsement hierarchy, use |
2980 | | // ehProof in the creation of the symmetric seed so that child |
2981 | | // objects in the endorsement hierarchy are voided on TPM2_Clear() |
2982 | | // or TPM2_ChangeEPS() |
2983 | 0 | if( parentHandle == TPM_RH_ENDORSEMENT |
2984 | 0 | && publicArea->objectAttributes.fixedTPM == SET) |
2985 | 0 | proof = &gp.ehProof; |
2986 | | // For all object types, the size of seedValue is the digest size |
2987 | | // of its nameAlg |
2988 | 0 | sensitive->seedValue.t.size |
2989 | 0 | = CryptGetHashDigestSize(publicArea->nameAlg); |
2990 | | // Compute seedValue using implementation-dependent method |
2991 | 0 | _cpri__GenerateSeededRandom(sensitive->seedValue.t.size, |
2992 | 0 | sensitive->seedValue.t.buffer, |
2993 | 0 | hashAlg, |
2994 | 0 | &seed->b, |
2995 | 0 | "seedValuea", |
2996 | 0 | &name.b, |
2997 | 0 | (TPM2B *)proof); |
2998 | 0 | } |
2999 | 3 | else |
3000 | 3 | { |
3001 | 3 | sensitive->seedValue.t.size = 0; |
3002 | 3 | } |
3003 | 3 | } |
3004 | 3 | return result; |
3005 | 3 | } |
3006 | | // |
3007 | | // 10.2.9.13 CryptObjectIsPublicConsistent() |
3008 | | // |
3009 | | // This function checks that the key sizes in the public area are consistent. For an asymmetric key, the size |
3010 | | // of the public key must match the size indicated by the public->parameters. |
3011 | | // Checks for the algorithm types matching the key type are handled by the unmarshaling operation. |
3012 | | // |
3013 | | // Return Value Meaning |
3014 | | // |
3015 | | // TRUE sizes are consistent |
3016 | | // FALSE sizes are not consistent |
3017 | | // |
3018 | | BOOL |
3019 | | CryptObjectIsPublicConsistent( |
3020 | | TPMT_PUBLIC *publicArea // IN: public area |
3021 | | ) |
3022 | 40 | { |
3023 | 40 | BOOL OK = TRUE; |
3024 | 40 | switch (publicArea->type) |
3025 | 40 | { |
3026 | 0 | #ifdef TPM_ALG_RSA |
3027 | 33 | case TPM_ALG_RSA: |
3028 | 33 | OK = CryptAreKeySizesConsistent(publicArea); |
3029 | 33 | break; |
3030 | 0 | #endif //TPM_ALG_RSA |
3031 | 0 | #ifdef TPM_ALG_ECC |
3032 | 7 | case TPM_ALG_ECC: |
3033 | 7 | { |
3034 | 7 | const ECC_CURVE *curveValue; |
3035 | | // Check that the public point is on the indicated curve. |
3036 | 7 | OK = CryptEccIsPointOnCurve( |
3037 | 7 | publicArea->parameters.eccDetail.curveID, |
3038 | 7 | &publicArea->unique.ecc); |
3039 | 7 | if(OK) |
3040 | 6 | { |
3041 | 6 | curveValue = CryptEccGetCurveDataPointer( |
3042 | 6 | publicArea->parameters.eccDetail.curveID); |
3043 | 6 | pAssert(curveValue != NULL); |
3044 | | // The input ECC curve must be a supported curve |
3045 | | // IF a scheme is defined for the curve, then that scheme must |
3046 | | // be used. |
3047 | 6 | OK = (curveValue->sign.scheme == TPM_ALG_NULL |
3048 | 6 | || ( publicArea->parameters.eccDetail.scheme.scheme |
3049 | 0 | == curveValue->sign.scheme)); |
3050 | 6 | OK = OK && CryptAreKeySizesConsistent(publicArea); |
3051 | 6 | } |
3052 | 7 | } |
3053 | 7 | break; |
3054 | 0 | #endif //TPM_ALG_ECC |
3055 | 0 | default: |
3056 | | // Symmetric object common checks |
3057 | | // There is noting to check with a symmetric key that is public only. |
3058 | | // Also not sure that there is anything useful to be done with it |
3059 | | // either. |
3060 | 0 | break; |
3061 | 40 | } |
3062 | 40 | return OK; |
3063 | 40 | } |
3064 | | // |
3065 | | // |
3066 | | // |
3067 | | // 10.2.9.14 CryptObjectPublicPrivateMatch() |
3068 | | // |
3069 | | // This function checks the cryptographic binding between the public and sensitive areas. |
3070 | | // |
3071 | | // Error Returns Meaning |
3072 | | // |
3073 | | // TPM_RC_TYPE the type of the public and private areas are not the same |
3074 | | // TPM_RC_FAILURE crypto error |
3075 | | // TPM_RC_BINDING the public and private areas are not cryptographically matched. |
3076 | | // |
3077 | | TPM_RC |
3078 | | CryptObjectPublicPrivateMatch( |
3079 | | OBJECT *object // IN: the object to check |
3080 | | ) |
3081 | 39 | { |
3082 | 39 | TPMT_PUBLIC *publicArea; |
3083 | 39 | TPMT_SENSITIVE *sensitive; |
3084 | 39 | TPM_RC result = TPM_RC_SUCCESS; |
3085 | 39 | BOOL isAsymmetric = FALSE; |
3086 | 39 | pAssert(object != NULL); |
3087 | 39 | publicArea = &object->publicArea; |
3088 | 39 | sensitive = &object->sensitive; |
3089 | 39 | if(publicArea->type != sensitive->sensitiveType) |
3090 | 0 | return TPM_RC_TYPE; |
3091 | 39 | switch(publicArea->type) |
3092 | 39 | { |
3093 | 0 | #ifdef TPM_ALG_RSA |
3094 | 33 | case TPM_ALG_RSA: |
3095 | 33 | isAsymmetric = TRUE; |
3096 | | // The public and private key sizes need to be consistent |
3097 | 33 | if(sensitive->sensitive.rsa.t.size != publicArea->unique.rsa.t.size/2) |
3098 | 1 | result = TPM_RC_BINDING; |
3099 | 32 | else |
3100 | | // Load key by computing the private exponent |
3101 | 32 | result = CryptLoadPrivateRSA(object); |
3102 | 33 | break; |
3103 | 0 | #endif |
3104 | 0 | #ifdef TPM_ALG_ECC |
3105 | | // This function is called from ObjectLoad() which has already checked to |
3106 | | // see that the public point is on the curve so no need to repeat that |
3107 | | // check. |
3108 | 6 | case TPM_ALG_ECC: |
3109 | 6 | isAsymmetric = TRUE; |
3110 | 6 | if( publicArea->unique.ecc.x.t.size |
3111 | 6 | != sensitive->sensitive.ecc.t.size) |
3112 | 3 | result = TPM_RC_BINDING; |
3113 | 3 | else if(publicArea->nameAlg != TPM_ALG_NULL) |
3114 | 3 | { |
3115 | 3 | TPMS_ECC_POINT publicToCompare; |
3116 | | // Compute ECC public key |
3117 | 3 | CryptEccPointMultiply(&publicToCompare, |
3118 | 3 | publicArea->parameters.eccDetail.curveID, |
3119 | 3 | &sensitive->sensitive.ecc, NULL); |
3120 | | // Compare ECC public key |
3121 | 3 | if( (!Memory2BEqual(&publicArea->unique.ecc.x.b, |
3122 | 3 | &publicToCompare.x.b)) |
3123 | 3 | || (!Memory2BEqual(&publicArea->unique.ecc.y.b, |
3124 | 0 | &publicToCompare.y.b))) |
3125 | 3 | result = TPM_RC_BINDING; |
3126 | 3 | } |
3127 | 6 | break; |
3128 | | // |
3129 | 0 | #endif |
3130 | 0 | case TPM_ALG_KEYEDHASH: |
3131 | 0 | break; |
3132 | 0 | case TPM_ALG_SYMCIPHER: |
3133 | 0 | if( (publicArea->parameters.symDetail.sym.keyBits.sym + 7)/8 |
3134 | 0 | != sensitive->sensitive.sym.t.size) |
3135 | 0 | result = TPM_RC_BINDING; |
3136 | 0 | break; |
3137 | 0 | default: |
3138 | | // The choice here is an assert or a return of a bad type for the object |
3139 | 0 | pAssert(0); |
3140 | 0 | break; |
3141 | 39 | } |
3142 | | // For asymmetric keys, the algorithm for validating the linkage between |
3143 | | // the public and private areas is algorithm dependent. For symmetric keys |
3144 | | // the linkage is based on hashing the symKey and obfuscation values. |
3145 | 39 | if( result == TPM_RC_SUCCESS && !isAsymmetric |
3146 | 39 | && publicArea->nameAlg != TPM_ALG_NULL) |
3147 | 0 | { |
3148 | 0 | TPM2B_DIGEST uniqueToCompare; |
3149 | | // Compute unique for symmetric key |
3150 | 0 | CryptComputeSymmetricUnique(publicArea->nameAlg, sensitive, |
3151 | 0 | &uniqueToCompare); |
3152 | | // Compare unique |
3153 | 0 | if(!Memory2BEqual(&publicArea->unique.sym.b, |
3154 | 0 | &uniqueToCompare.b)) |
3155 | 0 | result = TPM_RC_BINDING; |
3156 | 0 | } |
3157 | 39 | return result; |
3158 | 39 | } |
3159 | | // |
3160 | | // |
3161 | | // 10.2.9.15 CryptGetSignHashAlg() |
3162 | | // |
3163 | | // Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is not |
3164 | | // NULL This is a function for easy access |
3165 | | // |
3166 | | TPMI_ALG_HASH |
3167 | | CryptGetSignHashAlg( |
3168 | | TPMT_SIGNATURE *auth // IN: signature |
3169 | | ) |
3170 | 0 | { |
3171 | 0 | pAssert(auth->sigAlg != TPM_ALG_NULL); |
3172 | | // Get authHash algorithm based on signing scheme |
3173 | 0 | switch(auth->sigAlg) |
3174 | 0 | { |
3175 | 0 | #ifdef TPM_ALG_RSA |
3176 | 0 | case TPM_ALG_RSASSA: |
3177 | 0 | return auth->signature.rsassa.hash; |
3178 | 0 | case TPM_ALG_RSAPSS: |
3179 | 0 | return auth->signature.rsapss.hash; |
3180 | 0 | #endif //TPM_ALG_RSA |
3181 | 0 | #ifdef TPM_ALG_ECC |
3182 | 0 | case TPM_ALG_ECDSA: |
3183 | 0 | return auth->signature.ecdsa.hash; |
3184 | 0 | #endif //TPM_ALG_ECC |
3185 | 0 | case TPM_ALG_HMAC: |
3186 | 0 | return auth->signature.hmac.hashAlg; |
3187 | 0 | default: |
3188 | 0 | return TPM_ALG_NULL; |
3189 | 0 | } |
3190 | 0 | } |
3191 | | // |
3192 | | // |
3193 | | // 10.2.9.16 CryptIsSplitSign() |
3194 | | // |
3195 | | // This function us used to determine if the signing operation is a split signing operation that required a |
3196 | | // TPM2_Commit(). |
3197 | | // |
3198 | | BOOL |
3199 | | CryptIsSplitSign( |
3200 | | TPM_ALG_ID scheme // IN: the algorithm selector |
3201 | | ) |
3202 | 0 | { |
3203 | 0 | if( 0 |
3204 | 0 | # ifdef TPM_ALG_ECDAA |
3205 | 0 | || scheme == TPM_ALG_ECDAA |
3206 | 0 | # endif // TPM_ALG_ECDAA |
3207 | 0 | ) |
3208 | 0 | return TRUE; |
3209 | 0 | return FALSE; |
3210 | 0 | } |
3211 | | // |
3212 | | // |
3213 | | // 10.2.9.17 CryptIsSignScheme() |
3214 | | // |
3215 | | // This function indicates if a scheme algorithm is a sign algorithm. |
3216 | | // |
3217 | | BOOL |
3218 | | CryptIsSignScheme( |
3219 | | TPMI_ALG_ASYM_SCHEME scheme |
3220 | | ) |
3221 | 15 | { |
3222 | 15 | BOOL isSignScheme = FALSE; |
3223 | 15 | switch(scheme) |
3224 | 15 | { |
3225 | 0 | #ifdef TPM_ALG_RSA |
3226 | | // If RSA is implemented, then both signing schemes are required |
3227 | 4 | case TPM_ALG_RSASSA: |
3228 | 11 | case TPM_ALG_RSAPSS: |
3229 | 11 | isSignScheme = TRUE; |
3230 | 11 | break; |
3231 | 0 | #endif //TPM_ALG_RSA |
3232 | 0 | #ifdef TPM_ALG_ECC |
3233 | | // If ECC is implemented ECDSA is required |
3234 | 2 | case TPM_ALG_ECDSA: |
3235 | 2 | #ifdef TPM_ALG_ECDAA |
3236 | | // ECDAA is optional |
3237 | 2 | case TPM_ALG_ECDAA: |
3238 | 2 | #endif |
3239 | 2 | #ifdef TPM_ALG_ECSCHNORR |
3240 | | // Schnorr is also optional |
3241 | 4 | case TPM_ALG_ECSCHNORR: |
3242 | 4 | #endif |
3243 | 4 | #ifdef TPM_ALG_SM2 |
3244 | 4 | case TPM_ALG_SM2: |
3245 | 4 | #endif |
3246 | 4 | isSignScheme = TRUE; |
3247 | 4 | break; |
3248 | 0 | #endif //TPM_ALG_ECC |
3249 | 0 | default: |
3250 | 0 | break; |
3251 | 15 | } |
3252 | 15 | return isSignScheme; |
3253 | 15 | } |
3254 | | // |
3255 | | // |
3256 | | // 10.2.9.18 CryptIsDecryptScheme() |
3257 | | // |
3258 | | // This function indicate if a scheme algorithm is a decrypt algorithm. |
3259 | | // |
3260 | | BOOL |
3261 | | CryptIsDecryptScheme( |
3262 | | TPMI_ALG_ASYM_SCHEME scheme |
3263 | | ) |
3264 | 8 | { |
3265 | 8 | BOOL isDecryptScheme = FALSE; |
3266 | 8 | switch(scheme) |
3267 | 8 | { |
3268 | 0 | #ifdef TPM_ALG_RSA |
3269 | | // If RSA is implemented, then both decrypt schemes are required |
3270 | 0 | case TPM_ALG_RSAES: |
3271 | 7 | case TPM_ALG_OAEP: |
3272 | 7 | isDecryptScheme = TRUE; |
3273 | 7 | break; |
3274 | 0 | #endif //TPM_ALG_RSA |
3275 | 0 | #ifdef TPM_ALG_ECC |
3276 | | // If ECC is implemented ECDH is required |
3277 | 1 | case TPM_ALG_ECDH: |
3278 | 1 | #ifdef TPM_ALG_SM2 |
3279 | 1 | case TPM_ALG_SM2: |
3280 | 1 | #endif |
3281 | | #ifdef TPM_ALG_ECMQV |
3282 | | case TPM_ALG_ECMQV: |
3283 | | #endif |
3284 | 1 | isDecryptScheme = TRUE; |
3285 | 1 | break; |
3286 | 0 | #endif //TPM_ALG_ECC |
3287 | 0 | default: |
3288 | 0 | break; |
3289 | 8 | } |
3290 | 8 | return isDecryptScheme; |
3291 | 8 | } |
3292 | | // |
3293 | | // |
3294 | | // 10.2.9.19 CryptSelectSignScheme() |
3295 | | // |
3296 | | // This function is used by the attestation and signing commands. It implements the rules for selecting the |
3297 | | // signature scheme to use in signing. This function requires that the signing key either be TPM_RH_NULL |
3298 | | // or be loaded. |
3299 | | // If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input |
3300 | | // scheme should be chosen. In the case that both object and input scheme has a non-NULL scheme |
3301 | | // algorithm, if the schemes are compatible, the input scheme will be chosen. |
3302 | | // |
3303 | | // |
3304 | | // |
3305 | | // |
3306 | | // Error Returns Meaning |
3307 | | // |
3308 | | // TPM_RC_KEY key referenced by signHandle is not a signing key |
3309 | | // TPM_RC_SCHEME both scheme and key's default scheme are empty; or scheme is |
3310 | | // empty while key's default scheme requires explicit input scheme (split |
3311 | | // signing); or non-empty default key scheme differs from scheme |
3312 | | // |
3313 | | TPM_RC |
3314 | | CryptSelectSignScheme( |
3315 | | TPMI_DH_OBJECT signHandle, // IN: handle of signing key |
3316 | | TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme |
3317 | | ) |
3318 | 0 | { |
3319 | 0 | OBJECT *signObject; |
3320 | 0 | TPMT_SIG_SCHEME *objectScheme; |
3321 | 0 | TPMT_PUBLIC *publicArea; |
3322 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
3323 | | // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless |
3324 | | // of the setting of scheme |
3325 | 0 | if(signHandle == TPM_RH_NULL) |
3326 | 0 | { |
3327 | 0 | scheme->scheme = TPM_ALG_NULL; |
3328 | 0 | scheme->details.any.hashAlg = TPM_ALG_NULL; |
3329 | 0 | } |
3330 | 0 | else |
3331 | 0 | { |
3332 | | // sign handle is not NULL so... |
3333 | | // Get sign object pointer |
3334 | 0 | signObject = ObjectGet(signHandle); |
3335 | 0 | publicArea = &signObject->publicArea; |
3336 | | // is this a signing key? |
3337 | 0 | if(!publicArea->objectAttributes.sign) |
3338 | 0 | result = TPM_RC_KEY; |
3339 | 0 | else |
3340 | 0 | { |
3341 | | // "parms" defined to avoid long code lines. |
3342 | 0 | TPMU_PUBLIC_PARMS *parms = &publicArea->parameters; |
3343 | 0 | if (CryptIsAsymAlgorithm(publicArea->type)) { |
3344 | 0 | objectScheme = (TPMT_SIG_SCHEME *)&parms->asymDetail.scheme; |
3345 | 0 | } else if (publicArea->type == TPM_ALG_KEYEDHASH) { |
3346 | 0 | objectScheme = (TPMT_SIG_SCHEME *)&parms->keyedHashDetail.scheme; |
3347 | 0 | } else { |
3348 | 0 | return TPM_RC_SCHEME; |
3349 | 0 | } |
3350 | | // If the object doesn't have a default scheme, then use the |
3351 | | // input scheme. |
3352 | 0 | if(objectScheme->scheme == TPM_ALG_NULL) |
3353 | 0 | { |
3354 | | // Input and default can't both be NULL |
3355 | 0 | if(scheme->scheme == TPM_ALG_NULL) |
3356 | 0 | result = TPM_RC_SCHEME; |
3357 | | // Assume that the scheme is compatible with the key. If not, |
3358 | | // we will generate an error in the signing operation. |
3359 | 0 | } |
3360 | 0 | else if(scheme->scheme == TPM_ALG_NULL) |
3361 | 0 | { |
3362 | | // input scheme is NULL so use default |
3363 | | // First, check to see if the default requires that the caller |
3364 | | // provided scheme data |
3365 | 0 | if(CryptIsSplitSign(objectScheme->scheme)) |
3366 | 0 | result = TPM_RC_SCHEME; |
3367 | 0 | else |
3368 | 0 | { |
3369 | 0 | scheme->scheme = objectScheme->scheme; |
3370 | 0 | scheme->details.any.hashAlg |
3371 | 0 | = objectScheme->details.any.hashAlg; |
3372 | 0 | } |
3373 | 0 | } |
3374 | 0 | else |
3375 | 0 | { |
3376 | | // Both input and object have scheme selectors |
3377 | | // If the scheme and the hash are not the same then... |
3378 | 0 | if( objectScheme->scheme != scheme->scheme |
3379 | 0 | || ( objectScheme->details.any.hashAlg |
3380 | 0 | != scheme->details.any.hashAlg)) |
3381 | 0 | result = TPM_RC_SCHEME; |
3382 | 0 | } |
3383 | 0 | } |
3384 | 0 | } |
3385 | 0 | return result; |
3386 | 0 | } |
3387 | | // |
3388 | | // |
3389 | | // 10.2.9.20 CryptSign() |
3390 | | // |
3391 | | // Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and the |
3392 | | // generic TPM2_Sign() command. This function checks the key scheme and digest size. It does not check |
3393 | | // if the sign operation is allowed for restricted key. It should be checked before the function is called. The |
3394 | | // function will assert if the key is not a signing key. |
3395 | | // |
3396 | | // Error Returns Meaning |
3397 | | // |
3398 | | // TPM_RC_SCHEME signScheme is not compatible with the signing key type |
3399 | | // TPM_RC_VALUE digest value is greater than the modulus of signHandle or size of |
3400 | | // hashData does not match hash algorithm insignScheme (for an RSA |
3401 | | // key); invalid commit status or failed to generate r value (for an ECC |
3402 | | // key) |
3403 | | // |
3404 | | TPM_RC |
3405 | | CryptSign( |
3406 | | TPMI_DH_OBJECT signHandle, // IN: The handle of sign key |
3407 | | TPMT_SIG_SCHEME *signScheme, // IN: sign scheme. |
3408 | | TPM2B_DIGEST *digest, // IN: The digest being signed |
3409 | | TPMT_SIGNATURE *signature // OUT: signature |
3410 | | ) |
3411 | 0 | { |
3412 | 0 | OBJECT *signKey = ObjectGet(signHandle); |
3413 | 0 | TPM_RC result = TPM_RC_SCHEME; |
3414 | | // check if input handle is a sign key |
3415 | 0 | pAssert(signKey->publicArea.objectAttributes.sign == SET); |
3416 | | // Must have the private portion loaded. This check is made during |
3417 | | // authorization. |
3418 | 0 | pAssert(signKey->attributes.publicOnly == CLEAR); |
3419 | | // Initialize signature scheme |
3420 | 0 | signature->sigAlg = signScheme->scheme; |
3421 | | // If the signature algorithm is TPM_ALG_NULL, then we are done |
3422 | 0 | if(signature->sigAlg == TPM_ALG_NULL) |
3423 | 0 | return TPM_RC_SUCCESS; |
3424 | | // All the schemes other than TPM_ALG_NULL have a hash algorithm |
3425 | 0 | TEST_HASH(signScheme->details.any.hashAlg); |
3426 | | // Initialize signature hash |
3427 | | // Note: need to do the check for alg null first because the null scheme |
3428 | | // doesn't have a hashAlg member. |
3429 | 0 | signature->signature.any.hashAlg = signScheme->details.any.hashAlg; |
3430 | | // perform sign operation based on different key type |
3431 | 0 | switch (signKey->publicArea.type) |
3432 | 0 | { |
3433 | 0 | #ifdef TPM_ALG_RSA |
3434 | 0 | case TPM_ALG_RSA: |
3435 | 0 | result = CryptSignRSA(signKey, signScheme, digest, signature); |
3436 | 0 | break; |
3437 | 0 | #endif //TPM_ALG_RSA |
3438 | 0 | #ifdef TPM_ALG_ECC |
3439 | 0 | case TPM_ALG_ECC: |
3440 | 0 | result = CryptSignECC(signKey, signScheme, digest, signature); |
3441 | 0 | break; |
3442 | 0 | #endif //TPM_ALG_ECC |
3443 | 0 | case TPM_ALG_KEYEDHASH: |
3444 | 0 | result = CryptSignHMAC(signKey, signScheme, digest, signature); |
3445 | 0 | break; |
3446 | 0 | default: |
3447 | 0 | break; |
3448 | 0 | } |
3449 | 0 | return result; |
3450 | 0 | } |
3451 | | // |
3452 | | // |
3453 | | // 10.2.9.21 CryptVerifySignature() |
3454 | | // |
3455 | | // This function is used to verify a signature. It is called by TPM2_VerifySignature() and |
3456 | | // TPM2_PolicySigned(). |
3457 | | // Since this operation only requires use of a public key, no consistency checks are necessary for the key to |
3458 | | // signature type because a caller can load any public key that they like with any scheme that they like. This |
3459 | | // routine simply makes sure that the signature is correct, whatever the type. |
3460 | | // This function requires that auth is not a NULL pointer. |
3461 | | // |
3462 | | // Error Returns Meaning |
3463 | | // |
3464 | | // TPM_RC_SIGNATURE the signature is not genuine |
3465 | | // TPM_RC_SCHEME the scheme is not supported |
3466 | | // TPM_RC_HANDLE an HMAC key was selected but the private part of the key is not |
3467 | | // loaded |
3468 | | // |
3469 | | TPM_RC |
3470 | | CryptVerifySignature( |
3471 | | TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key |
3472 | | TPM2B_DIGEST *digest, // IN: The digest being validated |
3473 | | TPMT_SIGNATURE *signature // IN: signature |
3474 | | ) |
3475 | 0 | { |
3476 | | // NOTE: ObjectGet will either return a pointer to a loaded object or |
3477 | | // will assert. It will never return a non-valid value. This makes it save |
3478 | | // to initialize 'publicArea' with the return value from ObjectGet() without |
3479 | | // checking it first. |
3480 | 0 | OBJECT *authObject = ObjectGet(keyHandle); |
3481 | 0 | TPMT_PUBLIC *publicArea = &authObject->publicArea; |
3482 | 0 | TPM_RC result = TPM_RC_SCHEME; |
3483 | | // The input unmarshaling should prevent any input signature from being |
3484 | | // a NULL signature, but just in case |
3485 | 0 | if(signature->sigAlg == TPM_ALG_NULL) |
3486 | 0 | return TPM_RC_SIGNATURE; |
3487 | 0 | switch (publicArea->type) |
3488 | 0 | { |
3489 | 0 | #ifdef TPM_ALG_RSA |
3490 | 0 | case TPM_ALG_RSA: |
3491 | 0 | result = CryptRSAVerifySignature(authObject, digest, signature); |
3492 | 0 | break; |
3493 | 0 | #endif //TPM_ALG_RSA |
3494 | 0 | #ifdef TPM_ALG_ECC |
3495 | 0 | case TPM_ALG_ECC: |
3496 | 0 | result = CryptECCVerifySignature(authObject, digest, signature); |
3497 | 0 | break; |
3498 | 0 | #endif // TPM_ALG_ECC |
3499 | 0 | case TPM_ALG_KEYEDHASH: |
3500 | 0 | if(authObject->attributes.publicOnly) |
3501 | 0 | result = TPM_RC_HANDLE; |
3502 | 0 | else |
3503 | 0 | result = CryptHMACVerifySignature(authObject, digest, signature); |
3504 | 0 | break; |
3505 | 0 | default: |
3506 | 0 | break; |
3507 | 0 | } |
3508 | 0 | return result; |
3509 | 0 | } |
3510 | | // |
3511 | | // |
3512 | | // 10.2.10 Math functions |
3513 | | // |
3514 | | // 10.2.10.1 CryptDivide() |
3515 | | // |
3516 | | // This function interfaces to the math library for large number divide. |
3517 | | // |
3518 | | // Error Returns Meaning |
3519 | | // |
3520 | | // TPM_RC_SIZE quotient or remainder is too small to receive the result |
3521 | | // |
3522 | | TPM_RC |
3523 | | CryptDivide( |
3524 | | TPM2B *numerator, // IN: numerator |
3525 | | TPM2B *denominator, // IN: denominator |
3526 | | TPM2B *quotient, // OUT: quotient = numerator / denominator. |
3527 | | TPM2B *remainder // OUT: numerator mod denominator. |
3528 | | ) |
3529 | 0 | { |
3530 | 0 | pAssert( numerator != NULL && denominator!= NULL |
3531 | 0 | && (quotient != NULL || remainder != NULL) |
3532 | 0 | ); |
3533 | | // assume denominator is not 0 |
3534 | 0 | pAssert(denominator->size != 0); |
3535 | 0 | return TranslateCryptErrors(_math__Div(numerator, |
3536 | 0 | denominator, |
3537 | 0 | quotient, |
3538 | 0 | remainder) |
3539 | 0 | ); |
3540 | 0 | } |
3541 | | // |
3542 | | // |
3543 | | // 10.2.10.2 CryptCompare() |
3544 | | // |
3545 | | // This function interfaces to the math library for large number, unsigned compare. |
3546 | | // |
3547 | | // Return Value Meaning |
3548 | | // |
3549 | | // 1 if a > b |
3550 | | // 0 if a = b |
3551 | | // -1 if a < b |
3552 | | // |
3553 | | LIB_EXPORT int |
3554 | | CryptCompare( |
3555 | | const UINT32 aSize, // IN: size of a |
3556 | | const BYTE *a, // IN: a buffer |
3557 | | const UINT32 bSize, // IN: size of b |
3558 | | const BYTE *b // IN: b buffer |
3559 | | ) |
3560 | 0 | { |
3561 | 0 | return _math__uComp(aSize, a, bSize, b); |
3562 | 0 | } |
3563 | | // |
3564 | | // |
3565 | | // 10.2.10.3 CryptCompareSigned() |
3566 | | // |
3567 | | // This function interfaces to the math library for large number, signed compare. |
3568 | | // |
3569 | | // Return Value Meaning |
3570 | | // |
3571 | | // 1 if a > b |
3572 | | // 0 if a = b |
3573 | | // -1 if a < b |
3574 | | // |
3575 | | int |
3576 | | CryptCompareSigned( |
3577 | | UINT32 aSize, // IN: size of a |
3578 | | BYTE *a, // IN: a buffer |
3579 | | UINT32 bSize, // IN: size of b |
3580 | | BYTE *b // IN: b buffer |
3581 | | ) |
3582 | 0 | { |
3583 | 0 | return _math__Comp(aSize, a, bSize, b); |
3584 | 0 | } |
3585 | | // |
3586 | | // |
3587 | | // 10.2.10.4 CryptGetTestResult |
3588 | | // |
3589 | | // This function returns the results of a self-test function. |
3590 | | // |
3591 | | // NOTE: the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior is |
3592 | | // placed here due to the limitation of a software simulation environment. For the correct behavior, consult the |
3593 | | // part 3 specification for TPM2_GetTestResult(). |
3594 | | // |
3595 | | TPM_RC |
3596 | | CryptGetTestResult( |
3597 | | TPM2B_MAX_BUFFER *outData // OUT: test result data |
3598 | | ) |
3599 | 0 | { |
3600 | 0 | outData->t.size = 0; |
3601 | 0 | return TPM_RC_SUCCESS; |
3602 | 0 | } |
3603 | | // |
3604 | | // |
3605 | | // 10.2.11 Capability Support |
3606 | | // |
3607 | | // 10.2.11.1 CryptCapGetECCCurve() |
3608 | | // |
3609 | | // This function returns the list of implemented ECC curves. |
3610 | | // |
3611 | | // Return Value Meaning |
3612 | | // |
3613 | | // YES if no more ECC curve is available |
3614 | | // NO if there are more ECC curves not reported |
3615 | | // |
3616 | | #ifdef TPM_ALG_ECC //% 5 |
3617 | | TPMI_YES_NO |
3618 | | CryptCapGetECCCurve( |
3619 | | TPM_ECC_CURVE curveID, // IN: the starting ECC curve |
3620 | | UINT32 maxCount, // IN: count of returned curve |
3621 | | TPML_ECC_CURVE *curveList // OUT: ECC curve list |
3622 | | ) |
3623 | 0 | { |
3624 | 0 | TPMI_YES_NO more = NO; |
3625 | 0 | UINT16 i; |
3626 | 0 | UINT32 count = _cpri__EccGetCurveCount(); |
3627 | 0 | TPM_ECC_CURVE curve; |
3628 | | // Initialize output property list |
3629 | 0 | curveList->count = 0; |
3630 | | // The maximum count of curves we may return is MAX_ECC_CURVES |
3631 | 0 | if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES; |
3632 | | // Scan the eccCurveValues array |
3633 | 0 | for(i = 0; i < count; i++) |
3634 | 0 | { |
3635 | 0 | curve = _cpri__GetCurveIdByIndex(i); |
3636 | | // If curveID is less than the starting curveID, skip it |
3637 | 0 | if(curve < curveID) |
3638 | 0 | continue; |
3639 | 0 | if(curveList->count < maxCount) |
3640 | 0 | { |
3641 | | // If we have not filled up the return list, add more curves to |
3642 | | // it |
3643 | 0 | curveList->eccCurves[curveList->count] = curve; |
3644 | 0 | curveList->count++; |
3645 | 0 | } |
3646 | 0 | else |
3647 | 0 | { |
3648 | | // If the return list is full but we still have curves |
3649 | | // available, report this and stop iterating |
3650 | 0 | more = YES; |
3651 | 0 | break; |
3652 | 0 | } |
3653 | 0 | } |
3654 | 0 | return more; |
3655 | 0 | } |
3656 | | // |
3657 | | // |
3658 | | // 10.2.11.2 CryptCapGetEccCurveNumber() |
3659 | | // |
3660 | | // This function returns the number of ECC curves supported by the TPM. |
3661 | | // |
3662 | | UINT32 |
3663 | | CryptCapGetEccCurveNumber( |
3664 | | void |
3665 | | ) |
3666 | 0 | { |
3667 | | // There is an array that holds the curve data. Its size divided by the |
3668 | | // size of an entry is the number of values in the table. |
3669 | 0 | return _cpri__EccGetCurveCount(); |
3670 | 0 | } |
3671 | | #endif //TPM_ALG_ECC //% 5 |
3672 | | // |
3673 | | // |
3674 | | // 10.2.11.3 CryptAreKeySizesConsistent() |
3675 | | // |
3676 | | // This function validates that the public key size values are consistent for an asymmetric key. |
3677 | | // |
3678 | | // NOTE: This is not a comprehensive test of the public key. |
3679 | | // |
3680 | | // |
3681 | | // Return Value Meaning |
3682 | | // |
3683 | | // TRUE sizes are consistent |
3684 | | // FALSE sizes are not consistent |
3685 | | // |
3686 | | BOOL |
3687 | | CryptAreKeySizesConsistent( |
3688 | | TPMT_PUBLIC *publicArea // IN: the public area to check |
3689 | | ) |
3690 | 80 | { |
3691 | 80 | BOOL consistent = FALSE; |
3692 | 80 | switch (publicArea->type) |
3693 | 80 | { |
3694 | 0 | #ifdef TPM_ALG_RSA |
3695 | 67 | case TPM_ALG_RSA: |
3696 | | // The key size in bits is filtered by the unmarshaling |
3697 | 67 | consistent = ( ((publicArea->parameters.rsaDetail.keyBits+7)/8) |
3698 | 67 | == publicArea->unique.rsa.t.size); |
3699 | 67 | break; |
3700 | 0 | #endif //TPM_ALG_RSA |
3701 | 0 | #ifdef TPM_ALG_ECC |
3702 | 13 | case TPM_ALG_ECC: |
3703 | 13 | { |
3704 | 13 | UINT16 keySizeInBytes; |
3705 | 13 | TPM_ECC_CURVE curveId = publicArea->parameters.eccDetail.curveID; |
3706 | 13 | keySizeInBytes = CryptEccGetKeySizeInBytes(curveId); |
3707 | 13 | consistent = keySizeInBytes > 0 |
3708 | 13 | && publicArea->unique.ecc.x.t.size <= keySizeInBytes |
3709 | 13 | && publicArea->unique.ecc.y.t.size <= keySizeInBytes; |
3710 | 13 | } |
3711 | 13 | break; |
3712 | 0 | #endif //TPM_ALG_ECC |
3713 | 0 | default: |
3714 | 0 | break; |
3715 | 80 | } |
3716 | 80 | return consistent; |
3717 | 80 | } |
3718 | | // |
3719 | | // |
3720 | | // 10.2.11.4 CryptAlgSetImplemented() |
3721 | | // |
3722 | | // This function initializes the bit vector with one bit for each implemented algorithm. This function is called |
3723 | | // from _TPM_Init(). The vector of implemented algorithms should be generated by the part 2 parser so that |
3724 | | // the g_implementedAlgorithms vector can be a const. That's not how it is now |
3725 | | // |
3726 | | void |
3727 | | CryptAlgsSetImplemented( |
3728 | | void |
3729 | | ) |
3730 | 0 | { |
3731 | 0 | AlgorithmGetImplementedVector(&g_implementedAlgorithms); |
3732 | 0 | } |