/src/libtpms/src/tpm12/tpm_cryptoh.c
Line | Count | Source |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* High Level Platform Independent Cryptography */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: tpm_cryptoh.c 4540 2011-04-07 18:51:34Z kgoldman $ */ |
7 | | /* */ |
8 | | /* (c) Copyright IBM Corporation 2006, 2010. */ |
9 | | /* */ |
10 | | /* All rights reserved. */ |
11 | | /* */ |
12 | | /* Redistribution and use in source and binary forms, with or without */ |
13 | | /* modification, are permitted provided that the following conditions are */ |
14 | | /* met: */ |
15 | | /* */ |
16 | | /* Redistributions of source code must retain the above copyright notice, */ |
17 | | /* this list of conditions and the following disclaimer. */ |
18 | | /* */ |
19 | | /* Redistributions in binary form must reproduce the above copyright */ |
20 | | /* notice, this list of conditions and the following disclaimer in the */ |
21 | | /* documentation and/or other materials provided with the distribution. */ |
22 | | /* */ |
23 | | /* Neither the names of the IBM Corporation nor the names of its */ |
24 | | /* contributors may be used to endorse or promote products derived from */ |
25 | | /* this software without specific prior written permission. */ |
26 | | /* */ |
27 | | /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ |
28 | | /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ |
29 | | /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ |
30 | | /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ |
31 | | /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ |
32 | | /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ |
33 | | /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ |
34 | | /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ |
35 | | /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ |
36 | | /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ |
37 | | /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
38 | | /********************************************************************************/ |
39 | | |
40 | | #include <stdio.h> |
41 | | #include <stdlib.h> |
42 | | #include <string.h> |
43 | | #include <stdarg.h> |
44 | | |
45 | | #include "tpm_admin.h" |
46 | | #include "tpm_auth.h" |
47 | | #include "tpm_crypto.h" |
48 | | #include "tpm_debug.h" |
49 | | #include "tpm_digest.h" |
50 | | #include "tpm_error.h" |
51 | | #include "tpm_io.h" |
52 | | #include "tpm_memory.h" |
53 | | #include "tpm_migration.h" |
54 | | #include "tpm_nonce.h" |
55 | | #include "tpm_key.h" |
56 | | #include "tpm_pcr.h" |
57 | | #include "tpm_process.h" |
58 | | #include "tpm_store.h" |
59 | | #include "tpm_ver.h" |
60 | | |
61 | | #include "tpm_cryptoh.h" |
62 | | |
63 | | /* local prototypes */ |
64 | | |
65 | | static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, |
66 | | uint32_t length0, unsigned char *buffer0, |
67 | | va_list ap); |
68 | | static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC hmac, |
69 | | const TPM_SECRET key, |
70 | | va_list ap); |
71 | | |
72 | | static TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, |
73 | | void **sha1_context, |
74 | | TPM_SIZED_BUFFER *hashData); |
75 | | |
76 | | /* |
77 | | TPM_SIGN_INFO |
78 | | */ |
79 | | |
80 | | /* TPM_SignInfo_Init() |
81 | | |
82 | | sets members to default values |
83 | | sets all pointers to NULL and sizes to 0 |
84 | | always succeeds - no return code |
85 | | */ |
86 | | |
87 | | void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info) |
88 | 0 | { |
89 | 0 | printf(" TPM_SignInfo_Init:\n"); |
90 | 0 | memset(tpm_sign_info->fixed, 0, TPM_SIGN_INFO_FIXED_SIZE); |
91 | 0 | TPM_Nonce_Init(tpm_sign_info->replay); |
92 | 0 | TPM_SizedBuffer_Init(&(tpm_sign_info->data)); |
93 | 0 | return; |
94 | 0 | } |
95 | | |
96 | | /* TPM_SignInfo_Store() |
97 | | |
98 | | serialize the structure to a stream contained in 'sbuffer' |
99 | | returns 0 or error codes |
100 | | */ |
101 | | |
102 | | TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer, |
103 | | const TPM_SIGN_INFO *tpm_sign_info) |
104 | 0 | { |
105 | 0 | TPM_RESULT rc = 0; |
106 | |
|
107 | 0 | printf(" TPM_SignInfo_Store:\n"); |
108 | | /* store the tag */ |
109 | 0 | if (rc == 0) { |
110 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SIGNINFO); |
111 | 0 | } |
112 | | /* store the fixed */ |
113 | 0 | if (rc == 0) { |
114 | 0 | rc = TPM_Sbuffer_Append(sbuffer, tpm_sign_info->fixed, TPM_SIGN_INFO_FIXED_SIZE); |
115 | 0 | } |
116 | | /* store the replay */ |
117 | 0 | if (rc == 0) { |
118 | 0 | rc = TPM_Nonce_Store(sbuffer, tpm_sign_info->replay); |
119 | 0 | } |
120 | | /* store the dataLen and data */ |
121 | 0 | if (rc == 0) { |
122 | 0 | rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sign_info->data)); |
123 | 0 | } |
124 | 0 | if (rc == 0) { |
125 | 0 | const unsigned char *buffer; |
126 | 0 | uint32_t length; |
127 | 0 | TPM_Sbuffer_Get(sbuffer, &buffer, &length); |
128 | 0 | TPM_PrintAll(" TPM_SignInfo_Store: Buffer", buffer, length); |
129 | 0 | } |
130 | 0 | return rc; |
131 | 0 | } |
132 | | |
133 | | /* TPM_SignInfo_Delete() |
134 | | |
135 | | No-OP if the parameter is NULL, else: |
136 | | frees memory allocated for the sign_info |
137 | | sets pointers to NULL |
138 | | calls TPM_SignInfo_Init to set members back to default values |
139 | | The sign_info itself is not freed |
140 | | */ |
141 | | |
142 | | void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info) |
143 | 0 | { |
144 | 0 | printf(" TPM_SignInfo_Delete:\n"); |
145 | 0 | if (tpm_sign_info != NULL) { |
146 | 0 | TPM_SizedBuffer_Delete(&(tpm_sign_info->data)); |
147 | 0 | TPM_SignInfo_Init(tpm_sign_info); |
148 | 0 | } |
149 | 0 | return; |
150 | 0 | } |
151 | | |
152 | | /* |
153 | | TPM_CERTIFY_INFO |
154 | | */ |
155 | | |
156 | | /* TPM_CertifyInfo_Init() |
157 | | |
158 | | sets members to default values |
159 | | sets all pointers to NULL and sizes to 0 |
160 | | always succeeds - no return code |
161 | | */ |
162 | | |
163 | | void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info) |
164 | 0 | { |
165 | 0 | printf(" TPM_CertifyInfo_Init:\n"); |
166 | 0 | TPM_StructVer_Init(&(tpm_certify_info->version)); |
167 | 0 | tpm_certify_info->keyUsage = TPM_KEY_UNINITIALIZED; |
168 | 0 | tpm_certify_info->keyFlags = 0; |
169 | 0 | tpm_certify_info->authDataUsage = TPM_AUTH_ALWAYS; |
170 | 0 | TPM_KeyParms_Init(&(tpm_certify_info->algorithmParms)); |
171 | 0 | TPM_Digest_Init(tpm_certify_info->pubkeyDigest); |
172 | 0 | TPM_Nonce_Init(tpm_certify_info->data); |
173 | 0 | tpm_certify_info->parentPCRStatus = TRUE; |
174 | 0 | TPM_SizedBuffer_Init(&(tpm_certify_info->pcrInfo)); |
175 | 0 | tpm_certify_info->tpm_pcr_info = NULL; |
176 | 0 | return; |
177 | 0 | } |
178 | | |
179 | | #if 0 |
180 | | /* TPM_CertifyInfo_Load() |
181 | | |
182 | | deserialize the structure from a 'stream' |
183 | | 'stream_size' is checked for sufficient data |
184 | | returns 0 or error codes |
185 | | |
186 | | Before use, call TPM_CertifyInfo_Init() |
187 | | After use, call TPM_CertifyInfo_Delete() to free memory |
188 | | |
189 | | NOTE: Never called. |
190 | | */ |
191 | | |
192 | | TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info, |
193 | | unsigned char **stream, |
194 | | uint32_t *stream_size) |
195 | | { |
196 | | TPM_RESULT rc = 0; |
197 | | |
198 | | printf(" TPM_CertifyInfo_Load:\n"); |
199 | | /* load version */ |
200 | | if (rc == 0) { |
201 | | rc = TPM_StructVer_Load(&(tpm_certify_info->version), stream, stream_size); |
202 | | } |
203 | | /* check ver immediately to ease debugging */ |
204 | | if (rc == 0) { |
205 | | rc = TPM_StructVer_CheckVer(&(tpm_certify_info->version)); |
206 | | } |
207 | | /* load keyUsage */ |
208 | | if (rc == 0) { |
209 | | rc = TPM_Load16(&(tpm_certify_info->keyUsage), stream, stream_size); |
210 | | } |
211 | | /* load keyFlags */ |
212 | | if (rc == 0) { |
213 | | rc = TPM_KeyFlags_Load(&(tpm_certify_info->keyFlags), stream, stream_size); |
214 | | } |
215 | | /* load authDataUsage */ |
216 | | if (rc == 0) { |
217 | | rc = TPM_Load8(&(tpm_certify_info->authDataUsage), stream, stream_size); |
218 | | } |
219 | | /* load algorithmParms */ |
220 | | if (rc == 0) { |
221 | | rc = TPM_KeyParms_Load(&(tpm_certify_info->algorithmParms), stream, stream_size); |
222 | | } |
223 | | /* load pubkeyDigest */ |
224 | | if (rc == 0) { |
225 | | rc = TPM_Digest_Load(tpm_certify_info->pubkeyDigest, stream, stream_size); |
226 | | } |
227 | | /* load data */ |
228 | | if (rc == 0) { |
229 | | rc = TPM_Nonce_Load(tpm_certify_info->data, stream, stream_size); |
230 | | } |
231 | | /* load parentPCRStatus */ |
232 | | if (rc == 0) { |
233 | | rc = TPM_LoadBool(&(tpm_certify_info->parentPCRStatus), stream, stream_size); |
234 | | } |
235 | | /* load pcrInfo */ |
236 | | if (rc == 0) { |
237 | | rc = TPM_SizedBuffer_Load(&(tpm_certify_info->pcrInfo), stream, stream_size); |
238 | | } |
239 | | /* set TPM_PCR_INFO tpm_pcr_info cache from pcrInfo */ |
240 | | if (rc == 0) { |
241 | | rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_certify_info->tpm_pcr_info), |
242 | | &(tpm_certify_info->pcrInfo)); |
243 | | } |
244 | | return rc; |
245 | | } |
246 | | #endif |
247 | | |
248 | | /* TPM_CertifyInfo_Store() |
249 | | |
250 | | serialize the structure to a stream contained in 'sbuffer' |
251 | | returns 0 or error codes |
252 | | */ |
253 | | |
254 | | TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer, |
255 | | TPM_CERTIFY_INFO *tpm_certify_info) |
256 | 0 | { |
257 | 0 | TPM_RESULT rc = 0; |
258 | |
|
259 | 0 | printf(" TPM_CertifyInfo_Store:\n"); |
260 | | /* store version */ |
261 | 0 | if (rc == 0) { |
262 | 0 | rc = TPM_StructVer_Store(sbuffer, &(tpm_certify_info->version)); |
263 | 0 | } |
264 | | /* store keyUsage */ |
265 | 0 | if (rc == 0) { |
266 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info->keyUsage); |
267 | 0 | } |
268 | | /* store keyFlags */ |
269 | 0 | if (rc == 0) { |
270 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info->keyFlags); |
271 | 0 | } |
272 | | /* store authDataUsage */ |
273 | 0 | if (rc == 0) { |
274 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->authDataUsage), |
275 | 0 | sizeof(TPM_AUTH_DATA_USAGE)); |
276 | 0 | } |
277 | | /* store algorithmParms */ |
278 | 0 | if (rc == 0) { |
279 | 0 | rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info->algorithmParms)); |
280 | 0 | } |
281 | | /* store pubkeyDigest */ |
282 | 0 | if (rc == 0) { |
283 | 0 | rc = TPM_Digest_Store(sbuffer, tpm_certify_info->pubkeyDigest); |
284 | 0 | } |
285 | | /* store data */ |
286 | 0 | if (rc == 0) { |
287 | 0 | rc = TPM_Nonce_Store(sbuffer, tpm_certify_info->data); |
288 | 0 | } |
289 | | /* store parentPCRStatus */ |
290 | 0 | if (rc == 0) { |
291 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->parentPCRStatus), |
292 | 0 | sizeof(TPM_BOOL)); |
293 | 0 | } |
294 | | /* copy cache to pcrInfo */ |
295 | 0 | if (rc == 0) { |
296 | 0 | rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info->pcrInfo), |
297 | 0 | tpm_certify_info->tpm_pcr_info, |
298 | 0 | (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); |
299 | 0 | } |
300 | | /* copy pcrInfo to sbuffer */ |
301 | 0 | if (rc == 0) { |
302 | 0 | rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info->pcrInfo)); |
303 | 0 | } |
304 | 0 | return rc; |
305 | 0 | } |
306 | | |
307 | | /* TPM_CertifyInfo_Delete() |
308 | | |
309 | | No-OP if the parameter is NULL, else: |
310 | | frees memory allocated for the object |
311 | | sets pointers to NULL |
312 | | calls TPM_CertifyInfo_Init to set members back to default values |
313 | | The object itself is not freed |
314 | | */ |
315 | | |
316 | | void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info) |
317 | 0 | { |
318 | 0 | printf(" TPM_CertifyInfo_Delete:\n"); |
319 | 0 | if (tpm_certify_info != NULL) { |
320 | 0 | TPM_KeyParms_Delete(&(tpm_certify_info->algorithmParms)); |
321 | | /* pcrInfo */ |
322 | 0 | TPM_SizedBuffer_Delete(&(tpm_certify_info->pcrInfo)); |
323 | | /* pcr cache */ |
324 | 0 | TPM_PCRInfo_Delete(tpm_certify_info->tpm_pcr_info); |
325 | 0 | free(tpm_certify_info->tpm_pcr_info); |
326 | 0 | TPM_CertifyInfo_Init(tpm_certify_info); |
327 | 0 | } |
328 | 0 | return; |
329 | 0 | } |
330 | | |
331 | | /* TPM_CertifyInfo_Set() fills in tpm_certify_info with the information from the key pointed to be |
332 | | tpm_key |
333 | | */ |
334 | | |
335 | | TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info, |
336 | | TPM_KEY *tpm_key) |
337 | 0 | { |
338 | 0 | TPM_RESULT rc = 0; |
339 | |
|
340 | 0 | printf(" TPM_CertifyInfo_Set:\n"); |
341 | 0 | if (rc == 0) { |
342 | 0 | tpm_certify_info->keyUsage = tpm_key->keyUsage; |
343 | 0 | tpm_certify_info->keyFlags = tpm_key->keyFlags; |
344 | 0 | tpm_certify_info->authDataUsage = tpm_key->authDataUsage; |
345 | 0 | rc = TPM_KeyParms_Copy(&(tpm_certify_info->algorithmParms), |
346 | 0 | &(tpm_key->algorithmParms)); |
347 | 0 | } |
348 | | /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY |
349 | | representation of the key to be certified */ |
350 | 0 | if (rc == 0) { |
351 | 0 | rc = TPM_SHA1(tpm_certify_info->pubkeyDigest, |
352 | 0 | tpm_key->pubKey.size, tpm_key->pubKey.buffer, |
353 | 0 | 0, NULL); |
354 | 0 | } |
355 | 0 | return rc; |
356 | 0 | } |
357 | | |
358 | | /* |
359 | | TPM_CERTIFY_INFO2 |
360 | | */ |
361 | | |
362 | | /* TPM_CertifyInfo2_Init() |
363 | | |
364 | | sets members to default values |
365 | | sets all pointers to NULL and sizes to 0 |
366 | | always succeeds - no return code |
367 | | */ |
368 | | |
369 | | void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2) |
370 | 0 | { |
371 | 0 | printf(" TPM_CertifyInfo2_Init:\n"); |
372 | 0 | tpm_certify_info2->fill = 0x00; |
373 | 0 | tpm_certify_info2->payloadType = TPM_PT_ASYM; |
374 | 0 | tpm_certify_info2->keyUsage = TPM_KEY_UNINITIALIZED; |
375 | 0 | tpm_certify_info2->keyFlags = 0; |
376 | 0 | tpm_certify_info2->authDataUsage = TPM_AUTH_ALWAYS; |
377 | 0 | TPM_KeyParms_Init(&(tpm_certify_info2->algorithmParms)); |
378 | 0 | TPM_Digest_Init(tpm_certify_info2->pubkeyDigest); |
379 | 0 | TPM_Nonce_Init(tpm_certify_info2->data); |
380 | 0 | tpm_certify_info2->parentPCRStatus = TRUE; |
381 | 0 | TPM_SizedBuffer_Init(&(tpm_certify_info2->pcrInfo)); |
382 | 0 | TPM_SizedBuffer_Init(&(tpm_certify_info2->migrationAuthority)); |
383 | 0 | tpm_certify_info2->tpm_pcr_info_short = NULL; |
384 | 0 | return; |
385 | 0 | } |
386 | | |
387 | | #if 0 |
388 | | /* TPM_CertifyInfo2_Load() |
389 | | |
390 | | deserialize the structure from a 'stream' |
391 | | 'stream_size' is checked for sufficient data |
392 | | returns 0 or error codes |
393 | | |
394 | | Before use, call TPM_CertifyInfo2_Init() |
395 | | After use, call TPM_CertifyInfo2_Delete() to free memory |
396 | | */ |
397 | | |
398 | | TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2, |
399 | | unsigned char **stream, |
400 | | uint32_t *stream_size) |
401 | | { |
402 | | TPM_RESULT rc = 0; |
403 | | |
404 | | printf(" TPM_CertifyInfo2_Load:\n"); |
405 | | /* check tag */ |
406 | | if (rc == 0) { |
407 | | rc = TPM_CheckTag(TPM_TAG_CERTIFY_INFO2, stream, stream_size); |
408 | | } |
409 | | /* load fill */ |
410 | | if (rc == 0) { |
411 | | rc = TPM_Load8(&(tpm_certify_info2->fill), stream, stream_size); |
412 | | } |
413 | | /* check fill immediately to ease debugging */ |
414 | | if (rc == 0) { |
415 | | if (tpm_certify_info2->fill != 0x00) { |
416 | | printf("TPM_CertifyInfo2_Load: Error checking fill %02x\n", tpm_certify_info2->fill); |
417 | | rc = TPM_INVALID_STRUCTURE; |
418 | | } |
419 | | } |
420 | | /* load payloadType */ |
421 | | if (rc == 0) { |
422 | | rc = TPM_Load8(&(tpm_certify_info2->payloadType), stream, stream_size); |
423 | | } |
424 | | /* load keyUsage */ |
425 | | if (rc == 0) { |
426 | | rc = TPM_Load16(&(tpm_certify_info2->keyUsage), stream, stream_size); |
427 | | } |
428 | | /* load keyFlags */ |
429 | | if (rc == 0) { |
430 | | rc = TPM_KeyFlags_Load(&(tpm_certify_info2->keyFlags), stream, stream_size); |
431 | | } |
432 | | /* load authDataUsage */ |
433 | | if (rc == 0) { |
434 | | rc = TPM_Load8(&(tpm_certify_info2->authDataUsage), stream, stream_size); |
435 | | } |
436 | | /* load algorithmParms */ |
437 | | if (rc == 0) { |
438 | | rc = TPM_KeyParms_Load(&(tpm_certify_info2->algorithmParms), stream, stream_size); |
439 | | } |
440 | | /* load pubkeyDigest */ |
441 | | if (rc == 0) { |
442 | | rc = TPM_Digest_Load(tpm_certify_info2->pubkeyDigest, stream, stream_size); |
443 | | } |
444 | | /* load data */ |
445 | | if (rc == 0) { |
446 | | rc = TPM_Nonce_Load(tpm_certify_info2->data, stream, stream_size); |
447 | | } |
448 | | /* load parentPCRStatus */ |
449 | | if (rc == 0) { |
450 | | rc = TPM_LoadBool(&(tpm_certify_info2->parentPCRStatus), stream, stream_size); |
451 | | } |
452 | | /* load pcrInfo */ |
453 | | if (rc == 0) { |
454 | | rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->pcrInfo), stream, stream_size); |
455 | | } |
456 | | /* set TPM_PCR_INFO2 tpm_pcr_info cache from pcrInfo */ |
457 | | if (rc == 0) { |
458 | | rc = TPM_PCRInfoShort_CreateFromBuffer(&(tpm_certify_info2->tpm_pcr_info_short), |
459 | | &(tpm_certify_info2->pcrInfo)); |
460 | | } |
461 | | /* load migrationAuthority */ |
462 | | if (rc == 0) { |
463 | | rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->migrationAuthority), stream, stream_size); |
464 | | } |
465 | | /* check migrationAuthority immediately to ease debugging */ |
466 | | if (rc == 0) { |
467 | | if ((tpm_certify_info2->migrationAuthority.buffer != NULL) && |
468 | | (tpm_certify_info2->migrationAuthority.size != TPM_DIGEST_SIZE)) { |
469 | | printf("TPM_CertifyInfo2_Load: Error checking migrationAuthority %p, %u\n", |
470 | | tpm_certify_info2->migrationAuthority.buffer, |
471 | | tpm_certify_info2->migrationAuthority.size); |
472 | | rc = TPM_INVALID_STRUCTURE; |
473 | | } |
474 | | } |
475 | | return rc; |
476 | | } |
477 | | #endif |
478 | | |
479 | | /* TPM_CertifyInfo2_Store() |
480 | | |
481 | | serialize the structure to a stream contained in 'sbuffer' |
482 | | returns 0 or error codes |
483 | | */ |
484 | | |
485 | | TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer, |
486 | | TPM_CERTIFY_INFO2 *tpm_certify_info2) |
487 | 0 | { |
488 | 0 | TPM_RESULT rc = 0; |
489 | |
|
490 | 0 | printf(" TPM_CertifyInfo2_Store:\n"); |
491 | | /* store tag */ |
492 | 0 | if (rc == 0) { |
493 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CERTIFY_INFO2); |
494 | 0 | } |
495 | | /* store fill */ |
496 | 0 | if (rc == 0) { |
497 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->fill), sizeof(BYTE)); |
498 | 0 | } |
499 | | /* store payloadType */ |
500 | 0 | if (rc == 0) { |
501 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->payloadType), |
502 | 0 | sizeof(TPM_PAYLOAD_TYPE)); |
503 | 0 | } |
504 | | /* store keyUsage */ |
505 | 0 | if (rc == 0) { |
506 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info2->keyUsage); |
507 | 0 | } |
508 | | /* store keyFlags */ |
509 | 0 | if (rc == 0) { |
510 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info2->keyFlags); |
511 | 0 | } |
512 | | /* store authDataUsage */ |
513 | 0 | if (rc == 0) { |
514 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->authDataUsage), |
515 | 0 | sizeof(TPM_AUTH_DATA_USAGE)); |
516 | 0 | } |
517 | | /* store algorithmParms */ |
518 | 0 | if (rc == 0) { |
519 | 0 | rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info2->algorithmParms)); |
520 | 0 | } |
521 | | /* store pubkeyDigest */ |
522 | 0 | if (rc == 0) { |
523 | 0 | rc = TPM_Digest_Store(sbuffer, tpm_certify_info2->pubkeyDigest); |
524 | 0 | } |
525 | | /* store data */ |
526 | 0 | if (rc == 0) { |
527 | 0 | rc = TPM_Nonce_Store(sbuffer, tpm_certify_info2->data); |
528 | 0 | } |
529 | | /* store parentPCRStatus */ |
530 | 0 | if (rc == 0) { |
531 | 0 | rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->parentPCRStatus), |
532 | 0 | sizeof(TPM_BOOL)); |
533 | 0 | } |
534 | | /* copy cache to pcrInfo */ |
535 | 0 | if (rc == 0) { |
536 | 0 | rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info2->pcrInfo), |
537 | 0 | tpm_certify_info2->tpm_pcr_info_short, |
538 | 0 | (TPM_STORE_FUNCTION_T)TPM_PCRInfoShort_Store); |
539 | 0 | } |
540 | | /* copy pcrInfo to sbuffer */ |
541 | 0 | if (rc == 0) { |
542 | 0 | rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->pcrInfo)); |
543 | 0 | } |
544 | | /* store migrationAuthority */ |
545 | 0 | if (rc == 0) { |
546 | 0 | rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->migrationAuthority)); |
547 | 0 | } |
548 | 0 | return rc; |
549 | 0 | } |
550 | | |
551 | | /* TPM_CertifyInfo2_Delete() |
552 | | |
553 | | No-OP if the parameter is NULL, else: |
554 | | frees memory allocated for the object |
555 | | sets pointers to NULL |
556 | | calls TPM_CertifyInfo2_Init to set members back to default values |
557 | | The object itself is not freed |
558 | | */ |
559 | | |
560 | | void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2) |
561 | 0 | { |
562 | 0 | printf(" TPM_CertifyInfo2_Delete:\n"); |
563 | 0 | if (tpm_certify_info2 != NULL) { |
564 | 0 | TPM_KeyParms_Delete(&(tpm_certify_info2->algorithmParms)); |
565 | | /* pcrInfo */ |
566 | 0 | TPM_SizedBuffer_Delete(&(tpm_certify_info2->pcrInfo)); |
567 | | /* pcr cache */ |
568 | 0 | TPM_PCRInfoShort_Delete(tpm_certify_info2->tpm_pcr_info_short); |
569 | 0 | free(tpm_certify_info2->tpm_pcr_info_short); |
570 | 0 | TPM_SizedBuffer_Delete(&(tpm_certify_info2->migrationAuthority)); |
571 | 0 | TPM_CertifyInfo2_Init(tpm_certify_info2); |
572 | 0 | } |
573 | 0 | return; |
574 | 0 | } |
575 | | |
576 | | /* TPM_CertifyInfo2_Set() fills in tpm_certify_info2 with the information from the key pointed to by |
577 | | tpm_key. |
578 | | |
579 | | */ |
580 | | |
581 | | TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2, |
582 | | TPM_KEY *tpm_key) |
583 | 0 | { |
584 | 0 | TPM_RESULT rc = 0; |
585 | 0 | TPM_STORE_ASYMKEY *tpm_store_asymkey; |
586 | |
|
587 | 0 | printf(" TPM_CertifyInfo_Set:\n"); |
588 | | /* get the TPM_STORE_ASYMKEY object */ |
589 | 0 | if (rc == 0) { |
590 | 0 | rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); |
591 | 0 | } |
592 | 0 | if (rc == 0) { |
593 | 0 | tpm_certify_info2->payloadType = tpm_store_asymkey->payload; |
594 | 0 | tpm_certify_info2->keyUsage = tpm_key->keyUsage; |
595 | 0 | tpm_certify_info2->keyFlags = tpm_key->keyFlags; |
596 | 0 | tpm_certify_info2->authDataUsage = tpm_key->authDataUsage; |
597 | 0 | rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); |
598 | 0 | } |
599 | 0 | if (rc == 0) { |
600 | 0 | rc = TPM_KeyParms_Copy(&(tpm_certify_info2->algorithmParms), |
601 | 0 | &(tpm_key->algorithmParms)); |
602 | 0 | } |
603 | | /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY |
604 | | representation of the key to be certified */ |
605 | 0 | if (rc == 0) { |
606 | 0 | rc = TPM_SHA1(tpm_certify_info2->pubkeyDigest, |
607 | 0 | tpm_key->pubKey.size, tpm_key->pubKey.buffer, |
608 | 0 | 0, NULL); |
609 | 0 | } |
610 | 0 | return rc; |
611 | 0 | } |
612 | | |
613 | | /* |
614 | | TPM_SYMMETRIC_KEY |
615 | | */ |
616 | | |
617 | | /* TPM_SymmetricKey_Init() |
618 | | |
619 | | sets members to default values |
620 | | sets all pointers to NULL and sizes to 0 |
621 | | always succeeds - no return code |
622 | | */ |
623 | | |
624 | | void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key) |
625 | 0 | { |
626 | 0 | printf(" TPM_SymmetricKey_Init:\n"); |
627 | 0 | tpm_symmetric_key->algId = 0; |
628 | 0 | tpm_symmetric_key->encScheme = TPM_ES_NONE; |
629 | 0 | tpm_symmetric_key->size = 0; |
630 | 0 | tpm_symmetric_key->data = NULL; |
631 | 0 | return; |
632 | 0 | } |
633 | | |
634 | | /* TPM_SymmetricKey_Load() |
635 | | |
636 | | deserialize the structure from a 'stream' |
637 | | 'stream_size' is checked for sufficient data |
638 | | returns 0 or error codes |
639 | | |
640 | | Before use, call TPM_SymmetricKey_Init() |
641 | | After use, call TPM_SymmetricKey_Delete() to free memory |
642 | | */ |
643 | | |
644 | | TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key, |
645 | | unsigned char **stream, |
646 | | uint32_t *stream_size) |
647 | 0 | { |
648 | 0 | TPM_RESULT rc = 0; |
649 | |
|
650 | 0 | printf(" TPM_SymmetricKey_Load:\n"); |
651 | | /* load algId */ |
652 | 0 | if (rc == 0) { |
653 | 0 | rc = TPM_Load32(&(tpm_symmetric_key->algId), stream, stream_size); |
654 | 0 | } |
655 | | /* load encScheme */ |
656 | 0 | if (rc == 0) { |
657 | 0 | rc = TPM_Load16(&(tpm_symmetric_key->encScheme), stream, stream_size); |
658 | 0 | } |
659 | | /* load size */ |
660 | 0 | if (rc == 0) { |
661 | 0 | rc = TPM_Load16(&(tpm_symmetric_key->size), stream, stream_size); |
662 | 0 | } |
663 | | /* allocate memory for the data */ |
664 | 0 | if ((rc == 0) && (tpm_symmetric_key->size > 0)) { |
665 | 0 | rc = TPM_Malloc(&(tpm_symmetric_key->data), tpm_symmetric_key->size); |
666 | 0 | } |
667 | | /* load data */ |
668 | 0 | if ((rc == 0) && (tpm_symmetric_key->size > 0)) { |
669 | 0 | rc = TPM_Loadn(tpm_symmetric_key->data, tpm_symmetric_key->size, stream, stream_size); |
670 | 0 | } |
671 | 0 | return rc; |
672 | 0 | } |
673 | | |
674 | | /* TPM_SymmetricKey_Store() |
675 | | |
676 | | serialize the structure to a stream contained in 'sbuffer' |
677 | | returns 0 or error codes |
678 | | */ |
679 | | |
680 | | TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer, |
681 | | const TPM_SYMMETRIC_KEY *tpm_symmetric_key) |
682 | 0 | { |
683 | 0 | TPM_RESULT rc = 0; |
684 | |
|
685 | 0 | printf(" TPM_SymmetricKey_Store:\n"); |
686 | | /* store algId */ |
687 | 0 | if (rc == 0) { |
688 | 0 | rc = TPM_Sbuffer_Append32(sbuffer, tpm_symmetric_key->algId); |
689 | 0 | } |
690 | | /* store encScheme */ |
691 | 0 | if (rc == 0) { |
692 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->encScheme); |
693 | 0 | } |
694 | | /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */ |
695 | | /* store size */ |
696 | 0 | if (rc == 0) { |
697 | 0 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->size); |
698 | 0 | } |
699 | | /* store data */ |
700 | 0 | if (rc == 0) { |
701 | 0 | rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key->data, tpm_symmetric_key->size); |
702 | 0 | } |
703 | 0 | return rc; |
704 | 0 | } |
705 | | |
706 | | /* TPM_SymmetricKey_Delete() |
707 | | |
708 | | No-OP if the parameter is NULL, else: |
709 | | frees memory allocated for the object |
710 | | sets pointers to NULL |
711 | | calls TPM_SymmetricKey_Init to set members back to default values |
712 | | The object itself is not freed |
713 | | */ |
714 | | |
715 | | void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key) |
716 | 0 | { |
717 | 0 | printf(" TPM_SymmetricKey_Delete:\n"); |
718 | 0 | if (tpm_symmetric_key != NULL) { |
719 | 0 | free(tpm_symmetric_key->data); |
720 | 0 | TPM_SymmetricKey_Init(tpm_symmetric_key); |
721 | 0 | } |
722 | 0 | return; |
723 | 0 | } |
724 | | |
725 | | /* TPM_SymmetricKeyData_EncryptSbuffer() encrypts 'sbuffer' to 'encrypt_data' |
726 | | |
727 | | Padding is included, so the output may be larger than the input. |
728 | | |
729 | | 'encrypt_data' must be free by the caller |
730 | | */ |
731 | | |
732 | | TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data, |
733 | | TPM_STORE_BUFFER *sbuffer, |
734 | | const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data) |
735 | 0 | { |
736 | 0 | TPM_RESULT rc = 0; |
737 | 0 | const unsigned char *decrypt_data; /* serialization buffer */ |
738 | 0 | uint32_t decrypt_data_size; /* serialization size */ |
739 | |
|
740 | 0 | printf(" TPM_SymmetricKeyData_EncryptSbuffer:\n"); |
741 | 0 | if (rc == 0) { |
742 | | /* get the serialization results */ |
743 | 0 | TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); |
744 | | /* platform dependent symmetric key encrypt */ |
745 | 0 | rc = TPM_SymmetricKeyData_Encrypt(&(encrypt_data->buffer), /* output, caller frees */ |
746 | 0 | &(encrypt_data->size), /* output */ |
747 | 0 | decrypt_data, /* input */ |
748 | 0 | decrypt_data_size, /* input */ |
749 | 0 | tpm_symmetric_key_data); |
750 | 0 | } |
751 | 0 | return rc; |
752 | 0 | } |
753 | | |
754 | | /* TPM_SymmetricKeyData_StreamCrypt() encrypts or decrypts 'data_in' to 'data_out ' |
755 | | |
756 | | It assumes that the size of data_out and data_in are equal, and that a stream cipher mode is |
757 | | used. For the supported stream ciphers, encrypt and decrypt are equivalent, so no direction flag |
758 | | is required. |
759 | | |
760 | | AES 128 with CTR or OFB modes are supported. For CTR mode, pad is the initial count. For OFB |
761 | | mode, pad is the IV. |
762 | | */ |
763 | | |
764 | | TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out, /* output */ |
765 | | const unsigned char *data_in, /* input */ |
766 | | uint32_t data_size, /* input */ |
767 | | TPM_ALGORITHM_ID algId, /* algorithm */ |
768 | | TPM_ENC_SCHEME encScheme, /* mode */ |
769 | | const unsigned char *symmetric_key, /* input */ |
770 | | uint32_t symmetric_key_size, /* input */ |
771 | | unsigned char *pad_in, /* input */ |
772 | | uint32_t pad_in_size) /* input */ |
773 | 0 | { |
774 | 0 | TPM_RESULT rc = 0; |
775 | |
|
776 | 0 | printf(" TPM_SymmetricKeyData_StreamCrypt:\n"); |
777 | 0 | switch (algId) { |
778 | 0 | case TPM_ALG_AES128: |
779 | 0 | switch (encScheme) { |
780 | 0 | case TPM_ES_SYM_CTR: |
781 | 0 | rc = TPM_SymmetricKeyData_CtrCrypt(data_out, |
782 | 0 | data_in, |
783 | 0 | data_size, |
784 | 0 | symmetric_key, |
785 | 0 | symmetric_key_size, |
786 | 0 | pad_in, |
787 | 0 | pad_in_size); |
788 | 0 | break; |
789 | 0 | case TPM_ES_SYM_OFB: |
790 | 0 | rc = TPM_SymmetricKeyData_OfbCrypt(data_out, |
791 | 0 | data_in, |
792 | 0 | data_size, |
793 | 0 | symmetric_key, |
794 | 0 | symmetric_key_size, |
795 | 0 | pad_in, |
796 | 0 | pad_in_size); |
797 | 0 | break; |
798 | 0 | default: |
799 | 0 | printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad AES128 encScheme %04x\n", |
800 | 0 | encScheme); |
801 | 0 | rc = TPM_INAPPROPRIATE_ENC; |
802 | 0 | break; |
803 | 0 | } |
804 | 0 | break; |
805 | 0 | default: |
806 | 0 | printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad algID %08x\n", algId); |
807 | 0 | rc = TPM_INAPPROPRIATE_ENC; |
808 | 0 | break; |
809 | 0 | } |
810 | 0 | return rc; |
811 | 0 | } |
812 | | |
813 | | /* These functions perform high-level, platform independent functions. |
814 | | They call the lower level, platform dependent crypto functions in |
815 | | tpm_crypto.c |
816 | | */ |
817 | | |
818 | | /* TPM_SHA1Sbuffer() calculates the SHA-1 digest of a TPM_STORE_BUFFER. |
819 | | |
820 | | This is commonly used when calculating a digest on a serialized structure. Structures are |
821 | | serialized to a TPM_STORE_BUFFER. |
822 | | |
823 | | The TPM_STORE_BUFFER is not deleted. |
824 | | */ |
825 | | |
826 | | TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest, |
827 | | TPM_STORE_BUFFER *sbuffer) |
828 | 0 | { |
829 | 0 | TPM_RESULT rc = 0; |
830 | 0 | const unsigned char *buffer; /* serialized buffer */ |
831 | 0 | uint32_t length; /* serialization length */ |
832 | |
|
833 | 0 | printf(" TPM_SHA1Sbuffer:\n"); |
834 | 0 | if (rc == 0) { |
835 | | /* get the components of the TPM_STORE_BUFFER */ |
836 | 0 | TPM_Sbuffer_Get(sbuffer, &buffer, &length); |
837 | 0 | TPM_PrintFour(" TPM_SHA1Sbuffer: input", buffer); |
838 | | /* hash the serialized buffer to tpm_digest */ |
839 | 0 | rc = TPM_SHA1(tpm_digest, |
840 | 0 | length, buffer, |
841 | 0 | 0, NULL); |
842 | 0 | } |
843 | 0 | return rc; |
844 | 0 | } |
845 | | |
846 | | /* TPM_SHA1_GenerateStructure() generates a SHA-1 digest of a structure. It serializes the |
847 | | structure and hashes the result. |
848 | | |
849 | | tpmStructure is the structure to be serialized |
850 | | storeFunction is the serialization function for the structure |
851 | | */ |
852 | | |
853 | | TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest, |
854 | | void *tpmStructure, |
855 | | TPM_STORE_FUNCTION_T storeFunction) |
856 | 0 | { |
857 | 0 | TPM_RESULT rc = 0; |
858 | 0 | TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ |
859 | |
|
860 | 0 | printf(" TPM_SHA1_GenerateStructure:\n"); |
861 | 0 | TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ |
862 | | /* Serialize the structure */ |
863 | 0 | if (rc == 0) { |
864 | 0 | rc = storeFunction(&sbuffer, tpmStructure); |
865 | 0 | } |
866 | | /* hash the serialized buffer to tpm_hmac */ |
867 | 0 | if (rc == 0) { |
868 | 0 | rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); |
869 | 0 | } |
870 | 0 | TPM_Sbuffer_Delete(&sbuffer); /* @1 */ |
871 | 0 | return rc; |
872 | 0 | } |
873 | | |
874 | | /* TPM_SHA1_CheckStructure() generates a SHA-1 digest of a structure. It serializes the structure |
875 | | and hashes the result. It compares the result to 'expected_digest' and returns 'error' on |
876 | | mismatch. |
877 | | |
878 | | tpmStructure is the structure to be serialized |
879 | | storeFunction is the serialization function for the structure |
880 | | */ |
881 | | |
882 | | |
883 | | |
884 | | TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest, |
885 | | void *tpmStructure, |
886 | | TPM_STORE_FUNCTION_T storeFunction, |
887 | | TPM_RESULT error) |
888 | 0 | { |
889 | 0 | TPM_RESULT rc = 0; |
890 | 0 | TPM_DIGEST actual_digest; |
891 | |
|
892 | 0 | printf(" TPM_SHA1_CheckStructure:\n"); |
893 | | /* hash the serialized buffer to tpm_digest */ |
894 | 0 | if (rc == 0) { |
895 | 0 | rc = TPM_SHA1_GenerateStructure(actual_digest, tpmStructure, storeFunction); |
896 | 0 | } |
897 | | /* check the digests */ |
898 | 0 | if (rc == 0) { |
899 | 0 | rc = TPM_Digest_Compare(actual_digest, expected_digest); |
900 | 0 | if (rc != 0) { |
901 | 0 | rc = error; |
902 | 0 | } |
903 | 0 | } |
904 | 0 | return rc; |
905 | 0 | } |
906 | | |
907 | | /* TPM_SHA1() can be called directly to hash a list of streams. |
908 | | |
909 | | The ... arguments to be hashed are a list of the form |
910 | | size_t length, unsigned char *buffer |
911 | | terminated by a 0 length |
912 | | */ |
913 | | |
914 | | TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...) |
915 | 0 | { |
916 | 0 | TPM_RESULT rc = 0; |
917 | 0 | va_list ap; |
918 | |
|
919 | 0 | printf(" TPM_SHA1:\n"); |
920 | 0 | va_start(ap, md); |
921 | 0 | rc = TPM_SHA1_valist(md, 0, NULL, ap); |
922 | 0 | va_end(ap); |
923 | 0 | return rc; |
924 | 0 | } |
925 | | |
926 | | /* TPM_SHA1_Check() digests the list of streams and compares the result to 'digest_expect' |
927 | | */ |
928 | | |
929 | | TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...) |
930 | 0 | { |
931 | 0 | TPM_RESULT rc = 0; |
932 | 0 | TPM_DIGEST digest_actual; |
933 | 0 | va_list ap; |
934 | |
|
935 | 0 | printf(" TPM_SHA1_Check:\n"); |
936 | 0 | if (rc == 0) { |
937 | 0 | va_start(ap, digest_expect); |
938 | 0 | rc = TPM_SHA1_valist(digest_actual, 0, NULL, ap); |
939 | 0 | va_end(ap); |
940 | 0 | } |
941 | 0 | if (rc == 0) { |
942 | 0 | rc = TPM_Digest_Compare(digest_expect, digest_actual); |
943 | 0 | } |
944 | 0 | return rc; |
945 | 0 | } |
946 | | |
947 | | /* TPM_SHA1_valist() is the internal function, called with the va_list already created. |
948 | | |
949 | | It is called from TPM_SHA1() to do a simple hash. Typically length0==0 and buffer0==NULL. |
950 | | |
951 | | It can also be called from the HMAC function to hash the variable number of input parameters. In |
952 | | that case, the va_list for the text is already formed. length0 and buffer0 are used to input the |
953 | | padded key. |
954 | | */ |
955 | | |
956 | | static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, |
957 | | uint32_t length0, unsigned char *buffer0, |
958 | | va_list ap) |
959 | 0 | { |
960 | 0 | TPM_RESULT rc = 0; |
961 | 0 | uint32_t length; |
962 | 0 | unsigned char *buffer; |
963 | 0 | void *context = NULL; /* platform dependent context */ |
964 | 0 | TPM_BOOL done = FALSE; |
965 | | |
966 | 0 | printf(" TPM_SHA1_valist:\n"); |
967 | 0 | if (rc == 0) { |
968 | 0 | rc = TPM_SHA1InitCmd(&context); |
969 | 0 | } |
970 | 0 | if (rc == 0) { |
971 | 0 | if (length0 !=0) { /* optional first text block */ |
972 | 0 | printf(" TPM_SHA1_valist: Digesting %u bytes\n", length0); |
973 | 0 | rc = TPM_SHA1UpdateCmd(context, buffer0, length0); /* hash the buffer */ |
974 | 0 | } |
975 | 0 | } |
976 | 0 | while ((rc == 0) && !done) { |
977 | 0 | length = va_arg(ap, uint32_t); /* first vararg is the length */ |
978 | 0 | if (length != 0) { /* loop until a zero length argument terminates */ |
979 | 0 | buffer = va_arg(ap, unsigned char *); /* second vararg is the array */ |
980 | 0 | printf(" TPM_SHA1_valist: Digesting %u bytes\n", length); |
981 | 0 | rc = TPM_SHA1UpdateCmd(context, buffer, length); /* hash the buffer */ |
982 | 0 | } |
983 | 0 | else { |
984 | 0 | done = TRUE; |
985 | 0 | } |
986 | 0 | } |
987 | 0 | if (rc == 0) { |
988 | 0 | rc = TPM_SHA1FinalCmd(md, context); |
989 | 0 | } |
990 | 0 | if (rc == 0) { |
991 | 0 | TPM_PrintFour(" TPM_SHA1_valist: Digest", md); |
992 | 0 | } |
993 | | /* call TPM_SHA1Delete even if there was an error */ |
994 | 0 | TPM_SHA1Delete(&context); |
995 | 0 | return rc; |
996 | 0 | } |
997 | | |
998 | | /* TPM_HMAC_GenerateSbuffer() calculates the HMAC digest of a TPM_STORE_BUFFER. |
999 | | |
1000 | | This is commonly used when calculating an HMAC on a serialized structure. Structures are |
1001 | | serialized to a TPM_STORE_BUFFER. |
1002 | | |
1003 | | The TPM_STORE_BUFFER is not deleted. |
1004 | | */ |
1005 | | |
1006 | | TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac, |
1007 | | const TPM_SECRET hmac_key, |
1008 | | TPM_STORE_BUFFER *sbuffer) |
1009 | 0 | { |
1010 | 0 | TPM_RESULT rc = 0; |
1011 | 0 | const unsigned char *buffer; /* serialized buffer */ |
1012 | 0 | uint32_t length; /* serialization length */ |
1013 | |
|
1014 | 0 | printf(" TPM_HMAC_GenerateSbuffer:\n"); |
1015 | 0 | if (rc == 0) { |
1016 | | /* get the components of the TPM_STORE_BUFFER */ |
1017 | 0 | TPM_Sbuffer_Get(sbuffer, &buffer, &length); |
1018 | | /* HMAC the serialized buffer to tpm_hmac */ |
1019 | 0 | rc = TPM_HMAC_Generate(tpm_hmac, |
1020 | 0 | hmac_key, |
1021 | 0 | length, buffer, |
1022 | 0 | 0, NULL); |
1023 | 0 | } |
1024 | 0 | return rc; |
1025 | 0 | } |
1026 | | |
1027 | | /* TPM_HMAC_GenerateStructure() generates an HMAC of a structure. It serializes the structure and |
1028 | | HMAC's the result. |
1029 | | |
1030 | | hmacKey is the HMAC key |
1031 | | tpmStructure is the structure to be serialized |
1032 | | storeFunction is the serialization function for the structure |
1033 | | */ |
1034 | | |
1035 | | TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac, |
1036 | | const TPM_SECRET hmac_key, |
1037 | | void *tpmStructure, |
1038 | | TPM_STORE_FUNCTION_T storeFunction) |
1039 | 0 | { |
1040 | 0 | TPM_RESULT rc = 0; |
1041 | 0 | TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ |
1042 | |
|
1043 | 0 | printf(" TPM_HMAC_GenerateStructure:\n"); |
1044 | 0 | TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ |
1045 | | /* Serialize the structure */ |
1046 | 0 | if (rc == 0) { |
1047 | 0 | rc = storeFunction(&sbuffer, tpmStructure); |
1048 | 0 | } |
1049 | | /* hash the serialized buffer to tpm_hmac */ |
1050 | 0 | if (rc == 0) { |
1051 | 0 | rc = TPM_HMAC_GenerateSbuffer(tpm_hmac, hmac_key, &sbuffer); |
1052 | 0 | } |
1053 | 0 | TPM_Sbuffer_Delete(&sbuffer); /* @1 */ |
1054 | 0 | return rc; |
1055 | 0 | } |
1056 | | |
1057 | | /* TPM_HMAC_Generate() can be called directly to HMAC a list of streams. |
1058 | | |
1059 | | The ... arguments are a message list of the form |
1060 | | size_t length, unsigned char *buffer |
1061 | | terminated by a 0 length |
1062 | | */ |
1063 | | |
1064 | | TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac, |
1065 | | const TPM_SECRET hmac_key, |
1066 | | ...) |
1067 | 0 | { |
1068 | 0 | TPM_RESULT rc = 0; |
1069 | 0 | va_list ap; |
1070 | | |
1071 | 0 | printf(" TPM_HMAC_Generate:\n"); |
1072 | 0 | va_start(ap, hmac_key); |
1073 | 0 | rc = TPM_HMAC_Generatevalist(tpm_hmac, hmac_key, ap); |
1074 | 0 | va_end(ap); |
1075 | 0 | return rc; |
1076 | 0 | } |
1077 | | |
1078 | | /* TPM_HMAC_Generatevalist() is the internal function, called with the va_list already created. |
1079 | | |
1080 | | It is called from TPM_HMAC_Generate() and TPM_HMAC_Check() with the va_list for the text already |
1081 | | formed. |
1082 | | */ |
1083 | | |
1084 | 0 | #define TPM_HMAC_BLOCK_SIZE 64 |
1085 | | |
1086 | | static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC tpm_hmac, |
1087 | | const TPM_SECRET key, |
1088 | | va_list ap) |
1089 | 0 | { |
1090 | 0 | TPM_RESULT rc = 0; |
1091 | 0 | unsigned char ipad[TPM_HMAC_BLOCK_SIZE]; |
1092 | 0 | unsigned char opad[TPM_HMAC_BLOCK_SIZE]; |
1093 | 0 | size_t i; |
1094 | 0 | TPM_DIGEST inner_hash; |
1095 | |
|
1096 | 0 | printf(" TPM_HMAC_Generatevalist:\n"); |
1097 | | /* calculate key XOR ipad and key XOR opad */ |
1098 | 0 | if (rc == 0) { |
1099 | | /* first part, key XOR pad */ |
1100 | 0 | for (i = 0 ; i < TPM_AUTHDATA_SIZE ; i++) { |
1101 | 0 | ipad[i] = key[i] ^ 0x36; /* magic numbers from RFC 2104 */ |
1102 | 0 | opad[i] = key[i] ^ 0x5c; |
1103 | 0 | } |
1104 | | /* second part, 0x00 XOR pad */ |
1105 | 0 | memset(ipad + TPM_AUTHDATA_SIZE, 0x36, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); |
1106 | 0 | memset(opad + TPM_AUTHDATA_SIZE, 0x5c, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); |
1107 | | /* calculate the inner hash, hash the key XOR ipad and the text */ |
1108 | 0 | rc = TPM_SHA1_valist(inner_hash, |
1109 | 0 | TPM_HMAC_BLOCK_SIZE, ipad, ap); |
1110 | 0 | } |
1111 | | /* hash the key XOR opad and the previous hash */ |
1112 | 0 | if (rc == 0) { |
1113 | 0 | rc = TPM_SHA1(tpm_hmac, |
1114 | 0 | TPM_HMAC_BLOCK_SIZE, opad, |
1115 | 0 | TPM_DIGEST_SIZE, inner_hash, |
1116 | 0 | 0, NULL); |
1117 | 0 | } |
1118 | 0 | if (rc == 0) { |
1119 | 0 | TPM_PrintFour(" TPM_HMAC_Generatevalist: HMAC", tpm_hmac); |
1120 | 0 | } |
1121 | 0 | return rc; |
1122 | 0 | } |
1123 | | |
1124 | | /* TPM_HMAC_CheckSbuffer() checks the HMAC of a TPM_STORE_BUFFER. |
1125 | | |
1126 | | This is commonly used when checking an HMAC on a serialized structure. Structures are serialized |
1127 | | to a TPM_STORE_BUFFER. |
1128 | | |
1129 | | The TPM_STORE_BUFFER is not deleted. |
1130 | | */ |
1131 | | |
1132 | | TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid, /* result */ |
1133 | | TPM_HMAC expect, /* expected */ |
1134 | | const TPM_SECRET hmac_key, /* key */ |
1135 | | TPM_STORE_BUFFER *sbuffer) /* data stream */ |
1136 | 0 | { |
1137 | 0 | TPM_RESULT rc = 0; |
1138 | 0 | const unsigned char *buffer; /* serialized buffer */ |
1139 | 0 | uint32_t length; /* serialization length */ |
1140 | |
|
1141 | 0 | printf(" TPM_HMAC_CheckSbuffer:\n"); |
1142 | 0 | if (rc == 0) { |
1143 | | /* get the components of the TPM_STORE_BUFFER */ |
1144 | 0 | TPM_Sbuffer_Get(sbuffer, &buffer, &length); |
1145 | | /* HMAC the serialized buffer to tpm_hmac */ |
1146 | 0 | rc = TPM_HMAC_Check(valid, |
1147 | 0 | expect, |
1148 | 0 | hmac_key, |
1149 | 0 | length, buffer, |
1150 | 0 | 0, NULL); |
1151 | 0 | } |
1152 | 0 | return rc; |
1153 | 0 | } |
1154 | | |
1155 | | /* TPM_HMAC_Check() can be called directly to check the HMAC of a list of streams. |
1156 | | |
1157 | | The ... arguments are a list of the form |
1158 | | size_t length, unsigned char *buffer |
1159 | | terminated by a 0 length |
1160 | | |
1161 | | */ |
1162 | | |
1163 | | TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid, |
1164 | | TPM_HMAC expect, |
1165 | | const TPM_SECRET key, |
1166 | | ...) |
1167 | 0 | { |
1168 | 0 | TPM_RESULT rc = 0; |
1169 | 0 | va_list ap; |
1170 | 0 | TPM_HMAC actual; |
1171 | 0 | int result; |
1172 | |
|
1173 | 0 | printf(" TPM_HMAC_Check:\n"); |
1174 | 0 | va_start(ap, key); |
1175 | 0 | if (rc == 0) { |
1176 | 0 | rc = TPM_HMAC_Generatevalist(actual, key, ap); |
1177 | 0 | } |
1178 | 0 | if (rc == 0) { |
1179 | 0 | TPM_PrintFour(" TPM_HMAC_Check: Calculated", actual); |
1180 | 0 | TPM_PrintFour(" TPM_HMAC_Check: Received ", expect); |
1181 | 0 | result = memcmp(expect, actual, TPM_DIGEST_SIZE); |
1182 | 0 | if (result == 0) { |
1183 | 0 | *valid = TRUE; |
1184 | 0 | } |
1185 | 0 | else { |
1186 | 0 | *valid = FALSE; |
1187 | 0 | } |
1188 | 0 | } |
1189 | 0 | va_end(ap); |
1190 | 0 | return rc; |
1191 | 0 | } |
1192 | | |
1193 | | /* TPM_HMAC_CheckStructure() is a generic function that checks the integrity HMAC of a structure. |
1194 | | |
1195 | | hmacKey is the HMAC key |
1196 | | tpmStructure is the structure to be serialized |
1197 | | expect is the expected HMAC, a member of the structure |
1198 | | storeFunction is the serialization function for the structure |
1199 | | error is the failure return code |
1200 | | |
1201 | | The function saves a copy of the expected HMAC, and then NULL's the structure member. It |
1202 | | serializes the structure, generates an HMAC, and compares it to the expected value. |
1203 | | |
1204 | | As a side effect, the structure member is zeroed. |
1205 | | */ |
1206 | | |
1207 | | TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key, |
1208 | | void *tpmStructure, |
1209 | | TPM_HMAC expect, |
1210 | | TPM_STORE_FUNCTION_T storeFunction, |
1211 | | TPM_RESULT error) |
1212 | 0 | { |
1213 | 0 | TPM_RESULT rc = 0; |
1214 | 0 | TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ |
1215 | 0 | TPM_HMAC saveExpect; |
1216 | 0 | TPM_BOOL valid; |
1217 | |
|
1218 | 0 | printf(" TPM_HMAC_CheckStructure:\n"); |
1219 | 0 | TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ |
1220 | 0 | if (rc == 0) { |
1221 | 0 | TPM_Digest_Copy(saveExpect, expect); /* save the expected value */ |
1222 | 0 | TPM_Digest_Init(expect); /* set value in structure to NULL */ |
1223 | 0 | rc = storeFunction(&sbuffer, |
1224 | 0 | tpmStructure); |
1225 | 0 | } |
1226 | | /* verify the HMAC of the serialized structure */ |
1227 | 0 | if (rc == 0) { |
1228 | 0 | rc = TPM_HMAC_CheckSbuffer(&valid, /* result */ |
1229 | 0 | saveExpect, /* expected */ |
1230 | 0 | hmac_key, /* key */ |
1231 | 0 | &sbuffer); /* data stream */ |
1232 | 0 | } |
1233 | 0 | if (rc == 0) { |
1234 | 0 | if (!valid) { |
1235 | 0 | printf("TPM_HMAC_CheckStructure: Error checking HMAC\n"); |
1236 | 0 | rc = error; |
1237 | 0 | } |
1238 | 0 | } |
1239 | 0 | TPM_Sbuffer_Delete(&sbuffer); /* @1 */ |
1240 | 0 | return rc; |
1241 | 0 | } |
1242 | | |
1243 | | /* TPM_XOR XOR's 'in1' and 'in2' of 'length', putting the result in 'out' |
1244 | | |
1245 | | */ |
1246 | | |
1247 | | void TPM_XOR(unsigned char *out, |
1248 | | const unsigned char *in1, |
1249 | | const unsigned char *in2, |
1250 | | size_t length) |
1251 | 0 | { |
1252 | 0 | size_t i; |
1253 | | |
1254 | 0 | for (i = 0 ; i < length ; i++) { |
1255 | 0 | out[i] = in1[i] ^ in2[i]; |
1256 | 0 | } |
1257 | 0 | return; |
1258 | 0 | } |
1259 | | |
1260 | | /* TPM_MGF1() generates an MGF1 'array' of length 'arrayLen' from 'seed' of length 'seedlen' |
1261 | | |
1262 | | The openSSL DLL doesn't export MGF1 in Windows or Linux 1.0.0, so this version is created from |
1263 | | scratch. |
1264 | | |
1265 | | Algorithm and comments (not the code) from: |
1266 | | |
1267 | | PKCS #1: RSA Cryptography Specifications Version 2.1 B.2.1 MGF1 |
1268 | | |
1269 | | Prototype designed to be compatible with openSSL |
1270 | | |
1271 | | MGF1 is a Mask Generation Function based on a hash function. |
1272 | | |
1273 | | MGF1 (mgfSeed, maskLen) |
1274 | | |
1275 | | Options: |
1276 | | |
1277 | | Hash hash function (hLen denotes the length in octets of the hash |
1278 | | function output) |
1279 | | |
1280 | | Input: |
1281 | | |
1282 | | mgfSeed seed from which mask is generated, an octet string |
1283 | | maskLen intended length in octets of the mask, at most 2^32(hLen) |
1284 | | |
1285 | | Output: |
1286 | | mask mask, an octet string of length l; or "mask too long" |
1287 | | |
1288 | | Error: "mask too long' |
1289 | | */ |
1290 | | |
1291 | | TPM_RESULT TPM_MGF1(unsigned char *mask, |
1292 | | uint32_t maskLen, |
1293 | | const unsigned char *mgfSeed, |
1294 | | uint32_t mgfSeedlen) |
1295 | 0 | { |
1296 | 0 | TPM_RESULT rc = 0; |
1297 | 0 | unsigned char counter[4]; /* 4 octets */ |
1298 | 0 | uint32_t count; /* counter as an integral type */ |
1299 | 0 | uint32_t outLen; |
1300 | 0 | TPM_DIGEST lastDigest; |
1301 | | |
1302 | 0 | printf(" TPM_MGF1: Output length %u\n", maskLen); |
1303 | 0 | if (rc == 0) { |
1304 | | /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */ |
1305 | 0 | if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) { /*constant condition*/ |
1306 | 0 | printf(" TPM_MGF1: Error (fatal), Output length too large for 32 bit counter\n"); |
1307 | 0 | rc = TPM_FAIL; /* should never occur */ |
1308 | 0 | } |
1309 | 0 | } |
1310 | | /* 1.If l > 2^32(hLen), output "mask too long" and stop. */ |
1311 | | /* NOTE Checked by caller */ |
1312 | | /* 2. Let T be the empty octet string. */ |
1313 | | /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */ |
1314 | 0 | for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) { |
1315 | | /* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */ |
1316 | | /* C = I2OSP(counter, 4) NOTE Basically big endian */ |
1317 | 0 | uint32_t count_n = htonl(count); |
1318 | 0 | memcpy(counter, &count_n, 4); |
1319 | | /* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */ |
1320 | | /* T = T || Hash (mgfSeed || C) */ |
1321 | | /* If the entire digest is needed for the mask */ |
1322 | 0 | if ((outLen + TPM_DIGEST_SIZE) < maskLen) { |
1323 | 0 | rc = TPM_SHA1(mask + outLen, |
1324 | 0 | mgfSeedlen, mgfSeed, |
1325 | 0 | 4, counter, |
1326 | 0 | 0, NULL); |
1327 | 0 | outLen += TPM_DIGEST_SIZE; |
1328 | 0 | } |
1329 | | /* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */ |
1330 | 0 | else { |
1331 | | /* hash to a temporary digest variable */ |
1332 | 0 | rc = TPM_SHA1(lastDigest, |
1333 | 0 | mgfSeedlen, mgfSeed, |
1334 | 0 | 4, counter, |
1335 | 0 | 0, NULL); |
1336 | | /* copy what's needed */ |
1337 | 0 | memcpy(mask + outLen, lastDigest, maskLen - outLen); |
1338 | 0 | outLen = maskLen; /* outLen = outLen + maskLen - outLen */ |
1339 | 0 | } |
1340 | 0 | } |
1341 | | /* 4.Output the leading l octets of T as the octet string mask. */ |
1342 | 0 | return rc; |
1343 | 0 | } |
1344 | | |
1345 | | /* TPM_MGF1_GenerateArray() generates an array of length arrayLen using the varargs as the seed. |
1346 | | |
1347 | | Since the seed is a known length, it is passed in rather that extracted from the varargs. If the |
1348 | | seed length turns out to be wrong once the varargs are parsed, TPM_FAIL is returned. |
1349 | | |
1350 | | 'array' must be freed by the caller. |
1351 | | */ |
1352 | | |
1353 | | TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array, |
1354 | | uint32_t arrayLen, |
1355 | | uint32_t seedLen, |
1356 | | ...) |
1357 | 0 | { |
1358 | 0 | TPM_RESULT rc = 0; |
1359 | 0 | va_list ap; |
1360 | 0 | unsigned char *seed; /* constructed MGF1 seed */ |
1361 | 0 | size_t vaLength; /* next seed segment length */ |
1362 | 0 | unsigned char *vaBuffer; /* next seed segment buffer */ |
1363 | 0 | uint32_t seedLeft; /* remaining seed bytes required */ |
1364 | 0 | unsigned char *seedBuffer; /* running pointer to the seed array */ |
1365 | 0 | TPM_BOOL done = FALSE; /* done when a vaLength == 0 is reached */ |
1366 | |
|
1367 | 0 | printf(" TPM_MGF1_GenerateArray: arrayLen %u seedLen %u\n", arrayLen, seedLen); |
1368 | 0 | seed = NULL; /* freed @1 */ |
1369 | 0 | *array = NULL; /* freed by caller */ |
1370 | 0 | va_start(ap, seedLen); |
1371 | | /* allocate temporary memory for the seed */ |
1372 | 0 | if (rc == 0) { |
1373 | 0 | rc = TPM_Malloc(&seed, seedLen); |
1374 | 0 | seedBuffer = seed; |
1375 | 0 | seedLeft = seedLen; |
1376 | 0 | } |
1377 | | /* construct the seed */ |
1378 | 0 | while ((rc == 0) && !done) { |
1379 | 0 | vaLength = (size_t)va_arg(ap, uint32_t); /* first vararg is the length */ |
1380 | 0 | if (vaLength != 0) { /* loop until a zero length argument terminates */ |
1381 | 0 | if (rc == 0) { |
1382 | 0 | printf(" TPM_MGF1_GenerateArray: Appending %lu bytes\n", (unsigned long)vaLength); |
1383 | 0 | if (vaLength > seedLeft) { |
1384 | 0 | printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too small\n"); |
1385 | 0 | rc = TPM_FAIL; /* internal error, should never occur */ |
1386 | 0 | } |
1387 | 0 | } |
1388 | 0 | if (rc == 0) { |
1389 | 0 | vaBuffer = va_arg(ap, unsigned char *); /* second vararg is the array */ |
1390 | 0 | memcpy(seedBuffer, vaBuffer, vaLength); |
1391 | 0 | seedBuffer += vaLength; |
1392 | 0 | seedLeft-= vaLength; |
1393 | 0 | } |
1394 | 0 | } |
1395 | 0 | else { |
1396 | 0 | done = TRUE; |
1397 | 0 | if (seedLeft != 0) { |
1398 | 0 | printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too large by %u\n", |
1399 | 0 | seedLeft); |
1400 | 0 | rc = TPM_FAIL; /* internal error, should never occur */ |
1401 | 0 | } |
1402 | 0 | } |
1403 | 0 | } |
1404 | | /* allocate memory for the array */ |
1405 | 0 | if (rc == 0) { |
1406 | 0 | rc = TPM_Malloc(array, arrayLen); |
1407 | 0 | } |
1408 | | /* generate the MGF1 array */ |
1409 | 0 | if (rc == 0) { |
1410 | 0 | rc = TPM_MGF1(*array, // libtpms changed: assign rc |
1411 | 0 | arrayLen, |
1412 | 0 | seed, |
1413 | 0 | seedLen); |
1414 | 0 | TPM_PrintFour(" TPM_MGF1_GenerateArray: MGF1", *array); |
1415 | 0 | } |
1416 | 0 | va_end(ap); |
1417 | 0 | free(seed); /* @1 */ |
1418 | 0 | return rc; |
1419 | 0 | } |
1420 | | |
1421 | | /* TPM_bn2binMalloc() allocates a buffer 'bin' and loads it from 'bn'. |
1422 | | 'bytes' is set to the allocated size of 'bin'. |
1423 | | |
1424 | | If padBytes is non-zero, 'bin' is padded with leading zeros if necessary, so that 'bytes' will |
1425 | | equal 'padBytes'. This is used when TPM data structures expect a fixed length while the crypto |
1426 | | library 'bn to bin' function might truncates leading zeros. |
1427 | | |
1428 | | '*bin' must be freed by the caller |
1429 | | */ |
1430 | | |
1431 | | TPM_RESULT TPM_bn2binMalloc(unsigned char **bin, /* freed by caller */ |
1432 | | unsigned int *bytes, |
1433 | | TPM_BIGNUM bn, |
1434 | | uint32_t padBytes) |
1435 | 0 | { |
1436 | 0 | TPM_RESULT rc = 0; |
1437 | |
|
1438 | 0 | printf(" TPM_bn2binMalloc: padBytes %u\n", padBytes); |
1439 | | /* number of bytes required in the bin array */ |
1440 | 0 | if (rc == 0) { |
1441 | 0 | rc = TPM_BN_num_bytes(bytes, bn); |
1442 | 0 | } |
1443 | | /* calculate the array size to malloc */ |
1444 | 0 | if (rc == 0) { |
1445 | | /* padBytes 0 says that no padding is required */ |
1446 | 0 | if (padBytes == 0) { |
1447 | 0 | padBytes = *bytes; /* setting equal yields no padding */ |
1448 | 0 | } |
1449 | | /* if the array with padding is still less than the number of bytes required by the bignum, |
1450 | | this function fails */ |
1451 | 0 | if (padBytes < *bytes) { |
1452 | 0 | printf("TPM_bn2binMalloc: Error, " |
1453 | 0 | "padBytes %u less than BN bytes %u\n", padBytes, *bytes); |
1454 | 0 | rc = TPM_SIZE; |
1455 | 0 | } |
1456 | | /* log if padding is occurring */ |
1457 | 0 | if (padBytes != *bytes) { |
1458 | 0 | printf(" TPM_bn2binMalloc: padBytes %u bytes %u\n", padBytes, *bytes); |
1459 | 0 | } |
1460 | 0 | } |
1461 | | /* allocate for the padded array */ |
1462 | 0 | if (rc == 0) { |
1463 | 0 | rc = TPM_Malloc(bin, padBytes); |
1464 | 0 | *bytes = padBytes; |
1465 | 0 | } |
1466 | | /* call the bignum to bin conversion */ |
1467 | 0 | if (rc == 0) { |
1468 | 0 | rc = TPM_bn2binArray(*bin, padBytes, bn); |
1469 | 0 | } |
1470 | 0 | return rc; |
1471 | 0 | } |
1472 | | |
1473 | | /* TPM_bn2binArray() loads the array 'bin' of size 'bytes' from 'bn' |
1474 | | |
1475 | | The data from 'bn' is right justified and zero padded. |
1476 | | */ |
1477 | | |
1478 | | TPM_RESULT TPM_bn2binArray(unsigned char *bin, |
1479 | | unsigned int bytes, |
1480 | | TPM_BIGNUM bn) |
1481 | 0 | { |
1482 | 0 | TPM_RESULT rc = 0; |
1483 | 0 | unsigned int numBytes; |
1484 | |
|
1485 | 0 | printf(" TPM_bn2binArray: size %u\n", bytes); |
1486 | 0 | if (rc == 0) { |
1487 | | /* zero pad */ |
1488 | 0 | memset(bin, 0, bytes); |
1489 | | /* bytes required for the bignum */ |
1490 | 0 | rc = TPM_BN_num_bytes(&numBytes, bn); |
1491 | 0 | } |
1492 | | /* if the array is less than the number of bytes required by the bignum, this function fails */ |
1493 | 0 | if (rc == 0) { |
1494 | 0 | printf(" TPM_bn2binArray: numBytes in bignum %u\n", numBytes); |
1495 | 0 | if (numBytes > bytes) { |
1496 | 0 | printf("TPM_bn2binArray: Error, " |
1497 | 0 | "BN bytes %u greater than array bytes %u\n", numBytes, bytes); |
1498 | 0 | rc = TPM_SIZE; |
1499 | 0 | } |
1500 | 0 | } |
1501 | 0 | if (rc == 0) { |
1502 | | /* if there are bytes in the bignum (it is not zero) */ |
1503 | 0 | if (numBytes > 0) { |
1504 | 0 | rc = TPM_bn2bin(bin + bytes - numBytes, /* store right justified */ |
1505 | 0 | bn); |
1506 | 0 | } |
1507 | 0 | } |
1508 | 0 | return rc; |
1509 | 0 | } |
1510 | | |
1511 | | /* TPM_2bin2bn() converts two byte arrays to a positive BIGNUM. |
1512 | | |
1513 | | The two byte arrays are concatenated. The concatenation is used to create the BIGNUM. |
1514 | | |
1515 | | bignum must be freed by the caller. |
1516 | | */ |
1517 | | |
1518 | | TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in, /* freed by caller */ |
1519 | | const unsigned char *bin0, uint32_t size0, |
1520 | | const unsigned char *bin1, uint32_t size1) |
1521 | 0 | { |
1522 | 0 | TPM_RESULT rc = 0; /* TPM return code */ |
1523 | 0 | TPM_STORE_BUFFER sBuffer; /* used of >1 element or first element is negative */ |
1524 | 0 | const unsigned char *buffer; |
1525 | 0 | uint32_t size; |
1526 | | |
1527 | 0 | printf(" TPM_bin2bn:\n"); |
1528 | 0 | TPM_Sbuffer_Init(&sBuffer); /* freed @1 */ |
1529 | | /* append the first element */ |
1530 | 0 | if (rc == 0) { |
1531 | 0 | rc = TPM_Sbuffer_Append(&sBuffer, bin0, size0); |
1532 | 0 | } |
1533 | | /* append the next element */ |
1534 | 0 | if (rc == 0) { |
1535 | 0 | rc = TPM_Sbuffer_Append(&sBuffer, bin1, size1); |
1536 | 0 | } |
1537 | | /* create the BIGNUM from the array */ |
1538 | 0 | if (rc == 0) { |
1539 | 0 | TPM_Sbuffer_Get(&sBuffer, &buffer, &size); |
1540 | | /* create the BIGNUM */ |
1541 | 0 | rc = TPM_bin2bn(bignum_in, buffer, size); /* freed by caller */ |
1542 | 0 | } |
1543 | 0 | TPM_Sbuffer_Delete(&sBuffer); /* @1 */ |
1544 | 0 | return rc; |
1545 | 0 | } |
1546 | | |
1547 | | /* TPM_RSAPrivateDecryptMalloc() allocates a buffer 'decrypt_data' of size 'decrypt_data_size' |
1548 | | and then calls TPM_RSAPrivateDecryptH(). |
1549 | | */ |
1550 | | |
1551 | | TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data, /* decrypted data */ |
1552 | | uint32_t *decrypt_data_length, /* length of data put into |
1553 | | decrypt_data */ |
1554 | | unsigned char *encrypt_data, |
1555 | | uint32_t encrypt_data_size, |
1556 | | TPM_KEY *tpm_key) |
1557 | 0 | { |
1558 | 0 | TPM_RESULT rc = 0; |
1559 | | |
1560 | | /* allocate space for the decrypted blob */ |
1561 | 0 | printf(" TPM_RSAPrivateDecryptMalloc: Return max data size %u bytes\n", |
1562 | 0 | tpm_key->pubKey.size); |
1563 | 0 | if (rc == 0) { |
1564 | 0 | rc = TPM_Malloc(decrypt_data, tpm_key->pubKey.size); |
1565 | 0 | } |
1566 | 0 | if (rc == 0) { |
1567 | 0 | rc = TPM_RSAPrivateDecryptH(*decrypt_data, |
1568 | 0 | decrypt_data_length, |
1569 | 0 | tpm_key->pubKey.size, |
1570 | 0 | encrypt_data, |
1571 | 0 | encrypt_data_size, |
1572 | 0 | tpm_key); |
1573 | 0 | } |
1574 | 0 | return rc; |
1575 | 0 | } |
1576 | | |
1577 | | /* TPM_RSAPrivateDecryptH() decrypts 'encrypt_data' using the private key in |
1578 | | 'tpm_key' and 'decrypt_data_length' bytes are moved to 'decrypt_data'. |
1579 | | |
1580 | | 'decrypt_data_length' is at most 'decrypt_data_size'. |
1581 | | */ |
1582 | | |
1583 | | TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data, /* decrypted data */ |
1584 | | uint32_t *decrypt_data_length, /* length of data put into |
1585 | | decrypt_data */ |
1586 | | uint32_t decrypt_data_size, /* size of decrypt_data buffer */ |
1587 | | unsigned char *encrypt_data, |
1588 | | uint32_t encrypt_data_size, |
1589 | | TPM_KEY *tpm_key) |
1590 | 0 | { |
1591 | 0 | TPM_RESULT rc = 0; |
1592 | 0 | unsigned char *narr; /* public modulus */ |
1593 | 0 | uint32_t nbytes; |
1594 | 0 | unsigned char *earr; /* public exponent */ |
1595 | 0 | uint32_t ebytes; |
1596 | 0 | unsigned char *darr; /* private exponent */ |
1597 | 0 | uint32_t dbytes; |
1598 | |
|
1599 | 0 | printf(" TPM_RSAPrivateDecryptH: Data size %u bytes\n", encrypt_data_size); |
1600 | 0 | TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Encrypt data", encrypt_data, encrypt_data_size); |
1601 | 0 | if (rc == 0) { |
1602 | 0 | if (tpm_key == NULL) { |
1603 | 0 | printf("TPM_RSAPrivateDecryptH: Error, NULL key\n"); |
1604 | 0 | rc = TPM_DECRYPT_ERROR; |
1605 | 0 | } |
1606 | 0 | } |
1607 | | /* extract the public key from TPM_KEY */ |
1608 | 0 | if (rc == 0) { |
1609 | 0 | rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); |
1610 | 0 | } |
1611 | | /* extract the private key from TPM_KEY */ |
1612 | 0 | if (rc == 0) { |
1613 | 0 | rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); |
1614 | 0 | } |
1615 | | /* extract the exponent from TPM_KEY */ |
1616 | 0 | if (rc == 0) { |
1617 | 0 | rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); |
1618 | 0 | } |
1619 | | /* check the key size vs the data size */ |
1620 | 0 | if (rc == 0) { |
1621 | 0 | if (encrypt_data_size > nbytes) { |
1622 | 0 | printf("TPM_RSAPrivateDecryptH: Error, data size too long for key size %u bytes\n", |
1623 | 0 | nbytes); |
1624 | 0 | rc = TPM_BAD_DATASIZE; |
1625 | 0 | } |
1626 | 0 | } |
1627 | 0 | if (rc == 0) { |
1628 | | /* debug printing */ |
1629 | 0 | printf(" TPM_RSAPrivateDecryptH: Public key length %u\n", nbytes); |
1630 | 0 | printf(" TPM_RSAPrivateDecryptH: Private key length %u\n", dbytes); |
1631 | 0 | TPM_PrintFour(" TPM_RSAPrivateDecryptH: Public key", narr); |
1632 | 0 | printf(" TPM_RSAPrivateDecryptH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); |
1633 | 0 | TPM_PrintFour(" TPM_RSAPrivateDecryptH: Private key", darr); |
1634 | | /* decrypt with private key */ |
1635 | 0 | rc = TPM_RSAPrivateDecrypt(decrypt_data, /* decrypted data */ |
1636 | 0 | decrypt_data_length, /* length of data put into decrypt_data */ |
1637 | 0 | decrypt_data_size, /* size of decrypt_data buffer */ |
1638 | 0 | tpm_key->algorithmParms.encScheme, /* encryption scheme */ |
1639 | 0 | encrypt_data, /* encrypted data */ |
1640 | 0 | encrypt_data_size, |
1641 | 0 | narr, /* public modulus */ |
1642 | 0 | nbytes, |
1643 | 0 | earr, /* public exponent */ |
1644 | 0 | ebytes, |
1645 | 0 | darr, /* private exponent */ |
1646 | 0 | dbytes); |
1647 | 0 | } |
1648 | 0 | if (rc == 0) { |
1649 | 0 | TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Decrypt data", decrypt_data, *decrypt_data_length); |
1650 | 0 | } |
1651 | 0 | return rc; |
1652 | 0 | } |
1653 | | |
1654 | | /* TPM_RSAPublicEncryptSbuffer_Key() encrypts 'sbuffer' using the public key in 'tpm_key' and |
1655 | | puts the results in 'encData' |
1656 | | */ |
1657 | | |
1658 | | TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data, |
1659 | | TPM_STORE_BUFFER *sbuffer, |
1660 | | TPM_KEY *tpm_key) |
1661 | 0 | { |
1662 | 0 | TPM_RESULT rc = 0; |
1663 | 0 | const unsigned char *decrypt_data; /* serialization buffer */ |
1664 | 0 | uint32_t decrypt_data_size; /* serialization size */ |
1665 | |
|
1666 | 0 | printf(" TPM_RSAPublicEncryptSbuffer_Key:\n"); |
1667 | | /* get the serialization results */ |
1668 | 0 | TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); |
1669 | | /* encrypt the serialization buffer with the public key, and place |
1670 | | the result in the enc_data buffer */ |
1671 | 0 | rc = TPM_RSAPublicEncrypt_Key(enc_data, |
1672 | 0 | decrypt_data, |
1673 | 0 | decrypt_data_size, |
1674 | 0 | tpm_key); |
1675 | 0 | return rc; |
1676 | 0 | } |
1677 | | |
1678 | | /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_key' and |
1679 | | puts the results in 'encData' |
1680 | | */ |
1681 | | |
1682 | | TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data, |
1683 | | const unsigned char *decrypt_data, |
1684 | | size_t decrypt_data_size, |
1685 | | TPM_KEY *tpm_key) |
1686 | 0 | { |
1687 | 0 | TPM_RESULT rc = 0; |
1688 | 0 | unsigned char *narr; /* public modulus */ |
1689 | 0 | uint32_t nbytes; |
1690 | 0 | unsigned char *earr; /* public exponent */ |
1691 | 0 | uint32_t ebytes; |
1692 | | |
1693 | 0 | printf(" TPM_RSAPublicEncrypt_Key: Data size %lu bytes\n", (unsigned long)decrypt_data_size); |
1694 | 0 | if (rc == 0) { |
1695 | 0 | if (tpm_key == NULL) { |
1696 | 0 | printf("TPM_RSAPublicEncrypt_Key: Error, NULL key\n"); |
1697 | 0 | rc = TPM_ENCRYPT_ERROR; |
1698 | 0 | } |
1699 | 0 | } |
1700 | | /* extract the public key from TPM_KEY */ |
1701 | 0 | if (rc == 0) { |
1702 | 0 | rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); |
1703 | 0 | } |
1704 | | /* extract the exponent from TPM_KEY */ |
1705 | 0 | if (rc == 0) { |
1706 | 0 | rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); |
1707 | 0 | } |
1708 | 0 | if (rc == 0) { |
1709 | 0 | rc = TPM_RSAPublicEncrypt_Common(enc_data, |
1710 | 0 | decrypt_data, |
1711 | 0 | decrypt_data_size, |
1712 | 0 | tpm_key->algorithmParms.encScheme, /* encryption scheme */ |
1713 | 0 | narr, |
1714 | 0 | nbytes, |
1715 | 0 | earr, |
1716 | 0 | ebytes); |
1717 | 0 | } |
1718 | 0 | return rc; |
1719 | 0 | } |
1720 | | |
1721 | | /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_pubkey' and |
1722 | | puts the results in 'encData' |
1723 | | */ |
1724 | | |
1725 | | TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data, |
1726 | | const unsigned char *decrypt_data, |
1727 | | size_t decrypt_data_size, |
1728 | | TPM_PUBKEY *tpm_pubkey) |
1729 | 0 | { |
1730 | 0 | TPM_RESULT rc = 0; |
1731 | 0 | unsigned char *narr; /* public modulus */ |
1732 | 0 | uint32_t nbytes; |
1733 | 0 | unsigned char *earr; /* public exponent */ |
1734 | 0 | uint32_t ebytes; |
1735 | | |
1736 | 0 | printf(" TPM_RSAPublicEncrypt_Pubkey: Data size %lu bytes\n", (unsigned long)decrypt_data_size); |
1737 | 0 | if (rc == 0) { |
1738 | 0 | if (tpm_pubkey == NULL) { |
1739 | 0 | printf("TPM_RSAPublicEncrypt_Pubkey: Error, NULL key\n"); |
1740 | 0 | rc = TPM_ENCRYPT_ERROR; |
1741 | 0 | } |
1742 | 0 | } |
1743 | | /* extract the public key from TPM_PUBKEY */ |
1744 | 0 | if (rc == 0) { |
1745 | 0 | rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); |
1746 | 0 | } |
1747 | | /* extract the exponent from TPM_KEY */ |
1748 | 0 | if (rc == 0) { |
1749 | 0 | rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); |
1750 | 0 | } |
1751 | 0 | if (rc == 0) { |
1752 | 0 | rc = TPM_RSAPublicEncrypt_Common(enc_data, |
1753 | 0 | decrypt_data, |
1754 | 0 | decrypt_data_size, |
1755 | 0 | tpm_pubkey->algorithmParms.encScheme, |
1756 | 0 | narr, |
1757 | 0 | nbytes, |
1758 | 0 | earr, |
1759 | 0 | ebytes); |
1760 | 0 | } |
1761 | 0 | return rc; |
1762 | 0 | } |
1763 | | |
1764 | | /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key modulus and |
1765 | | exponent, and puts the results in 'encData' |
1766 | | */ |
1767 | | |
1768 | | TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data, |
1769 | | const unsigned char *decrypt_data, |
1770 | | size_t decrypt_data_size, |
1771 | | TPM_ENC_SCHEME encScheme, |
1772 | | unsigned char *narr, /* public modulus */ |
1773 | | uint32_t nbytes, |
1774 | | unsigned char *earr, /* public exponent */ |
1775 | | uint32_t ebytes) |
1776 | | |
1777 | 0 | { |
1778 | 0 | TPM_RESULT rc = 0; |
1779 | 0 | unsigned char *encrypt_data = NULL; |
1780 | | |
1781 | 0 | printf(" TPM_RSAPublicEncrypt_Common: Data size %lu bytes\n", (unsigned long)decrypt_data_size); |
1782 | 0 | TPM_PrintFourLimit(" TPM_RSAPublicEncrypt_Common: Decrypt data", decrypt_data, decrypt_data_size); |
1783 | | /* check the key size vs the data size */ |
1784 | 0 | if (rc == 0) { |
1785 | 0 | if (decrypt_data_size > nbytes) { |
1786 | 0 | printf("TPM_RSAPublicEncrypt_Common: Error, data size too long for key size %u bytes\n", |
1787 | 0 | nbytes); |
1788 | 0 | rc = TPM_BAD_DATASIZE; |
1789 | 0 | } |
1790 | 0 | } |
1791 | | /* allocate an array for the encrypted data */ |
1792 | 0 | if (rc == 0) { |
1793 | 0 | rc = TPM_Malloc(&encrypt_data, nbytes); |
1794 | 0 | } |
1795 | | /* pad and encrypt the data */ |
1796 | 0 | if (rc == 0) { |
1797 | 0 | TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Public key", narr); |
1798 | 0 | printf(" TPM_RSAPublicEncrypt_Common: Exponent %02x %02x %02x\n", |
1799 | 0 | earr[0], earr[1], earr[2]); |
1800 | 0 | rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ |
1801 | 0 | nbytes, /* encrypted data size */ |
1802 | 0 | encScheme, /* encryption scheme */ |
1803 | 0 | decrypt_data, /* decrypted data */ |
1804 | 0 | decrypt_data_size, |
1805 | 0 | narr, /* public modulus */ |
1806 | 0 | nbytes, |
1807 | 0 | earr, /* public exponent */ |
1808 | 0 | ebytes); |
1809 | 0 | } |
1810 | | /* copy the result to the sized buffer */ |
1811 | 0 | if (rc == 0) { |
1812 | 0 | printf(" TPM_RSAPublicEncrypt_Common: Encrypt data size %u\n", nbytes); |
1813 | 0 | TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Encrypt data", encrypt_data); |
1814 | 0 | rc = TPM_SizedBuffer_Set(enc_data, nbytes, encrypt_data); |
1815 | 0 | } |
1816 | 0 | free(encrypt_data); /* @1 */ |
1817 | 0 | return rc; |
1818 | 0 | } |
1819 | | |
1820 | | /* |
1821 | | Signing Functions |
1822 | | |
1823 | | These commands show the TPM command and the allowed signature schemes: |
1824 | | |
1825 | | SHA DER INFO |
1826 | | TPM_GetAuditDigestSigned y n y |
1827 | | TPM_CertifyKey y n y |
1828 | | TPM_CertifyKey2 y n y |
1829 | | TPM_CertifySelfTest y n y |
1830 | | TPM_Quote y n y |
1831 | | TPM_Quote2 y n y |
1832 | | TPM_Sign y y y |
1833 | | TPM_MakeIdentity y n y |
1834 | | TPM_GetCapabilitySigned y n y |
1835 | | */ |
1836 | | |
1837 | | /* TPM_RSASignToSizedBuffer() signs 'message' using the private key in 'tpm_key' and places the |
1838 | | result in 'signature' |
1839 | | |
1840 | | 'signature' should be initialized and deleted by the caller |
1841 | | */ |
1842 | | |
1843 | | TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature, |
1844 | | const unsigned char *message, /* input */ |
1845 | | size_t message_size, /* input */ |
1846 | | TPM_KEY *tpm_key) /* input, signing key */ |
1847 | 0 | { |
1848 | 0 | TPM_RESULT rc = 0; |
1849 | 0 | TPM_RSA_KEY_PARMS *rsa_key_parms; |
1850 | 0 | unsigned int signature_length; |
1851 | | |
1852 | 0 | printf(" TPM_RSASignToSizedBuffer: Message size %lu bytes\n", (unsigned long)message_size); |
1853 | 0 | if (rc == 0) { |
1854 | 0 | rc = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, |
1855 | 0 | &(tpm_key->algorithmParms)); |
1856 | 0 | } |
1857 | | /* allocating space for the signature */ |
1858 | 0 | if (rc == 0) { |
1859 | 0 | rc = TPM_SizedBuffer_Allocate(signature, (rsa_key_parms->keyLength)/CHAR_BIT); |
1860 | 0 | } |
1861 | | /* sign */ |
1862 | 0 | if (rc == 0) { |
1863 | 0 | rc = TPM_RSASignH(signature->buffer, /* output signature */ |
1864 | 0 | &signature_length, /* output, size of signature */ |
1865 | 0 | signature->size, /* input, size of signature buffer */ |
1866 | 0 | message, /* message */ |
1867 | 0 | message_size, /* message size */ |
1868 | 0 | tpm_key); /* input, signing key */ |
1869 | 0 | } |
1870 | | /* sanity check on signature */ |
1871 | 0 | if (rc == 0) { |
1872 | 0 | if (signature_length != signature->size) { |
1873 | 0 | printf("TPM_RSASignToSizedBuffer: Error (fatal) signature_length %u sigSize %u\n", |
1874 | 0 | signature_length, signature->size); |
1875 | 0 | rc = TPM_FAIL; /* internal error, should never occur */ |
1876 | 0 | } |
1877 | 0 | } |
1878 | 0 | return rc; |
1879 | 0 | } |
1880 | | |
1881 | | |
1882 | | /* TPM_RSASignH() signs 'message' using the private key in 'tpm_key'. 'signature_length' bytes are |
1883 | | moved to 'signature'. |
1884 | | |
1885 | | 'signature_length' is at most 'signature_size'. |
1886 | | */ |
1887 | | |
1888 | | TPM_RESULT TPM_RSASignH(unsigned char *signature, /* output */ |
1889 | | unsigned int *signature_length, /* output, size of signature */ |
1890 | | unsigned int signature_size, /* input, size of signature buffer */ |
1891 | | const unsigned char *message, /* input */ |
1892 | | size_t message_size, /* input */ |
1893 | | TPM_KEY *tpm_key) /* input, signing key */ |
1894 | 0 | { |
1895 | 0 | TPM_RESULT rc = 0; |
1896 | 0 | unsigned char *narr; /* public modulus */ |
1897 | 0 | uint32_t nbytes; |
1898 | 0 | unsigned char *earr; /* public exponent */ |
1899 | 0 | uint32_t ebytes; |
1900 | 0 | unsigned char *darr; /* private exponent */ |
1901 | 0 | uint32_t dbytes; |
1902 | | |
1903 | 0 | printf(" TPM_RSASignH: Message size %lu bytes\n", (unsigned long)message_size); |
1904 | 0 | TPM_PrintFourLimit(" TPM_RSASignH: Message", message, message_size); |
1905 | | /* extract the public key from TPM_KEY */ |
1906 | 0 | if (rc == 0) { |
1907 | 0 | rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); |
1908 | 0 | } |
1909 | | /* extract the private key from TPM_KEY */ |
1910 | 0 | if (rc == 0) { |
1911 | 0 | rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); |
1912 | 0 | } |
1913 | | /* extract the exponent from TPM_KEY */ |
1914 | 0 | if (rc == 0) { |
1915 | 0 | rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); |
1916 | 0 | } |
1917 | 0 | if (rc == 0) { |
1918 | | /* debug printing */ |
1919 | 0 | TPM_PrintFour(" TPM_RSASignH: Public key", narr); |
1920 | 0 | printf(" TPM_RSASignH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); |
1921 | 0 | TPM_PrintFour(" TPM_RSASignH: Private key", darr); |
1922 | | /* sign with private key */ |
1923 | 0 | rc = TPM_RSASign(signature, /* output */ |
1924 | 0 | signature_length, /* output, size of signature */ |
1925 | 0 | signature_size, /* input, size of signature buffer */ |
1926 | 0 | tpm_key->algorithmParms.sigScheme, /* input, type of signature */ |
1927 | 0 | message, /* input */ |
1928 | 0 | message_size, /* input */ |
1929 | 0 | narr, /* public modulus */ |
1930 | 0 | nbytes, |
1931 | 0 | earr, /* public exponent */ |
1932 | 0 | ebytes, |
1933 | 0 | darr, /* private exponent */ |
1934 | 0 | dbytes); |
1935 | 0 | } |
1936 | 0 | if (rc == 0) { |
1937 | 0 | TPM_PrintFour(" TPM_RSASignH: Signature", signature); |
1938 | 0 | } |
1939 | 0 | return rc; |
1940 | 0 | } |
1941 | | |
1942 | | /* TPM_RSAVerifyH() verifies 'message' using the TPM format public key in 'tpm_pubkey' |
1943 | | */ |
1944 | | |
1945 | | TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature, /* input */ |
1946 | | const unsigned char *message, /* input */ |
1947 | | uint32_t message_size, /* input */ |
1948 | | TPM_PUBKEY *tpm_pubkey) /* input, verify key */ |
1949 | 0 | { |
1950 | 0 | TPM_RESULT rc = 0; |
1951 | 0 | unsigned char *narr; /* public modulus */ |
1952 | 0 | uint32_t nbytes; |
1953 | 0 | unsigned char *earr; /* public exponent */ |
1954 | 0 | uint32_t ebytes; |
1955 | |
|
1956 | 0 | printf(" TPM_RSAVerifyH: Message size %u bytes\n", message_size); |
1957 | | /* extract the public key from TPM_PUBKEY */ |
1958 | 0 | if (rc == 0) { |
1959 | 0 | rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); |
1960 | 0 | } |
1961 | | /* extract the exponent from TPM_PUBKEY */ |
1962 | 0 | if (rc == 0) { |
1963 | 0 | rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); |
1964 | 0 | } |
1965 | 0 | if (rc == 0) { |
1966 | | /* debug printing */ |
1967 | 0 | TPM_PrintFour(" TPM_RSAVerifyH: Public key", narr); |
1968 | 0 | TPM_PrintAll(" TPM_RSAVerifyH: Public exponent", earr, ebytes); |
1969 | | /* verify with public key */ |
1970 | 0 | rc = TPM_RSAVerify(signature->buffer, /* input signature buffer */ |
1971 | 0 | signature->size, /* input, size of signature buffer */ |
1972 | 0 | tpm_pubkey->algorithmParms.sigScheme, /* input, type of signature */ |
1973 | 0 | message, /* message */ |
1974 | 0 | message_size, /* message size */ |
1975 | 0 | narr, /* public modulus */ |
1976 | 0 | nbytes, |
1977 | 0 | earr, /* public exponent */ |
1978 | 0 | ebytes); |
1979 | 0 | } |
1980 | 0 | return rc; |
1981 | 0 | } |
1982 | | |
1983 | | /* TPM_RSAVerify() verifies the 'signature' of size 'signature_size' on the 'message' of size |
1984 | | 'message_size' using the public key n,e and the signature scheme 'sigScheme' as specified in PKCS |
1985 | | #1 v2.0. |
1986 | | */ |
1987 | | |
1988 | | TPM_RESULT TPM_RSAVerify(unsigned char *signature, /* input */ |
1989 | | unsigned int signature_size, /* input, size of signature buffer */ |
1990 | | TPM_SIG_SCHEME sigScheme, /* input, type of signature */ |
1991 | | const unsigned char *message, /* input */ |
1992 | | uint32_t message_size, /* input */ |
1993 | | unsigned char *narr, /* public modulus */ |
1994 | | uint32_t nbytes, |
1995 | | unsigned char *earr, /* public exponent */ |
1996 | | uint32_t ebytes) |
1997 | 0 | { |
1998 | 0 | TPM_RESULT rc = 0; |
1999 | | |
2000 | 0 | printf(" TPM_RSAVerify:\n"); |
2001 | | /* determine the signature scheme for the key */ |
2002 | 0 | if (rc == 0) { |
2003 | 0 | switch(sigScheme) { |
2004 | 0 | case TPM_SS_NONE: |
2005 | 0 | printf("TPM_RSAVerify: Error, sigScheme TPM_SS_NONE\n"); |
2006 | 0 | rc = TPM_INVALID_KEYUSAGE; |
2007 | 0 | break; |
2008 | 0 | case TPM_SS_RSASSAPKCS1v15_SHA1: |
2009 | 0 | case TPM_SS_RSASSAPKCS1v15_INFO: |
2010 | 0 | rc = TPM_RSAVerifySHA1(signature, |
2011 | 0 | signature_size, |
2012 | 0 | message, |
2013 | 0 | message_size, |
2014 | 0 | narr, /* public modulus */ |
2015 | 0 | nbytes, |
2016 | 0 | earr, /* public exponent */ |
2017 | 0 | ebytes); |
2018 | 0 | break; |
2019 | 0 | case TPM_SS_RSASSAPKCS1v15_DER: |
2020 | 0 | printf("TPM_RSAVerify: Error, sigScheme %04hx unsupported\n", sigScheme); |
2021 | 0 | rc = TPM_INVALID_KEYUSAGE; |
2022 | 0 | break; |
2023 | 0 | default: |
2024 | 0 | printf("TPM_RSAVerify: Error, sigScheme %04hx unknown\n", sigScheme); |
2025 | 0 | rc = TPM_INVALID_KEYUSAGE; |
2026 | 0 | break; |
2027 | 0 | } |
2028 | 0 | } |
2029 | 0 | return rc; |
2030 | 0 | } |
2031 | | |
2032 | | /* |
2033 | | OAEP Padding |
2034 | | */ |
2035 | | |
2036 | | /* TPM_RSA_padding_add_PKCS1_OAEP() is a variation of the the openSSL function |
2037 | | |
2038 | | int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, |
2039 | | unsigned char *f, int fl, unsigned char *p, int pl); |
2040 | | |
2041 | | It is used for TPM migration. The "encoding parameter" pl is replaced by pHash and the generated |
2042 | | random seed is replaced by a seed parameter. |
2043 | | |
2044 | | This function was independently written from the PKCS1 specification "9.1.1.1 Encoding |
2045 | | Operation", intended to be unencumbered by any license. |
2046 | | |
2047 | | |
2048 | | | seed | pHash | PS | 01 | Message | |
2049 | | |
2050 | | SHA1 SHA1 flen |
2051 | | |
2052 | | | <- emLen -> | |
2053 | | | db |
2054 | | | maskDb |
2055 | | | dbMask | |
2056 | | | seedMask |
2057 | | | maskSeed |
2058 | | */ |
2059 | | |
2060 | | TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, |
2061 | | const unsigned char *from, uint32_t fLen, |
2062 | | const unsigned char *pHash, /* input 20 bytes */ |
2063 | | const unsigned char *seed) /* input 20 bytes */ |
2064 | 0 | { |
2065 | 0 | TPM_RESULT rc = 0; |
2066 | 0 | unsigned char *dbMask; |
2067 | 0 | unsigned char *db; |
2068 | 0 | unsigned char *maskedDb; |
2069 | 0 | unsigned char *seedMask; |
2070 | 0 | unsigned char *maskedSeed; |
2071 | |
|
2072 | 0 | printf(" TPM_RSA_padding_add_PKCS1_OAEP: fLen %d emLen %d\n", fLen, emLen); |
2073 | 0 | TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: from", from, fLen); |
2074 | 0 | TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: pHash", pHash); |
2075 | 0 | TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: seed", seed); |
2076 | | |
2077 | 0 | dbMask = NULL; /* freed @1 */ |
2078 | | |
2079 | | /* 1. If the length of P is greater than the input limitation for */ |
2080 | | /* the hash function (2^61-1 octets for SHA-1) then output "parameter */ |
2081 | | /* string too long" and stop. */ |
2082 | | /* NOTE Not done, pHash is input directly */ |
2083 | | /* 2. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */ |
2084 | 0 | if (rc == 0) { |
2085 | 0 | if (emLen < ((2 * TPM_DIGEST_SIZE) + 1 + fLen)) { |
2086 | 0 | printf("TPM_RSA_padding_add_PKCS1_OAEP: Error, " |
2087 | 0 | "message length %u too large for encoded length %u\n", fLen, emLen); |
2088 | 0 | rc = TPM_ENCRYPT_ERROR; |
2089 | 0 | } |
2090 | 0 | } |
2091 | | /* 3. Generate an octet string PS consisting of emLen-||M||-2hLen-1 zero octets. The length of |
2092 | | PS may be 0. */ |
2093 | | /* NOTE Created directly in DB (step 5) */ |
2094 | | |
2095 | | /* 4. Let pHash = Hash(P), an octet string of length hLen. */ |
2096 | | /* NOTE pHash is input directly */ |
2097 | | |
2098 | | /* 5. Concatenate pHash, PS, the message M, and other padding to form a data block DB as: DB = |
2099 | | pHash || PS || 01 || M */ |
2100 | 0 | if (rc == 0) { |
2101 | | /* NOTE Since db is eventually maskedDb, part of em, create directly in em */ |
2102 | 0 | db = em + TPM_DIGEST_SIZE; |
2103 | 0 | memcpy(db, pHash, TPM_DIGEST_SIZE); /* pHash */ |
2104 | 0 | memset(db + TPM_DIGEST_SIZE, 0, /* PS */ |
2105 | 0 | emLen - fLen - (2 * TPM_DIGEST_SIZE) - 1); |
2106 | | /* PSlen = emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 |
2107 | | 0x01 index = TPM_DIGEST_SIZE + PSlen |
2108 | | = TPM_DIGEST_SIZE + emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 |
2109 | | = emlen - fLen - TPM_DIGEST_SIZE - 1 */ |
2110 | 0 | db[emLen - fLen - TPM_DIGEST_SIZE - 1] = 0x01; |
2111 | 0 | memcpy(db + emLen - fLen - TPM_DIGEST_SIZE, from, fLen); /* M */ |
2112 | | |
2113 | | /* 6. Generate a random octet string seed of length hLen. */ |
2114 | | /* NOTE seed is input directly */ |
2115 | | |
2116 | | /* 7. Let dbMask = MGF(seed, emLen-hLen). */ |
2117 | 0 | rc = TPM_Malloc(&dbMask, emLen - TPM_DIGEST_SIZE); |
2118 | 0 | } |
2119 | 0 | if (rc == 0) { |
2120 | 0 | rc = TPM_MGF1(dbMask, emLen - TPM_DIGEST_SIZE, seed, TPM_DIGEST_SIZE); |
2121 | 0 | } |
2122 | 0 | if (rc == 0) { |
2123 | | /* 8. Let maskedDB = DB \xor dbMask. */ |
2124 | | /* NOTE Since maskedDB is eventually em, XOR directly to em */ |
2125 | 0 | maskedDb = em + TPM_DIGEST_SIZE; |
2126 | 0 | TPM_XOR(maskedDb, db, dbMask, emLen - TPM_DIGEST_SIZE); |
2127 | | |
2128 | | /* 9. Let seedMask = MGF(maskedDB, hLen). */ |
2129 | | /* NOTE Since seedMask is eventually em, create directly to em */ |
2130 | 0 | seedMask = em; |
2131 | 0 | rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDb, emLen - TPM_DIGEST_SIZE); |
2132 | 0 | } |
2133 | 0 | if (rc == 0) { |
2134 | | /* 10. Let maskedSeed = seed \xor seedMask. */ |
2135 | | /* NOTE Since maskedSeed is eventually em, create directly to em */ |
2136 | 0 | maskedSeed = em; |
2137 | 0 | TPM_XOR(maskedSeed, seed, seedMask, TPM_DIGEST_SIZE); |
2138 | | |
2139 | | /* 11. Let EM = maskedSeed || maskedDB. */ |
2140 | | /* NOTE Created directly in em */ |
2141 | | |
2142 | | /* 12. Output EM. */ |
2143 | 0 | TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: em", em, emLen); |
2144 | 0 | } |
2145 | 0 | free(dbMask); /* @1 */ |
2146 | 0 | return rc; |
2147 | 0 | } |
2148 | | |
2149 | | /* TPM_RSA_padding_check_PKCS1_OAEP() is a variation of the openSSL function |
2150 | | |
2151 | | int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, |
2152 | | unsigned char *f, int fl, int rsa_len, unsigned char *p, int pl); |
2153 | | |
2154 | | It is used for TPM key migration. In addition to the message 'to' and message length 'tlen', the |
2155 | | seed and 'pHash are returned. |
2156 | | |
2157 | | This function was independently written from the PKCS1 specification "9.1.1.2 Decoding |
2158 | | Operation", intended to be unencumbered by the any license. |
2159 | | |
2160 | | | seed | pHash | PS | 01 | Message | |
2161 | | SHA1 SHA1 |
2162 | | | <- emLen -> | |
2163 | | |
2164 | | | maskedSeed |
2165 | | | seedMask |
2166 | | | maskedDB |
2167 | | | db |
2168 | | | <- dbMask -> | |
2169 | | |
2170 | | */ |
2171 | | |
2172 | | TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, |
2173 | | const unsigned char *em, uint32_t emLen, |
2174 | | unsigned char *pHash, /* output 20 bytes */ |
2175 | | unsigned char *seed) /* output 20 bytes */ |
2176 | 0 | { |
2177 | 0 | TPM_RESULT rc = 0; |
2178 | 0 | const unsigned char *maskedSeed; |
2179 | 0 | const unsigned char *maskedDB; |
2180 | 0 | uint32_t dbLen; |
2181 | 0 | unsigned char *dbMask; |
2182 | 0 | unsigned char *seedMask; |
2183 | 0 | unsigned char *db; |
2184 | 0 | size_t i; |
2185 | |
|
2186 | 0 | printf(" TPM_RSA_padding_check_PKCS1_OAEP: emLen %d tSize %d\n", emLen, tSize); |
2187 | 0 | TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: em", em, emLen); |
2188 | |
|
2189 | 0 | dbMask = NULL; /* freed @1 */ |
2190 | | |
2191 | | /* 1. If the length of P is greater than the input limitation for the hash function (2^61-1 |
2192 | | octets for SHA-1) then output "parameter string too long" and stop. */ |
2193 | | /* NOTE There is no P input. pHash is calculated for the output, but no comparison is |
2194 | | performed. */ |
2195 | | |
2196 | | /* 2. If ||EM|| < 2hLen+1, then output "decoding error" and stop. */ |
2197 | 0 | if (rc == 0) { |
2198 | 0 | if (emLen < (2 * TPM_DIGEST_SIZE) + 1) { |
2199 | 0 | printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, encoded length %u too small\n", emLen); |
2200 | 0 | rc = TPM_DECRYPT_ERROR; |
2201 | 0 | } |
2202 | 0 | } |
2203 | 0 | if (rc == 0) { |
2204 | | /* 3. Let maskedSeed be the first hLen octets of EM and let maskedDB be the remaining ||EM|| |
2205 | | - hLen octets. */ |
2206 | 0 | maskedSeed = em; |
2207 | 0 | maskedDB = em + TPM_DIGEST_SIZE; |
2208 | 0 | dbLen = emLen - TPM_DIGEST_SIZE; |
2209 | | /* 4. Let seedMask = MGF(maskedDB, hLen). */ |
2210 | | /* NOTE Created directly in seed */ |
2211 | 0 | seedMask = seed; |
2212 | 0 | rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDB, dbLen); |
2213 | 0 | } |
2214 | 0 | if (rc == 0) { |
2215 | | /* 5. Let seed = maskedSeed \xor seedMask. */ |
2216 | 0 | TPM_XOR(seed, maskedSeed, seedMask, TPM_DIGEST_SIZE); |
2217 | | /* 6. Let dbMask = MGF(seed, ||EM|| - hLen). */ |
2218 | 0 | rc = TPM_Malloc(&dbMask, dbLen); |
2219 | 0 | } |
2220 | 0 | if (rc == 0) { |
2221 | 0 | rc = TPM_MGF1(dbMask, dbLen, seed, TPM_DIGEST_SIZE); |
2222 | 0 | } |
2223 | 0 | if (rc == 0) { |
2224 | | /* 7. Let DB = maskedDB \xor dbMask. */ |
2225 | | /* NOTE XOR back to dbMask, since dbMask no longer needed */ |
2226 | 0 | db = dbMask; |
2227 | 0 | TPM_XOR(db, maskedDB, dbMask, dbLen); |
2228 | | /* 8. Let pHash = Hash(P), an octet string of length hLen. */ |
2229 | | /* NOTE pHash is input directly */ |
2230 | | /* 9. Separate DB into an octet string pHash' consisting of the first hLen octets of DB, |
2231 | | ... */ |
2232 | 0 | memcpy(pHash, db, TPM_DIGEST_SIZE); |
2233 | | /* ... a (possibly empty) octet string PS consisting of consecutive zero octets following |
2234 | | pHash', and a message M as: DB = pHash' || PS || 01 || M */ |
2235 | 0 | for (i = TPM_DIGEST_SIZE; i < dbLen; i++) { |
2236 | 0 | if (db[i] != 0x00) { |
2237 | 0 | break; /* skip the PS segment */ |
2238 | 0 | } |
2239 | 0 | } |
2240 | | /* If there is no 01 octet to separate PS from M, output "decoding error" and stop. */ |
2241 | 0 | if (i == dbLen) { |
2242 | 0 | printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); |
2243 | 0 | rc = TPM_DECRYPT_ERROR; |
2244 | 0 | } |
2245 | 0 | } |
2246 | 0 | if (rc == 0) { |
2247 | 0 | if (db[i] != 0x01) { |
2248 | 0 | printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); |
2249 | 0 | rc = TPM_DECRYPT_ERROR; |
2250 | 0 | } |
2251 | 0 | } |
2252 | | /* 10. If pHash' does not equal pHash, output "decoding error" and stop. */ |
2253 | | /* NOTE No pHash input to compare */ |
2254 | | /* 11. Output M. */ |
2255 | 0 | if (rc == 0) { |
2256 | 0 | i++; /* skip the 0x01 to the beginning of the message M */ |
2257 | 0 | *tLen = dbLen - i; |
2258 | 0 | if (*tLen > tSize) { |
2259 | 0 | printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, tSize %u too small for message %u\n", |
2260 | 0 | tSize, *tLen); |
2261 | 0 | rc = TPM_DECRYPT_ERROR; |
2262 | 0 | } |
2263 | 0 | } |
2264 | 0 | if (rc == 0) { |
2265 | 0 | memcpy(to, db + i, *tLen); |
2266 | 0 | printf(" TPM_RSA_padding_check_PKCS1_OAEP: tLen %d \n", *tLen); |
2267 | 0 | TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: to", to, *tLen); |
2268 | 0 | TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: pHash", pHash); |
2269 | 0 | TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: seed", seed); |
2270 | 0 | } |
2271 | 0 | free(dbMask); /* @1 */ |
2272 | 0 | return rc; |
2273 | 0 | } |
2274 | | |
2275 | | /* TPM_RSA_exponent_verify() validates the public exponent against a list of legal values. Some |
2276 | | values (e.g. even numbers) will have the key generator. |
2277 | | */ |
2278 | | |
2279 | | TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent) |
2280 | 0 | { |
2281 | 0 | TPM_RESULT rc = 0; |
2282 | 0 | size_t i; |
2283 | 0 | int found; |
2284 | |
|
2285 | 0 | static const unsigned long legalExponent[] = { 3,5,7,17,257,65537 }; |
2286 | | |
2287 | 0 | for (i = 0, found = FALSE ; |
2288 | 0 | !found && (i < (sizeof(legalExponent) / sizeof (unsigned long))) ; |
2289 | 0 | i++) { |
2290 | |
|
2291 | 0 | if (exponent == legalExponent[i]) { |
2292 | 0 | found = TRUE; |
2293 | 0 | } |
2294 | 0 | } |
2295 | 0 | if (!found) { |
2296 | 0 | printf("TPM_RSA_exponent_verify: Error, public exponent %lu is illegal\n", exponent ); |
2297 | 0 | rc = TPM_BAD_KEY_PROPERTY; |
2298 | 0 | } |
2299 | 0 | return rc; |
2300 | 0 | } |
2301 | | |
2302 | | /* SHA1 and HMAC test driver |
2303 | | |
2304 | | Returns TPM_FAILEDSELFTEST on error |
2305 | | */ |
2306 | | |
2307 | | TPM_RESULT TPM_CryptoTest(void) |
2308 | 0 | { |
2309 | 0 | TPM_RESULT rc = 0; |
2310 | 0 | int not_equal; |
2311 | 0 | TPM_BOOL valid; |
2312 | | |
2313 | | /* SHA1 */ |
2314 | 0 | unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; |
2315 | 0 | unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, |
2316 | 0 | 0x3B,0xD2,0x6E,0xBA,0xAE, |
2317 | 0 | 0x4A,0xA1,0xF9,0x51,0x29, |
2318 | 0 | 0xE5,0xE5,0x46,0x70,0xF1}; |
2319 | 0 | TPM_DIGEST actual; |
2320 | 0 | uint32_t actual_size; |
2321 | | |
2322 | | /* HMAC */ |
2323 | 0 | unsigned char key2[] = {0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa, |
2324 | 0 | 0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa}; |
2325 | 0 | unsigned char expect2[] = {0x12,0x5d,0x73,0x42,0xb9,0xac,0x11,0xcd,0x91,0xa3, |
2326 | 0 | 0x9a,0xf4,0x8a,0xa1,0x7b,0x4f,0x63,0xf1,0x75,0xd3}; |
2327 | | /* data 0xdd repeated 50 times */ |
2328 | 0 | unsigned char data2[50]; |
2329 | | |
2330 | | /* oaep tests */ |
2331 | 0 | const unsigned char oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; |
2332 | 0 | unsigned char pHash_in[TPM_DIGEST_SIZE]; |
2333 | 0 | unsigned char pHash_out[TPM_DIGEST_SIZE]; |
2334 | 0 | unsigned char seed_in[TPM_DIGEST_SIZE] = {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, |
2335 | 0 | 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, |
2336 | 0 | 0xf0,0xf1,0xf2,0xf3}; |
2337 | 0 | unsigned char seed_out[TPM_DIGEST_SIZE]; |
2338 | 0 | unsigned char oaep_in[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; |
2339 | 0 | unsigned char oaep_pad[256]; |
2340 | 0 | unsigned char oaep_out[8]; |
2341 | 0 | uint32_t oeap_length; |
2342 | | |
2343 | | /* symmetric key with pad */ |
2344 | 0 | TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data = NULL; /* opaque structure, freed @7 */ |
2345 | 0 | unsigned char clrStream[64]; /* expected */ |
2346 | 0 | unsigned char *encStream; /* encrypted */ |
2347 | 0 | uint32_t encSize; |
2348 | 0 | unsigned char *decStream; /* actual */ |
2349 | 0 | uint32_t decSize; |
2350 | | |
2351 | | /* symmetric key ctr and ofb mode */ |
2352 | 0 | TPM_SECRET symKey; |
2353 | 0 | TPM_NONCE pad; /* CTR or IV */ |
2354 | 0 | TPM_ENCAUTH symClear; |
2355 | 0 | TPM_ENCAUTH symEnc; |
2356 | 0 | TPM_ENCAUTH symDec; |
2357 | | |
2358 | | /* RSA encrypt and decrypt, sign and verify */ |
2359 | 0 | unsigned char *n; /* public key - modulus */ |
2360 | 0 | unsigned char *p; /* private key prime */ |
2361 | 0 | unsigned char *q; /* private key prime */ |
2362 | 0 | unsigned char *d; /* private key (private exponent) */ |
2363 | 0 | unsigned char encrypt_data[2048/8]; /* encrypted data */ |
2364 | 0 | unsigned char signature[2048/8]; /* signature; libtpms added */ |
2365 | |
|
2366 | 0 | printf(" TPM_CryptoTest:\n"); |
2367 | 0 | encStream = NULL; /* freed @1 */ |
2368 | 0 | decStream = NULL; /* freed @2 */ |
2369 | 0 | n = NULL; /* freed @3 */ |
2370 | 0 | p = NULL; /* freed @4 */ |
2371 | 0 | q = NULL; /* freed @5 */ |
2372 | 0 | d = NULL; /* freed @6 */ |
2373 | | |
2374 | 0 | if (rc == 0) { |
2375 | 0 | printf(" TPM_CryptoTest: Test 1 - SHA1 one part\n"); |
2376 | 0 | rc = TPM_SHA1(actual, |
2377 | 0 | (uint32_t)sizeof(buffer1) - 1, buffer1, |
2378 | 0 | 0, NULL); |
2379 | 0 | } |
2380 | 0 | if (rc == 0) { |
2381 | 0 | not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); |
2382 | 0 | if (not_equal) { |
2383 | 0 | printf("TPM_CryptoTest: Error in test 1\n"); |
2384 | 0 | TPM_PrintFour("\texpect", expect1); |
2385 | 0 | TPM_PrintFour("\tactual", actual); |
2386 | 0 | rc = TPM_FAILEDSELFTEST; |
2387 | 0 | } |
2388 | 0 | } |
2389 | 0 | if (rc == 0) { |
2390 | 0 | printf(" TPM_CryptoTest: Test 2 - SHA1 two parts\n"); |
2391 | 0 | rc = TPM_SHA1(actual, |
2392 | 0 | 16, buffer1, /* first 16 */ |
2393 | 0 | (uint32_t)sizeof(buffer1) - 17, buffer1 + 16, /* rest */ |
2394 | 0 | 0, NULL); |
2395 | 0 | } |
2396 | 0 | if (rc == 0) { |
2397 | 0 | not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); |
2398 | 0 | if (not_equal) { |
2399 | 0 | printf("TPM_CryptoTest: Error in test 2\n"); |
2400 | 0 | TPM_PrintFour("\texpect", expect1); |
2401 | 0 | TPM_PrintFour("\tactual", actual); |
2402 | 0 | rc = TPM_FAILEDSELFTEST; |
2403 | 0 | } |
2404 | 0 | } |
2405 | 0 | if (rc == 0) { |
2406 | 0 | printf(" TPM_CryptoTest: Test 3 - HMAC generate - one part\n"); |
2407 | 0 | memset(data2, 0xdd, 50); |
2408 | 0 | rc = TPM_HMAC_Generate(actual, |
2409 | 0 | key2, |
2410 | 0 | 50, data2, |
2411 | 0 | 0, NULL); |
2412 | 0 | } |
2413 | 0 | if (rc == 0) { |
2414 | 0 | not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); |
2415 | 0 | if (not_equal) { |
2416 | 0 | printf("TPM_CryptoTest: Error in test 3\n"); |
2417 | 0 | TPM_PrintFour("\texpect", expect1); |
2418 | 0 | TPM_PrintFour("\tactual", actual); |
2419 | 0 | rc = TPM_FAILEDSELFTEST; |
2420 | 0 | } |
2421 | 0 | } |
2422 | 0 | if (rc == 0) { |
2423 | 0 | printf(" TPM_CryptoTest: Test 4 - HMAC generate - two parts\n"); |
2424 | 0 | memset(data2, 0xdd, 50); |
2425 | 0 | rc = TPM_HMAC_Generate(actual, |
2426 | 0 | key2, |
2427 | 0 | 20, data2, |
2428 | 0 | 30, data2 + 20, |
2429 | 0 | 0, NULL); |
2430 | 0 | } |
2431 | 0 | if (rc == 0) { |
2432 | 0 | not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); |
2433 | 0 | if (not_equal) { |
2434 | 0 | printf("TPM_CryptoTest: Error in test 3\n"); |
2435 | 0 | TPM_PrintFour("\texpect", expect2); |
2436 | 0 | TPM_PrintFour("\tactual", actual); |
2437 | 0 | rc = TPM_FAILEDSELFTEST; |
2438 | 0 | } |
2439 | 0 | } |
2440 | 0 | if (rc == 0) { |
2441 | 0 | printf(" TPM_CryptoTest: Test 4 - HMAC check - two parts\n"); |
2442 | 0 | memset(data2, 0xdd, 50); |
2443 | 0 | rc = TPM_HMAC_Check(&valid, |
2444 | 0 | expect2, |
2445 | 0 | key2, |
2446 | 0 | 20, data2, |
2447 | 0 | 30, data2 + 20, |
2448 | 0 | 0, NULL); |
2449 | 0 | } |
2450 | 0 | if (rc == 0) { |
2451 | 0 | if (!valid) { |
2452 | 0 | printf("TPM_CryptoTest: Error in test 4\n"); |
2453 | 0 | TPM_PrintFour("\texpect", expect1); |
2454 | 0 | TPM_PrintFour("\tactual", actual); |
2455 | 0 | rc = TPM_FAILEDSELFTEST; |
2456 | 0 | } |
2457 | 0 | } |
2458 | 0 | if (rc == 0) { |
2459 | 0 | printf(" TPM_CryptoTest: Test 5 - OAEP add and check\n"); |
2460 | 0 | rc = TPM_SHA1(pHash_in, |
2461 | 0 | sizeof(oaep_pad_str), oaep_pad_str, |
2462 | 0 | 0, NULL); |
2463 | 0 | } |
2464 | 0 | if (rc == 0) { |
2465 | 0 | rc = TPM_RSA_padding_add_PKCS1_OAEP(oaep_pad, sizeof(oaep_pad), |
2466 | 0 | oaep_in, sizeof(oaep_in), |
2467 | 0 | pHash_in, seed_in); |
2468 | 0 | } |
2469 | 0 | if (rc == 0) { |
2470 | 0 | rc = TPM_RSA_padding_check_PKCS1_OAEP(oaep_out, &oeap_length, sizeof(oaep_out), |
2471 | 0 | oaep_pad, sizeof(oaep_pad), |
2472 | 0 | pHash_out, |
2473 | 0 | seed_out); |
2474 | 0 | } |
2475 | 0 | if (rc == 0) { |
2476 | 0 | if (oeap_length != sizeof(oaep_out)) { |
2477 | 0 | printf("TPM_CryptoTest: Error in test 5, expect length %lu, actual length %u\n", |
2478 | 0 | (unsigned long)sizeof(oaep_out), oeap_length); |
2479 | 0 | rc = TPM_FAILEDSELFTEST; |
2480 | 0 | } |
2481 | 0 | } |
2482 | 0 | if (rc == 0) { |
2483 | 0 | not_equal = memcmp(oaep_in, oaep_out, sizeof(oaep_out)); |
2484 | 0 | if (not_equal) { |
2485 | 0 | printf("TPM_CryptoTest: Error in test 5 oaep\n"); |
2486 | 0 | TPM_PrintFour("\tin ", oaep_in); |
2487 | 0 | TPM_PrintFour("\tout", oaep_out); |
2488 | 0 | rc = TPM_FAILEDSELFTEST; |
2489 | 0 | } |
2490 | 0 | } |
2491 | 0 | if (rc == 0) { |
2492 | 0 | not_equal = memcmp(pHash_in, pHash_out, sizeof(pHash_in)); |
2493 | 0 | if (not_equal) { |
2494 | 0 | printf("TPM_CryptoTest: Error in test 5 pHash\n"); |
2495 | 0 | TPM_PrintFour("\tpHash_in ", pHash_in); |
2496 | 0 | TPM_PrintFour("\tpHash_out", pHash_out); |
2497 | 0 | rc = TPM_FAILEDSELFTEST; |
2498 | 0 | } |
2499 | 0 | } |
2500 | 0 | if (rc == 0) { |
2501 | 0 | not_equal = memcmp(seed_in, seed_out, sizeof(seed_in)); |
2502 | 0 | if (not_equal) { |
2503 | 0 | printf("TPM_CryptoTest: Error in test 5 seed\n"); |
2504 | 0 | TPM_PrintFour("\tseed_in ", seed_in); |
2505 | 0 | TPM_PrintFour("\tseed_out", seed_out); |
2506 | 0 | rc = TPM_FAILEDSELFTEST; |
2507 | 0 | } |
2508 | 0 | } |
2509 | 0 | if (rc == 0) { |
2510 | 0 | printf(" TPM_CryptoTest: Test 6 - Symmetric key with PKCS pad test\n"); |
2511 | | /* allocate memory for the key token */ |
2512 | 0 | rc = TPM_SymmetricKeyData_New(&tpm_symmetric_key_data); /* freed @7 */ |
2513 | 0 | } |
2514 | | /* generate a key */ |
2515 | 0 | if (rc == 0) { |
2516 | 0 | rc = TPM_SymmetricKeyData_GenerateKey(tpm_symmetric_key_data); |
2517 | 0 | } |
2518 | | /* generate clear text */ |
2519 | 0 | if (rc == 0) { |
2520 | 0 | rc = TPM_Random(clrStream, sizeof(clrStream)); |
2521 | 0 | } |
2522 | | /* symmetric encrypt */ |
2523 | 0 | if (rc == 0) { |
2524 | 0 | rc = TPM_SymmetricKeyData_Encrypt(&encStream, /* output, freed @1 */ |
2525 | 0 | &encSize, /* output */ |
2526 | 0 | clrStream, /* input */ |
2527 | 0 | sizeof(clrStream), /* input */ |
2528 | 0 | tpm_symmetric_key_data); /* key */ |
2529 | 0 | } |
2530 | | /* symmetric decrypt */ |
2531 | 0 | if (rc == 0) { |
2532 | 0 | rc = TPM_SymmetricKeyData_Decrypt(&decStream, /* output, freed by caller */ |
2533 | 0 | &decSize, /* output */ |
2534 | 0 | encStream, /* input */ |
2535 | 0 | encSize, /* input */ |
2536 | 0 | tpm_symmetric_key_data); /* key */ |
2537 | 0 | } |
2538 | | /* symmetric compare */ |
2539 | 0 | if (rc == 0) { |
2540 | 0 | if (sizeof(clrStream) != decSize) { |
2541 | 0 | printf("TPM_CryptoTest: Error in test 6, in %lu, out %u\n", |
2542 | 0 | (unsigned long)sizeof(clrStream), decSize); |
2543 | 0 | rc = TPM_FAILEDSELFTEST; |
2544 | 0 | } |
2545 | 0 | } |
2546 | 0 | if (rc == 0) { |
2547 | 0 | not_equal = memcmp(clrStream, decStream, sizeof(clrStream)); |
2548 | 0 | if (not_equal) { |
2549 | 0 | printf("TPM_CryptoTest: Error in test 6\n"); |
2550 | 0 | TPM_PrintFour("\tclear stream in", clrStream); |
2551 | 0 | TPM_PrintFour("\tdecrypted stream", decStream); |
2552 | 0 | rc = TPM_FAILEDSELFTEST; |
2553 | 0 | } |
2554 | 0 | } |
2555 | 0 | if (rc == 0) { |
2556 | 0 | printf(" TPM_CryptoTest: Test 7 - Symmetric key with CTR mode\n"); |
2557 | | /* generate a key */ |
2558 | 0 | rc = TPM_Random(symKey, TPM_SECRET_SIZE); |
2559 | 0 | } |
2560 | | /* generate CTR */ |
2561 | 0 | if (rc == 0) { |
2562 | 0 | rc = TPM_Random(pad, TPM_NONCE_SIZE); |
2563 | 0 | } |
2564 | | /* generate clear text */ |
2565 | 0 | if (rc == 0) { |
2566 | 0 | rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); |
2567 | 0 | } |
2568 | 0 | if (rc == 0) { |
2569 | 0 | rc = TPM_SymmetricKeyData_CtrCrypt(symEnc, /* output */ |
2570 | 0 | symClear, /* input */ |
2571 | 0 | TPM_AUTHDATA_SIZE, /* input */ |
2572 | 0 | symKey, /* in */ |
2573 | 0 | TPM_SECRET_SIZE, /* in */ |
2574 | 0 | pad, /* input */ |
2575 | 0 | TPM_NONCE_SIZE); /* input */ |
2576 | 0 | } |
2577 | 0 | if (rc == 0) { |
2578 | 0 | rc = TPM_SymmetricKeyData_CtrCrypt(symDec, /* output */ |
2579 | 0 | symEnc, /* input */ |
2580 | 0 | TPM_AUTHDATA_SIZE, /* input */ |
2581 | 0 | symKey, /* in */ |
2582 | 0 | TPM_SECRET_SIZE, /* in */ |
2583 | 0 | pad, /* input */ |
2584 | 0 | TPM_NONCE_SIZE); /* input */ |
2585 | 0 | } |
2586 | | /* symmetric compare */ |
2587 | 0 | if (rc == 0) { |
2588 | 0 | rc = TPM_Secret_Compare(symDec, symClear); |
2589 | 0 | if (rc != 0) { |
2590 | 0 | printf("TPM_CryptoTest: Error in test 8\n"); |
2591 | 0 | TPM_PrintFour("\tclear stream in", symClear); |
2592 | 0 | TPM_PrintFour("\tdecrypted stream", symDec); |
2593 | 0 | } |
2594 | 0 | } |
2595 | 0 | if (rc == 0) { |
2596 | 0 | printf(" TPM_CryptoTest: Test 8 - Symmetric key with OFB mode\n"); |
2597 | | /* generate a key */ |
2598 | 0 | rc = TPM_Random(symKey, TPM_SECRET_SIZE); |
2599 | 0 | } |
2600 | | /* generate IV */ |
2601 | 0 | if (rc == 0) { |
2602 | 0 | rc = TPM_Random(pad, TPM_NONCE_SIZE); |
2603 | 0 | } |
2604 | | /* generate clear text */ |
2605 | 0 | if (rc == 0) { |
2606 | 0 | rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); |
2607 | 0 | } |
2608 | 0 | if (rc == 0) { |
2609 | 0 | rc = TPM_SymmetricKeyData_OfbCrypt(symEnc, /* output */ |
2610 | 0 | symClear, /* input */ |
2611 | 0 | TPM_AUTHDATA_SIZE, /* input */ |
2612 | 0 | symKey, /* in */ |
2613 | 0 | TPM_SECRET_SIZE, /* in */ |
2614 | 0 | pad, /* input */ |
2615 | 0 | TPM_NONCE_SIZE); /* input */ |
2616 | 0 | } |
2617 | 0 | if (rc == 0) { |
2618 | 0 | rc = TPM_SymmetricKeyData_OfbCrypt(symDec, /* output */ |
2619 | 0 | symEnc, /* input */ |
2620 | 0 | TPM_AUTHDATA_SIZE, /* input */ |
2621 | 0 | symKey, /* in */ |
2622 | 0 | TPM_SECRET_SIZE, /* in */ |
2623 | 0 | pad, /* input */ |
2624 | 0 | TPM_NONCE_SIZE); /* input */ |
2625 | 0 | } |
2626 | | /* symmetric compare */ |
2627 | 0 | if (rc == 0) { |
2628 | 0 | rc = TPM_Secret_Compare(symDec, symClear); |
2629 | 0 | if (rc != 0) { |
2630 | 0 | printf("TPM_CryptoTest: Error in test 8\n"); |
2631 | 0 | TPM_PrintFour("\tclear stream in", symClear); |
2632 | 0 | TPM_PrintFour("\tdecrypted stream", symDec); |
2633 | 0 | } |
2634 | 0 | } |
2635 | | /* RSA OAEP encrypt and decrypt */ |
2636 | 0 | if (rc == 0) { |
2637 | 0 | printf(" TPM_CryptoTest: Test 9 - RSA encrypt with OAEP padding\n"); |
2638 | | /* generate a key */ |
2639 | 0 | rc = TPM_RSAGenerateKeyPair(&n, /* public key - modulus */ |
2640 | 0 | &p, /* private key prime */ |
2641 | 0 | &q, /* private key prime */ |
2642 | 0 | &d, /* private key (private exponent) */ |
2643 | 0 | 2048, /* key size in bits */ |
2644 | 0 | tpm_default_rsa_exponent, /* public exponent as an array */ |
2645 | 0 | 3); |
2646 | 0 | } |
2647 | | /* encrypt */ |
2648 | 0 | if (rc == 0) { |
2649 | 0 | rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ |
2650 | 0 | sizeof(encrypt_data), /* size of encrypted data buffer */ |
2651 | 0 | TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ |
2652 | 0 | expect1, /* decrypted data */ |
2653 | 0 | sizeof(expect1), |
2654 | 0 | n, /* public modulus */ |
2655 | 0 | 2048/8, |
2656 | 0 | tpm_default_rsa_exponent, /* public exponent */ |
2657 | 0 | 3); |
2658 | 0 | } |
2659 | 0 | if (rc == 0) { |
2660 | 0 | rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ |
2661 | 0 | &actual_size, /* length of data put into |
2662 | | decrypt_data */ |
2663 | 0 | TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ |
2664 | 0 | TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ |
2665 | 0 | encrypt_data, /* encrypted data */ |
2666 | 0 | sizeof(encrypt_data), |
2667 | 0 | n, /* public modulus */ |
2668 | 0 | 2048/8, |
2669 | 0 | tpm_default_rsa_exponent, /* public exponent */ |
2670 | 0 | 3, |
2671 | 0 | d, /* private exponent */ |
2672 | 0 | 2048/8); |
2673 | 0 | } |
2674 | 0 | if (rc == 0) { |
2675 | 0 | if (actual_size != TPM_DIGEST_SIZE) { |
2676 | 0 | printf("TPM_CryptoTest: Error in test 9, expect length %u, actual length %u\n", |
2677 | 0 | TPM_DIGEST_SIZE, actual_size); |
2678 | 0 | rc = TPM_FAILEDSELFTEST; |
2679 | 0 | } |
2680 | 0 | } |
2681 | 0 | if (rc == 0) { |
2682 | 0 | not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); |
2683 | 0 | if (not_equal) { |
2684 | 0 | printf("TPM_CryptoTest: Error in test 9\n"); |
2685 | 0 | TPM_PrintFour("\tin ", expect1); |
2686 | 0 | TPM_PrintFour("\tout", actual); |
2687 | 0 | rc = TPM_FAILEDSELFTEST; |
2688 | 0 | } |
2689 | 0 | } |
2690 | | /* RSA PKCS1 pad, encrypt and decrypt */ |
2691 | 0 | if (rc == 0) { |
2692 | 0 | printf(" TPM_CryptoTest: Test 10 - RSA encrypt with PKCS padding\n"); |
2693 | | /* encrypt */ |
2694 | 0 | rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ |
2695 | 0 | sizeof(encrypt_data), /* size of encrypted data buffer */ |
2696 | 0 | TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ |
2697 | 0 | expect1, /* decrypted data */ |
2698 | 0 | sizeof(expect1), |
2699 | 0 | n, /* public modulus */ |
2700 | 0 | 2048/8, |
2701 | 0 | tpm_default_rsa_exponent, /* public exponent */ |
2702 | 0 | 3); |
2703 | 0 | } |
2704 | | /* decrypt */ |
2705 | 0 | if (rc == 0) { |
2706 | 0 | rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ |
2707 | 0 | &actual_size, /* length of data put into |
2708 | | decrypt_data */ |
2709 | 0 | TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ |
2710 | 0 | TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ |
2711 | 0 | encrypt_data, /* encrypted data */ |
2712 | 0 | sizeof(encrypt_data), |
2713 | 0 | n, /* public modulus */ |
2714 | 0 | 2048/8, |
2715 | 0 | tpm_default_rsa_exponent, /* public exponent */ |
2716 | 0 | 3, |
2717 | 0 | d, /* private exponent */ |
2718 | 0 | 2048/8); |
2719 | 0 | } |
2720 | | /* check length after padding removed */ |
2721 | 0 | if (rc == 0) { |
2722 | 0 | if (actual_size != TPM_DIGEST_SIZE) { |
2723 | 0 | printf("TPM_CryptoTest: Error in test 10, expect length %u, actual length %u\n", |
2724 | 0 | TPM_DIGEST_SIZE, actual_size); |
2725 | 0 | rc = TPM_FAILEDSELFTEST; |
2726 | 0 | } |
2727 | 0 | } |
2728 | | /* check data */ |
2729 | 0 | if (rc == 0) { |
2730 | 0 | not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); |
2731 | 0 | if (not_equal) { |
2732 | 0 | printf("TPM_CryptoTest: Error in test 10\n"); |
2733 | 0 | TPM_PrintFour("\tin ", expect1); |
2734 | 0 | TPM_PrintFour("\tout", actual); |
2735 | 0 | rc = TPM_FAILEDSELFTEST; |
2736 | 0 | } |
2737 | 0 | } |
2738 | | |
2739 | | // libtpms added begin |
2740 | |
|
2741 | 0 | if (rc == 0) { |
2742 | 0 | printf(" TPM_CryptoTest: Test 11a - RSA sign with PKCS1v15 padding\n"); |
2743 | 0 | rc = TPM_RSASign(signature, |
2744 | 0 | &actual_size, |
2745 | 0 | sizeof(signature), |
2746 | 0 | TPM_SS_RSASSAPKCS1v15_SHA1, |
2747 | 0 | expect1, |
2748 | 0 | sizeof(expect1), |
2749 | 0 | n, /* public modulus */ |
2750 | 0 | 2048/8, |
2751 | 0 | tpm_default_rsa_exponent, /* public exponent */ |
2752 | 0 | 3, |
2753 | 0 | d, /* private exponent */ |
2754 | 0 | 2048/8); |
2755 | 0 | } |
2756 | 0 | if (rc == 0) { |
2757 | 0 | rc = TPM_RSAVerify(signature, /* input signature buffer */ |
2758 | 0 | sizeof(signature), /* input, size of signature buffer */ |
2759 | 0 | TPM_SS_RSASSAPKCS1v15_SHA1, /* input, type of signature */ |
2760 | 0 | expect1, /* message */ |
2761 | 0 | sizeof(expect1), /* message size */ |
2762 | 0 | n, /* public modulus */ |
2763 | 0 | 2048/8, |
2764 | 0 | tpm_default_rsa_exponent,/* public exponent */ |
2765 | 0 | 3); |
2766 | 0 | } |
2767 | |
|
2768 | | #if 0 |
2769 | | /* Verification with TPM_SS_RSASSAPKCS1v15_DER is not supported */ |
2770 | | if (rc == 0) { |
2771 | | printf(" TPM_CryptoTest: Test 11b - RSA sign with PKCS1v15_DER padding\n"); |
2772 | | rc = TPM_RSASign(signature, |
2773 | | &actual_size, |
2774 | | sizeof(signature), |
2775 | | TPM_SS_RSASSAPKCS1v15_DER, |
2776 | | expect1, |
2777 | | sizeof(expect1), |
2778 | | n, /* public modulus */ |
2779 | | 2048/8, |
2780 | | tpm_default_rsa_exponent, /* public exponent */ |
2781 | | 3, |
2782 | | d, /* private exponent */ |
2783 | | 2048/8); |
2784 | | } |
2785 | | if (rc == 0) { |
2786 | | rc = TPM_RSAVerify(signature, /* input signature buffer */ |
2787 | | sizeof(signature), /* input, size of signature buffer */ |
2788 | | TPM_SS_RSASSAPKCS1v15_DER, /* input, type of signature */ |
2789 | | expect1, /* message */ |
2790 | | sizeof(expect1), /* message size */ |
2791 | | n, /* public modulus */ |
2792 | | 2048/8, |
2793 | | tpm_default_rsa_exponent,/* public exponent */ |
2794 | | 3); |
2795 | | } |
2796 | | #endif // libtpms added end |
2797 | | |
2798 | | /* run library specific self tests as required */ |
2799 | 0 | if (rc == 0) { |
2800 | 0 | rc = TPM_Crypto_TestSpecific(); |
2801 | 0 | } |
2802 | 0 | if (rc != 0) { |
2803 | 0 | rc = TPM_FAILEDSELFTEST; |
2804 | 0 | } |
2805 | 0 | free(encStream); /* @1 */ |
2806 | 0 | free(decStream); /* @2 */ |
2807 | 0 | free(n); /* @3 */ |
2808 | 0 | free(p); /* @4 */ |
2809 | 0 | free(q); /* @5 */ |
2810 | 0 | free(d); /* @6 */ |
2811 | 0 | TPM_SymmetricKeyData_Free(&tpm_symmetric_key_data); /* @7 */ |
2812 | 0 | return rc; |
2813 | 0 | } |
2814 | | |
2815 | | /* 13.5 TPM_Sign rev 111 |
2816 | | |
2817 | | The Sign command signs data and returns the resulting digital signature. |
2818 | | |
2819 | | The TPM does not allow TPM_Sign with a TPM_KEY_IDENTITY (AIK) because TPM_Sign can sign arbitrary |
2820 | | data and could be used to fake a quote. (This could have been relaxed to allow TPM_Sign with an |
2821 | | AIK if the signature scheme is _INFO For an _INFO key, the metadata prevents TPM_Sign from faking |
2822 | | a quote.) |
2823 | | |
2824 | | The TPM MUST support all values of areaToSignSize that are legal for the defined signature scheme |
2825 | | and key size. The maximum value of areaToSignSize is determined by the defined signature scheme |
2826 | | and key size. |
2827 | | |
2828 | | In the case of PKCS1v15_SHA1 the areaToSignSize MUST be TPM_DIGEST (the hash size of a sha1 |
2829 | | operation - see 8.5.1 TPM_SS_RSASSAPKCS1v15_SHA1). In the case of PKCS1v15_DER the maximum size |
2830 | | of areaToSign is k - 11 octets, where k is limited by the key size (see 8.5.2 |
2831 | | TPM_SS_RSASSAPKCS1v15_DER). |
2832 | | */ |
2833 | | |
2834 | | TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state, |
2835 | | TPM_STORE_BUFFER *response, |
2836 | | TPM_TAG tag, |
2837 | | uint32_t paramSize, |
2838 | | TPM_COMMAND_CODE ordinal, |
2839 | | unsigned char *command, |
2840 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
2841 | 0 | { |
2842 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
2843 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
2844 | | |
2845 | | /* input parameters */ |
2846 | 0 | TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform |
2847 | | digital signatures. */ |
2848 | 0 | TPM_SIZED_BUFFER areaToSign; /* The value to sign */ |
2849 | 0 | TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization |
2850 | | */ |
2851 | 0 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ |
2852 | 0 | TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ |
2853 | 0 | TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the use of |
2854 | | keyHandle. HMAC key: key.usageAuth */ |
2855 | | /* processing parameters */ |
2856 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
2857 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
2858 | 0 | TPM_DIGEST inParamDigest; |
2859 | 0 | TPM_BOOL auditStatus ; /* audit the ordinal */ |
2860 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
2861 | 0 | TPM_BOOL authHandleValid = FALSE; |
2862 | 0 | TPM_SECRET *hmacKey; |
2863 | 0 | TPM_KEY *key = NULL; /* the key specified by keyHandle */ |
2864 | 0 | TPM_RSA_KEY_PARMS *rsa_key_parms; /* for key */ |
2865 | 0 | TPM_BOOL parentPCRStatus; |
2866 | 0 | TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ |
2867 | 0 | TPM_SECRET *keyUsageAuth; |
2868 | 0 | TPM_SIGN_INFO tpm_sign_info; |
2869 | 0 | const unsigned char *S1_data; /* data to be signed */ |
2870 | 0 | uint32_t S1_size; |
2871 | 0 | TPM_DIGEST infoDigest; /* TPM_SIGN_INFO structure digest */ |
2872 | 0 | TPM_STORE_BUFFER sbuffer; |
2873 | | |
2874 | | /* output parameters */ |
2875 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
2876 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
2877 | 0 | TPM_DIGEST outParamDigest; |
2878 | 0 | TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ |
2879 | |
|
2880 | 0 | printf("TPM_Process_Sign: Ordinal Entry\n"); |
2881 | 0 | TPM_SizedBuffer_Init(&areaToSign); /* freed @1 */ |
2882 | 0 | TPM_SignInfo_Init(&tpm_sign_info); /* freed @2 */ |
2883 | 0 | TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ |
2884 | 0 | TPM_SizedBuffer_Init(&sig); /* freed @4 */ |
2885 | | /* |
2886 | | get inputs |
2887 | | */ |
2888 | | /* get keyHandle parameter */ |
2889 | 0 | if (returnCode == TPM_SUCCESS) { |
2890 | 0 | returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); |
2891 | 0 | } |
2892 | | /* save the starting point of inParam's for authorization and auditing */ |
2893 | 0 | inParamStart = command; |
2894 | 0 | if (returnCode == TPM_SUCCESS) { |
2895 | 0 | printf("TPM_Process_Sign: keyHandle %08x\n", keyHandle); |
2896 | | /* get areaToSignSize and areaToSign parameters */ |
2897 | 0 | returnCode = TPM_SizedBuffer_Load(&areaToSign, &command, ¶mSize); /* freed @1 */ |
2898 | 0 | } |
2899 | 0 | if (returnCode == TPM_SUCCESS) { |
2900 | 0 | printf("TPM_Process_Sign: Signing %u bytes\n", areaToSign.size); |
2901 | 0 | } |
2902 | | /* save the ending point of inParam's for authorization and auditing */ |
2903 | 0 | inParamEnd = command; |
2904 | | /* digest the input parameters */ |
2905 | 0 | if (returnCode == TPM_SUCCESS) { |
2906 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
2907 | 0 | &auditStatus, /* output */ |
2908 | 0 | &transportEncrypt, /* output */ |
2909 | 0 | tpm_state, |
2910 | 0 | tag, |
2911 | 0 | ordinal, |
2912 | 0 | inParamStart, |
2913 | 0 | inParamEnd, |
2914 | 0 | transportInternal); |
2915 | 0 | } |
2916 | | /* check state */ |
2917 | 0 | if (returnCode == TPM_SUCCESS) { |
2918 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); |
2919 | 0 | } |
2920 | | /* check tag */ |
2921 | 0 | if (returnCode == TPM_SUCCESS) { |
2922 | 0 | returnCode = TPM_CheckRequestTag10(tag); |
2923 | 0 | } |
2924 | | /* get the optional 'below the line' authorization parameters */ |
2925 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
2926 | 0 | returnCode = TPM_AuthParams_Get(&authHandle, |
2927 | 0 | &authHandleValid, |
2928 | 0 | nonceOdd, |
2929 | 0 | &continueAuthSession, |
2930 | 0 | privAuth, |
2931 | 0 | &command, ¶mSize); |
2932 | 0 | } |
2933 | 0 | if (returnCode == TPM_SUCCESS) { |
2934 | 0 | if (paramSize != 0) { |
2935 | 0 | printf("TPM_Process_Sign: Error, command has %u extra bytes\n", paramSize); |
2936 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
2937 | 0 | } |
2938 | 0 | } |
2939 | | /* do not terminate sessions if the command did not parse correctly */ |
2940 | 0 | if (returnCode != TPM_SUCCESS) { |
2941 | 0 | authHandleValid = FALSE; |
2942 | 0 | } |
2943 | | /* |
2944 | | Processing |
2945 | | */ |
2946 | | /* get the key corresponding to the keyHandle parameter */ |
2947 | 0 | if (returnCode == TPM_SUCCESS) { |
2948 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, |
2949 | 0 | FALSE, /* not r/o, used to sign */ |
2950 | 0 | FALSE, /* do not ignore PCRs */ |
2951 | 0 | FALSE); /* cannot use EK */ |
2952 | 0 | } |
2953 | | /* check TPM_AUTH_DATA_USAGE authDataUsage */ |
2954 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { |
2955 | 0 | if (key->authDataUsage != TPM_AUTH_NEVER) { |
2956 | 0 | printf("TPM_Process_Sign: Error, authorization required\n"); |
2957 | 0 | returnCode = TPM_AUTHFAIL; |
2958 | 0 | } |
2959 | 0 | } |
2960 | | /* get keyHandle -> usageAuth */ |
2961 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
2962 | 0 | returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); |
2963 | 0 | } |
2964 | | /* get the session data */ |
2965 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
2966 | 0 | returnCode = TPM_AuthSessions_GetData(&auth_session_data, |
2967 | 0 | &hmacKey, |
2968 | 0 | tpm_state, |
2969 | 0 | authHandle, |
2970 | 0 | TPM_PID_NONE, |
2971 | 0 | TPM_ET_KEYHANDLE, |
2972 | 0 | ordinal, |
2973 | 0 | key, |
2974 | 0 | keyUsageAuth, /* OIAP */ |
2975 | 0 | key->tpm_store_asymkey->pubDataDigest); /* OSAP */ |
2976 | 0 | } |
2977 | | /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */ |
2978 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
2979 | 0 | returnCode = TPM_Authdata_Check(tpm_state, |
2980 | 0 | *hmacKey, /* HMAC key */ |
2981 | 0 | inParamDigest, |
2982 | 0 | auth_session_data, /* authorization session */ |
2983 | 0 | nonceOdd, /* Nonce generated by system |
2984 | | associated with authHandle */ |
2985 | 0 | continueAuthSession, |
2986 | 0 | privAuth); /* Authorization digest for input */ |
2987 | 0 | } |
2988 | | /* 2. If the areaToSignSize is 0 the TPM returns TPM_BAD_PARAMETER. */ |
2989 | 0 | if (returnCode == TPM_SUCCESS) { |
2990 | 0 | if (areaToSign.size == 0) { |
2991 | 0 | printf("TPM_Process_Sign: Error, areaToSignSize is 0\n"); |
2992 | 0 | returnCode = TPM_BAD_PARAMETER; |
2993 | 0 | } |
2994 | 0 | } |
2995 | | /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, if not return |
2996 | | the error code TPM_INVALID_KEYUSAGE */ |
2997 | 0 | if (returnCode == TPM_SUCCESS) { |
2998 | 0 | if ((key->keyUsage != TPM_KEY_SIGNING) && ((key->keyUsage) != TPM_KEY_LEGACY)) { |
2999 | 0 | printf("TPM_Process_Sign: Error, keyUsage %04hx is invalid\n", key->keyUsage); |
3000 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
3001 | 0 | } |
3002 | 0 | } |
3003 | | /* 4. The TPM verifies that the signature scheme and key size can properly sign the areaToSign |
3004 | | parameter. NOTE Done in 5. - 7.*/ |
3005 | | /* get key -> TPM_RSA_KEY_PARMS */ |
3006 | 0 | if (returnCode == TPM_SUCCESS) { |
3007 | 0 | returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, |
3008 | 0 | &(key->algorithmParms)); |
3009 | 0 | } |
3010 | 0 | if (returnCode == TPM_SUCCESS) { |
3011 | | /* 5. If signature scheme is TPM_SS_RSASSAPKCS1v15_SHA1 then */ |
3012 | 0 | if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) { |
3013 | 0 | printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1\n"); |
3014 | | /* a. Validate that areaToSignSize is 20 return TPM_BAD_PARAMETER on error */ |
3015 | 0 | if (returnCode == TPM_SUCCESS) { |
3016 | 0 | if (areaToSign.size != TPM_DIGEST_SIZE) { |
3017 | 0 | printf("TPM_Process_Sign: Error, areaToSignSize %d should be %u\n", |
3018 | 0 | areaToSign.size, TPM_DIGEST_SIZE); |
3019 | 0 | returnCode = TPM_BAD_PARAMETER; |
3020 | 0 | } |
3021 | 0 | } |
3022 | | /* b. Set S1 to areaToSign */ |
3023 | 0 | if (returnCode == TPM_SUCCESS) { |
3024 | 0 | S1_size = areaToSign.size; |
3025 | 0 | S1_data = areaToSign.buffer; |
3026 | 0 | } |
3027 | 0 | } |
3028 | | /* 6. Else if signature scheme is TPM_SS_RSASSAPKCS1v15_DER then */ |
3029 | 0 | else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_DER) { |
3030 | 0 | printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_DER\n"); |
3031 | | /* a. Validate that areaToSignSize is at least 11 bytes less than the key size, return |
3032 | | TPM_BAD_PARAMETER on error */ |
3033 | 0 | if (returnCode == TPM_SUCCESS) { |
3034 | 0 | if (areaToSign.size > (((rsa_key_parms->keyLength)/CHAR_BIT) - 11)) { |
3035 | 0 | printf("TPM_Process_Sign: Error, areaToSignSize %d should be 11-%u\n", |
3036 | 0 | areaToSign.size, ((rsa_key_parms->keyLength)/CHAR_BIT)); |
3037 | 0 | returnCode = TPM_BAD_PARAMETER; |
3038 | 0 | } |
3039 | 0 | } |
3040 | | /* b. Set S1 to areaToSign */ |
3041 | 0 | if (returnCode == TPM_SUCCESS) { |
3042 | 0 | S1_size = areaToSign.size; |
3043 | 0 | S1_data = areaToSign.buffer; |
3044 | 0 | } |
3045 | 0 | } |
3046 | | /* 7. else if signature scheme is TPM_SS_RSASSAPKCS1v15_INFO then */ |
3047 | 0 | else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) { |
3048 | 0 | printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_INFO\n"); |
3049 | 0 | if (returnCode == TPM_SUCCESS) { |
3050 | | /* a. Create S2 a TPM_SIGN_INFO structure */ |
3051 | | /* NOTE: Done by TPM_SignInfo_Init() */ |
3052 | | /* b. Set S2 -> fixed to "SIGN" */ |
3053 | 0 | memcpy(tpm_sign_info.fixed, "SIGN", TPM_SIGN_INFO_FIXED_SIZE); |
3054 | | /* c.i. If nonceOdd is not present due to an unauthorized command return |
3055 | | TPM_BAD_PARAMETER */ |
3056 | 0 | if (tag == TPM_TAG_RQU_COMMAND) { |
3057 | 0 | printf("TPM_Process_Sign: Error, TPM_SS_RSASSAPKCS1v15_INFO and no auth\n"); |
3058 | 0 | returnCode = TPM_BAD_PARAMETER; |
3059 | 0 | } |
3060 | 0 | } |
3061 | 0 | if (returnCode == TPM_SUCCESS) { |
3062 | | /* c. Set S2 -> replay to nonceOdd */ |
3063 | 0 | TPM_Nonce_Copy(tpm_sign_info.replay, nonceOdd); |
3064 | | /* d. Set S2 -> dataLen to areaToSignSize */ |
3065 | | /* e. Set S2 -> data to areaToSign */ |
3066 | 0 | returnCode = TPM_SizedBuffer_Copy(&(tpm_sign_info.data), &areaToSign); |
3067 | 0 | } |
3068 | | /* f. Set S1 to the SHA-1(S2) */ |
3069 | 0 | if (returnCode == TPM_SUCCESS) { |
3070 | 0 | returnCode = TPM_SHA1_GenerateStructure(infoDigest, |
3071 | 0 | &tpm_sign_info, |
3072 | 0 | (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); |
3073 | 0 | S1_size = TPM_DIGEST_SIZE; |
3074 | 0 | S1_data = infoDigest; |
3075 | 0 | } |
3076 | 0 | } |
3077 | | /* 8. Else return TPM_INVALID_KEYUSAGE */ |
3078 | 0 | else { |
3079 | 0 | printf("TPM_Process_Sign: Error, sigScheme %04hx\n", key->algorithmParms.sigScheme); |
3080 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
3081 | 0 | } |
3082 | 0 | } |
3083 | | /* 9. The TPM computes the signature, sig, using the key referenced by keyHandle using S1 as the |
3084 | | value to sign */ |
3085 | 0 | if (returnCode == TPM_SUCCESS) { |
3086 | 0 | TPM_PrintAll("TPM_Process_Sign: Digest to sign", S1_data, S1_size); |
3087 | 0 | returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ |
3088 | 0 | S1_data, /* message */ |
3089 | 0 | S1_size, /* message size */ |
3090 | 0 | key); /* input, signing key */ |
3091 | 0 | } |
3092 | | /* |
3093 | | response |
3094 | | */ |
3095 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3096 | 0 | if (rcf == 0) { |
3097 | 0 | printf("TPM_Process_Sign: Ordinal returnCode %08x %u\n", |
3098 | 0 | returnCode, returnCode); |
3099 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3100 | 0 | } |
3101 | | /* success response, append the rest of the parameters. */ |
3102 | 0 | if (rcf == 0) { |
3103 | 0 | if (returnCode == TPM_SUCCESS) { |
3104 | | /* checkpoint the beginning of the outParam's */ |
3105 | 0 | outParamStart = response->buffer_current - response->buffer; |
3106 | | /* 10. Return the computed signature in Sig */ |
3107 | 0 | returnCode = TPM_SizedBuffer_Store(response, &sig); |
3108 | | /* checkpoint the end of the outParam's */ |
3109 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3110 | 0 | } |
3111 | | /* digest the above the line output parameters */ |
3112 | 0 | if (returnCode == TPM_SUCCESS) { |
3113 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3114 | 0 | auditStatus, /* input audit status */ |
3115 | 0 | transportEncrypt, |
3116 | 0 | tag, |
3117 | 0 | returnCode, |
3118 | 0 | ordinal, /* command ordinal */ |
3119 | 0 | response->buffer + outParamStart, /* start */ |
3120 | 0 | outParamEnd - outParamStart); /* length */ |
3121 | 0 | } |
3122 | | /* calculate and set the below the line parameters */ |
3123 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
3124 | 0 | returnCode = TPM_AuthParams_Set(response, |
3125 | 0 | *hmacKey, /* owner HMAC key */ |
3126 | 0 | auth_session_data, |
3127 | 0 | outParamDigest, |
3128 | 0 | nonceOdd, |
3129 | 0 | continueAuthSession); |
3130 | 0 | } |
3131 | | /* audit if required */ |
3132 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3133 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3134 | 0 | transportEncrypt, |
3135 | 0 | inParamDigest, |
3136 | 0 | outParamDigest, |
3137 | 0 | ordinal); |
3138 | 0 | } |
3139 | | /* adjust the initial response */ |
3140 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3141 | 0 | } |
3142 | | /* if there was an error, or continueAuthSession is FALSE, terminate the session */ |
3143 | 0 | if (((rcf != 0) || |
3144 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
3145 | 0 | !continueAuthSession) && |
3146 | 0 | authHandleValid) { |
3147 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); |
3148 | 0 | } |
3149 | | /* |
3150 | | cleanup |
3151 | | */ |
3152 | 0 | TPM_SizedBuffer_Delete(&areaToSign); /* @1 */ |
3153 | 0 | TPM_SignInfo_Delete(&tpm_sign_info); /* @2 */ |
3154 | 0 | TPM_Sbuffer_Delete(&sbuffer); /* @3 */ |
3155 | 0 | TPM_SizedBuffer_Delete(&sig); /* @4 */ |
3156 | 0 | return rcf; |
3157 | 0 | } |
3158 | | |
3159 | | /* 13.1 TPM_SHA1Start rev 96 |
3160 | | |
3161 | | This capability starts the process of calculating a SHA-1 digest. |
3162 | | |
3163 | | The exposure of the SHA-1 processing is a convenience to platforms in a mode that do not have |
3164 | | sufficient memory to perform SHA-1 themselves. As such the use of SHA-1 is restrictive on the |
3165 | | TPM. |
3166 | | |
3167 | | The TPM may not allow any other types of processing during the execution of a SHA-1 |
3168 | | session. There is only one SHA-1 session active on a TPM. The exclusivity of a SHA-1 |
3169 | | context is due to the relatively large volatile buffer it requires in order to hold the |
3170 | | intermediate results between the SHA-1 context commands. This buffer can be in |
3171 | | contradiction to other command needs. |
3172 | | |
3173 | | After the execution of SHA1Start, and prior to SHA1End, the receipt of any command other than |
3174 | | SHA1Update will cause the invalidation of the SHA-1 session. |
3175 | | */ |
3176 | | |
3177 | | TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state, |
3178 | | TPM_STORE_BUFFER *response, |
3179 | | TPM_TAG tag, |
3180 | | uint32_t paramSize, |
3181 | | TPM_COMMAND_CODE ordinal, |
3182 | | unsigned char *command, |
3183 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3184 | 0 | { |
3185 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3186 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3187 | | |
3188 | | /* input parameters - none */ |
3189 | | |
3190 | | /* processing parameters */ |
3191 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3192 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3193 | 0 | TPM_DIGEST inParamDigest; |
3194 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3195 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3196 | | |
3197 | | /* output parameters */ |
3198 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3199 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3200 | 0 | TPM_DIGEST outParamDigest; |
3201 | 0 | uint32_t maxNumBytes = TPM_SHA1_MAXNUMBYTES; /* Maximum number of bytes that can be sent |
3202 | | to TPM_SHA1Update. Must be a multiple of |
3203 | | 64 bytes. */ |
3204 | |
|
3205 | 0 | printf("TPM_Process_SHA1Start: Ordinal Entry\n"); |
3206 | | /* |
3207 | | get inputs |
3208 | | */ |
3209 | | /* save the starting point of inParam's for authorization and auditing */ |
3210 | 0 | inParamStart = command; |
3211 | | /* save the ending point of inParam's for authorization and auditing */ |
3212 | 0 | inParamEnd = command; |
3213 | | /* digest the input parameters */ |
3214 | 0 | if (returnCode == TPM_SUCCESS) { |
3215 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3216 | 0 | &auditStatus, /* output */ |
3217 | 0 | &transportEncrypt, /* output */ |
3218 | 0 | tpm_state, |
3219 | 0 | tag, |
3220 | 0 | ordinal, |
3221 | 0 | inParamStart, |
3222 | 0 | inParamEnd, |
3223 | 0 | transportInternal); |
3224 | 0 | } |
3225 | | /* check state */ |
3226 | 0 | if (returnCode == TPM_SUCCESS) { |
3227 | 0 | returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | |
3228 | 0 | TPM_CHECK_NO_LOCKOUT)); |
3229 | 0 | } |
3230 | | /* check tag */ |
3231 | 0 | if (returnCode == TPM_SUCCESS) { |
3232 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3233 | 0 | } |
3234 | 0 | if (returnCode == TPM_SUCCESS) { |
3235 | 0 | if (paramSize != 0) { |
3236 | 0 | printf("TPM_Process_SHA1Start: Error, command has %u extra bytes\n", |
3237 | 0 | paramSize); |
3238 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
3239 | 0 | } |
3240 | 0 | } |
3241 | | /* |
3242 | | Processing |
3243 | | */ |
3244 | | /* This capability prepares the TPM for a subsequent TPM_SHA1Update, TPM_SHA1Complete or |
3245 | | TPM_SHA1CompleteExtend command. The capability SHALL open a thread that calculates a SHA-1 |
3246 | | digest. |
3247 | | */ |
3248 | 0 | if (returnCode == TPM_SUCCESS) { |
3249 | 0 | if (transportInternal == NULL) { |
3250 | 0 | tpm_state->transportHandle = 0; /* SHA-1 thread not within transport */ |
3251 | 0 | } |
3252 | 0 | else { |
3253 | 0 | tpm_state->transportHandle = transportInternal->transHandle; /* SHA-1 thread within |
3254 | | transport */ |
3255 | 0 | } |
3256 | 0 | returnCode = TPM_SHA1InitCmd(&(tpm_state->sha1_context)); |
3257 | 0 | } |
3258 | | /* |
3259 | | response |
3260 | | */ |
3261 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3262 | 0 | if (rcf == 0) { |
3263 | 0 | printf("TPM_Process_SHA1Start: Ordinal returnCode %08x %u\n", |
3264 | 0 | returnCode, returnCode); |
3265 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3266 | 0 | } |
3267 | | /* success response, append the rest of the parameters. */ |
3268 | 0 | if (rcf == 0) { |
3269 | 0 | if (returnCode == TPM_SUCCESS) { |
3270 | | /* checkpoint the beginning of the outParam's */ |
3271 | 0 | outParamStart = response->buffer_current - response->buffer; |
3272 | | /* append maxNumBytes */ |
3273 | 0 | returnCode = TPM_Sbuffer_Append32(response, maxNumBytes); |
3274 | | /* checkpoint the end of the outParam's */ |
3275 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3276 | 0 | } |
3277 | | /* digest the above the line output parameters */ |
3278 | 0 | if (returnCode == TPM_SUCCESS) { |
3279 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3280 | 0 | auditStatus, /* input audit status */ |
3281 | 0 | transportEncrypt, |
3282 | 0 | tag, |
3283 | 0 | returnCode, |
3284 | 0 | ordinal, /* command ordinal */ |
3285 | 0 | response->buffer + outParamStart, /* start */ |
3286 | 0 | outParamEnd - outParamStart); /* length */ |
3287 | 0 | } |
3288 | | /* audit if required */ |
3289 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3290 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3291 | 0 | transportEncrypt, |
3292 | 0 | inParamDigest, |
3293 | 0 | outParamDigest, |
3294 | 0 | ordinal); |
3295 | 0 | } |
3296 | | /* adjust the initial response */ |
3297 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3298 | 0 | } |
3299 | 0 | return rcf; |
3300 | 0 | } |
3301 | | |
3302 | | /* 13.2 TPM_SHA1Update rev 114 |
3303 | | |
3304 | | This capability inputs complete blocks of data into a pending SHA-1 digest. At the end of the |
3305 | | process, the digest remains pending. |
3306 | | */ |
3307 | | |
3308 | | TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state, |
3309 | | TPM_STORE_BUFFER *response, |
3310 | | TPM_TAG tag, |
3311 | | uint32_t paramSize, |
3312 | | TPM_COMMAND_CODE ordinal, |
3313 | | unsigned char *command, |
3314 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3315 | 0 | { |
3316 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3317 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3318 | | |
3319 | | /* input parameters */ |
3320 | 0 | TPM_SIZED_BUFFER hashData; /* Bytes to be hashed */ |
3321 | | |
3322 | | /* processing parameters */ |
3323 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3324 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3325 | 0 | TPM_DIGEST inParamDigest; |
3326 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3327 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3328 | | |
3329 | | /* output parameters */ |
3330 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3331 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3332 | 0 | TPM_DIGEST outParamDigest; |
3333 | |
|
3334 | 0 | printf("TPM_Process_SHA1Update: Ordinal Entry\n"); |
3335 | 0 | TPM_SizedBuffer_Init(&hashData); /* freed @1 */ |
3336 | | /* |
3337 | | get inputs |
3338 | | */ |
3339 | | /* save the starting point of inParam's for authorization and auditing */ |
3340 | 0 | inParamStart = command; |
3341 | | /* load hashData */ |
3342 | 0 | if (returnCode == TPM_SUCCESS) { |
3343 | 0 | returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); |
3344 | 0 | } |
3345 | | /* save the ending point of inParam's for authorization and auditing */ |
3346 | 0 | inParamEnd = command; |
3347 | | /* digest the input parameters */ |
3348 | 0 | if (returnCode == TPM_SUCCESS) { |
3349 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3350 | 0 | &auditStatus, /* output */ |
3351 | 0 | &transportEncrypt, /* output */ |
3352 | 0 | tpm_state, |
3353 | 0 | tag, |
3354 | 0 | ordinal, |
3355 | 0 | inParamStart, |
3356 | 0 | inParamEnd, |
3357 | 0 | transportInternal); |
3358 | 0 | } |
3359 | | /* check state */ |
3360 | 0 | if (returnCode == TPM_SUCCESS) { |
3361 | 0 | returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | |
3362 | 0 | TPM_CHECK_NO_LOCKOUT)); |
3363 | 0 | } |
3364 | | /* check tag */ |
3365 | 0 | if (returnCode == TPM_SUCCESS) { |
3366 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3367 | 0 | } |
3368 | 0 | if (returnCode == TPM_SUCCESS) { |
3369 | 0 | if (paramSize != 0) { |
3370 | 0 | printf("TPM_Process_SHA1Update: Error, command has %u extra bytes\n", |
3371 | 0 | paramSize); |
3372 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
3373 | 0 | } |
3374 | 0 | } |
3375 | | /* |
3376 | | Processing |
3377 | | */ |
3378 | | /* This command SHALL incorporate complete blocks of data into the digest of an existing SHA-1 |
3379 | | thread. Only integral numbers of complete blocks (64 bytes each) can be processed. |
3380 | | */ |
3381 | | /* 1. If there is no existing SHA-1 thread, return TPM_SHA_THREAD */ |
3382 | 0 | if (returnCode == TPM_SUCCESS) { |
3383 | 0 | if (tpm_state->sha1_context == NULL) { |
3384 | 0 | printf("TPM_Process_SHA1Update: Error, no existing SHA1 thread\n"); |
3385 | 0 | returnCode = TPM_SHA_THREAD; |
3386 | 0 | } |
3387 | 0 | } |
3388 | | /* 2. If numBytes is not a multiple of 64 */ |
3389 | 0 | if (returnCode == TPM_SUCCESS) { |
3390 | 0 | printf("TPM_Process_SHA1Update: numBytes %u bytes\n", hashData.size); |
3391 | 0 | if ((hashData.size % 64) != 0) { |
3392 | 0 | printf("TPM_Process_SHA1Update: Error, numBytes not integral number of blocks\n"); |
3393 | | /* a. Return TPM_SHA_ERROR */ |
3394 | 0 | returnCode = TPM_SHA_ERROR; |
3395 | | /* b. The TPM MAY terminate the SHA-1 thread */ |
3396 | 0 | TPM_SHA1Delete(&(tpm_state->sha1_context)); |
3397 | 0 | } |
3398 | 0 | } |
3399 | | /* 3. If numBytes is greater than maxNumBytes returned by TPM_SHA1Start */ |
3400 | 0 | if (returnCode == TPM_SUCCESS) { |
3401 | 0 | if (hashData.size > TPM_SHA1_MAXNUMBYTES) { |
3402 | | /* a. Return TPM_SHA_ERROR */ |
3403 | 0 | returnCode = TPM_SHA_ERROR; |
3404 | | /* b. The TPM MAY terminate the SHA-1 thread */ |
3405 | 0 | TPM_SHA1Delete(&(tpm_state->sha1_context)); |
3406 | 0 | } |
3407 | 0 | } |
3408 | | /* 4. Incorporate hashData into the digest of the existing SHA-1 thread. */ |
3409 | 0 | if (returnCode == TPM_SUCCESS) { |
3410 | 0 | returnCode = TPM_SHA1UpdateCmd(tpm_state->sha1_context, hashData.buffer, hashData.size); |
3411 | 0 | } |
3412 | | /* |
3413 | | response |
3414 | | */ |
3415 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3416 | 0 | if (rcf == 0) { |
3417 | 0 | printf("TPM_Process_SHA1Update: Ordinal returnCode %08x %u\n", |
3418 | 0 | returnCode, returnCode); |
3419 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3420 | 0 | } |
3421 | | /* success response, append the rest of the parameters. */ |
3422 | 0 | if (rcf == 0) { |
3423 | 0 | if (returnCode == TPM_SUCCESS) { |
3424 | | /* checkpoint the beginning of the outParam's */ |
3425 | 0 | outParamStart = response->buffer_current - response->buffer; |
3426 | | /* checkpoint the end of the outParam's */ |
3427 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3428 | 0 | } |
3429 | | /* digest the above the line output parameters */ |
3430 | 0 | if (returnCode == TPM_SUCCESS) { |
3431 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3432 | 0 | auditStatus, /* input audit status */ |
3433 | 0 | transportEncrypt, |
3434 | 0 | tag, |
3435 | 0 | returnCode, |
3436 | 0 | ordinal, /* command ordinal */ |
3437 | 0 | response->buffer + outParamStart, /* start */ |
3438 | 0 | outParamEnd - outParamStart); /* length */ |
3439 | 0 | } |
3440 | | /* audit if required */ |
3441 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3442 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3443 | 0 | transportEncrypt, |
3444 | 0 | inParamDigest, |
3445 | 0 | outParamDigest, |
3446 | 0 | ordinal); |
3447 | 0 | } |
3448 | | /* adjust the initial response */ |
3449 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3450 | 0 | } |
3451 | | /* |
3452 | | cleanup |
3453 | | */ |
3454 | 0 | TPM_SizedBuffer_Delete(&hashData); /* @1 */ |
3455 | 0 | return rcf; |
3456 | 0 | } |
3457 | | |
3458 | | /* 13.3 TPM_SHA1Complete rev 87 |
3459 | | |
3460 | | This capability terminates a pending SHA-1 calculation. |
3461 | | */ |
3462 | | |
3463 | | TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state, |
3464 | | TPM_STORE_BUFFER *response, |
3465 | | TPM_TAG tag, |
3466 | | uint32_t paramSize, |
3467 | | TPM_COMMAND_CODE ordinal, |
3468 | | unsigned char *command, |
3469 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3470 | 0 | { |
3471 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3472 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3473 | | |
3474 | | /* input parameters */ |
3475 | 0 | TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ |
3476 | | |
3477 | | /* processing parameters */ |
3478 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3479 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3480 | 0 | TPM_DIGEST inParamDigest; |
3481 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3482 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3483 | | |
3484 | | /* output parameters */ |
3485 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3486 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3487 | 0 | TPM_DIGEST outParamDigest; |
3488 | 0 | TPM_DIGEST hashValue; /* The output of the SHA-1 hash. */ |
3489 | 0 | TPM_SizedBuffer_Init(&hashData); /* freed @1 */ |
3490 | |
|
3491 | 0 | printf("TPM_Process_SHA1Complete: Ordinal Entry\n"); |
3492 | | /* |
3493 | | get inputs |
3494 | | */ |
3495 | | /* save the starting point of inParam's for authorization and auditing */ |
3496 | 0 | inParamStart = command; |
3497 | | /* load hashData */ |
3498 | 0 | if (returnCode == TPM_SUCCESS) { |
3499 | 0 | returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); |
3500 | 0 | } |
3501 | | /* save the ending point of inParam's for authorization and auditing */ |
3502 | 0 | inParamEnd = command; |
3503 | | /* digest the input parameters */ |
3504 | 0 | if (returnCode == TPM_SUCCESS) { |
3505 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3506 | 0 | &auditStatus, /* output */ |
3507 | 0 | &transportEncrypt, /* output */ |
3508 | 0 | tpm_state, |
3509 | 0 | tag, |
3510 | 0 | ordinal, |
3511 | 0 | inParamStart, |
3512 | 0 | inParamEnd, |
3513 | 0 | transportInternal); |
3514 | 0 | } |
3515 | | /* check state */ |
3516 | 0 | if (returnCode == TPM_SUCCESS) { |
3517 | 0 | returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | |
3518 | 0 | TPM_CHECK_NO_LOCKOUT)); |
3519 | 0 | } |
3520 | | /* check tag */ |
3521 | 0 | if (returnCode == TPM_SUCCESS) { |
3522 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3523 | 0 | } |
3524 | 0 | if (returnCode == TPM_SUCCESS) { |
3525 | 0 | if (paramSize != 0) { |
3526 | 0 | printf("TPM_Process_SHA1Complete: Error, command has %u extra bytes\n", |
3527 | 0 | paramSize); |
3528 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
3529 | 0 | } |
3530 | 0 | } |
3531 | | /* |
3532 | | Processing |
3533 | | */ |
3534 | | /* This command SHALL incorporate a partial or complete block of data into the digest of an |
3535 | | existing SHA-1 thread, and terminate that thread. hashDataSize MAY have values in the range |
3536 | | of 0 through 64, inclusive. If the SHA-1 thread has received no bytes the TPM SHALL |
3537 | | calculate the SHA-1 of the empty buffer. |
3538 | | */ |
3539 | 0 | if (returnCode == TPM_SUCCESS) { |
3540 | 0 | returnCode = TPM_SHA1CompleteCommon(hashValue, |
3541 | 0 | &(tpm_state->sha1_context), |
3542 | 0 | &hashData); |
3543 | 0 | } |
3544 | | /* |
3545 | | response |
3546 | | */ |
3547 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3548 | 0 | if (rcf == 0) { |
3549 | 0 | printf("TPM_Process_SHA1Complete: Ordinal returnCode %08x %u\n", |
3550 | 0 | returnCode, returnCode); |
3551 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3552 | 0 | } |
3553 | | /* success response, append the rest of the parameters. */ |
3554 | 0 | if (rcf == 0) { |
3555 | 0 | if (returnCode == TPM_SUCCESS) { |
3556 | | /* checkpoint the beginning of the outParam's */ |
3557 | 0 | outParamStart = response->buffer_current - response->buffer; |
3558 | | /* append hashValue */ |
3559 | 0 | returnCode = TPM_Digest_Store(response, hashValue); |
3560 | | /* checkpoint the end of the outParam's */ |
3561 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3562 | 0 | } |
3563 | | /* digest the above the line output parameters */ |
3564 | 0 | if (returnCode == TPM_SUCCESS) { |
3565 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3566 | 0 | auditStatus, /* input audit status */ |
3567 | 0 | transportEncrypt, |
3568 | 0 | tag, |
3569 | 0 | returnCode, |
3570 | 0 | ordinal, /* command ordinal */ |
3571 | 0 | response->buffer + outParamStart, /* start */ |
3572 | 0 | outParamEnd - outParamStart); /* length */ |
3573 | 0 | } |
3574 | | /* audit if required */ |
3575 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3576 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3577 | 0 | transportEncrypt, |
3578 | 0 | inParamDigest, |
3579 | 0 | outParamDigest, |
3580 | 0 | ordinal); |
3581 | 0 | } |
3582 | | /* adjust the initial response */ |
3583 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3584 | 0 | } |
3585 | | /* |
3586 | | cleanup |
3587 | | */ |
3588 | 0 | TPM_SizedBuffer_Delete(&hashData); /* @1 */ |
3589 | 0 | return rcf; |
3590 | 0 | } |
3591 | | |
3592 | | /* 13.4 TPM_SHA1CompleteExtend rev 109 |
3593 | | |
3594 | | This capability terminates a pending SHA-1 calculation and EXTENDS the result into a Platform |
3595 | | Configuration Register using a SHA-1 hash process. |
3596 | | |
3597 | | This command is designed to complete a hash sequence and extend a PCR in memory-less |
3598 | | environments. |
3599 | | |
3600 | | This command SHALL incorporate a partial or complete block of data into the digest of an existing |
3601 | | SHA-1 thread, EXTEND the resultant digest into a PCR, and terminate the thread. hashDataSize MAY |
3602 | | have values in the range of 0 through 64, inclusive. |
3603 | | */ |
3604 | | |
3605 | | TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state, |
3606 | | TPM_STORE_BUFFER *response, |
3607 | | TPM_TAG tag, |
3608 | | uint32_t paramSize, |
3609 | | TPM_COMMAND_CODE ordinal, |
3610 | | unsigned char *command, |
3611 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3612 | 0 | { |
3613 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3614 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3615 | | |
3616 | | /* input parameters */ |
3617 | 0 | TPM_PCRINDEX pcrNum; /* Index of the PCR to be modified */ |
3618 | 0 | TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ |
3619 | | |
3620 | | /* processing parameters */ |
3621 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3622 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3623 | 0 | TPM_DIGEST inParamDigest; |
3624 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3625 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3626 | | |
3627 | | /* output parameters */ |
3628 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3629 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3630 | 0 | TPM_DIGEST outParamDigest; |
3631 | 0 | TPM_DIGEST h1HashValue; /* The output of the SHA-1 hash. */ |
3632 | 0 | TPM_PCRVALUE outDigest; /* The PCR value after execution of the command. */ |
3633 | | |
3634 | 0 | printf("TPM_Process_SHA1CompleteExtend: Ordinal Entry\n"); |
3635 | 0 | TPM_SizedBuffer_Init(&hashData); /* freed @1 */ |
3636 | | /* |
3637 | | get inputs |
3638 | | */ |
3639 | | /* save the starting point of inParam's for authorization and auditing */ |
3640 | 0 | inParamStart = command; |
3641 | | /* get pcrNum */ |
3642 | 0 | if (returnCode == TPM_SUCCESS) { |
3643 | 0 | returnCode = TPM_Load32(&pcrNum, &command, ¶mSize); |
3644 | 0 | } |
3645 | | /* get hashData */ |
3646 | 0 | if (returnCode == TPM_SUCCESS) { |
3647 | 0 | printf("TPM_Process_SHA1CompleteExtend: pcrNum %u\n", pcrNum); |
3648 | 0 | returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); |
3649 | 0 | } |
3650 | | /* save the ending point of inParam's for authorization and auditing */ |
3651 | 0 | inParamEnd = command; |
3652 | | /* digest the input parameters */ |
3653 | 0 | if (returnCode == TPM_SUCCESS) { |
3654 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3655 | 0 | &auditStatus, /* output */ |
3656 | 0 | &transportEncrypt, /* output */ |
3657 | 0 | tpm_state, |
3658 | 0 | tag, |
3659 | 0 | ordinal, |
3660 | 0 | inParamStart, |
3661 | 0 | inParamEnd, |
3662 | 0 | transportInternal); |
3663 | 0 | } |
3664 | | /* check state */ |
3665 | 0 | if (returnCode == TPM_SUCCESS) { |
3666 | 0 | returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | |
3667 | 0 | TPM_CHECK_NO_LOCKOUT)); |
3668 | 0 | } |
3669 | | /* check tag */ |
3670 | 0 | if (returnCode == TPM_SUCCESS) { |
3671 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3672 | 0 | } |
3673 | 0 | if (returnCode == TPM_SUCCESS) { |
3674 | 0 | if (paramSize != 0) { |
3675 | 0 | printf("TPM_Process_SHA1CompleteExtend: Error, command has %u extra bytes\n", |
3676 | 0 | paramSize); |
3677 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
3678 | 0 | } |
3679 | 0 | } |
3680 | | /* |
3681 | | Processing |
3682 | | */ |
3683 | | /* 1. 1.Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */ |
3684 | | /* 2. Map V1 to TPM_STANY_DATA */ |
3685 | | /* 3. Map L1 to V1 -> localityModifier */ |
3686 | | /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> pcrAttrib |
3687 | | [PCRIndex]. pcrExtendLocal, return TPM_BAD_LOCALITY */ |
3688 | | /* NOTE Done in TPM_ExtendCommon() */ |
3689 | | /* 5. Create H1 the TPM_DIGEST of the SHA-1 session ensuring that hashData, if any, is */ |
3690 | | /* added to the SHA-1 session */ |
3691 | 0 | if (returnCode == TPM_SUCCESS) { |
3692 | 0 | returnCode = TPM_SHA1CompleteCommon(h1HashValue, |
3693 | 0 | &(tpm_state->sha1_context), |
3694 | 0 | &hashData); |
3695 | 0 | } |
3696 | | /* 6. Perform the actions of TPM_Extend using H1 as the data and pcrNum as the PCR to extend */ |
3697 | 0 | if (returnCode == TPM_SUCCESS) { |
3698 | 0 | returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, h1HashValue); |
3699 | 0 | } |
3700 | | /* |
3701 | | response |
3702 | | */ |
3703 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3704 | 0 | if (rcf == 0) { |
3705 | 0 | printf("TPM_Process_SHA1CompleteExtend: Ordinal returnCode %08x %u\n", |
3706 | 0 | returnCode, returnCode); |
3707 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3708 | 0 | } |
3709 | | /* success response, append the rest of the parameters. */ |
3710 | 0 | if (rcf == 0) { |
3711 | 0 | if (returnCode == TPM_SUCCESS) { |
3712 | | /* checkpoint the beginning of the outParam's */ |
3713 | 0 | outParamStart = response->buffer_current - response->buffer; |
3714 | | /* append hashValue */ |
3715 | 0 | returnCode = TPM_Digest_Store(response, h1HashValue); |
3716 | 0 | } |
3717 | | /* append outDigest */ |
3718 | 0 | if (returnCode == TPM_SUCCESS) { |
3719 | 0 | returnCode = TPM_Digest_Store(response, outDigest); |
3720 | | /* checkpoint the end of the outParam's */ |
3721 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3722 | 0 | } |
3723 | | /* digest the above the line output parameters */ |
3724 | 0 | if (returnCode == TPM_SUCCESS) { |
3725 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3726 | 0 | auditStatus, /* input audit status */ |
3727 | 0 | transportEncrypt, |
3728 | 0 | tag, |
3729 | 0 | returnCode, |
3730 | 0 | ordinal, /* command ordinal */ |
3731 | 0 | response->buffer + outParamStart, /* start */ |
3732 | 0 | outParamEnd - outParamStart); /* length */ |
3733 | 0 | } |
3734 | | /* audit if required */ |
3735 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3736 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3737 | 0 | transportEncrypt, |
3738 | 0 | inParamDigest, |
3739 | 0 | outParamDigest, |
3740 | 0 | ordinal); |
3741 | 0 | } |
3742 | | /* adjust the initial response */ |
3743 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3744 | 0 | } |
3745 | | /* |
3746 | | cleanup |
3747 | | */ |
3748 | 0 | TPM_SizedBuffer_Delete(&hashData); /* @1 */ |
3749 | 0 | return rcf; |
3750 | 0 | } |
3751 | | |
3752 | | /* TPM_SHA1CompleteCommon() is common code for TPM_Process_SHA1Complete() and |
3753 | | TPM_Process_SHA1CompleteExtend() |
3754 | | */ |
3755 | | |
3756 | | TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, /* output: digest */ |
3757 | | void **sha1_context, /* IO: SHA1 context */ |
3758 | | TPM_SIZED_BUFFER *hashData) /* final data to be hashed */ |
3759 | 0 | { |
3760 | 0 | TPM_RESULT rc = 0; |
3761 | | |
3762 | | /* The TPM specification says that the last data chunk must be 0-64 bytes */ |
3763 | 0 | printf("TPM_SHA1CompleteCommon: %u bytes\n", hashData->size); |
3764 | 0 | if (rc == 0) { |
3765 | 0 | if (hashData->size > 64) { |
3766 | 0 | printf("TPM_SHA1CompleteCommon: Error, hashDataSize %u not 0-64\n", |
3767 | 0 | hashData->size); |
3768 | 0 | rc = TPM_SHA_ERROR; |
3769 | 0 | } |
3770 | 0 | } |
3771 | | /* cannot call SHA1Complete() before SHA1Start() */ |
3772 | 0 | if (rc == 0) { |
3773 | 0 | if (*sha1_context == NULL) { |
3774 | 0 | printf("TPM_SHA1CompleteCommon: Error, no existing SHA1 thread\n"); |
3775 | 0 | rc = TPM_SHA_THREAD; |
3776 | 0 | } |
3777 | 0 | } |
3778 | 0 | if ((rc == 0) && (hashData->size != 0)) { |
3779 | 0 | rc = TPM_SHA1UpdateCmd(*sha1_context, hashData->buffer, hashData->size); |
3780 | 0 | } |
3781 | 0 | if (rc == 0) { |
3782 | 0 | rc = TPM_SHA1FinalCmd(hashValue, *sha1_context); |
3783 | 0 | } |
3784 | | /* the SHA1 thread should be terminated even if there is an error */ |
3785 | 0 | TPM_SHA1Delete(sha1_context); |
3786 | 0 | return rc; |
3787 | 0 | } |
3788 | | |
3789 | | /* 13.6 TPM_GetRandom rev 87 |
3790 | | |
3791 | | GetRandom returns the next bytesRequested bytes from the random number generator to the caller. |
3792 | | |
3793 | | It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG |
3794 | | bytes such that the frequency of bytesRequested being more than the number of bytes available is |
3795 | | an infrequent occurrence. |
3796 | | */ |
3797 | | |
3798 | | TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state, |
3799 | | TPM_STORE_BUFFER *response, |
3800 | | TPM_TAG tag, |
3801 | | uint32_t paramSize, |
3802 | | TPM_COMMAND_CODE ordinal, |
3803 | | unsigned char *command, |
3804 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3805 | 0 | { |
3806 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3807 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3808 | | |
3809 | | /* input parameters */ |
3810 | 0 | uint32_t bytesRequested; /* Number of bytes to return */ |
3811 | | |
3812 | | /* processing parameters */ |
3813 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3814 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3815 | 0 | TPM_DIGEST inParamDigest; |
3816 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3817 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3818 | | |
3819 | | /* output parameters */ |
3820 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3821 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3822 | 0 | TPM_DIGEST outParamDigest; |
3823 | 0 | TPM_SIZED_BUFFER randomBytes; /* The returned bytes */ |
3824 | |
|
3825 | 0 | printf("TPM_Process_GetRandom: Ordinal Entry\n"); |
3826 | 0 | TPM_SizedBuffer_Init(&randomBytes); /* freed @1 */ |
3827 | | /* |
3828 | | get inputs |
3829 | | */ |
3830 | | /* save the starting point of inParam's for authorization and auditing */ |
3831 | 0 | inParamStart = command; |
3832 | | /* get bytesRequested parameter */ |
3833 | 0 | if (returnCode == TPM_SUCCESS) { |
3834 | 0 | returnCode = TPM_Load32(&bytesRequested, &command, ¶mSize); |
3835 | 0 | } |
3836 | | /* save the ending point of inParam's for authorization and auditing */ |
3837 | 0 | inParamEnd = command; |
3838 | | /* digest the input parameters */ |
3839 | 0 | if (returnCode == TPM_SUCCESS) { |
3840 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3841 | 0 | &auditStatus, /* output */ |
3842 | 0 | &transportEncrypt, /* output */ |
3843 | 0 | tpm_state, |
3844 | 0 | tag, |
3845 | 0 | ordinal, |
3846 | 0 | inParamStart, |
3847 | 0 | inParamEnd, |
3848 | 0 | transportInternal); |
3849 | 0 | } |
3850 | | /* check state */ |
3851 | 0 | if (returnCode == TPM_SUCCESS) { |
3852 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); |
3853 | 0 | } |
3854 | | /* check tag */ |
3855 | 0 | if (returnCode == TPM_SUCCESS) { |
3856 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3857 | 0 | } |
3858 | 0 | if (returnCode == TPM_SUCCESS) { |
3859 | 0 | if (paramSize != 0) { |
3860 | 0 | printf("TPM_Process_GetRandom: Error, command has %u extra bytes\n", |
3861 | 0 | paramSize); |
3862 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
3863 | 0 | } |
3864 | 0 | } |
3865 | | /* |
3866 | | Processing |
3867 | | */ |
3868 | | /* 1. The TPM determines if amount bytesRequested is available from the TPM. */ |
3869 | 0 | if (returnCode == TPM_SUCCESS) { |
3870 | 0 | printf("TPM_Process_GetRandom: bytesRequested %u\n", bytesRequested); |
3871 | 0 | if (bytesRequested > TPM_RANDOM_MAX) { |
3872 | 0 | bytesRequested = TPM_RANDOM_MAX; |
3873 | 0 | printf("TPM_Process_GetRandom: bytes available %u\n", bytesRequested); |
3874 | 0 | } |
3875 | 0 | } |
3876 | | /* 2. Set randomBytesSize to the number of bytes available from the RNG. This number MAY be less |
3877 | | than bytesRequested. */ |
3878 | 0 | if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { |
3879 | 0 | returnCode = TPM_SizedBuffer_Allocate(&randomBytes, bytesRequested); |
3880 | 0 | } |
3881 | | /* 3. Set randomBytes to the next randomBytesSize bytes from the RNG */ |
3882 | 0 | if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { |
3883 | 0 | returnCode = TPM_Random(randomBytes.buffer, bytesRequested); |
3884 | 0 | } |
3885 | | /* |
3886 | | response |
3887 | | */ |
3888 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
3889 | 0 | if (rcf == 0) { |
3890 | 0 | printf("TPM_Process_GetRandom: Ordinal returnCode %08x %u\n", |
3891 | 0 | returnCode, returnCode); |
3892 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
3893 | 0 | } |
3894 | | /* success response, append the rest of the parameters. */ |
3895 | 0 | if (rcf == 0) { |
3896 | 0 | if (returnCode == TPM_SUCCESS) { |
3897 | | /* checkpoint the beginning of the outParam's */ |
3898 | 0 | outParamStart = response->buffer_current - response->buffer; |
3899 | | /* append randomBytes */ |
3900 | 0 | returnCode = TPM_SizedBuffer_Store(response, &randomBytes); |
3901 | | /* checkpoint the end of the outParam's */ |
3902 | 0 | outParamEnd = response->buffer_current - response->buffer; |
3903 | 0 | } |
3904 | | /* digest the above the line output parameters */ |
3905 | 0 | if (returnCode == TPM_SUCCESS) { |
3906 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
3907 | 0 | auditStatus, /* input audit status */ |
3908 | 0 | transportEncrypt, |
3909 | 0 | tag, |
3910 | 0 | returnCode, |
3911 | 0 | ordinal, /* command ordinal */ |
3912 | 0 | response->buffer + outParamStart, /* start */ |
3913 | 0 | outParamEnd - outParamStart); /* length */ |
3914 | 0 | } |
3915 | | /* audit if required */ |
3916 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
3917 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
3918 | 0 | transportEncrypt, |
3919 | 0 | inParamDigest, |
3920 | 0 | outParamDigest, |
3921 | 0 | ordinal); |
3922 | 0 | } |
3923 | | /* adjust the initial response */ |
3924 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
3925 | 0 | } |
3926 | | /* |
3927 | | cleanup |
3928 | | */ |
3929 | 0 | TPM_SizedBuffer_Delete(&randomBytes); /* freed @1 */ |
3930 | 0 | return rcf; |
3931 | 0 | } |
3932 | | |
3933 | | /* 13.7 TPM_StirRandom rev 109 |
3934 | | |
3935 | | StirRandom adds entropy to the RNG state. |
3936 | | */ |
3937 | | |
3938 | | TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state, |
3939 | | TPM_STORE_BUFFER *response, |
3940 | | TPM_TAG tag, |
3941 | | uint32_t paramSize, |
3942 | | TPM_COMMAND_CODE ordinal, |
3943 | | unsigned char *command, |
3944 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
3945 | 0 | { |
3946 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
3947 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
3948 | | |
3949 | | /* input parameters */ |
3950 | 0 | TPM_SIZED_BUFFER inData; /* Data to add entropy to RNG state, |
3951 | | Number of bytes of input */ |
3952 | | |
3953 | | /* processing parameters */ |
3954 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
3955 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
3956 | 0 | TPM_DIGEST inParamDigest; |
3957 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
3958 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
3959 | | |
3960 | | /* output parameters */ |
3961 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
3962 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
3963 | 0 | TPM_DIGEST outParamDigest; |
3964 | |
|
3965 | 0 | printf("TPM_Process_StirRandom: Ordinal Entry\n"); |
3966 | 0 | TPM_SizedBuffer_Init(&inData); /* freed @1 */ |
3967 | | /* |
3968 | | get inputs |
3969 | | */ |
3970 | | /* save the starting point of inParam's for authorization and auditing */ |
3971 | 0 | inParamStart = command; |
3972 | | /* get inData parameter */ |
3973 | 0 | if (returnCode == TPM_SUCCESS) { |
3974 | 0 | returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); |
3975 | 0 | } |
3976 | | /* save the ending point of inParam's for authorization and auditing */ |
3977 | 0 | inParamEnd = command; |
3978 | | /* digest the input parameters */ |
3979 | 0 | if (returnCode == TPM_SUCCESS) { |
3980 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
3981 | 0 | &auditStatus, /* output */ |
3982 | 0 | &transportEncrypt, /* output */ |
3983 | 0 | tpm_state, |
3984 | 0 | tag, |
3985 | 0 | ordinal, |
3986 | 0 | inParamStart, |
3987 | 0 | inParamEnd, |
3988 | 0 | transportInternal); |
3989 | 0 | } |
3990 | | /* check state */ |
3991 | 0 | if (returnCode == TPM_SUCCESS) { |
3992 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); |
3993 | 0 | } |
3994 | | /* check tag */ |
3995 | 0 | if (returnCode == TPM_SUCCESS) { |
3996 | 0 | returnCode = TPM_CheckRequestTag0(tag); |
3997 | 0 | } |
3998 | 0 | if (returnCode == TPM_SUCCESS) { |
3999 | 0 | if (paramSize != 0) { |
4000 | 0 | printf("TPM_Process_StirRandom: Error, command has %u extra bytes\n", |
4001 | 0 | paramSize); |
4002 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
4003 | 0 | } |
4004 | 0 | } |
4005 | | /* |
4006 | | Processing |
4007 | | */ |
4008 | | /* 1. If dataSize is not less than 256 bytes, the TPM MAY return TPM_BAD_PARAMETER. */ |
4009 | | /* The TPM updates the state of the current RNG using the appropriate mixing function. */ |
4010 | 0 | if (returnCode == TPM_SUCCESS) { |
4011 | 0 | returnCode = TPM_StirRandomCmd(&inData); |
4012 | 0 | } |
4013 | | /* |
4014 | | response |
4015 | | */ |
4016 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
4017 | 0 | if (rcf == 0) { |
4018 | 0 | printf("TPM_Process_StirRandom: Ordinal returnCode %08x %u\n", |
4019 | 0 | returnCode, returnCode); |
4020 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
4021 | 0 | } |
4022 | 0 | if (rcf == 0) { |
4023 | 0 | if (returnCode == TPM_SUCCESS) { |
4024 | | /* checkpoint the beginning of the outParam's */ |
4025 | 0 | outParamStart = response->buffer_current - response->buffer; |
4026 | | /* checkpoint the end of the outParam's */ |
4027 | 0 | outParamEnd = response->buffer_current - response->buffer; |
4028 | 0 | } |
4029 | | /* digest the above the line output parameters */ |
4030 | 0 | if (returnCode == TPM_SUCCESS) { |
4031 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
4032 | 0 | auditStatus, /* input audit status */ |
4033 | 0 | transportEncrypt, |
4034 | 0 | tag, |
4035 | 0 | returnCode, |
4036 | 0 | ordinal, /* command ordinal */ |
4037 | 0 | response->buffer + outParamStart, /* start */ |
4038 | 0 | outParamEnd - outParamStart); /* length */ |
4039 | 0 | } |
4040 | | /* audit if required */ |
4041 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
4042 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
4043 | 0 | transportEncrypt, |
4044 | 0 | inParamDigest, |
4045 | 0 | outParamDigest, |
4046 | 0 | ordinal); |
4047 | 0 | } |
4048 | | /* adjust the initial response */ |
4049 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
4050 | 0 | } |
4051 | | /* |
4052 | | cleanup |
4053 | | */ |
4054 | 0 | TPM_SizedBuffer_Delete(&inData); /* @1 */ |
4055 | 0 | return rcf; |
4056 | 0 | } |
4057 | | |
4058 | | /* 13.8 TPM_CertifyKey rev 107 |
4059 | | |
4060 | | The TPM_CertifyKey operation allows one key to certify the public portion of another key. A TPM |
4061 | | identity key may be used to certify non-migratable keys but is not permitted to certify migratory |
4062 | | keys or certified migration keys. As such, it allows the TPM to make the statement "this key is |
4063 | | held in a TPM-shielded location, and it will never be revealed." For this statement to have |
4064 | | veracity, the Challenger must trust the policies used by the entity that issued the identity and |
4065 | | the maintenance policy of the TPM manufacturer. |
4066 | | |
4067 | | Signing and legacy keys may be used to certify both migratable and non-migratable keys. Then the |
4068 | | usefulness of a certificate depends on the trust in the certifying key by the recipient of the |
4069 | | certificate. |
4070 | | |
4071 | | The key to be certified must be loaded before TPM_CertifyKey is called. |
4072 | | |
4073 | | The determination to use the TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 on the output is based on |
4074 | | which PCRs and what localities the certified key is restricted to. A key to be certified that |
4075 | | does not have locality restrictions and which uses no PCRs greater than PCR #15 will cause this |
4076 | | command to return and sign a TPM_CERTIFY_INFO structure, which provides compatibility with V1.1 |
4077 | | TPMs. |
4078 | | |
4079 | | When this command is run to certify all other keys (those that use PCR #16 or higher, as well as |
4080 | | those limited by locality in any way), it will return and sign a TPM_CERTIFY_INFO2 structure. |
4081 | | |
4082 | | TPM_CertifyKey does not support the case where (a) the certifying key requires a usage |
4083 | | authorization to be provided but (b) the key-to-be-certified does not. In such cases, |
4084 | | TPM_CertifyKey2 must be used. |
4085 | | |
4086 | | If a command tag (in the parameter array) specifies only one authorisation session, then the TPM |
4087 | | convention is that the first session listed is ignored (authDataUsage must be TPM_AUTH_NEVER for |
4088 | | this key) and the incoming session data is used for the second auth session in the list. In |
4089 | | TPM_CertifyKey, the first session is the certifying key and the second session is the |
4090 | | key-to-be-certified. In TPM_CertifyKey2, the first session is the key-to-be-certified and the |
4091 | | second session is the certifying key. |
4092 | | */ |
4093 | | |
4094 | | TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state, |
4095 | | TPM_STORE_BUFFER *response, |
4096 | | TPM_TAG tag, |
4097 | | uint32_t paramSize, |
4098 | | TPM_COMMAND_CODE ordinal, |
4099 | | unsigned char *command, |
4100 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
4101 | 0 | { |
4102 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
4103 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
4104 | | |
4105 | | /* input parameters */ |
4106 | 0 | TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ |
4107 | 0 | TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ |
4108 | 0 | TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce |
4109 | | provided to prevent replay-attacks) */ |
4110 | 0 | TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ |
4111 | 0 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle |
4112 | | */ |
4113 | 0 | TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session |
4114 | | handle */ |
4115 | 0 | TPM_AUTHDATA certAuth; /* The authorization session digest for inputs and |
4116 | | certHandle. HMAC key: certKey.auth. */ |
4117 | 0 | TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be |
4118 | | signed. */ |
4119 | 0 | TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle |
4120 | | */ |
4121 | 0 | TPM_BOOL continueKeySession = TRUE; /* The continue use flag for the authorization session |
4122 | | handle */ |
4123 | 0 | TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key |
4124 | | to be signed. HMAC key: key.usageAuth. */ |
4125 | | |
4126 | | /* processing parameters */ |
4127 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
4128 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
4129 | 0 | TPM_DIGEST inParamDigest; |
4130 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
4131 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
4132 | 0 | TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ |
4133 | 0 | TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ |
4134 | 0 | TPM_BOOL certAuthHandleValid = FALSE; |
4135 | 0 | TPM_BOOL keyAuthHandleValid = FALSE; |
4136 | 0 | TPM_SECRET *certHmacKey; |
4137 | 0 | TPM_SECRET *targetHmacKey; |
4138 | 0 | TPM_BOOL certPCRStatus; |
4139 | 0 | TPM_BOOL targetPCRStatus; |
4140 | 0 | TPM_KEY *certKey = NULL; /* the key specified by certHandle */ |
4141 | 0 | TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ |
4142 | 0 | TPM_SECRET *certKeyUsageAuth; |
4143 | 0 | TPM_SECRET *targetKeyUsageAuth; |
4144 | 0 | TPM_BOOL pcrUsage; |
4145 | 0 | TPM_LOCALITY_SELECTION localityAtRelease; |
4146 | 0 | int v1Version; /* TPM 1.1 or TPM 1.2 */ |
4147 | 0 | int certifyType = 0; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 */ |
4148 | 0 | TPM_DIGEST m1Digest; /* digest of certifyInfo */ |
4149 | | |
4150 | | /* output parameters */ |
4151 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
4152 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
4153 | 0 | TPM_DIGEST outParamDigest; |
4154 | 0 | TPM_CERTIFY_INFO certifyInfo; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 structure |
4155 | | that provides information relative to keyhandle |
4156 | | NOTE This is c1 in the Actions. */ |
4157 | 0 | TPM_CERTIFY_INFO2 certifyInfo2; |
4158 | 0 | TPM_SIZED_BUFFER outData; /* The signature of certifyInfo */ |
4159 | |
|
4160 | 0 | printf("TPM_Process_CertifyKey: Ordinal Entry\n"); |
4161 | 0 | TPM_CertifyInfo_Init(&certifyInfo); /* freed @1 */ |
4162 | 0 | TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @2 */ |
4163 | 0 | TPM_SizedBuffer_Init(&outData); /* freed @3 */ |
4164 | | /* |
4165 | | get inputs |
4166 | | */ |
4167 | | /* get certHandle parameter */ |
4168 | 0 | if (returnCode == TPM_SUCCESS) { |
4169 | 0 | returnCode = TPM_Load32(&certHandle, &command, ¶mSize); |
4170 | 0 | } |
4171 | | /* get keyHandle parameter */ |
4172 | 0 | if (returnCode == TPM_SUCCESS) { |
4173 | 0 | printf("TPM_Process_CertifyKey: certHandle %08x\n", certHandle); |
4174 | 0 | returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); |
4175 | 0 | } |
4176 | | /* save the starting point of inParam's for authorization and auditing */ |
4177 | 0 | inParamStart = command; |
4178 | | /* get antiReplay parameter */ |
4179 | 0 | if (returnCode == TPM_SUCCESS) { |
4180 | 0 | printf("TPM_Process_CertifyKey: keyHandle %08x\n", keyHandle); |
4181 | 0 | returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); |
4182 | 0 | } |
4183 | | /* save the ending point of inParam's for authorization and auditing */ |
4184 | 0 | inParamEnd = command; |
4185 | | /* digest the input parameters */ |
4186 | 0 | if (returnCode == TPM_SUCCESS) { |
4187 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
4188 | 0 | &auditStatus, /* output */ |
4189 | 0 | &transportEncrypt, /* output */ |
4190 | 0 | tpm_state, |
4191 | 0 | tag, |
4192 | 0 | ordinal, |
4193 | 0 | inParamStart, |
4194 | 0 | inParamEnd, |
4195 | 0 | transportInternal); |
4196 | 0 | } |
4197 | | /* check state */ |
4198 | 0 | if (returnCode == TPM_SUCCESS) { |
4199 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); |
4200 | 0 | } |
4201 | | /* check tag */ |
4202 | 0 | if (returnCode == TPM_SUCCESS) { |
4203 | 0 | returnCode = TPM_CheckRequestTag210(tag); |
4204 | 0 | } |
4205 | | /* get the optional 'below the line' authorization parameters */ |
4206 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4207 | 0 | returnCode = TPM_AuthParams_Get(&certAuthHandle, |
4208 | 0 | &certAuthHandleValid, |
4209 | 0 | nonceOdd, |
4210 | 0 | &continueAuthSession, |
4211 | 0 | certAuth, |
4212 | 0 | &command, ¶mSize); |
4213 | 0 | } |
4214 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4215 | 0 | printf("TPM_Process_CertifyKey: certAuthHandle %08x\n", certAuthHandle); |
4216 | 0 | } |
4217 | | /* get the optional 'below the line' authorization parameters */ |
4218 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4219 | 0 | returnCode = TPM_AuthParams_Get(&keyAuthHandle, |
4220 | 0 | &keyAuthHandleValid, |
4221 | 0 | keynonceOdd, |
4222 | 0 | &continueKeySession, |
4223 | 0 | keyAuth, |
4224 | 0 | &command, ¶mSize); |
4225 | 0 | } |
4226 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4227 | 0 | printf("TPM_Process_CertifyKey: keyAuthHandle %08x\n", keyAuthHandle); |
4228 | 0 | } |
4229 | 0 | if (returnCode == TPM_SUCCESS) { |
4230 | 0 | if (paramSize != 0) { |
4231 | 0 | printf("TPM_Process_CertifyKey: Error, command has %u extra bytes\n", |
4232 | 0 | paramSize); |
4233 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
4234 | 0 | } |
4235 | 0 | } |
4236 | | /* do not terminate sessions if the command did not parse correctly */ |
4237 | 0 | if (returnCode != TPM_SUCCESS) { |
4238 | 0 | certAuthHandleValid = FALSE; |
4239 | 0 | keyAuthHandleValid = FALSE; |
4240 | 0 | } |
4241 | | /* |
4242 | | Processing |
4243 | | */ |
4244 | | /* get the key corresponding to the certHandle parameter */ |
4245 | 0 | if (returnCode == TPM_SUCCESS) { |
4246 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, |
4247 | 0 | FALSE, /* not read-only */ |
4248 | 0 | FALSE, /* do not ignore PCRs */ |
4249 | 0 | FALSE); /* cannot use EK */ |
4250 | 0 | } |
4251 | | /* get the key corresponding to the keyHandle parameter */ |
4252 | 0 | if (returnCode == TPM_SUCCESS) { |
4253 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, |
4254 | 0 | FALSE, /* not read-only */ |
4255 | 0 | FALSE, /* do not ignore PCRs */ |
4256 | 0 | FALSE); /* cannot use EK */ |
4257 | 0 | } |
4258 | | /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of |
4259 | | TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ |
4260 | 0 | if (returnCode == TPM_SUCCESS) { |
4261 | 0 | if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && |
4262 | 0 | (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { |
4263 | 0 | printf("TPM_Process_CertifyKey: Error, invalid certKey sigScheme %04hx\n", |
4264 | 0 | certKey->algorithmParms.sigScheme); |
4265 | 0 | returnCode = TPM_BAD_KEY_PROPERTY; |
4266 | 0 | } |
4267 | 0 | } |
4268 | | /* 2. Verify command and key AuthData values */ |
4269 | | /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ |
4270 | | /* i. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key |
4271 | | pointed to by certHandle, return TPM_AUTHFAIL on error */ |
4272 | | /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key |
4273 | | pointed to by keyHandle, return TPM_AUTH2FAIL on error */ |
4274 | | /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ |
4275 | | /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return |
4276 | | TPM_AUTHFAIL on error. */ |
4277 | | /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key |
4278 | | pointed to by keyHandle, return TPM_AUTHFAIL on error */ |
4279 | | /* c. else if tag is TPM_TAG_RQU_COMMAND */ |
4280 | | /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return |
4281 | | TPM_AUTHFAIL on error. */ |
4282 | | /* ii. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key |
4283 | | referenced by keyHandle, return TPM_AUTHFAIL on error. */ |
4284 | | |
4285 | | /* NOTE: Simplified the above logic as follows */ |
4286 | | /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ |
4287 | | /* get certHandle -> usageAuth */ |
4288 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4289 | 0 | returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); |
4290 | 0 | } |
4291 | | /* get the first session data */ |
4292 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4293 | 0 | returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, |
4294 | 0 | &certHmacKey, |
4295 | 0 | tpm_state, |
4296 | 0 | certAuthHandle, |
4297 | 0 | TPM_PID_NONE, |
4298 | 0 | TPM_ET_KEYHANDLE, |
4299 | 0 | ordinal, |
4300 | 0 | certKey, |
4301 | 0 | certKeyUsageAuth, /* OIAP */ |
4302 | 0 | certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ |
4303 | 0 | } |
4304 | | /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key |
4305 | | pointed to by certHandle, return TPM_AUTHFAIL on error */ |
4306 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4307 | 0 | returnCode = TPM_Authdata_Check(tpm_state, |
4308 | 0 | *certHmacKey, /* HMAC key */ |
4309 | 0 | inParamDigest, |
4310 | 0 | cert_auth_session_data, /* authorization session */ |
4311 | 0 | nonceOdd, /* Nonce generated by system |
4312 | | associated with authHandle */ |
4313 | 0 | continueAuthSession, |
4314 | 0 | certAuth); /* Authorization digest for input */ |
4315 | 0 | } |
4316 | | /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ |
4317 | | /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return |
4318 | | TPM_AUTHFAIL on error. */ |
4319 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { |
4320 | 0 | if (certKey->authDataUsage != TPM_AUTH_NEVER) { |
4321 | 0 | printf("TPM_Process_CertifyKey: Error, cert key authorization required\n"); |
4322 | 0 | returnCode = TPM_AUTHFAIL; |
4323 | 0 | } |
4324 | 0 | } |
4325 | | /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of |
4326 | | authorization data */ |
4327 | | /* get keyHandle -> usageAuth */ |
4328 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4329 | 0 | returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); |
4330 | 0 | } |
4331 | | /* get the second session data */ |
4332 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4333 | 0 | returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, |
4334 | 0 | &targetHmacKey, |
4335 | 0 | tpm_state, |
4336 | 0 | keyAuthHandle, |
4337 | 0 | TPM_PID_NONE, |
4338 | 0 | TPM_ET_KEYHANDLE, |
4339 | 0 | ordinal, |
4340 | 0 | targetKey, |
4341 | 0 | targetKeyUsageAuth, /* OIAP */ |
4342 | 0 | targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ |
4343 | 0 | } |
4344 | | /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key |
4345 | | pointed to by keyHandle, return TPM_AUTH2FAIL on error */ |
4346 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4347 | 0 | returnCode = TPM_Auth2data_Check(tpm_state, |
4348 | 0 | *targetHmacKey, /* HMAC key */ |
4349 | 0 | inParamDigest, |
4350 | 0 | target_auth_session_data, /* authorization session */ |
4351 | 0 | keynonceOdd, /* Nonce generated by system |
4352 | | associated with authHandle */ |
4353 | 0 | continueKeySession, |
4354 | 0 | keyAuth); /* Authorization digest for input */ |
4355 | 0 | } |
4356 | | /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced |
4357 | | by keyHandle, return TPM_AUTHFAIL on error. */ |
4358 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { |
4359 | 0 | if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { |
4360 | 0 | printf("TPM_Process_CertifyKey: Error, target key authorization required\n"); |
4361 | 0 | returnCode = TPM_AUTHFAIL; |
4362 | 0 | } |
4363 | 0 | } |
4364 | | /* 3. If keyHandle -> payload is not TPM_PT_ASYM, return TPM_INVALID_KEYUSAGE. */ |
4365 | 0 | if (returnCode == TPM_SUCCESS) { |
4366 | 0 | if (targetKey->tpm_store_asymkey->payload != TPM_PT_ASYM) { |
4367 | 0 | printf("TPM_Process_CertifyKey: Error, target key invalid payload %02x\n", |
4368 | 0 | targetKey->tpm_store_asymkey->payload); |
4369 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
4370 | 0 | } |
4371 | 0 | } |
4372 | | /* 4. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is |
4373 | | TPM_KEY_IDENTITY) */ |
4374 | 0 | if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { |
4375 | | /* a. If keyHandle -> keyflags -> keyInfo -> migratable is TRUE return TPM_MIGRATEFAIL */ |
4376 | 0 | if (targetKey->keyFlags & TPM_MIGRATABLE) { |
4377 | 0 | printf("TPM_Process_CertifyKey: Error, target key is migratable\n"); |
4378 | 0 | returnCode = TPM_MIGRATEFAIL; |
4379 | 0 | } |
4380 | 0 | } |
4381 | | /* 5. Validate that certHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, |
4382 | | if not return TPM_INVALID_KEYUSAGE */ |
4383 | 0 | if (returnCode == TPM_SUCCESS) { |
4384 | 0 | printf("TPM_Process_CertifyKey: certHandle -> keyUsage %04hx\n", certKey->keyUsage); |
4385 | 0 | if ((certKey->keyUsage != TPM_KEY_SIGNING) && |
4386 | 0 | ((certKey->keyUsage) != TPM_KEY_IDENTITY) && |
4387 | 0 | ((certKey->keyUsage) != TPM_KEY_LEGACY)) { |
4388 | 0 | printf("TPM_Process_CertifyKey: Error, certHandle -> keyUsage %04hx is invalid\n", |
4389 | 0 | certKey->keyUsage); |
4390 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
4391 | 0 | } |
4392 | 0 | } |
4393 | | /* 6. Validate that keyHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, |
4394 | | TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ |
4395 | 0 | if (returnCode == TPM_SUCCESS) { |
4396 | 0 | printf("TPM_Process_CertifyKey: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); |
4397 | 0 | if ((targetKey->keyUsage != TPM_KEY_SIGNING) && |
4398 | 0 | ((targetKey->keyUsage) != TPM_KEY_STORAGE) && |
4399 | 0 | ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && |
4400 | 0 | ((targetKey->keyUsage) != TPM_KEY_BIND) && |
4401 | 0 | ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { |
4402 | 0 | printf("TPM_Process_CertifyKey: Error, keyHandle -> keyUsage %04hx is invalid\n", |
4403 | 0 | targetKey->keyUsage); |
4404 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
4405 | 0 | } |
4406 | 0 | } |
4407 | | /* 7. If keyHandle -> digestAtRelease requires the use of PCRs 16 or higher to calculate or if |
4408 | | keyHandle -> localityAtRelease is not 0x1F */ |
4409 | | /* get PCR usage 16 and higher */ |
4410 | 0 | if (returnCode == TPM_SUCCESS) { |
4411 | 0 | returnCode = TPM_Key_GetPCRUsage(&pcrUsage, targetKey, 2); |
4412 | 0 | } |
4413 | | /* get localityAtRelease */ |
4414 | 0 | if (returnCode == TPM_SUCCESS) { |
4415 | 0 | returnCode = TPM_Key_GetLocalityAtRelease(&localityAtRelease, targetKey); |
4416 | 0 | } |
4417 | 0 | if (returnCode == TPM_SUCCESS) { |
4418 | 0 | if (pcrUsage || (localityAtRelease != TPM_LOC_ALL)) { |
4419 | | /* a. Set V1 to 1.2 */ |
4420 | 0 | v1Version = 2; /* locality or >2 PCR's */ |
4421 | 0 | } |
4422 | | /* 8. Else */ |
4423 | 0 | else { |
4424 | | /* a. Set V1 to 1.1 */ |
4425 | 0 | v1Version = 1; /* no locality and <= 2 PCR's */ |
4426 | 0 | } |
4427 | 0 | } |
4428 | 0 | if (returnCode == TPM_SUCCESS) { |
4429 | 0 | printf("TPM_Process_CertifyKey: V1 %d\n", v1Version); |
4430 | | /* 9. If keyHandle -> pcrInfoSize is not 0 */ |
4431 | 0 | if (targetKey->pcrInfo.size != 0) { |
4432 | 0 | printf("TPM_Process_CertifyKey: Setting PCR info from key\n"); |
4433 | | /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ |
4434 | | /* i. Create a digestAtRelease according to the specified PCR registers and |
4435 | | compare to keyHandle -> digestAtRelease and if a mismatch return |
4436 | | TPM_WRONGPCRVAL */ |
4437 | | /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ |
4438 | | /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ |
4439 | | /* b. If V1 is 1.1 */ |
4440 | 0 | if (v1Version == 1) { |
4441 | 0 | certifyType = 1; |
4442 | | /* i. Create C1 a TPM_CERTIFY_INFO structure */ |
4443 | | /* NOTE: Done by TPM_CertifyInfo_Init() */ |
4444 | | /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ |
4445 | | /* NOTE: Done in common _Set() code below */ |
4446 | | /* iii. The TPM MUST set c1 -> pcrInfoSize to 44. */ |
4447 | | /* iv. The TPM MUST set c1 -> pcrInfo to a TPM_PCR_INFO structure properly filled |
4448 | | out using the information from keyHandle. */ |
4449 | | /* This function actually creates the cache, which is serialized later */ |
4450 | 0 | if (returnCode == TPM_SUCCESS) { |
4451 | 0 | returnCode = TPM_PCRInfo_CreateFromKey(&(certifyInfo.tpm_pcr_info), |
4452 | 0 | targetKey); |
4453 | 0 | } |
4454 | | /* v. The TPM MUST set c1 -> digestAtCreation to 20 bytes of 0x00. */ |
4455 | 0 | if (returnCode == TPM_SUCCESS) { |
4456 | 0 | TPM_Digest_Init(certifyInfo.tpm_pcr_info->digestAtCreation); |
4457 | 0 | } |
4458 | 0 | } |
4459 | | /* c. Else */ |
4460 | 0 | else { |
4461 | 0 | certifyType = 2; |
4462 | | /* i. Create C1 a TPM_CERTIFY_INFO2 structure */ |
4463 | | /* NOTE: Done by TPM_CertifyInfo2_Init() */ |
4464 | | /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ |
4465 | | /* NOTE: Done in common _Set() code below */ |
4466 | | /* iii. Set C1 -> pcrInfoSize to the size of an appropriate TPM_PCR_INFO_SHORT |
4467 | | structure. */ |
4468 | | /* iv. Set C1 -> pcrInfo to a properly filled out TPM_PCR_INFO_SHORT structure, |
4469 | | using the information from keyHandle. */ |
4470 | | /* This function actually creates the cache, which is serialized later */ |
4471 | 0 | if (returnCode == TPM_SUCCESS) { |
4472 | 0 | returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), |
4473 | 0 | targetKey); |
4474 | 0 | } |
4475 | | /* v. Set C1 -> migrationAuthoritySize to 0 */ |
4476 | | /* NOTE: Done by TPM_CertifyInfo2_Init() */ |
4477 | 0 | } |
4478 | 0 | } |
4479 | | /* 10. Else */ |
4480 | 0 | else { |
4481 | 0 | certifyType = 1; |
4482 | | /* a. Create C1 a TPM_CERTIFY_INFO structure */ |
4483 | | /* NOTE: Done by TPM_CertifyInfo_Init() */ |
4484 | | /* b. Fill in C1 with the information from the key pointed to be keyHandle */ |
4485 | | /* NOTE: Done in common _Set() code below */ |
4486 | | /* c. The TPM MUST set c1 -> pcrInfoSize to 0 */ |
4487 | | /* NOTE: Done by TPM_CertifyInfo_Init() */ |
4488 | 0 | } |
4489 | 0 | } |
4490 | | /* 11. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that |
4491 | | <key> is the actual public modulus, and does not include any structure formatting. */ |
4492 | | /* 12. Set C1 -> pubKeyDigest to H1 */ |
4493 | | /* NOTE: Done by TPM_CertifyInfo_Set() or TPM_CertifyInfo2_Set() */ |
4494 | | /* 13. The TPM copies the antiReplay parameter to c1 -> data. */ |
4495 | | /* Set C1 -> parentPCRStatus to the value from keyHandle NOTE: Implied in specification */ |
4496 | | /* Fill in C1 with the information from the key pointed to by keyHandle */ |
4497 | 0 | if (returnCode == TPM_SUCCESS) { |
4498 | 0 | printf("TPM_Process_CertifyKey: Setting certifyInfo from target key\n"); |
4499 | 0 | if (certifyType == 1) { |
4500 | 0 | TPM_Digest_Copy(certifyInfo.data, antiReplay); |
4501 | 0 | certifyInfo.parentPCRStatus = targetPCRStatus; |
4502 | 0 | returnCode = TPM_CertifyInfo_Set(&certifyInfo, targetKey); |
4503 | 0 | } |
4504 | 0 | else { |
4505 | 0 | TPM_Digest_Copy(certifyInfo2.data, antiReplay); |
4506 | 0 | certifyInfo2.parentPCRStatus = targetPCRStatus; |
4507 | 0 | returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); |
4508 | 0 | } |
4509 | 0 | } |
4510 | | /* 14. The TPM sets certifyInfo to C1. */ |
4511 | | /* NOTE Created as certifyInfo or certifyInfo2 */ |
4512 | | /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1. */ |
4513 | 0 | if (returnCode == TPM_SUCCESS) { |
4514 | 0 | printf("TPM_Process_CertifyKey: Digesting certifyInfo\n"); |
4515 | 0 | if (certifyType == 1) { |
4516 | 0 | returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo, |
4517 | 0 | (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store); |
4518 | 0 | } |
4519 | 0 | else { |
4520 | 0 | returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, |
4521 | 0 | (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); |
4522 | 0 | } |
4523 | 0 | } |
4524 | | /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob |
4525 | | is returned in outData. */ |
4526 | 0 | if (returnCode == TPM_SUCCESS) { |
4527 | 0 | printf("TPM_Process_CertifyKey: Signing certifyInfo digest with certifying key\n"); |
4528 | 0 | returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ |
4529 | 0 | m1Digest, /* message */ |
4530 | 0 | TPM_DIGEST_SIZE, /* message size */ |
4531 | 0 | certKey); /* input, signing key */ |
4532 | 0 | } |
4533 | | /* |
4534 | | response |
4535 | | */ |
4536 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
4537 | 0 | if (rcf == 0) { |
4538 | 0 | printf("TPM_Process_CertifyKey: Ordinal returnCode %08x %u\n", |
4539 | 0 | returnCode, returnCode); |
4540 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
4541 | 0 | } |
4542 | | /* success response, append the rest of the parameters. */ |
4543 | 0 | if (rcf == 0) { |
4544 | 0 | if (returnCode == TPM_SUCCESS) { |
4545 | | /* checkpoint the beginning of the outParam's */ |
4546 | 0 | outParamStart = response->buffer_current - response->buffer; |
4547 | | /* Return certifyInfo */ |
4548 | 0 | if (certifyType == 1) { |
4549 | 0 | returnCode = TPM_CertifyInfo_Store(response, &certifyInfo); |
4550 | 0 | } |
4551 | 0 | else { |
4552 | 0 | returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); |
4553 | 0 | } |
4554 | 0 | } |
4555 | 0 | if (returnCode == TPM_SUCCESS) { |
4556 | | /* Return outData */ |
4557 | 0 | returnCode = TPM_SizedBuffer_Store(response, &outData); |
4558 | | /* checkpoint the end of the outParam's */ |
4559 | 0 | outParamEnd = response->buffer_current - response->buffer; |
4560 | 0 | } |
4561 | | /* digest the above the line output parameters */ |
4562 | 0 | if (returnCode == TPM_SUCCESS) { |
4563 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
4564 | 0 | auditStatus, /* input audit status */ |
4565 | 0 | transportEncrypt, |
4566 | 0 | tag, |
4567 | 0 | returnCode, |
4568 | 0 | ordinal, /* command ordinal */ |
4569 | 0 | response->buffer + outParamStart, /* start */ |
4570 | 0 | outParamEnd - outParamStart); /* length */ |
4571 | 0 | } |
4572 | | /* calculate and set the below the line parameters */ |
4573 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4574 | 0 | returnCode = TPM_AuthParams_Set(response, |
4575 | 0 | *certHmacKey, /* HMAC key */ |
4576 | 0 | cert_auth_session_data, |
4577 | 0 | outParamDigest, |
4578 | 0 | nonceOdd, |
4579 | 0 | continueAuthSession); |
4580 | 0 | } |
4581 | | /* calculate and set the below the line parameters */ |
4582 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4583 | 0 | returnCode = TPM_AuthParams_Set(response, |
4584 | 0 | *targetHmacKey, /* HMAC key */ |
4585 | 0 | target_auth_session_data, |
4586 | 0 | outParamDigest, |
4587 | 0 | keynonceOdd, |
4588 | 0 | continueKeySession); |
4589 | 0 | } |
4590 | | /* audit if required */ |
4591 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
4592 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
4593 | 0 | transportEncrypt, |
4594 | 0 | inParamDigest, |
4595 | 0 | outParamDigest, |
4596 | 0 | ordinal); |
4597 | 0 | } |
4598 | | /* adjust the initial response */ |
4599 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
4600 | 0 | } |
4601 | | /* if there was an error, or continueAuthSession is FALSE, terminate the session */ |
4602 | 0 | if (((rcf != 0) || |
4603 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
4604 | 0 | !continueKeySession) && |
4605 | 0 | keyAuthHandleValid) { |
4606 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); |
4607 | 0 | } |
4608 | 0 | if (((rcf != 0) || |
4609 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
4610 | 0 | !continueAuthSession) && |
4611 | 0 | certAuthHandleValid) { |
4612 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); |
4613 | 0 | } |
4614 | | /* |
4615 | | cleanup |
4616 | | */ |
4617 | 0 | TPM_CertifyInfo_Delete(&certifyInfo); /* @1 */ |
4618 | 0 | TPM_CertifyInfo2_Delete(&certifyInfo2); /* @2 */ |
4619 | 0 | TPM_SizedBuffer_Delete(&outData); /* @3 */ |
4620 | 0 | return rcf; |
4621 | 0 | } |
4622 | | |
4623 | | /* 13.9 TPM_CertifyKey2 rev 107 |
4624 | | |
4625 | | This command is based on TPM_CertifyKey, but includes the ability to certify a Certifiable |
4626 | | Migration Key (CMK), which requires extra input parameters. |
4627 | | |
4628 | | TPM_CertifyKey2 always produces a TPM_CERTIFY_INFO2 structure. |
4629 | | |
4630 | | TPM_CertifyKey2 does not support the case where (a) the key-to-be-certified requires a usage |
4631 | | authorization to be provided but (b) the certifying key does not. |
4632 | | |
4633 | | If a command tag (in the parameter array) specifies only one authorisation session, then the TPM |
4634 | | convention is that the first session listed is ignored (authDataUsage must be |
4635 | | TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER for this key) and the incoming session data is used for |
4636 | | the second auth session in the list. In TPM_CertifyKey2, the first session is the key to be |
4637 | | certified and the second session is the certifying key. |
4638 | | */ |
4639 | | |
4640 | | TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state, |
4641 | | TPM_STORE_BUFFER *response, |
4642 | | TPM_TAG tag, |
4643 | | uint32_t paramSize, |
4644 | | TPM_COMMAND_CODE ordinal, |
4645 | | unsigned char *command, |
4646 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
4647 | 0 | { |
4648 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
4649 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
4650 | | |
4651 | | /* input parameters */ |
4652 | 0 | TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ |
4653 | 0 | TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ |
4654 | 0 | TPM_DIGEST migrationPubDigest; /* The digest of a TPM_MSA_COMPOSITE structure, |
4655 | | containing at least one public key of a Migration |
4656 | | Authority */ |
4657 | 0 | TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce |
4658 | | provided to prevent replay-attacks) */ |
4659 | 0 | TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be |
4660 | | signed. */ |
4661 | 0 | TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle |
4662 | | */ |
4663 | 0 | TPM_BOOL continueKeySession; /* The continue use flag for the authorization session |
4664 | | handle */ |
4665 | 0 | TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key |
4666 | | to be signed. HMAC key: key.usageAuth. */ |
4667 | 0 | TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ |
4668 | 0 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle |
4669 | | */ |
4670 | 0 | TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session |
4671 | | handle */ |
4672 | 0 | TPM_AUTHDATA certAuth; /* Authorization HMAC key: certKey.auth. */ |
4673 | | |
4674 | | /* processing parameters */ |
4675 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
4676 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
4677 | 0 | TPM_DIGEST inParamDigest; |
4678 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
4679 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
4680 | 0 | TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ |
4681 | 0 | TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ |
4682 | 0 | TPM_BOOL certAuthHandleValid = FALSE; |
4683 | 0 | TPM_BOOL keyAuthHandleValid = FALSE; |
4684 | 0 | TPM_SECRET *certHmacKey; |
4685 | 0 | TPM_SECRET *targetHmacKey; |
4686 | 0 | TPM_BOOL certPCRStatus; |
4687 | 0 | TPM_BOOL targetPCRStatus; |
4688 | 0 | TPM_KEY *certKey = NULL; /* the key specified by certHandle */ |
4689 | 0 | TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ |
4690 | 0 | TPM_SECRET *certKeyUsageAuth; |
4691 | 0 | TPM_SECRET *targetKeyUsageAuth; |
4692 | 0 | TPM_STORE_ASYMKEY *targetStoreAsymkey; |
4693 | 0 | TPM_CMK_MIGAUTH m2CmkMigauth; |
4694 | 0 | TPM_BOOL hmacValid; |
4695 | 0 | TPM_DIGEST migrationAuthority; |
4696 | 0 | TPM_DIGEST m1Digest; /* digest of certifyInfo */ |
4697 | | |
4698 | | /* output parameters */ |
4699 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
4700 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
4701 | 0 | TPM_DIGEST outParamDigest; |
4702 | 0 | TPM_CERTIFY_INFO2 certifyInfo2; /* TPM_CERTIFY_INFO2 relative to keyHandle */ |
4703 | 0 | TPM_SIZED_BUFFER outData; /* The signed public key. */ |
4704 | |
|
4705 | 0 | printf("TPM_Process_CertifyKey2: Ordinal Entry\n"); |
4706 | 0 | TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @1 */ |
4707 | 0 | TPM_SizedBuffer_Init(&outData); /* freed @2 */ |
4708 | 0 | TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @3 */ |
4709 | | /* |
4710 | | get inputs |
4711 | | */ |
4712 | | /* get keyHandle parameter */ |
4713 | 0 | if (returnCode == TPM_SUCCESS) { |
4714 | 0 | returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); |
4715 | 0 | } |
4716 | | /* get certHandle parameter */ |
4717 | 0 | if (returnCode == TPM_SUCCESS) { |
4718 | 0 | printf("TPM_Process_CertifyKey2: keyHandle %08x\n", keyHandle); |
4719 | 0 | returnCode = TPM_Load32(&certHandle, &command, ¶mSize); |
4720 | 0 | } |
4721 | | /* save the starting point of inParam's for authorization and auditing */ |
4722 | 0 | inParamStart = command; |
4723 | | /* get antiReplay parameter */ |
4724 | 0 | if (returnCode == TPM_SUCCESS) { |
4725 | 0 | printf("TPM_Process_CertifyKey2: certHandle %08x\n", certHandle); |
4726 | | /* get the migrationPubDigest parameter */ |
4727 | 0 | returnCode = TPM_Digest_Load(migrationPubDigest, &command, ¶mSize); |
4728 | 0 | } |
4729 | | /* get the antiReplay parameter */ |
4730 | 0 | if (returnCode == TPM_SUCCESS) { |
4731 | 0 | returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); |
4732 | 0 | } |
4733 | | /* save the ending point of inParam's for authorization and auditing */ |
4734 | 0 | inParamEnd = command; |
4735 | | /* digest the input parameters */ |
4736 | 0 | if (returnCode == TPM_SUCCESS) { |
4737 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
4738 | 0 | &auditStatus, /* output */ |
4739 | 0 | &transportEncrypt, /* output */ |
4740 | 0 | tpm_state, |
4741 | 0 | tag, |
4742 | 0 | ordinal, |
4743 | 0 | inParamStart, |
4744 | 0 | inParamEnd, |
4745 | 0 | transportInternal); |
4746 | 0 | } |
4747 | | /* check state */ |
4748 | 0 | if (returnCode == TPM_SUCCESS) { |
4749 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); |
4750 | 0 | } |
4751 | | /* check tag */ |
4752 | 0 | if (returnCode == TPM_SUCCESS) { |
4753 | 0 | returnCode = TPM_CheckRequestTag210(tag); |
4754 | 0 | } |
4755 | | /* get the optional 'below the line' authorization parameters */ |
4756 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4757 | 0 | returnCode = TPM_AuthParams_Get(&keyAuthHandle, |
4758 | 0 | &keyAuthHandleValid, |
4759 | 0 | keynonceOdd, |
4760 | 0 | &continueKeySession, |
4761 | 0 | keyAuth, |
4762 | 0 | &command, ¶mSize); |
4763 | 0 | } |
4764 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4765 | 0 | printf("TPM_Process_CertifyKey2: keyAuthHandle %08x\n", keyAuthHandle); |
4766 | 0 | } |
4767 | | /* get the optional 'below the line' authorization parameters */ |
4768 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4769 | 0 | returnCode = TPM_AuthParams_Get(&certAuthHandle, |
4770 | 0 | &certAuthHandleValid, |
4771 | 0 | nonceOdd, |
4772 | 0 | &continueAuthSession, |
4773 | 0 | certAuth, |
4774 | 0 | &command, ¶mSize); |
4775 | 0 | } |
4776 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4777 | 0 | printf("TPM_Process_CertifyKey2: certAuthHandle %08x\n", certAuthHandle); |
4778 | 0 | } |
4779 | 0 | if (returnCode == TPM_SUCCESS) { |
4780 | 0 | if (paramSize != 0) { |
4781 | 0 | printf("TPM_Process_CertifyKey2: Error, command has %u extra bytes\n", |
4782 | 0 | paramSize); |
4783 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
4784 | 0 | } |
4785 | 0 | } |
4786 | | /* do not terminate sessions if the command did not parse correctly */ |
4787 | 0 | if (returnCode != TPM_SUCCESS) { |
4788 | 0 | certAuthHandleValid = FALSE; |
4789 | 0 | keyAuthHandleValid = FALSE; |
4790 | 0 | } |
4791 | | /* |
4792 | | Processing |
4793 | | */ |
4794 | | /* get the keys corresponding to the certHandle and keyHandle parameters */ |
4795 | 0 | if (returnCode == TPM_SUCCESS) { |
4796 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, |
4797 | 0 | FALSE, /* not read-only */ |
4798 | 0 | FALSE, /* do not ignore PCRs */ |
4799 | 0 | FALSE); /* cannot use EK */ |
4800 | 0 | } |
4801 | 0 | if (returnCode == TPM_SUCCESS) { |
4802 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, |
4803 | 0 | FALSE, /* not read-only */ |
4804 | 0 | FALSE, /* do not ignore PCRs */ |
4805 | 0 | FALSE); /* cannot use EK */ |
4806 | 0 | } |
4807 | | /* get the TPM_STORE_ASYMKEY cache for the target TPM_KEY */ |
4808 | 0 | if (returnCode == TPM_SUCCESS) { |
4809 | 0 | returnCode = TPM_Key_GetStoreAsymkey(&targetStoreAsymkey, targetKey); |
4810 | 0 | } |
4811 | | /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of |
4812 | | TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ |
4813 | 0 | if (returnCode == TPM_SUCCESS) { |
4814 | 0 | if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && |
4815 | 0 | (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { |
4816 | 0 | printf("TPM_Process_CertifyKey2: Error, invalid certKey sigScheme %04hx\n", |
4817 | 0 | certKey->algorithmParms.sigScheme); |
4818 | 0 | returnCode = TPM_BAD_KEY_PROPERTY; |
4819 | 0 | } |
4820 | 0 | } |
4821 | | /* 2. Verify command and key AuthData values: */ |
4822 | | /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ |
4823 | | /* i. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key |
4824 | | pointed to by keyHandle, return TPM_AUTHFAIL on error */ |
4825 | | /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key |
4826 | | pointed to by certHandle, return TPM_AUTH2FAIL on error */ |
4827 | | /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ |
4828 | | /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key |
4829 | | referenced by keyHandle, return TPM_AUTHFAIL on error */ |
4830 | | /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key |
4831 | | pointed to by certHandle, return TPM_AUTHFAIL on error */ |
4832 | | /* c. else if tag is TPM_TAG_RQU_COMMAND */ |
4833 | | /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key |
4834 | | referenced by keyHandle, return TPM_AUTHFAIL on error */ |
4835 | | /* ii. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return |
4836 | | TPM_AUTHFAIL on error. */ |
4837 | | /* NOTE: Simplified the above logic as follows */ |
4838 | | /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ |
4839 | | /* get keyHandle -> usageAuth */ |
4840 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4841 | 0 | returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); |
4842 | 0 | } |
4843 | | /* get the first session data */ |
4844 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4845 | 0 | returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, |
4846 | 0 | &targetHmacKey, |
4847 | 0 | tpm_state, |
4848 | 0 | keyAuthHandle, |
4849 | 0 | TPM_PID_NONE, |
4850 | 0 | TPM_ET_KEYHANDLE, |
4851 | 0 | ordinal, |
4852 | 0 | targetKey, |
4853 | 0 | targetKeyUsageAuth, /* OIAP */ |
4854 | 0 | targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ |
4855 | 0 | } |
4856 | | /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key |
4857 | | pointed to by keyHandle, return TPM_AUTHFAIL on error */ |
4858 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
4859 | 0 | returnCode = TPM_Authdata_Check(tpm_state, |
4860 | 0 | *targetHmacKey, /* HMAC key */ |
4861 | 0 | inParamDigest, |
4862 | 0 | target_auth_session_data, /* authorization session */ |
4863 | 0 | keynonceOdd, /* Nonce generated by system |
4864 | | associated with authHandle */ |
4865 | 0 | continueKeySession, |
4866 | 0 | keyAuth); /* Authorization digest for input */ |
4867 | 0 | } |
4868 | | /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ |
4869 | | /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced |
4870 | | by keyHandle, return TPM_AUTHFAIL on error. */ |
4871 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { |
4872 | 0 | if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { |
4873 | 0 | printf("TPM_Process_CertifyKey2: Error, target key authorization required\n"); |
4874 | 0 | returnCode = TPM_AUTHFAIL; |
4875 | 0 | } |
4876 | 0 | } |
4877 | | /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of |
4878 | | authorization data */ |
4879 | | /* get certHandle -> usageAuth */ |
4880 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4881 | 0 | returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); |
4882 | 0 | } |
4883 | | /* get the second session data */ |
4884 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4885 | 0 | returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, |
4886 | 0 | &certHmacKey, |
4887 | 0 | tpm_state, |
4888 | 0 | certAuthHandle, |
4889 | 0 | TPM_PID_NONE, |
4890 | 0 | TPM_ET_KEYHANDLE, |
4891 | 0 | ordinal, |
4892 | 0 | certKey, |
4893 | 0 | certKeyUsageAuth, /* OIAP */ |
4894 | 0 | certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ |
4895 | 0 | } |
4896 | | /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key |
4897 | | pointed to by certHandle, return TPM_AUTH2FAIL on error */ |
4898 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
4899 | 0 | returnCode = TPM_Auth2data_Check(tpm_state, |
4900 | 0 | *certHmacKey, /* HMAC key */ |
4901 | 0 | inParamDigest, |
4902 | 0 | cert_auth_session_data, /* authorization session */ |
4903 | 0 | nonceOdd, /* Nonce generated by system |
4904 | | associated with authHandle */ |
4905 | 0 | continueAuthSession, |
4906 | 0 | certAuth); /* Authorization digest for input */ |
4907 | 0 | } |
4908 | | /* If the command is TPM_TAG_RQU_COMMAND */ |
4909 | | /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return |
4910 | | TPM_AUTHFAIL on error. */ |
4911 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { |
4912 | 0 | if (certKey->authDataUsage != TPM_AUTH_NEVER) { |
4913 | 0 | printf("TPM_Process_CertifyKey2: Error, cert key authorization required\n"); |
4914 | 0 | returnCode = TPM_AUTHFAIL; |
4915 | 0 | } |
4916 | 0 | } |
4917 | | /* 3. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is |
4918 | | TPM_KEY_IDENTITY) */ |
4919 | 0 | if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { |
4920 | | /* a. If keyHandle -> keyFlags -> migratable is TRUE and |
4921 | | [keyHandle -> keyFlags-> migrateAuthority is FALSE or |
4922 | | (keyHandle -> payload != TPM_PT_MIGRATE_RESTRICTED and |
4923 | | keyHandle -> payload != TPM_PT_MIGRATE_EXTERNAL)] |
4924 | | return TPM_MIGRATEFAIL */ |
4925 | 0 | if ((targetKey->keyFlags & TPM_MIGRATABLE) && |
4926 | 0 | (!(targetKey->keyFlags & TPM_MIGRATEAUTHORITY) || |
4927 | 0 | ((targetStoreAsymkey->payload != TPM_PT_MIGRATE_RESTRICTED) && |
4928 | 0 | (targetStoreAsymkey->payload != TPM_PT_MIGRATE_EXTERNAL)))) { |
4929 | 0 | printf("TPM_Process_CertifyKey2: Error, target key migrate fail\n"); |
4930 | 0 | returnCode = TPM_MIGRATEFAIL; |
4931 | 0 | } |
4932 | 0 | } |
4933 | | /* 4. Validate that certHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or |
4934 | | TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ |
4935 | 0 | if (returnCode == TPM_SUCCESS) { |
4936 | 0 | printf("TPM_Process_CertifyKey2: certHandle ->keyUsage %04hx\n", certKey->keyUsage); |
4937 | 0 | if ((certKey->keyUsage != TPM_KEY_SIGNING) && |
4938 | 0 | ((certKey->keyUsage) != TPM_KEY_IDENTITY) && |
4939 | 0 | ((certKey->keyUsage) != TPM_KEY_LEGACY)) { |
4940 | 0 | printf("TPM_Process_CertifyKey2: Error, keyUsage %04hx is invalid\n", |
4941 | 0 | certKey->keyUsage); |
4942 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
4943 | 0 | } |
4944 | 0 | } |
4945 | | /* 5. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, |
4946 | | TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ |
4947 | 0 | if (returnCode == TPM_SUCCESS) { |
4948 | 0 | printf("TPM_Process_CertifyKey2: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); |
4949 | 0 | if ((targetKey->keyUsage != TPM_KEY_SIGNING) && |
4950 | 0 | ((targetKey->keyUsage) != TPM_KEY_STORAGE) && |
4951 | 0 | ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && |
4952 | 0 | ((targetKey->keyUsage) != TPM_KEY_BIND) && |
4953 | 0 | ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { |
4954 | 0 | printf("TPM_Process_CertifyKey2: Error, keyHandle -> keyUsage %04hx is invalid\n", |
4955 | 0 | targetKey->keyUsage); |
4956 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
4957 | 0 | } |
4958 | 0 | } |
4959 | | /* 6. The TPM SHALL create a c1 a TPM_CERTIFY_INFO2 structure from the key pointed to by |
4960 | | keyHandle */ |
4961 | 0 | if (returnCode == TPM_SUCCESS) { |
4962 | 0 | returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); |
4963 | 0 | } |
4964 | | /* 7. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that |
4965 | | <key> is the actual public modulus, and does not include any structure formatting. */ |
4966 | | /* 8. Set C1 -> pubKeyDigest to H1 */ |
4967 | | /* NOTE: Done by TPM_CertifyInfo2_Set() */ |
4968 | 0 | if (returnCode == TPM_SUCCESS) { |
4969 | | /* 9. Copy the antiReplay parameter to c1 -> data */ |
4970 | 0 | TPM_Digest_Copy(certifyInfo2.data, antiReplay); |
4971 | | /* 10. Copy other keyHandle parameters into C1 */ |
4972 | 0 | certifyInfo2.parentPCRStatus = targetPCRStatus; |
4973 | | /* 11. If keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */ |
4974 | 0 | if ((targetStoreAsymkey->payload == TPM_PT_MIGRATE_RESTRICTED) || |
4975 | 0 | (targetStoreAsymkey->payload == TPM_PT_MIGRATE_EXTERNAL)) { |
4976 | 0 | printf("TPM_Process_CertifyKey2: " |
4977 | 0 | "TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); |
4978 | | /* a. create thisPubKey, a TPM_PUBKEY structure containing the public key, algorithm and |
4979 | | parameters corresponding to keyHandle */ |
4980 | | /* NOTE Not required. Digest is created directly below */ |
4981 | | /* b. Verify that the migration authorization is valid for this key */ |
4982 | | /* i. Create M2 a TPM_CMK_MIGAUTH structure */ |
4983 | | /* NOTE Done by TPM_CmkMigauth_Init() */ |
4984 | 0 | if (returnCode == TPM_SUCCESS) { |
4985 | | /* ii. Set M2 -> msaDigest to migrationPubDigest */ |
4986 | 0 | TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationPubDigest ); |
4987 | | /* iii. Set M2 -> pubKeyDigest to SHA-1[thisPubKey] */ |
4988 | 0 | returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, targetKey); |
4989 | 0 | } |
4990 | | /* iv. Verify that [keyHandle -> migrationAuth] == HMAC(M2) signed by using tpmProof as |
4991 | | the secret and return error TPM_MA_SOURCE on mismatch */ |
4992 | 0 | if (returnCode == TPM_SUCCESS) { |
4993 | 0 | printf("TPM_Process_CertifyKey2: Check migrationAuth\n"); |
4994 | 0 | returnCode = |
4995 | 0 | TPM_CmkMigauth_CheckHMAC(&hmacValid, /* result */ |
4996 | 0 | targetStoreAsymkey->migrationAuth, /* expect */ |
4997 | 0 | tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ |
4998 | 0 | &m2CmkMigauth); |
4999 | 0 | } |
5000 | 0 | if (returnCode == TPM_SUCCESS) { |
5001 | 0 | if (!hmacValid) { |
5002 | 0 | printf("TPM_Process_CertifyKey2: Error, Invalid migrationAuth\n"); |
5003 | 0 | returnCode = TPM_MA_SOURCE; |
5004 | 0 | } |
5005 | 0 | } |
5006 | | /* c. Set C1 -> migrationAuthority = SHA-1(migrationPubDigest || keyHandle -> payload) |
5007 | | */ |
5008 | 0 | if (returnCode == TPM_SUCCESS) { |
5009 | 0 | printf("TPM_Process_CertifyKey2: Set migrationAuthority\n"); |
5010 | 0 | returnCode = TPM_SHA1(migrationAuthority, |
5011 | 0 | TPM_DIGEST_SIZE, migrationPubDigest, |
5012 | 0 | sizeof(TPM_PAYLOAD_TYPE), &(targetStoreAsymkey->payload), |
5013 | 0 | 0, NULL); |
5014 | 0 | } |
5015 | 0 | if (returnCode == TPM_SUCCESS) { |
5016 | 0 | returnCode = TPM_SizedBuffer_Set(&(certifyInfo2.migrationAuthority), |
5017 | 0 | TPM_DIGEST_SIZE, migrationAuthority); |
5018 | 0 | } |
5019 | | /* d. if keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED */ |
5020 | | /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_RESTRICTED */ |
5021 | | /* e. if keyHandle -> payload == TPM_PT_MIGRATE_EXTERNAL */ |
5022 | | /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_EXTERNAL */ |
5023 | | /* NOTE: Done by TPM_CertifyInfo2_Set() */ |
5024 | 0 | } |
5025 | | /* 12. Else */ |
5026 | 0 | else { |
5027 | 0 | printf("TPM_Process_CertifyKey2: " |
5028 | 0 | " Not TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); |
5029 | | /* a. set C1 -> migrationAuthority = NULL */ |
5030 | | /* b. set C1 -> migrationAuthoritySize = 0 */ |
5031 | | /* NOTE: Done by TPM_CertifyInfo2_Init() */ |
5032 | | /* c. Set C1 -> payloadType = TPM_PT_ASYM */ |
5033 | 0 | certifyInfo2.payloadType = TPM_PT_ASYM; |
5034 | 0 | } |
5035 | 0 | } |
5036 | 0 | if (returnCode == TPM_SUCCESS) { |
5037 | | /* 13. If keyHandle -> pcrInfoSize is not 0 */ |
5038 | 0 | if (targetKey->pcrInfo.size != 0) { |
5039 | 0 | printf("TPM_Process_CertifyKey2: Setting PCR info from key\n"); |
5040 | | /* a. The TPM MUST set c1 -> pcrInfoSize to match the pcrInfoSize from the keyHandle |
5041 | | key. */ |
5042 | | /* b. The TPM MUST set c1 -> pcrInfo to match the pcrInfo from the keyHandle key */ |
5043 | | /* This function actually creates the cache, which is serialized later */ |
5044 | 0 | if (returnCode == TPM_SUCCESS) { |
5045 | 0 | returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), |
5046 | 0 | targetKey); |
5047 | 0 | } |
5048 | | /* c. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ |
5049 | | /* i. Create a digestAtRelease according to the specified PCR registers and compare to |
5050 | | keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ |
5051 | | /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ |
5052 | | /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ |
5053 | 0 | } |
5054 | | /* 14. Else */ |
5055 | | /* a. The TPM MUST set c1 -> pcrInfoSize to 0 */ |
5056 | | /* NOTE: Done by TPM_CertifyInfo2_Init() */ |
5057 | 0 | } |
5058 | | /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1 */ |
5059 | 0 | if (returnCode == TPM_SUCCESS) { |
5060 | 0 | printf("TPM_Process_CertifyKey2: Digesting certifyInfo\n"); |
5061 | 0 | returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, |
5062 | 0 | (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); |
5063 | 0 | } |
5064 | | /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob |
5065 | | is returned in outData */ |
5066 | 0 | if (returnCode == TPM_SUCCESS) { |
5067 | 0 | printf("TPM_Process_CertifyKey2: Signing certifyInfo digest\n"); |
5068 | 0 | returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ |
5069 | 0 | m1Digest, /* message */ |
5070 | 0 | TPM_DIGEST_SIZE, /* message size */ |
5071 | 0 | certKey); /* input, signing key */ |
5072 | 0 | } |
5073 | | /* |
5074 | | response |
5075 | | */ |
5076 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
5077 | 0 | if (rcf == 0) { |
5078 | 0 | printf("TPM_Process_CertifyKey2: Ordinal returnCode %08x %u\n", |
5079 | 0 | returnCode, returnCode); |
5080 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
5081 | 0 | } |
5082 | | /* success response, append the rest of the parameters. */ |
5083 | 0 | if (rcf == 0) { |
5084 | 0 | if (returnCode == TPM_SUCCESS) { |
5085 | | /* checkpoint the beginning of the outParam's */ |
5086 | 0 | outParamStart = response->buffer_current - response->buffer; |
5087 | | /* Return certifyInfo */ |
5088 | 0 | returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); |
5089 | 0 | } |
5090 | 0 | if (returnCode == TPM_SUCCESS) { |
5091 | | /* Return outData */ |
5092 | 0 | returnCode = TPM_SizedBuffer_Store(response, &outData); |
5093 | | /* checkpoint the end of the outParam's */ |
5094 | 0 | outParamEnd = response->buffer_current - response->buffer; |
5095 | 0 | } |
5096 | | /* digest the above the line output parameters */ |
5097 | 0 | if (returnCode == TPM_SUCCESS) { |
5098 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
5099 | 0 | auditStatus, /* input audit status */ |
5100 | 0 | transportEncrypt, |
5101 | 0 | tag, |
5102 | 0 | returnCode, |
5103 | 0 | ordinal, /* command ordinal */ |
5104 | 0 | response->buffer + outParamStart, /* start */ |
5105 | 0 | outParamEnd - outParamStart); /* length */ |
5106 | 0 | } |
5107 | | /* calculate and set the below the line parameters */ |
5108 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { |
5109 | 0 | returnCode = TPM_AuthParams_Set(response, |
5110 | 0 | *targetHmacKey, /* HMAC key */ |
5111 | 0 | target_auth_session_data, |
5112 | 0 | outParamDigest, |
5113 | 0 | keynonceOdd, |
5114 | 0 | continueKeySession); |
5115 | 0 | } |
5116 | | /* calculate and set the below the line parameters */ |
5117 | 0 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { |
5118 | 0 | returnCode = TPM_AuthParams_Set(response, |
5119 | 0 | *certHmacKey, /* HMAC key */ |
5120 | 0 | cert_auth_session_data, |
5121 | 0 | outParamDigest, |
5122 | 0 | nonceOdd, |
5123 | 0 | continueAuthSession); |
5124 | 0 | } |
5125 | | /* audit if required */ |
5126 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
5127 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
5128 | 0 | transportEncrypt, |
5129 | 0 | inParamDigest, |
5130 | 0 | outParamDigest, |
5131 | 0 | ordinal); |
5132 | 0 | } |
5133 | | /* adjust the initial response */ |
5134 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
5135 | 0 | } |
5136 | | /* if there was an error, or continueAuthSession is FALSE, terminate the session */ |
5137 | 0 | if (((rcf != 0) || |
5138 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
5139 | 0 | !continueKeySession) && |
5140 | 0 | keyAuthHandleValid) { |
5141 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); |
5142 | 0 | } |
5143 | 0 | if (((rcf != 0) || |
5144 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
5145 | 0 | !continueAuthSession) && |
5146 | 0 | certAuthHandleValid) { |
5147 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); |
5148 | 0 | } |
5149 | | /* |
5150 | | cleanup |
5151 | | */ |
5152 | 0 | TPM_CertifyInfo2_Delete(&certifyInfo2); /* @1 */ |
5153 | 0 | TPM_SizedBuffer_Delete(&outData); /* @2 */ |
5154 | 0 | TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @3 */ |
5155 | 0 | return rcf; |
5156 | 0 | } |
5157 | | |
5158 | | /* 28.3 TPM_CertifySelfTest rev 94 |
5159 | | |
5160 | | CertifySelfTest causes the TPM to perform a full self-test and return an authenticated value if |
5161 | | the test passes. |
5162 | | |
5163 | | If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM |
5164 | | and the caller have AuthData. |
5165 | | |
5166 | | If a caller requires proof for a third party, the signing key must be one whose signature is |
5167 | | trusted by the third party. A TPM-identity key may be suitable. |
5168 | | |
5169 | | Information returned by TPM_CertifySelfTest MUST NOT aid identification of an individual TPM. |
5170 | | */ |
5171 | | |
5172 | | TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state, |
5173 | | TPM_STORE_BUFFER *response, |
5174 | | TPM_TAG tag, |
5175 | | uint32_t paramSize, |
5176 | | TPM_COMMAND_CODE ordinal, |
5177 | | unsigned char *command, |
5178 | | TPM_TRANSPORT_INTERNAL *transportInternal) |
5179 | 0 | { |
5180 | 0 | TPM_RESULT rcf = 0; /* fatal error precluding response */ |
5181 | 0 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ |
5182 | | |
5183 | | /* input parameters */ |
5184 | 0 | TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform |
5185 | | digital signatures. */ |
5186 | 0 | TPM_NONCE antiReplay; /* AntiReplay nonce to prevent replay of messages */ |
5187 | 0 | TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle |
5188 | | authorization */ |
5189 | 0 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ |
5190 | 0 | TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session |
5191 | | handle */ |
5192 | 0 | TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the |
5193 | | inputs and use of keyHandle. HMAC key: key.usageAuth */ |
5194 | | |
5195 | | /* processing parameters */ |
5196 | 0 | unsigned char * inParamStart; /* starting point of inParam's */ |
5197 | 0 | unsigned char * inParamEnd; /* ending point of inParam's */ |
5198 | 0 | TPM_DIGEST inParamDigest; |
5199 | 0 | TPM_BOOL auditStatus; /* audit the ordinal */ |
5200 | 0 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ |
5201 | 0 | TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ |
5202 | 0 | TPM_BOOL authHandleValid = FALSE; |
5203 | 0 | TPM_SECRET *hmacKey; |
5204 | 0 | TPM_KEY *sigKey; /* from keyHandle */ |
5205 | 0 | TPM_BOOL sigKeyPCRStatus; |
5206 | 0 | TPM_SECRET *sigKeyUsageAuth; |
5207 | 0 | TPM_COMMAND_CODE nOrdinal; /* ordinal in nbo */ |
5208 | 0 | TPM_DIGEST m2Digest; /* message to sign */ |
5209 | | |
5210 | | /* output parameters */ |
5211 | 0 | uint32_t outParamStart; /* starting point of outParam's */ |
5212 | 0 | uint32_t outParamEnd; /* ending point of outParam's */ |
5213 | 0 | TPM_DIGEST outParamDigest; |
5214 | 0 | TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ |
5215 | |
|
5216 | 0 | printf("TPM_Process_CertifySelfTest: Ordinal Entry\n"); |
5217 | 0 | TPM_SizedBuffer_Init(&sig); /* freed @1 */ |
5218 | | /* |
5219 | | get inputs |
5220 | | */ |
5221 | | /* get keyHandle parameter */ |
5222 | 0 | if (returnCode == TPM_SUCCESS) { |
5223 | 0 | returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); |
5224 | 0 | } |
5225 | | /* save the starting point of inParam's for authorization and auditing */ |
5226 | 0 | inParamStart = command; |
5227 | | /* get the antiReplay parameter */ |
5228 | 0 | if (returnCode == TPM_SUCCESS) { |
5229 | 0 | printf("TPM_Process_CertifySelfTest: keyHandle %08x\n", keyHandle); |
5230 | 0 | returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); |
5231 | 0 | } |
5232 | | /* save the ending point of inParam's for authorization and auditing */ |
5233 | 0 | inParamEnd = command; |
5234 | | /* digest the input parameters */ |
5235 | 0 | if (returnCode == TPM_SUCCESS) { |
5236 | 0 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ |
5237 | 0 | &auditStatus, /* output */ |
5238 | 0 | &transportEncrypt, /* output */ |
5239 | 0 | tpm_state, |
5240 | 0 | tag, |
5241 | 0 | ordinal, |
5242 | 0 | inParamStart, |
5243 | 0 | inParamEnd, |
5244 | 0 | transportInternal); |
5245 | 0 | } |
5246 | | /* check state */ |
5247 | 0 | if (returnCode == TPM_SUCCESS) { |
5248 | 0 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); |
5249 | 0 | } |
5250 | | /* check tag */ |
5251 | 0 | if (returnCode == TPM_SUCCESS) { |
5252 | 0 | returnCode = TPM_CheckRequestTag10(tag); |
5253 | 0 | } |
5254 | | /* get the optional 'below the line' authorization parameters */ |
5255 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
5256 | 0 | returnCode = TPM_AuthParams_Get(&authHandle, |
5257 | 0 | &authHandleValid, |
5258 | 0 | nonceOdd, |
5259 | 0 | &continueAuthSession, |
5260 | 0 | privAuth, |
5261 | 0 | &command, ¶mSize); |
5262 | 0 | } |
5263 | 0 | if (returnCode == TPM_SUCCESS) { |
5264 | 0 | if (paramSize != 0) { |
5265 | 0 | printf("TPM_Process_CertifySelfTest: Error, command has %u extra bytes\n", |
5266 | 0 | paramSize); |
5267 | 0 | returnCode = TPM_BAD_PARAM_SIZE; |
5268 | 0 | } |
5269 | 0 | } |
5270 | | /* do not terminate sessions if the command did not parse correctly */ |
5271 | 0 | if (returnCode != TPM_SUCCESS) { |
5272 | 0 | authHandleValid = FALSE; |
5273 | 0 | } |
5274 | | /* |
5275 | | Processing |
5276 | | */ |
5277 | | /* 1. The TPM SHALL perform TPM_SelfTestFull. If the test fails the TPM returns the appropriate |
5278 | | error code. */ |
5279 | 0 | if (returnCode == TPM_SUCCESS) { |
5280 | 0 | printf("TPM_Process_CertifySelfTest: Running self test\n"); |
5281 | 0 | returnCode = TPM_SelfTestFullCmd(tpm_state); |
5282 | 0 | } |
5283 | | /* 2. After successful completion of the self-test the TPM then validates the authorization to |
5284 | | use the key pointed to by keyHandle */ |
5285 | 0 | if (returnCode == TPM_SUCCESS) { |
5286 | 0 | returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &sigKeyPCRStatus, tpm_state, keyHandle, |
5287 | 0 | FALSE, /* not read-only */ |
5288 | 0 | FALSE, /* do not ignore PCRs */ |
5289 | 0 | FALSE); /* cannot use EK */ |
5290 | 0 | } |
5291 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ |
5292 | 0 | if (sigKey->authDataUsage != TPM_AUTH_NEVER) { |
5293 | 0 | printf("TPM_Process_CertifySelfTest: Error, authorization required\n"); |
5294 | 0 | returnCode = TPM_AUTHFAIL; |
5295 | 0 | } |
5296 | 0 | } |
5297 | | /* get keyHandle -> usageAuth */ |
5298 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
5299 | 0 | returnCode = TPM_Key_GetUsageAuth(&sigKeyUsageAuth, sigKey); |
5300 | 0 | } |
5301 | | /* get the session data */ |
5302 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
5303 | 0 | returnCode = TPM_AuthSessions_GetData(&auth_session_data, |
5304 | 0 | &hmacKey, |
5305 | 0 | tpm_state, |
5306 | 0 | authHandle, |
5307 | 0 | TPM_PID_NONE, |
5308 | 0 | TPM_ET_KEYHANDLE, |
5309 | 0 | ordinal, |
5310 | 0 | sigKey, |
5311 | 0 | sigKeyUsageAuth, /* OIAP */ |
5312 | 0 | sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ |
5313 | 0 | } |
5314 | | /* Validate the command parameters using privAuth */ |
5315 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
5316 | 0 | returnCode = TPM_Authdata_Check(tpm_state, |
5317 | 0 | *hmacKey, /* HMAC key */ |
5318 | 0 | inParamDigest, |
5319 | 0 | auth_session_data, /* authorization session */ |
5320 | 0 | nonceOdd, /* Nonce generated by system |
5321 | | associated with authHandle */ |
5322 | 0 | continueAuthSession, |
5323 | 0 | privAuth); /* Authorization digest for input */ |
5324 | 0 | } |
5325 | | /* a. If the key pointed to by keyHandle has a signature scheme that is not |
5326 | | TPM_SS_RSASSAPKCS1v15_SHA1, the TPM may either return TPM_BAD_SCHEME or may return |
5327 | | TPM_SUCCESS and a vendor specific signature. */ |
5328 | 0 | if (returnCode == TPM_SUCCESS) { |
5329 | 0 | if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { |
5330 | 0 | printf("TPM_Process_CertifySelfTest: Error, invalid sigKey sigScheme %04hx\n", |
5331 | 0 | sigKey->algorithmParms.sigScheme); |
5332 | 0 | returnCode = TPM_BAD_SCHEME; |
5333 | 0 | } |
5334 | 0 | } |
5335 | | /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or |
5336 | | TPM_KEY_IDENTITY. */ |
5337 | 0 | if (returnCode == TPM_SUCCESS) { |
5338 | 0 | if ((sigKey->keyUsage != TPM_KEY_SIGNING) && |
5339 | 0 | (sigKey->keyUsage != TPM_KEY_LEGACY) && |
5340 | 0 | (sigKey->keyUsage != TPM_KEY_IDENTITY)) { |
5341 | 0 | printf("TPM_Process_CertifySelfTest: Error, Illegal keyUsage %04hx\n", |
5342 | 0 | sigKey->keyUsage); |
5343 | 0 | returnCode = TPM_INVALID_KEYUSAGE; |
5344 | 0 | } |
5345 | 0 | } |
5346 | | /* 3. Create t1 the NOT null terminated string of "Test Passed" */ |
5347 | | /* 4. The TPM creates m2 the message to sign by concatenating t1 || AntiReplay || ordinal. */ |
5348 | 0 | if (returnCode == TPM_SUCCESS) { |
5349 | 0 | nOrdinal = htonl(ordinal); |
5350 | 0 | returnCode = TPM_SHA1(m2Digest, |
5351 | 0 | sizeof("Test Passed") - 1, "Test Passed", |
5352 | 0 | TPM_NONCE_SIZE, antiReplay, |
5353 | 0 | sizeof(TPM_COMMAND_CODE), &nOrdinal, |
5354 | 0 | 0, NULL); |
5355 | 0 | } |
5356 | | /* 5. The TPM signs the SHA-1 of m2 using the key identified by keyHandle, and returns the |
5357 | | signature as sig. */ |
5358 | 0 | if (returnCode == TPM_SUCCESS) { |
5359 | 0 | printf("TPM_Process_CertifySelfTest: Signing certifyInfo digest\n"); |
5360 | 0 | returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ |
5361 | 0 | m2Digest, /* message */ |
5362 | 0 | TPM_DIGEST_SIZE, /* message size */ |
5363 | 0 | sigKey); /* input, signing key */ |
5364 | 0 | } |
5365 | | /* |
5366 | | response |
5367 | | */ |
5368 | | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ |
5369 | 0 | if (rcf == 0) { |
5370 | 0 | printf("TPM_Process_CertifySelfTest: Ordinal returnCode %08x %u\n", |
5371 | 0 | returnCode, returnCode); |
5372 | 0 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); |
5373 | 0 | } |
5374 | | /* success response, append the rest of the parameters. */ |
5375 | 0 | if (rcf == 0) { |
5376 | 0 | if (returnCode == TPM_SUCCESS) { |
5377 | | /* checkpoint the beginning of the outParam's */ |
5378 | 0 | outParamStart = response->buffer_current - response->buffer; |
5379 | | /* return sig */ |
5380 | 0 | returnCode = TPM_SizedBuffer_Store(response, &sig); |
5381 | | /* checkpoint the end of the outParam's */ |
5382 | 0 | outParamEnd = response->buffer_current - response->buffer; |
5383 | 0 | } |
5384 | | /* digest the above the line output parameters */ |
5385 | 0 | if (returnCode == TPM_SUCCESS) { |
5386 | 0 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ |
5387 | 0 | auditStatus, /* input audit status */ |
5388 | 0 | transportEncrypt, |
5389 | 0 | tag, |
5390 | 0 | returnCode, |
5391 | 0 | ordinal, /* command ordinal */ |
5392 | 0 | response->buffer + outParamStart, /* start */ |
5393 | 0 | outParamEnd - outParamStart); /* length */ |
5394 | 0 | } |
5395 | | /* calculate and set the below the line parameters */ |
5396 | 0 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { |
5397 | 0 | returnCode = TPM_AuthParams_Set(response, |
5398 | 0 | *hmacKey, /* owner HMAC key */ |
5399 | 0 | auth_session_data, |
5400 | 0 | outParamDigest, |
5401 | 0 | nonceOdd, |
5402 | 0 | continueAuthSession); |
5403 | 0 | } |
5404 | | /* audit if required */ |
5405 | 0 | if ((returnCode == TPM_SUCCESS) && auditStatus) { |
5406 | 0 | returnCode = TPM_ProcessAudit(tpm_state, |
5407 | 0 | transportEncrypt, |
5408 | 0 | inParamDigest, |
5409 | 0 | outParamDigest, |
5410 | 0 | ordinal); |
5411 | 0 | } |
5412 | | /* adjust the initial response */ |
5413 | 0 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); |
5414 | 0 | } |
5415 | | /* if there was an error, or continueAuthSession is FALSE, terminate the session */ |
5416 | 0 | if (((rcf != 0) || |
5417 | 0 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || |
5418 | 0 | !continueAuthSession) && |
5419 | 0 | authHandleValid) { |
5420 | 0 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); |
5421 | 0 | } |
5422 | | /* |
5423 | | cleanup |
5424 | | */ |
5425 | 0 | TPM_SizedBuffer_Delete(&sig); /* @1 */ |
5426 | 0 | return rcf; |
5427 | 0 | } |