1 | /********************************************************************************/
|
---|
2 | /* */
|
---|
3 | /* TPM Identity Handling */
|
---|
4 | /* Written by Ken Goldman */
|
---|
5 | /* IBM Thomas J. Watson Research Center */
|
---|
6 | /* $Id: tpm_identity.c 4526 2011-03-24 21:14:42Z 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 |
|
---|
43 | #include "tpm_auth.h"
|
---|
44 | #include "tpm_crypto.h"
|
---|
45 | #include "tpm_cryptoh.h"
|
---|
46 | #include "tpm_debug.h"
|
---|
47 | #include "tpm_digest.h"
|
---|
48 | #include "tpm_error.h"
|
---|
49 | #include "tpm_io.h"
|
---|
50 | #include "tpm_key.h"
|
---|
51 | #include "tpm_memory.h"
|
---|
52 | #include "tpm_pcr.h"
|
---|
53 | #include "tpm_process.h"
|
---|
54 | #include "tpm_secret.h"
|
---|
55 | #include "tpm_storage.h"
|
---|
56 | #include "tpm_ver.h"
|
---|
57 | #include "tpm_identity.h"
|
---|
58 |
|
---|
59 | /*
|
---|
60 | TPM_EK_BLOB
|
---|
61 | */
|
---|
62 |
|
---|
63 | /* TPM_EKBlob_Init()
|
---|
64 |
|
---|
65 | sets members to default values
|
---|
66 | sets all pointers to NULL and sizes to 0
|
---|
67 | always succeeds - no return code
|
---|
68 | */
|
---|
69 |
|
---|
70 | void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob)
|
---|
71 | {
|
---|
72 | printf(" TPM_EKBlob_Init:\n");
|
---|
73 | tpm_ek_blob->ekType = 0;
|
---|
74 | TPM_SizedBuffer_Init(&(tpm_ek_blob->blob));
|
---|
75 | return;
|
---|
76 | }
|
---|
77 |
|
---|
78 | /* TPM_EKBlob_Load()
|
---|
79 |
|
---|
80 | deserialize the structure from a 'stream'
|
---|
81 | 'stream_size' is checked for sufficient data
|
---|
82 | returns 0 or error codes
|
---|
83 |
|
---|
84 | Before use, call TPM_EKBlob_Init()
|
---|
85 | After use, call TPM_EKBlob_Delete() to free memory
|
---|
86 | */
|
---|
87 |
|
---|
88 | TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob,
|
---|
89 | unsigned char **stream,
|
---|
90 | uint32_t *stream_size)
|
---|
91 | {
|
---|
92 | TPM_RESULT rc = 0;
|
---|
93 |
|
---|
94 | printf(" TPM_EKBlob_Load:\n");
|
---|
95 | /* check the tag */
|
---|
96 | if (rc == 0) {
|
---|
97 | rc = TPM_CheckTag(TPM_TAG_EK_BLOB, stream, stream_size);
|
---|
98 | }
|
---|
99 | /* load ekType */
|
---|
100 | if (rc == 0) {
|
---|
101 | rc = TPM_Load16(&(tpm_ek_blob->ekType), stream, stream_size);
|
---|
102 | }
|
---|
103 | /* load blob */
|
---|
104 | if (rc == 0) {
|
---|
105 | rc = TPM_SizedBuffer_Load(&(tpm_ek_blob->blob), stream, stream_size);
|
---|
106 | }
|
---|
107 | return rc;
|
---|
108 | }
|
---|
109 |
|
---|
110 | #if 0
|
---|
111 | /* TPM_EKBlob_Store()
|
---|
112 |
|
---|
113 | serialize the structure to a stream contained in 'sbuffer'
|
---|
114 | returns 0 or error codes
|
---|
115 | */
|
---|
116 |
|
---|
117 | TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer,
|
---|
118 | const TPM_EK_BLOB *tpm_ek_blob)
|
---|
119 | {
|
---|
120 | TPM_RESULT rc = 0;
|
---|
121 |
|
---|
122 | printf(" TPM_EKBlob_Store:\n");
|
---|
123 | if (rc == 0) {
|
---|
124 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB);
|
---|
125 | }
|
---|
126 | if (rc == 0) {
|
---|
127 | rc = TPM_Sbuffer_Append16(sbuffer, tpm_ek_blob->ekType);
|
---|
128 | }
|
---|
129 | if (rc == 0) {
|
---|
130 | rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_ek_blob->blob));
|
---|
131 | }
|
---|
132 | return rc;
|
---|
133 | }
|
---|
134 | #endif
|
---|
135 |
|
---|
136 | /* TPM_EKBlob_Delete()
|
---|
137 |
|
---|
138 | No-OP if the parameter is NULL, else:
|
---|
139 | frees memory allocated for the object
|
---|
140 | sets pointers to NULL
|
---|
141 | calls TPM_EKBlob_Init to set members back to default values
|
---|
142 | The object itself is not freed
|
---|
143 | */
|
---|
144 |
|
---|
145 | void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob)
|
---|
146 | {
|
---|
147 | printf(" TPM_EKBlob_Delete:\n");
|
---|
148 | if (tpm_ek_blob != NULL) {
|
---|
149 | TPM_SizedBuffer_Delete(&(tpm_ek_blob->blob));
|
---|
150 | TPM_EKBlob_Init(tpm_ek_blob);
|
---|
151 | }
|
---|
152 | return;
|
---|
153 | }
|
---|
154 |
|
---|
155 | /*
|
---|
156 | TPM_EK_BLOB_ACTIVATE
|
---|
157 | */
|
---|
158 |
|
---|
159 | /* TPM_EKBlobActivate_Init()
|
---|
160 |
|
---|
161 | sets members to default values
|
---|
162 | sets all pointers to NULL and sizes to 0
|
---|
163 | always succeeds - no return code
|
---|
164 | */
|
---|
165 |
|
---|
166 | void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
|
---|
167 | {
|
---|
168 | printf(" TPM_EKBlobActivate_Init:\n");
|
---|
169 | TPM_SymmetricKey_Init(&(tpm_ek_blob_activate->sessionKey));
|
---|
170 | TPM_Digest_Init(tpm_ek_blob_activate->idDigest);
|
---|
171 | TPM_PCRInfoShort_Init(&(tpm_ek_blob_activate->pcrInfo));
|
---|
172 | return;
|
---|
173 | }
|
---|
174 |
|
---|
175 | /* TPM_EKBlobActivate_Load()
|
---|
176 |
|
---|
177 | deserialize the structure from a 'stream'
|
---|
178 | 'stream_size' is checked for sufficient data
|
---|
179 | returns 0 or error codes
|
---|
180 |
|
---|
181 | Before use, call TPM_EKBlobActivate_Init()
|
---|
182 | After use, call TPM_EKBlobActivate_Delete() to free memory
|
---|
183 | */
|
---|
184 |
|
---|
185 | TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate,
|
---|
186 | unsigned char **stream,
|
---|
187 | uint32_t *stream_size)
|
---|
188 | {
|
---|
189 | TPM_RESULT rc = 0;
|
---|
190 |
|
---|
191 | printf(" TPM_EKBlobActivate_Load:\n");
|
---|
192 | /* check tag */
|
---|
193 | if (rc == 0) {
|
---|
194 | rc = TPM_CheckTag(TPM_TAG_EK_BLOB_ACTIVATE, stream, stream_size);
|
---|
195 | }
|
---|
196 | /* load sessionKey */
|
---|
197 | if (rc == 0) {
|
---|
198 | rc = TPM_SymmetricKey_Load(&(tpm_ek_blob_activate->sessionKey), stream, stream_size);
|
---|
199 | }
|
---|
200 | /* load idDigest */
|
---|
201 | if (rc == 0) {
|
---|
202 | rc = TPM_Digest_Load(tpm_ek_blob_activate->idDigest, stream, stream_size);
|
---|
203 | }
|
---|
204 | /* load pcrInfo */
|
---|
205 | if (rc == 0) {
|
---|
206 | rc = TPM_PCRInfoShort_Load(&(tpm_ek_blob_activate->pcrInfo), stream, stream_size, FALSE);
|
---|
207 | }
|
---|
208 | return rc;
|
---|
209 | }
|
---|
210 |
|
---|
211 | #if 0
|
---|
212 | /* TPM_EKBlobActivate_Store()
|
---|
213 |
|
---|
214 | serialize the structure to a stream contained in 'sbuffer'
|
---|
215 | returns 0 or error codes
|
---|
216 | */
|
---|
217 |
|
---|
218 | TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer,
|
---|
219 | const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
|
---|
220 | {
|
---|
221 | TPM_RESULT rc = 0;
|
---|
222 |
|
---|
223 | printf(" TPM_EKBlobActivate_Store:\n");
|
---|
224 | /* store tag */
|
---|
225 | if (rc == 0) {
|
---|
226 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_ACTIVATE);
|
---|
227 | }
|
---|
228 | /* store sessionKey */
|
---|
229 | if (rc == 0) {
|
---|
230 | rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_ek_blob_activate->sessionKey));
|
---|
231 | }
|
---|
232 | /* store idDigest */
|
---|
233 | if (rc == 0) {
|
---|
234 | rc = TPM_Digest_Store(sbuffer, tpm_ek_blob_activate->idDigest);
|
---|
235 | }
|
---|
236 | /* store pcrInfo */
|
---|
237 | if (rc == 0) {
|
---|
238 | rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_ek_blob_activate->pcrInfo), FALSE);
|
---|
239 | }
|
---|
240 | return rc;
|
---|
241 | }
|
---|
242 | #endif
|
---|
243 |
|
---|
244 | /* TPM_EKBlobActivate_Delete()
|
---|
245 |
|
---|
246 | No-OP if the parameter is NULL, else:
|
---|
247 | frees memory allocated for the object
|
---|
248 | sets pointers to NULL
|
---|
249 | calls TPM_EKBlobActivate_Init to set members back to default values
|
---|
250 | The object itself is not freed
|
---|
251 | */
|
---|
252 |
|
---|
253 | void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate)
|
---|
254 | {
|
---|
255 | printf(" TPM_EKBlobActivate_Delete:\n");
|
---|
256 | if (tpm_ek_blob_activate != NULL) {
|
---|
257 | TPM_SymmetricKey_Delete(&(tpm_ek_blob_activate->sessionKey));
|
---|
258 | TPM_PCRInfoShort_Delete(&(tpm_ek_blob_activate->pcrInfo));
|
---|
259 | TPM_EKBlobActivate_Init(tpm_ek_blob_activate);
|
---|
260 | }
|
---|
261 | return;
|
---|
262 | }
|
---|
263 |
|
---|
264 | /*
|
---|
265 | TPM_EK_BLOB_AUTH
|
---|
266 | */
|
---|
267 |
|
---|
268 | #if 0
|
---|
269 | /* TPM_EKBlobAuth_Init()
|
---|
270 |
|
---|
271 | sets members to default values
|
---|
272 | sets all pointers to NULL and sizes to 0
|
---|
273 | always succeeds - no return code
|
---|
274 | */
|
---|
275 |
|
---|
276 | void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
|
---|
277 | {
|
---|
278 | printf(" TPM_EKBlobAuth_Init:\n");
|
---|
279 | TPM_Secret_Init(tpm_ek_blob_auth->authValue);
|
---|
280 | return;
|
---|
281 | }
|
---|
282 |
|
---|
283 | /* TPM_EKBlobAuth_Load()
|
---|
284 |
|
---|
285 | deserialize the structure from a 'stream'
|
---|
286 | 'stream_size' is checked for sufficient data
|
---|
287 | returns 0 or error codes
|
---|
288 |
|
---|
289 | Before use, call TPM_EKBlobAuth_Init()
|
---|
290 | After use, call TPM_EKBlobAuth_Delete() to free memory
|
---|
291 | */
|
---|
292 |
|
---|
293 | TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth,
|
---|
294 | unsigned char **stream,
|
---|
295 | uint32_t *stream_size)
|
---|
296 | {
|
---|
297 | TPM_RESULT rc = 0;
|
---|
298 |
|
---|
299 | printf(" TPM_EKBlobAuth_Load:\n");
|
---|
300 | /* check tag */
|
---|
301 | if (rc == 0) {
|
---|
302 | rc = TPM_CheckTag(TPM_TAG_EK_BLOB_AUTH, stream, stream_size);
|
---|
303 | }
|
---|
304 | /* load authValue */
|
---|
305 | if (rc == 0) {
|
---|
306 | rc = TPM_Secret_Load(tpm_ek_blob_auth->authValue, stream, stream_size);
|
---|
307 | }
|
---|
308 | return rc;
|
---|
309 | }
|
---|
310 |
|
---|
311 | /* TPM_EKBlobAuth_Store()
|
---|
312 |
|
---|
313 | serialize the structure to a stream contained in 'sbuffer'
|
---|
314 | returns 0 or error codes
|
---|
315 | */
|
---|
316 |
|
---|
317 | TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer,
|
---|
318 | const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
|
---|
319 | {
|
---|
320 | TPM_RESULT rc = 0;
|
---|
321 |
|
---|
322 | printf(" TPM_EKBlobAuth_Store:\n");
|
---|
323 | if (rc == 0) {
|
---|
324 | rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_AUTH);
|
---|
325 | }
|
---|
326 | if (rc == 0) {
|
---|
327 | rc = TPM_Secret_Store(sbuffer, tpm_ek_blob_auth->authValue);
|
---|
328 | }
|
---|
329 | return rc;
|
---|
330 | }
|
---|
331 |
|
---|
332 | /* TPM_EKBlobAuth_Delete()
|
---|
333 |
|
---|
334 | No-OP if the parameter is NULL, else:
|
---|
335 | frees memory allocated for the object
|
---|
336 | sets pointers to NULL
|
---|
337 | calls TPM_EKBlobAuth_Init to set members back to default values
|
---|
338 | The object itself is not freed
|
---|
339 | */
|
---|
340 |
|
---|
341 | void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth)
|
---|
342 | {
|
---|
343 | printf(" TPM_EKBlobAuth_Delete:\n");
|
---|
344 | if (tpm_ek_blob_auth != NULL) {
|
---|
345 | TPM_EKBlobAuth_Init(tpm_ek_blob_auth);
|
---|
346 | }
|
---|
347 | return;
|
---|
348 | }
|
---|
349 | #endif
|
---|
350 |
|
---|
351 | /*
|
---|
352 | TPM_IDENTITY_CONTENTS
|
---|
353 | */
|
---|
354 |
|
---|
355 | /* TPM_IdentityContents_Init()
|
---|
356 |
|
---|
357 | sets members to default values
|
---|
358 | sets all pointers to NULL and sizes to 0
|
---|
359 | always succeeds - no return code
|
---|
360 | */
|
---|
361 |
|
---|
362 | void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
|
---|
363 | {
|
---|
364 | printf(" TPM_IdentityContents_Init:\n");
|
---|
365 | TPM_StructVer_Init(&(tpm_identity_contents->ver));
|
---|
366 | tpm_identity_contents->ordinal = TPM_ORD_MakeIdentity;
|
---|
367 | TPM_Digest_Init(tpm_identity_contents->labelPrivCADigest);
|
---|
368 | TPM_Pubkey_Init(&(tpm_identity_contents->identityPubKey));
|
---|
369 | return;
|
---|
370 | }
|
---|
371 |
|
---|
372 | /* TPM_IdentityContents_Load()
|
---|
373 |
|
---|
374 | deserialize the structure from a 'stream'
|
---|
375 | 'stream_size' is checked for sufficient data
|
---|
376 | returns 0 or error codes
|
---|
377 |
|
---|
378 | Before use, call TPM_IdentityContents_Init()
|
---|
379 | After use, call TPM_IdentityContents_Delete() to free memory
|
---|
380 |
|
---|
381 | NOTE: Never called.
|
---|
382 | */
|
---|
383 | #if 0
|
---|
384 | TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents,
|
---|
385 | unsigned char **stream,
|
---|
386 | uint32_t *stream_size)
|
---|
387 | {
|
---|
388 | TPM_RESULT rc = 0;
|
---|
389 |
|
---|
390 | printf(" TPM_IdentityContents_Load:\n");
|
---|
391 | /* load ver */
|
---|
392 | if (rc == 0) {
|
---|
393 | rc = TPM_StructVer_Load(&(tpm_identity_contents->ver), stream, stream_size);
|
---|
394 | }
|
---|
395 | /* check ver immediately to ease debugging */
|
---|
396 | if (rc == 0) {
|
---|
397 | rc = TPM_StructVer_CheckVer(&(tpm_identity_contents->ver));
|
---|
398 | }
|
---|
399 | /* load ordinal */
|
---|
400 | if (rc == 0) {
|
---|
401 | rc = TPM_Load32(&(tpm_identity_contents->ordinal), stream, stream_size);
|
---|
402 | }
|
---|
403 | /* load labelPrivCADigest */
|
---|
404 | if (rc == 0) {
|
---|
405 | rc = TPM_Digest_Load(tpm_identity_contents->labelPrivCADigest, stream, stream_size);
|
---|
406 | }
|
---|
407 | /* load identityPubKey */
|
---|
408 | if (rc == 0) {
|
---|
409 | rc = TPM_Pubkey_Load(&(tpm_identity_contents->identityPubKey), stream, stream_size);
|
---|
410 | }
|
---|
411 | return rc;
|
---|
412 | }
|
---|
413 | #endif
|
---|
414 |
|
---|
415 | /* TPM_IdentityContents_Store()
|
---|
416 |
|
---|
417 | serialize the structure to a stream contained in 'sbuffer'
|
---|
418 | returns 0 or error codes
|
---|
419 | */
|
---|
420 |
|
---|
421 | TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer,
|
---|
422 | TPM_IDENTITY_CONTENTS *tpm_identity_contents)
|
---|
423 | {
|
---|
424 | TPM_RESULT rc = 0;
|
---|
425 |
|
---|
426 | printf(" TPM_IdentityContents_Store:\n");
|
---|
427 | /* store ver */
|
---|
428 | if (rc == 0) {
|
---|
429 | rc = TPM_StructVer_Store(sbuffer, &(tpm_identity_contents->ver));
|
---|
430 | }
|
---|
431 | /* store ordinal */
|
---|
432 | if (rc == 0) {
|
---|
433 | rc = TPM_Sbuffer_Append32(sbuffer, tpm_identity_contents->ordinal);
|
---|
434 | }
|
---|
435 | /* store labelPrivCADigest */
|
---|
436 | if (rc == 0) {
|
---|
437 | rc = TPM_Digest_Store(sbuffer, tpm_identity_contents->labelPrivCADigest);
|
---|
438 | }
|
---|
439 | /* store identityPubKey */
|
---|
440 | if (rc == 0) {
|
---|
441 | rc = TPM_Pubkey_Store(sbuffer, &(tpm_identity_contents->identityPubKey));
|
---|
442 | }
|
---|
443 | return rc;
|
---|
444 | }
|
---|
445 |
|
---|
446 | /* TPM_IdentityContents_Delete()
|
---|
447 |
|
---|
448 | No-OP if the parameter is NULL, else:
|
---|
449 | frees memory allocated for the object
|
---|
450 | sets pointers to NULL
|
---|
451 | calls TPM_IdentityContents_Init to set members back to default values
|
---|
452 | The object itself is not freed
|
---|
453 | */
|
---|
454 |
|
---|
455 | void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents)
|
---|
456 | {
|
---|
457 | printf(" TPM_IdentityContents_Delete:\n");
|
---|
458 | if (tpm_identity_contents != NULL) {
|
---|
459 | TPM_Pubkey_Delete(&(tpm_identity_contents->identityPubKey));
|
---|
460 | TPM_IdentityContents_Init(tpm_identity_contents);
|
---|
461 | }
|
---|
462 | return;
|
---|
463 | }
|
---|
464 |
|
---|
465 | /*
|
---|
466 | TPM_ASYM_CA_CONTENTS
|
---|
467 | */
|
---|
468 |
|
---|
469 | /* TPM_AsymCaContents_Init()
|
---|
470 |
|
---|
471 | sets members to default values
|
---|
472 | sets all pointers to NULL and sizes to 0
|
---|
473 | always succeeds - no return code
|
---|
474 | */
|
---|
475 |
|
---|
476 | void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
|
---|
477 | {
|
---|
478 | printf(" TPM_AsymCaContents_Init:\n");
|
---|
479 | TPM_SymmetricKey_Init(&(tpm_asym_ca_contents->sessionKey));
|
---|
480 | TPM_Digest_Init(tpm_asym_ca_contents->idDigest);
|
---|
481 | return;
|
---|
482 | }
|
---|
483 |
|
---|
484 | /* TPM_AsymCaContents_Load()
|
---|
485 |
|
---|
486 | deserialize the structure from a 'stream'
|
---|
487 | 'stream_size' is checked for sufficient data
|
---|
488 | returns 0 or error codes
|
---|
489 |
|
---|
490 | Before use, call TPM_AsymCaContents_Init()
|
---|
491 | After use, call TPM_AsymCaContents_Delete() to free memory
|
---|
492 | */
|
---|
493 |
|
---|
494 | TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents,
|
---|
495 | unsigned char **stream,
|
---|
496 | uint32_t *stream_size)
|
---|
497 | {
|
---|
498 | TPM_RESULT rc = 0;
|
---|
499 |
|
---|
500 | printf(" TPM_AsymCaContents_Load:\n");
|
---|
501 | if (rc == 0) {
|
---|
502 | rc = TPM_SymmetricKey_Load(&(tpm_asym_ca_contents->sessionKey), stream, stream_size);
|
---|
503 | }
|
---|
504 | if (rc == 0) {
|
---|
505 | rc = TPM_Digest_Load(tpm_asym_ca_contents->idDigest, stream, stream_size);
|
---|
506 | }
|
---|
507 | return rc;
|
---|
508 | }
|
---|
509 |
|
---|
510 | #if 0
|
---|
511 | /* TPM_AsymCaContents_Store()
|
---|
512 |
|
---|
513 | serialize the structure to a stream contained in 'sbuffer'
|
---|
514 | returns 0 or error codes
|
---|
515 | */
|
---|
516 |
|
---|
517 | TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer,
|
---|
518 | const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
|
---|
519 | {
|
---|
520 | TPM_RESULT rc = 0;
|
---|
521 |
|
---|
522 | printf(" TPM_AsymCaContents_Store:\n");
|
---|
523 | if (rc == 0) {
|
---|
524 | rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_asym_ca_contents->sessionKey));
|
---|
525 | }
|
---|
526 | if (rc == 0) {
|
---|
527 | rc = TPM_Digest_Store(sbuffer, tpm_asym_ca_contents->idDigest);
|
---|
528 | }
|
---|
529 | return rc;
|
---|
530 | }
|
---|
531 | #endif
|
---|
532 |
|
---|
533 | /* TPM_AsymCaContents_Delete()
|
---|
534 |
|
---|
535 | No-OP if the parameter is NULL, else:
|
---|
536 | frees memory allocated for the object
|
---|
537 | sets pointers to NULL
|
---|
538 | calls TPM_AsymCaContents_Init to set members back to default values
|
---|
539 | The object itself is not freed
|
---|
540 | */
|
---|
541 |
|
---|
542 | void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents)
|
---|
543 | {
|
---|
544 | printf(" TPM_AsymCaContents_Delete:\n");
|
---|
545 | if (tpm_asym_ca_contents != NULL) {
|
---|
546 | TPM_SymmetricKey_Delete(&(tpm_asym_ca_contents->sessionKey));
|
---|
547 | TPM_AsymCaContents_Init(tpm_asym_ca_contents);
|
---|
548 | }
|
---|
549 | return;
|
---|
550 | }
|
---|
551 |
|
---|
552 |
|
---|
553 |
|
---|
554 |
|
---|
555 |
|
---|
556 |
|
---|
557 | /*
|
---|
558 | Processing Functions
|
---|
559 | */
|
---|
560 |
|
---|
561 | /* 15.1 TPM_MakeIdentity rev 114
|
---|
562 |
|
---|
563 | Generate a new Attestation Identity Key (AIK)
|
---|
564 |
|
---|
565 | labelPrivCADigest identifies the privacy CA that the owner expects to be the target CA for the
|
---|
566 | AIK. The selection is not enforced by the TPM. It is advisory only. It is included because the
|
---|
567 | TSS cannot be trusted to send the AIK to the correct privacy CA. The privacy CA can use this
|
---|
568 | parameter to validate that it is the target privacy CA and label intended by the TPM owner at the
|
---|
569 | time the key was created. The label can be used to indicate an application purpose.
|
---|
570 |
|
---|
571 | The public key of the new TPM identity SHALL be identityPubKey. The private key of the new TPM
|
---|
572 | identity SHALL be tpm_signature_key.
|
---|
573 |
|
---|
574 | Properties of the new identity
|
---|
575 |
|
---|
576 | TPM_PUBKEY identityPubKey This SHALL be the public key of a previously unused asymmetric key
|
---|
577 | pair.
|
---|
578 |
|
---|
579 | TPM_STORE_ASYMKEY tpm_signature_key This SHALL be the private key that forms a pair with
|
---|
580 | identityPubKey and SHALL be extant only in a TPM-shielded location.
|
---|
581 |
|
---|
582 | This capability also generates a TPM_KEY containing the tpm_signature_key.
|
---|
583 |
|
---|
584 | If identityPubKey is stored on a platform it SHALL exist only in storage to which access is
|
---|
585 | controlled and is available to authorized entities.
|
---|
586 | */
|
---|
587 |
|
---|
588 | TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state,
|
---|
589 | TPM_STORE_BUFFER *response,
|
---|
590 | TPM_TAG tag,
|
---|
591 | uint32_t paramSize,
|
---|
592 | TPM_COMMAND_CODE ordinal,
|
---|
593 | unsigned char *command,
|
---|
594 | TPM_TRANSPORT_INTERNAL *transportInternal)
|
---|
595 | {
|
---|
596 | TPM_RESULT rcf = 0; /* fatal error precluding response */
|
---|
597 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
|
---|
598 |
|
---|
599 | /* input parameters */
|
---|
600 | TPM_ENCAUTH identityAuth; /* Encrypted usage authorization data for the new identity
|
---|
601 | */
|
---|
602 | TPM_CHOSENID_HASH labelPrivCADigest; /* The digest of the identity label and privacy CA
|
---|
603 | chosen for the new TPM identity. */
|
---|
604 | TPM_KEY idKeyParams; /* Structure containing all parameters of new identity
|
---|
605 | key. pubKey.keyLength & idKeyParams.encData are both 0
|
---|
606 | MAY be TPM_KEY12 */
|
---|
607 | TPM_AUTHHANDLE srkAuthHandle; /* The authorization handle used for SRK authorization. */
|
---|
608 | TPM_NONCE srknonceOdd; /* Nonce generated by system associated with srkAuthHandle
|
---|
609 | */
|
---|
610 | TPM_BOOL continueSrkSession = TRUE; /* Ignored */
|
---|
611 | TPM_AUTHDATA srkAuth; /* The authorization digest for the inputs and the SRK. HMAC
|
---|
612 | key: srk.usageAuth. */
|
---|
613 | TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner
|
---|
614 | authorization. Session type MUST be OSAP. */
|
---|
615 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
|
---|
616 | TPM_BOOL continueAuthSession = TRUE; /* Ignored */
|
---|
617 | TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner. HMAC key:
|
---|
618 | ownerAuth. */
|
---|
619 | /* processing parameters */
|
---|
620 | unsigned char * inParamStart; /* starting point of inParam's */
|
---|
621 | unsigned char * inParamEnd; /* ending point of inParam's */
|
---|
622 | TPM_DIGEST inParamDigest;
|
---|
623 | TPM_BOOL auditStatus; /* audit the ordinal */
|
---|
624 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
|
---|
625 | TPM_BOOL srkAuthHandleValid = FALSE;
|
---|
626 | TPM_BOOL authHandleValid = FALSE;
|
---|
627 | TPM_AUTH_SESSION_DATA *srk_auth_session_data = NULL; /* session data for authHandle */
|
---|
628 | TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */
|
---|
629 | TPM_SECRET *srkHmacKey;
|
---|
630 | TPM_SECRET *hmacKey;
|
---|
631 | TPM_SECRET a1Auth;
|
---|
632 | TPM_STORE_ASYMKEY *idKeyStoreAsymkey;
|
---|
633 | TPM_IDENTITY_CONTENTS idContents;
|
---|
634 | TPM_DIGEST h1Digest; /* digest of TPM_IDENTITY_CONTENTS structure */
|
---|
635 | int ver;
|
---|
636 |
|
---|
637 | /* output parameters */
|
---|
638 | uint32_t outParamStart; /* starting point of outParam's */
|
---|
639 | uint32_t outParamEnd; /* ending point of outParam's */
|
---|
640 | TPM_DIGEST outParamDigest;
|
---|
641 | TPM_KEY idKey; /* The newly created identity key. MAY be TPM_KEY12
|
---|
642 | */
|
---|
643 | TPM_SIZED_BUFFER identityBinding; /* Signature of TPM_IDENTITY_CONTENTS using
|
---|
644 | idKey.private. */
|
---|
645 | printf("TPM_Process_MakeIdentity: Ordinal Entry\n");
|
---|
646 | TPM_Key_Init(&idKeyParams); /* freed @1 */
|
---|
647 | TPM_Key_Init(&idKey); /* freed @2 */
|
---|
648 | TPM_SizedBuffer_Init(&identityBinding); /* freed @3 */
|
---|
649 | TPM_IdentityContents_Init(&idContents); /* freed @4 */
|
---|
650 | /*
|
---|
651 | get inputs
|
---|
652 | */
|
---|
653 | /* save the starting point of inParam's for authorization and auditing */
|
---|
654 | inParamStart = command;
|
---|
655 | /* get identityAuth parameter */
|
---|
656 | if (returnCode == TPM_SUCCESS) {
|
---|
657 | returnCode = TPM_Authdata_Load(identityAuth, &command, ¶mSize);
|
---|
658 | }
|
---|
659 | /* get labelPrivCADigest parameter */
|
---|
660 | if (returnCode == TPM_SUCCESS) {
|
---|
661 | returnCode = TPM_Digest_Load(labelPrivCADigest, &command, ¶mSize);
|
---|
662 | }
|
---|
663 | /* get idKeyParams parameter */
|
---|
664 | if (returnCode == TPM_SUCCESS) {
|
---|
665 | returnCode = TPM_Key_Load(&idKeyParams, &command, ¶mSize);
|
---|
666 | }
|
---|
667 | /* save the ending point of inParam's for authorization and auditing */
|
---|
668 | inParamEnd = command;
|
---|
669 | /* digest the input parameters */
|
---|
670 | if (returnCode == TPM_SUCCESS) {
|
---|
671 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
|
---|
672 | &auditStatus, /* output */
|
---|
673 | &transportEncrypt, /* output */
|
---|
674 | tpm_state,
|
---|
675 | tag,
|
---|
676 | ordinal,
|
---|
677 | inParamStart,
|
---|
678 | inParamEnd,
|
---|
679 | transportInternal);
|
---|
680 | }
|
---|
681 | /* check state */
|
---|
682 | if (returnCode == TPM_SUCCESS) {
|
---|
683 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
|
---|
684 | }
|
---|
685 | /* check tag */
|
---|
686 | if (returnCode == TPM_SUCCESS) {
|
---|
687 | returnCode = TPM_CheckRequestTag21(tag);
|
---|
688 | }
|
---|
689 | /* get the optional 'below the line' authorization parameters */
|
---|
690 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
691 | returnCode = TPM_AuthParams_Get(&srkAuthHandle,
|
---|
692 | &srkAuthHandleValid,
|
---|
693 | srknonceOdd,
|
---|
694 | &continueSrkSession,
|
---|
695 | srkAuth,
|
---|
696 | &command, ¶mSize);
|
---|
697 | printf("TPM_Process_MakeIdentity: srkAuthHandle %08x\n", srkAuthHandle);
|
---|
698 | }
|
---|
699 | /* get the 'below the line' authorization parameters */
|
---|
700 | if (returnCode == TPM_SUCCESS) {
|
---|
701 | returnCode = TPM_AuthParams_Get(&authHandle,
|
---|
702 | &authHandleValid,
|
---|
703 | nonceOdd,
|
---|
704 | &continueAuthSession,
|
---|
705 | ownerAuth,
|
---|
706 | &command, ¶mSize);
|
---|
707 | }
|
---|
708 | if (returnCode == TPM_SUCCESS) {
|
---|
709 | printf("TPM_Process_MakeIdentity: authHandle %08x\n", authHandle);
|
---|
710 | }
|
---|
711 | if (returnCode == TPM_SUCCESS) {
|
---|
712 | if (paramSize != 0) {
|
---|
713 | printf("TPM_Process_MakeIdentity: Error, command has %u extra bytes\n",
|
---|
714 | paramSize);
|
---|
715 | returnCode = TPM_BAD_PARAM_SIZE;
|
---|
716 | }
|
---|
717 | }
|
---|
718 | /* do not terminate sessions if the command did not parse correctly */
|
---|
719 | if (returnCode != TPM_SUCCESS) {
|
---|
720 | srkAuthHandleValid = FALSE;
|
---|
721 | authHandleValid = FALSE;
|
---|
722 | }
|
---|
723 | /*
|
---|
724 | Processing
|
---|
725 | */
|
---|
726 | /* 1. Validate the idKeyParams parameters for the key description */
|
---|
727 | /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048 and MUST use the
|
---|
728 | default exponent. For interoperability the key length SHOULD be 2048 */
|
---|
729 | /* b. If the algorithm type is other than RSA the strength provided by the key MUST be
|
---|
730 | comparable to RSA 2048 */
|
---|
731 | /* c. If the TPM is not designed to create a key of the requested type, return the error code
|
---|
732 | TPM_BAD_KEY_PROPERTY */
|
---|
733 | /* d. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */
|
---|
734 | /* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */
|
---|
735 | if (returnCode == TPM_SUCCESS) {
|
---|
736 | returnCode = TPM_Key_CheckProperties(&ver, &idKeyParams, 2048,
|
---|
737 | tpm_state->tpm_permanent_flags.FIPS);
|
---|
738 | printf("TPM_Process_MakeIdentity: key parameters v = %d\n", ver);
|
---|
739 | }
|
---|
740 | /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity input
|
---|
741 | parameters. */
|
---|
742 | /* get the session data */
|
---|
743 | if (returnCode == TPM_SUCCESS) {
|
---|
744 | returnCode = TPM_AuthSessions_GetData(&auth_session_data,
|
---|
745 | &hmacKey,
|
---|
746 | tpm_state,
|
---|
747 | authHandle,
|
---|
748 | TPM_PID_OSAP,
|
---|
749 | TPM_ET_OWNER,
|
---|
750 | ordinal,
|
---|
751 | NULL,
|
---|
752 | NULL,
|
---|
753 | tpm_state->tpm_permanent_data.ownerAuth);
|
---|
754 | }
|
---|
755 | /* Validate the authorization to use the key pointed to by keyHandle */
|
---|
756 | if (returnCode == TPM_SUCCESS) {
|
---|
757 | returnCode = TPM_Auth2data_Check(tpm_state,
|
---|
758 | *hmacKey, /* HMAC key */
|
---|
759 | inParamDigest,
|
---|
760 | auth_session_data, /* authorization session */
|
---|
761 | nonceOdd, /* Nonce generated by system
|
---|
762 | associated with authHandle */
|
---|
763 | continueAuthSession,
|
---|
764 | ownerAuth); /* Authorization digest for input */
|
---|
765 | }
|
---|
766 | /* 3. Use srkAuthHandle to verify that the SRK owner authorized all TPM_MakeIdentity input
|
---|
767 | parameters. */
|
---|
768 | /* get the session data */
|
---|
769 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
770 | returnCode = TPM_AuthSessions_GetData
|
---|
771 | (&srk_auth_session_data,
|
---|
772 | &srkHmacKey,
|
---|
773 | tpm_state,
|
---|
774 | srkAuthHandle,
|
---|
775 | TPM_PID_NONE,
|
---|
776 | TPM_ET_KEYHANDLE,
|
---|
777 | ordinal,
|
---|
778 | &(tpm_state->tpm_permanent_data.srk),
|
---|
779 | /* OIAP */
|
---|
780 | &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth),
|
---|
781 | /* OSAP */
|
---|
782 | tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest);
|
---|
783 | }
|
---|
784 | /* Validate the authorization to use the key pointed to by keyHandle */
|
---|
785 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
786 | returnCode = TPM_Authdata_Check(tpm_state,
|
---|
787 | *srkHmacKey, /* HMAC key */
|
---|
788 | inParamDigest,
|
---|
789 | srk_auth_session_data, /* authorization session */
|
---|
790 | srknonceOdd, /* Nonce generated by system
|
---|
791 | associated with authHandle */
|
---|
792 | continueSrkSession,
|
---|
793 | srkAuth); /* Authorization digest for input */
|
---|
794 | }
|
---|
795 | /* if there is no SRK authorization, check that the SRK authDataUsage is TPM_AUTH_NEVER */
|
---|
796 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
797 | if (tpm_state->tpm_permanent_data.srk.authDataUsage != TPM_AUTH_NEVER) {
|
---|
798 | printf("TPM_Process_MakeIdentity: Error, SRK authorization required\n");
|
---|
799 | returnCode = TPM_AUTHFAIL;
|
---|
800 | }
|
---|
801 | }
|
---|
802 | /* 4. Verify that idKeyParams -> keyUsage is TPM_KEY_IDENTITY. If it is not, return
|
---|
803 | TPM_INVALID_KEYUSAGE */
|
---|
804 | /* NOTE: TPM_KEY_IDENTITY keys must use TPM_SS_RSASSAPKCS1v15_SHA1 */
|
---|
805 | if (returnCode == TPM_SUCCESS) {
|
---|
806 | printf("TPM_Process_MakeIdentity: Checking key parameters\n");
|
---|
807 | if (idKeyParams.keyUsage != TPM_KEY_IDENTITY) {
|
---|
808 | printf("TPM_Process_MakeIdentity: Error, "
|
---|
809 | "idKeyParams keyUsage %08x should be TPM_KEY_IDENTITY\n",
|
---|
810 | idKeyParams.keyUsage);
|
---|
811 | returnCode = TPM_INVALID_KEYUSAGE;
|
---|
812 | }
|
---|
813 | }
|
---|
814 | /* 5. Verify that idKeyParams -> keyFlags -> migratable is FALSE. If it is not, return
|
---|
815 | TPM_INVALID_KEYUSAGE */
|
---|
816 | if (returnCode == TPM_SUCCESS) {
|
---|
817 | if (idKeyParams.keyFlags & TPM_MIGRATABLE) {
|
---|
818 | printf("TPM_Process_MakeIdentity: Error, "
|
---|
819 | "idKeyParams keyFlags %08x cannot be migratable\n",
|
---|
820 | idKeyParams.keyFlags);
|
---|
821 | returnCode = TPM_INVALID_KEYUSAGE;
|
---|
822 | }
|
---|
823 | }
|
---|
824 | /* 6. Create a1 by decrypting identityAuth according to the ADIP indicated by authHandle. */
|
---|
825 | if (returnCode == TPM_SUCCESS) {
|
---|
826 | returnCode = TPM_AuthSessionData_Decrypt(a1Auth,
|
---|
827 | NULL,
|
---|
828 | identityAuth,
|
---|
829 | auth_session_data,
|
---|
830 | NULL,
|
---|
831 | NULL,
|
---|
832 | FALSE); /* even and odd */
|
---|
833 | }
|
---|
834 | /* 7. Set continueAuthSession and continueSRKSession to FALSE. */
|
---|
835 | if (returnCode == TPM_SUCCESS) {
|
---|
836 | continueAuthSession = FALSE;
|
---|
837 | continueSrkSession = FALSE;
|
---|
838 | /* 8. Determine the structure version */
|
---|
839 | /* a. If idKeyParams -> tag is TPM_TAG_KEY12 */
|
---|
840 | /* i. Set V1 to 2 */
|
---|
841 | /* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the default values for the
|
---|
842 | structure */
|
---|
843 | /* b. If idKeyParams -> ver is 1.1 */
|
---|
844 | /* i. Set V1 to 1 */
|
---|
845 | /* ii. Create idKey a TPM_KEY structure using idKeyParams as the default values for the
|
---|
846 | structure */
|
---|
847 | /* NOTE Done by TPM_Key_CheckProperties() */
|
---|
848 | /* NOTE The creation determination is done by TPM_Key_GenerateRSA() */
|
---|
849 | }
|
---|
850 | /* 9. Set the digestAtCreation values for pcrInfo */
|
---|
851 | /* NOTE Done as the key is generated */
|
---|
852 | /* a. For PCR_INFO_LONG include the locality of the current command */
|
---|
853 | /* 10. Create an asymmetric key pair (identityPubKey and tpm_signature_key) using a
|
---|
854 | TPM-protected capability, in accordance with the algorithm specified in idKeyParams */
|
---|
855 | if (returnCode == TPM_SUCCESS) {
|
---|
856 | /* generate the key pair, create the tpm_store_asymkey cache, copy key parameters, create
|
---|
857 | tpm_pcr_info cache, copies pcr parameters, sets digestAtCreation, sets pubKey, serializes
|
---|
858 | pcrInfo
|
---|
859 |
|
---|
860 | does not set encData */
|
---|
861 | printf("TPM_Process_MakeIdentity: Generating key\n");
|
---|
862 | returnCode = TPM_Key_GenerateRSA(&idKey,
|
---|
863 | tpm_state,
|
---|
864 | &(tpm_state->tpm_permanent_data.srk), /* parent key */
|
---|
865 | tpm_state->tpm_stclear_data.PCRS, /* PCR array */
|
---|
866 | ver,
|
---|
867 | idKeyParams.keyUsage,
|
---|
868 | idKeyParams.keyFlags,
|
---|
869 | idKeyParams.authDataUsage, /* TPM_AUTH_DATA_USAGE */
|
---|
870 | &(idKeyParams.algorithmParms), /* TPM_KEY_PARMS */
|
---|
871 | idKeyParams.tpm_pcr_info, /* TPM_PCR_INFO */
|
---|
872 | idKeyParams.tpm_pcr_info_long);/* TPM_PCR_INFO_LONG */
|
---|
873 |
|
---|
874 | }
|
---|
875 | /* 11. Ensure that the authorization information in A1 is properly stored in the idKey as
|
---|
876 | usageAuth. */
|
---|
877 | if (returnCode == TPM_SUCCESS) {
|
---|
878 | returnCode = TPM_Key_GetStoreAsymkey(&idKeyStoreAsymkey,
|
---|
879 | &idKey);
|
---|
880 | }
|
---|
881 | if (returnCode == TPM_SUCCESS) {
|
---|
882 | TPM_Secret_Copy(idKeyStoreAsymkey->usageAuth, a1Auth);
|
---|
883 | /* 12. Attach identityPubKey and tpm_signature_key to idKey */
|
---|
884 | /* Note: Done as the key is generated */
|
---|
885 | /* 13. Set idKey -> migrationAuth to TPM_PERMANENT_DATA -> tpmProof */
|
---|
886 | TPM_Secret_Copy(idKeyStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof);
|
---|
887 | /* 14. Ensure that all TPM_PAYLOAD_TYPE structures identity this key as TPM_PT_ASYM */
|
---|
888 | /* NOTE Done as the key is generated */
|
---|
889 | }
|
---|
890 | /* 15. Encrypt the private portion of idKey using the SRK as the parent key */
|
---|
891 | if (returnCode == TPM_SUCCESS) {
|
---|
892 | printf("TPM_Process_MakeIdentity: Encrypting key private part with SRK\n");
|
---|
893 | returnCode = TPM_Key_GenerateEncData(&idKey, &(tpm_state->tpm_permanent_data.srk));
|
---|
894 | }
|
---|
895 | /* 16. Create a TPM_IDENTITY_CONTENTS structure named idContents using labelPrivCADigest and the
|
---|
896 | information from idKey */
|
---|
897 | if (returnCode == TPM_SUCCESS) {
|
---|
898 | TPM_Digest_Copy(idContents.labelPrivCADigest, labelPrivCADigest);
|
---|
899 | returnCode = TPM_Pubkey_Set(&(idContents.identityPubKey), &idKey);
|
---|
900 | }
|
---|
901 | /* 17. Sign idContents using tpm_signature_key and TPM_SS_RSASSAPKCS1v15_SHA1. Store the result
|
---|
902 | in identityBinding. */
|
---|
903 | /* NOTE: TPM_Key_CheckProperties() verified TPM_SS_RSASSAPKCS1v15_SHA1 */
|
---|
904 | /* serialize tpm_identity_contents and hash the results*/
|
---|
905 | if (returnCode == TPM_SUCCESS) {
|
---|
906 | returnCode = TPM_SHA1_GenerateStructure(h1Digest,
|
---|
907 | &idContents,
|
---|
908 | (TPM_STORE_FUNCTION_T)TPM_IdentityContents_Store);
|
---|
909 | }
|
---|
910 | /* sign the digest */
|
---|
911 | if (returnCode == TPM_SUCCESS) {
|
---|
912 | printf("TPM_Process_MakeIdentity: Signing digest of TPM_IDENTITY_CONTENTS\n");
|
---|
913 | returnCode = TPM_RSASignToSizedBuffer(&identityBinding, h1Digest, TPM_DIGEST_SIZE, &idKey);
|
---|
914 | }
|
---|
915 | #if 0 /* NOTE Debug code to reverse the signature */
|
---|
916 | if (returnCode == TPM_SUCCESS) {
|
---|
917 | unsigned char *message = NULL;
|
---|
918 | unsigned char *narr = NULL;
|
---|
919 | uint32_t nbytes;
|
---|
920 | unsigned char *earr = NULL;
|
---|
921 | uint32_t ebytes;
|
---|
922 | if (returnCode == 0) {
|
---|
923 | returnCode = TPM_Malloc(&message, identityBinding.size); /* freed @10 */
|
---|
924 | }
|
---|
925 | if (returnCode == 0) {
|
---|
926 | returnCode = TPM_Key_GetPublicKey(&nbytes, &narr, &idKey);
|
---|
927 | }
|
---|
928 | if (returnCode == 0) {
|
---|
929 | returnCode = TPM_Key_GetExponent(&ebytes, &earr, &idKey);
|
---|
930 | }
|
---|
931 | if (returnCode == 0) {
|
---|
932 | returnCode = TPM_RSAPublicEncryptRaw(message, /* output */
|
---|
933 | identityBinding.size,
|
---|
934 | identityBinding.buffer, /* input */
|
---|
935 | identityBinding.size,
|
---|
936 | narr, /* public modulus */
|
---|
937 | nbytes,
|
---|
938 | earr, /* public exponent */
|
---|
939 | ebytes);
|
---|
940 | }
|
---|
941 | free(message); /* @10 */
|
---|
942 | }
|
---|
943 | #endif
|
---|
944 | /*
|
---|
945 | response
|
---|
946 | */
|
---|
947 | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
|
---|
948 | if (rcf == 0) {
|
---|
949 | printf("TPM_Process_MakeIdentity: Ordinal returnCode %08x %u\n",
|
---|
950 | returnCode, returnCode);
|
---|
951 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
|
---|
952 | }
|
---|
953 | /* success response, append the rest of the parameters. */
|
---|
954 | if (rcf == 0) {
|
---|
955 | if (returnCode == TPM_SUCCESS) {
|
---|
956 | /* checkpoint the beginning of the outParam's */
|
---|
957 | outParamStart = response->buffer_current - response->buffer;
|
---|
958 | /* return idKey */
|
---|
959 | returnCode = TPM_Key_Store(response, &idKey);
|
---|
960 | }
|
---|
961 | if (returnCode == TPM_SUCCESS) {
|
---|
962 | /* return identityBinding */
|
---|
963 | returnCode = TPM_SizedBuffer_Store(response, &identityBinding);
|
---|
964 | /* checkpoint the end of the outParam's */
|
---|
965 | outParamEnd = response->buffer_current - response->buffer;
|
---|
966 | }
|
---|
967 | /* digest the above the line output parameters */
|
---|
968 | if (returnCode == TPM_SUCCESS) {
|
---|
969 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
|
---|
970 | auditStatus, /* input audit status */
|
---|
971 | transportEncrypt,
|
---|
972 | tag,
|
---|
973 | returnCode,
|
---|
974 | ordinal, /* command ordinal */
|
---|
975 | response->buffer + outParamStart, /* start */
|
---|
976 | outParamEnd - outParamStart); /* length */
|
---|
977 | }
|
---|
978 | /* calculate and set the below the line parameters */
|
---|
979 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
980 | returnCode = TPM_AuthParams_Set(response,
|
---|
981 | *srkHmacKey, /* owner HMAC key */
|
---|
982 | srk_auth_session_data,
|
---|
983 | outParamDigest,
|
---|
984 | srknonceOdd,
|
---|
985 | continueSrkSession);
|
---|
986 | }
|
---|
987 | /* calculate and set the below the line parameters */
|
---|
988 | if (returnCode == TPM_SUCCESS) {
|
---|
989 | returnCode = TPM_AuthParams_Set(response,
|
---|
990 | *hmacKey, /* owner HMAC key */
|
---|
991 | auth_session_data,
|
---|
992 | outParamDigest,
|
---|
993 | nonceOdd,
|
---|
994 | continueAuthSession);
|
---|
995 | }
|
---|
996 | /* audit if required */
|
---|
997 | if ((returnCode == TPM_SUCCESS) && auditStatus) {
|
---|
998 | returnCode = TPM_ProcessAudit(tpm_state,
|
---|
999 | transportEncrypt,
|
---|
1000 | inParamDigest,
|
---|
1001 | outParamDigest,
|
---|
1002 | ordinal);
|
---|
1003 | }
|
---|
1004 | /* adjust the initial response */
|
---|
1005 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
|
---|
1006 | }
|
---|
1007 | /* if there was an error, or continueSrkSession is FALSE, terminate the session */
|
---|
1008 | if (((rcf != 0) ||
|
---|
1009 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
|
---|
1010 | !continueSrkSession) &&
|
---|
1011 | srkAuthHandleValid) {
|
---|
1012 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, srkAuthHandle);
|
---|
1013 | }
|
---|
1014 | /* if there was an error, or continueAuthSession is FALSE, terminate the session */
|
---|
1015 | if (((rcf != 0) ||
|
---|
1016 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
|
---|
1017 | !continueAuthSession) &&
|
---|
1018 | authHandleValid) {
|
---|
1019 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
|
---|
1020 | }
|
---|
1021 | /*
|
---|
1022 | cleanup
|
---|
1023 | */
|
---|
1024 | TPM_Key_Delete(&idKeyParams); /* freed @1 */
|
---|
1025 | TPM_Key_Delete(&idKey); /* freed @2 */
|
---|
1026 | TPM_SizedBuffer_Delete(&identityBinding); /* freed @3 */
|
---|
1027 | TPM_IdentityContents_Delete(&idContents); /* freed @4 */
|
---|
1028 | return rcf;
|
---|
1029 | }
|
---|
1030 |
|
---|
1031 | /* 15.2 TPM_ActivateIdentity rev 107
|
---|
1032 |
|
---|
1033 | The purpose of TPM_ActivateIdentity is to twofold. The first purpose is to obtain assurance that
|
---|
1034 | the credential in the TPM_SYM_CA_ATTESTATION is for this TPM. The second purpose is to obtain the
|
---|
1035 | session key used to encrypt the TPM_IDENTITY_CREDENTIAL.
|
---|
1036 |
|
---|
1037 | The command TPM_ActivateIdentity activates a TPM identity created using the command
|
---|
1038 | TPM_MakeIdentity.
|
---|
1039 |
|
---|
1040 | The command assumes the availability of the private key associated with the identity. The command
|
---|
1041 | will verify the association between the keys during the process.
|
---|
1042 |
|
---|
1043 | The command will decrypt the input blob and extract the session key and verify the connection
|
---|
1044 | between the public and private keys. The input blob can be in 1.1 or 1.2 format.
|
---|
1045 | */
|
---|
1046 |
|
---|
1047 | TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state,
|
---|
1048 | TPM_STORE_BUFFER *response,
|
---|
1049 | TPM_TAG tag,
|
---|
1050 | uint32_t paramSize,
|
---|
1051 | TPM_COMMAND_CODE ordinal,
|
---|
1052 | unsigned char *command,
|
---|
1053 | TPM_TRANSPORT_INTERNAL *transportInternal)
|
---|
1054 | {
|
---|
1055 | TPM_RESULT rcf = 0; /* fatal error precluding response */
|
---|
1056 | TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */
|
---|
1057 |
|
---|
1058 | /* input parameters */
|
---|
1059 | TPM_KEY_HANDLE idKeyHandle; /* handle of identity key to be activated */
|
---|
1060 | TPM_SIZED_BUFFER blob; /* The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB */
|
---|
1061 | TPM_AUTHHANDLE idKeyAuthHandle; /* The authorization handle used for ID key
|
---|
1062 | authorization. */
|
---|
1063 | TPM_NONCE idKeynonceOdd; /* Nonce generated by system associated with idKeyAuthHandle
|
---|
1064 | */
|
---|
1065 | TPM_BOOL continueIdKeySession = TRUE; /* Continue usage flag for idKeyAuthHandle. */
|
---|
1066 | TPM_AUTHDATA idKeyAuth; /* The authorization digest for the inputs and ID key. HMAC
|
---|
1067 | key: idKey.usageAuth. */
|
---|
1068 | TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */
|
---|
1069 | TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */
|
---|
1070 | TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization
|
---|
1071 | handle */
|
---|
1072 | TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and
|
---|
1073 | owner. HMAC key: ownerAuth. */
|
---|
1074 |
|
---|
1075 | /* processing parameters */
|
---|
1076 | unsigned char * inParamStart; /* starting point of inParam's */
|
---|
1077 | unsigned char * inParamEnd; /* ending point of inParam's */
|
---|
1078 | TPM_DIGEST inParamDigest;
|
---|
1079 | TPM_BOOL auditStatus; /* audit the ordinal */
|
---|
1080 | TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */
|
---|
1081 | TPM_BOOL idKeyAuthHandleValid = FALSE;
|
---|
1082 | TPM_BOOL authHandleValid = FALSE;
|
---|
1083 | TPM_AUTH_SESSION_DATA *id_key_auth_session_data = NULL; /* session data for authHandle */
|
---|
1084 | TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */
|
---|
1085 | TPM_SECRET *idKeyHmacKey;
|
---|
1086 | TPM_SECRET *hmacKey;
|
---|
1087 | TPM_KEY *idKey; /* Identity key to be activated */
|
---|
1088 | TPM_SECRET *idKeyUsageAuth;
|
---|
1089 | TPM_BOOL idPCRStatus;
|
---|
1090 | TPM_DIGEST h1Digest; /* digest of public key in idKey */
|
---|
1091 | unsigned char *b1Blob = NULL; /* decrypted blob */
|
---|
1092 | uint32_t b1BlobLength = 0; /* actual valid data */
|
---|
1093 | TPM_STRUCTURE_TAG hTag; /* b1 tag in host byte order */
|
---|
1094 | int vers = 0; /* version of blob */
|
---|
1095 | unsigned char *stream;
|
---|
1096 | uint32_t stream_size;
|
---|
1097 | TPM_EK_BLOB b1EkBlob;
|
---|
1098 | TPM_ASYM_CA_CONTENTS b1AsymCaContents;
|
---|
1099 | TPM_SYMMETRIC_KEY *k1 = NULL;
|
---|
1100 | TPM_EK_BLOB_ACTIVATE a1;
|
---|
1101 |
|
---|
1102 | /* output parameters */
|
---|
1103 | uint32_t outParamStart; /* starting point of outParam's */
|
---|
1104 | uint32_t outParamEnd; /* ending point of outParam's */
|
---|
1105 | TPM_DIGEST outParamDigest;
|
---|
1106 | TPM_SYMMETRIC_KEY symmetricKey; /* The decrypted symmetric key. */
|
---|
1107 |
|
---|
1108 | printf("TPM_Process_ActivateIdentity: Ordinal Entry\n");
|
---|
1109 | TPM_SizedBuffer_Init(&blob); /* freed @1 */
|
---|
1110 | TPM_SymmetricKey_Init(&symmetricKey); /* freed @2 */
|
---|
1111 | TPM_AsymCaContents_Init(&b1AsymCaContents); /* freed @4 */
|
---|
1112 | TPM_EKBlob_Init(&b1EkBlob); /* freed @5 */
|
---|
1113 | TPM_EKBlobActivate_Init(&a1); /* freed @6 */
|
---|
1114 | /*
|
---|
1115 | get inputs
|
---|
1116 | */
|
---|
1117 | /* get idKey parameter */
|
---|
1118 | if (returnCode == TPM_SUCCESS) {
|
---|
1119 | returnCode = TPM_Load32(&idKeyHandle, &command, ¶mSize);
|
---|
1120 | }
|
---|
1121 | /* save the starting point of inParam's for authorization and auditing */
|
---|
1122 | inParamStart = command;
|
---|
1123 | /* get blob parameter */
|
---|
1124 | if (returnCode == TPM_SUCCESS) {
|
---|
1125 | returnCode = TPM_SizedBuffer_Load(&blob, &command, ¶mSize);
|
---|
1126 | }
|
---|
1127 | /* save the ending point of inParam's for authorization and auditing */
|
---|
1128 | inParamEnd = command;
|
---|
1129 | /* digest the input parameters */
|
---|
1130 | if (returnCode == TPM_SUCCESS) {
|
---|
1131 | returnCode = TPM_GetInParamDigest(inParamDigest, /* output */
|
---|
1132 | &auditStatus, /* output */
|
---|
1133 | &transportEncrypt, /* output */
|
---|
1134 | tpm_state,
|
---|
1135 | tag,
|
---|
1136 | ordinal,
|
---|
1137 | inParamStart,
|
---|
1138 | inParamEnd,
|
---|
1139 | transportInternal);
|
---|
1140 | }
|
---|
1141 | /* check state */
|
---|
1142 | if (returnCode == TPM_SUCCESS) {
|
---|
1143 | returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL);
|
---|
1144 | }
|
---|
1145 | /* check tag */
|
---|
1146 | if (returnCode == TPM_SUCCESS) {
|
---|
1147 | returnCode = TPM_CheckRequestTag21(tag);
|
---|
1148 | }
|
---|
1149 | /* get the optional 'below the line' authorization parameters */
|
---|
1150 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
1151 | returnCode = TPM_AuthParams_Get(&idKeyAuthHandle,
|
---|
1152 | &idKeyAuthHandleValid,
|
---|
1153 | idKeynonceOdd,
|
---|
1154 | &continueIdKeySession,
|
---|
1155 | idKeyAuth,
|
---|
1156 | &command, ¶mSize);
|
---|
1157 | printf("TPM_Process_ActivateIdentity: idKeyAuthHandle %08x\n", idKeyAuthHandle);
|
---|
1158 | }
|
---|
1159 | /* get the 'below the line' authorization parameters */
|
---|
1160 | if (returnCode == TPM_SUCCESS) {
|
---|
1161 | returnCode = TPM_AuthParams_Get(&authHandle,
|
---|
1162 | &authHandleValid,
|
---|
1163 | nonceOdd,
|
---|
1164 | &continueAuthSession,
|
---|
1165 | ownerAuth,
|
---|
1166 | &command, ¶mSize);
|
---|
1167 | }
|
---|
1168 | if (returnCode == TPM_SUCCESS) {
|
---|
1169 | printf("TPM_Process_ActivateIdentity: authHandle %08x\n", authHandle);
|
---|
1170 | }
|
---|
1171 | if (returnCode == TPM_SUCCESS) {
|
---|
1172 | if (paramSize != 0) {
|
---|
1173 | printf("TPM_Process_ActivateIdentity: Error, command has %u extra bytes\n",
|
---|
1174 | paramSize);
|
---|
1175 | returnCode = TPM_BAD_PARAM_SIZE;
|
---|
1176 | }
|
---|
1177 | }
|
---|
1178 | /* do not terminate sessions if the command did not parse correctly */
|
---|
1179 | if (returnCode != TPM_SUCCESS) {
|
---|
1180 | idKeyAuthHandleValid = FALSE;
|
---|
1181 | authHandleValid = FALSE;
|
---|
1182 | }
|
---|
1183 | /*
|
---|
1184 | Processing
|
---|
1185 | */
|
---|
1186 | /* 1. Using the authHandle field, validate the owner's authorization to execute the command and
|
---|
1187 | all of the incoming parameters. */
|
---|
1188 | /* get the session data */
|
---|
1189 | if (returnCode == TPM_SUCCESS) {
|
---|
1190 | returnCode = TPM_AuthSessions_GetData(&auth_session_data,
|
---|
1191 | &hmacKey,
|
---|
1192 | tpm_state,
|
---|
1193 | authHandle,
|
---|
1194 | TPM_PID_NONE,
|
---|
1195 | TPM_ET_OWNER,
|
---|
1196 | ordinal,
|
---|
1197 | NULL,
|
---|
1198 | &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */
|
---|
1199 | tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */
|
---|
1200 | }
|
---|
1201 | /* Validate the authorization to use the key pointed to by keyHandle */
|
---|
1202 | if (returnCode == TPM_SUCCESS) {
|
---|
1203 | returnCode = TPM_Authdata_Check(tpm_state,
|
---|
1204 | *hmacKey, /* HMAC key */
|
---|
1205 | inParamDigest,
|
---|
1206 | auth_session_data, /* authorization session */
|
---|
1207 | nonceOdd, /* Nonce generated by system
|
---|
1208 | associated with authHandle */
|
---|
1209 | continueAuthSession,
|
---|
1210 | ownerAuth); /* Authorization digest for input */
|
---|
1211 | }
|
---|
1212 | /* 2. Using the idKeyAuthHandle, validate the authorization to execute command and all of the
|
---|
1213 | incoming parameters */
|
---|
1214 | /* get the idKey */
|
---|
1215 | if (returnCode == TPM_SUCCESS) {
|
---|
1216 | returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idKeyHandle,
|
---|
1217 | FALSE, /* not r/o, using to authenticate */
|
---|
1218 | FALSE, /* do not ignore PCRs */
|
---|
1219 | FALSE); /* cannot use EK */
|
---|
1220 | }
|
---|
1221 | /* get keyHandle -> usageAuth */
|
---|
1222 | if (returnCode == TPM_SUCCESS) {
|
---|
1223 | returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey);
|
---|
1224 | }
|
---|
1225 | /* get the session data */
|
---|
1226 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
1227 | returnCode = TPM_AuthSessions_GetData(&id_key_auth_session_data,
|
---|
1228 | &idKeyHmacKey,
|
---|
1229 | tpm_state,
|
---|
1230 | idKeyAuthHandle,
|
---|
1231 | TPM_PID_NONE,
|
---|
1232 | TPM_ET_KEYHANDLE,
|
---|
1233 | ordinal,
|
---|
1234 | idKey,
|
---|
1235 | idKeyUsageAuth, /* OIAP */
|
---|
1236 | idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */
|
---|
1237 | }
|
---|
1238 | /* Validate the authorization to use the key pointed to by keyHandle */
|
---|
1239 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
1240 | returnCode = TPM_Auth2data_Check(tpm_state,
|
---|
1241 | *idKeyHmacKey, /* HMAC key */
|
---|
1242 | inParamDigest,
|
---|
1243 | id_key_auth_session_data, /* authorization session */
|
---|
1244 | idKeynonceOdd, /* Nonce generated by system
|
---|
1245 | associated with authHandle */
|
---|
1246 | continueIdKeySession,
|
---|
1247 | idKeyAuth); /* Authorization digest for input */
|
---|
1248 | }
|
---|
1249 | /* if there is no idKey authorization, check that the idKey -> authDataUsage is TPM_AUTH_NEVER
|
---|
1250 | */
|
---|
1251 | if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
1252 | if (idKey->authDataUsage != TPM_AUTH_NEVER) {
|
---|
1253 | printf("TPM_Process_ActivateIdentity: Error, ID key authorization required\n");
|
---|
1254 | returnCode = TPM_AUTHFAIL;
|
---|
1255 | }
|
---|
1256 | }
|
---|
1257 | /* 3. Validate that the idKey is the public key of a valid TPM identity by checking that
|
---|
1258 | idKeyHandle -> keyUsage is TPM_KEY_IDENTITY. Return TPM_BAD_PARAMETER on mismatch */
|
---|
1259 | if (returnCode == TPM_SUCCESS) {
|
---|
1260 | printf("TPM_Process_ActivateIdentity: Checking for identity key\n");
|
---|
1261 | if (idKey->keyUsage != TPM_KEY_IDENTITY) {
|
---|
1262 | printf("TPM_Process_ActivateIdentity: Error, keyUsage %04hx must be TPM_KEY_IDENTITY\n",
|
---|
1263 | idKey->keyUsage);
|
---|
1264 | returnCode = TPM_BAD_PARAMETER;
|
---|
1265 | }
|
---|
1266 | }
|
---|
1267 | /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */
|
---|
1268 | if (returnCode == TPM_SUCCESS) {
|
---|
1269 | returnCode = TPM_Key_GeneratePubkeyDigest(h1Digest, idKey);
|
---|
1270 | }
|
---|
1271 | /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */
|
---|
1272 | if (returnCode == TPM_SUCCESS) {
|
---|
1273 | printf("TPM_Process_ActivateIdentity: Decrypting blob with EK\n");
|
---|
1274 | returnCode = TPM_RSAPrivateDecryptMalloc(&b1Blob, /* decrypted data */
|
---|
1275 | &b1BlobLength, /* actual size of b1 data */
|
---|
1276 | blob.buffer,
|
---|
1277 | blob.size,
|
---|
1278 | &(tpm_state->tpm_permanent_data.endorsementKey));
|
---|
1279 | }
|
---|
1280 | /* 6. Determine the type and version of B1 */
|
---|
1281 | if (returnCode == TPM_SUCCESS) {
|
---|
1282 | stream = b1Blob; /* b1 must be preserved for the free */
|
---|
1283 | stream_size = b1BlobLength;
|
---|
1284 | /* convert possible tag to uint16_t */
|
---|
1285 | hTag = ntohs(*(TPM_STRUCTURE_TAG *)b1Blob);
|
---|
1286 | /* a. If B1 -> tag is TPM_TAG_EK_BLOB then */
|
---|
1287 | if (hTag == TPM_TAG_EK_BLOB) {
|
---|
1288 | /* i. B1 is a TPM_EK_BLOB */
|
---|
1289 | printf("TPM_Process_ActivateIdentity: b1 is TPM_EK_BLOB\n");
|
---|
1290 | vers = 2;
|
---|
1291 | returnCode = TPM_EKBlob_Load(&b1EkBlob, &stream, &stream_size);
|
---|
1292 | }
|
---|
1293 | /* b. Else */
|
---|
1294 | else {
|
---|
1295 | /* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this structure it is possible
|
---|
1296 | for the TPM to make a mistake here but other sections of the structure undergo
|
---|
1297 | validation */
|
---|
1298 | printf("TPM_Process_ActivateIdentity: b1 is TPM_ASYM_CA_CONTENTS\n");
|
---|
1299 | vers = 1;
|
---|
1300 | returnCode = TPM_AsymCaContents_Load(&b1AsymCaContents, &stream, &stream_size);
|
---|
1301 | }
|
---|
1302 | }
|
---|
1303 | /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */
|
---|
1304 | if ((returnCode == TPM_SUCCESS) && (vers == 1)) {
|
---|
1305 | /* a. Compare H1 to B1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
|
---|
1306 | if (returnCode == TPM_SUCCESS) {
|
---|
1307 | returnCode = TPM_Digest_Compare(h1Digest, b1AsymCaContents.idDigest);
|
---|
1308 | if (returnCode != 0) {
|
---|
1309 | printf("TPM_Process_ActivateIdentity: Error "
|
---|
1310 | "comparing TPM_ASYM_CA_CONTENTS idDigest\n");
|
---|
1311 | returnCode = TPM_BAD_PARAMETER;
|
---|
1312 | }
|
---|
1313 | }
|
---|
1314 | /* b. Set K1 to B1 -> sessionKey */
|
---|
1315 | if (returnCode == TPM_SUCCESS) {
|
---|
1316 | k1 = &(b1AsymCaContents.sessionKey);
|
---|
1317 | }
|
---|
1318 | }
|
---|
1319 | /* 8. If B1 is a TPM_EK_BLOB then */
|
---|
1320 | if ((returnCode == TPM_SUCCESS) && (vers == 2)) {
|
---|
1321 | /* a. Validate that B1 -> ekType is TPM_EK_TYPE_ACTIVATE, return TPM_BAD_TYPE if not. */
|
---|
1322 | if (returnCode == TPM_SUCCESS) {
|
---|
1323 | if (b1EkBlob.ekType != TPM_EK_TYPE_ACTIVATE) {
|
---|
1324 | printf("TPM_Process_ActivateIdentity: Error, "
|
---|
1325 | "TPM_EK_BLOB not ekType TPM_EK_TYPE_ACTIVATE\n");
|
---|
1326 | returnCode = TPM_BAD_TYPE;
|
---|
1327 | }
|
---|
1328 | }
|
---|
1329 | /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1 -> blob */
|
---|
1330 | if (returnCode == TPM_SUCCESS) {
|
---|
1331 | stream = b1EkBlob.blob.buffer;
|
---|
1332 | stream_size = b1EkBlob.blob.size;
|
---|
1333 | returnCode = TPM_EKBlobActivate_Load(&a1, &stream, &stream_size);
|
---|
1334 | }
|
---|
1335 | /* c. Compare H1 to A1 -> idDigest on mismatch return TPM_BAD_PARAMETER */
|
---|
1336 | if (returnCode == TPM_SUCCESS) {
|
---|
1337 | returnCode = TPM_Digest_Compare(h1Digest, a1.idDigest);
|
---|
1338 | if (returnCode != 0) {
|
---|
1339 | printf("TPM_Process_ActivateIdentity: Error "
|
---|
1340 | "comparing TPM_EK_TYPE_ACTIVATE idDigest\n");
|
---|
1341 | returnCode = TPM_BAD_PARAMETER;
|
---|
1342 | }
|
---|
1343 | }
|
---|
1344 | /* d. If A1 -> pcrSelection is not NULL */
|
---|
1345 | /* i. Compute a composite hash C1 using the PCR selection A1 -> pcrSelection */
|
---|
1346 | /* ii. Compare C1 to A1 -> pcrInfo -> digestAtRelease and return TPM_WRONGPCRVAL on a
|
---|
1347 | mismatch */
|
---|
1348 | /* e. If A1 -> pcrInfo specifies a locality ensure that the appropriate locality has been
|
---|
1349 | asserted, return TPM_BAD_LOCALITY on error */
|
---|
1350 | if (returnCode == TPM_SUCCESS) {
|
---|
1351 | if (returnCode == TPM_SUCCESS) {
|
---|
1352 | returnCode =
|
---|
1353 | TPM_PCRInfoShort_CheckDigest(&(a1.pcrInfo),
|
---|
1354 | tpm_state->tpm_stclear_data.PCRS, /* PCR array */
|
---|
1355 | tpm_state->tpm_stany_flags.localityModifier);
|
---|
1356 | }
|
---|
1357 | }
|
---|
1358 | /* f. Set K1 to A1 -> symmetricKey */
|
---|
1359 | if (returnCode == TPM_SUCCESS) {
|
---|
1360 | k1 = &(a1.sessionKey);
|
---|
1361 | }
|
---|
1362 | }
|
---|
1363 | /*
|
---|
1364 | response
|
---|
1365 | */
|
---|
1366 | /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */
|
---|
1367 | if (rcf == 0) {
|
---|
1368 | printf("TPM_Process_ActivateIdentity: Ordinal returnCode %08x %u\n",
|
---|
1369 | returnCode, returnCode);
|
---|
1370 | rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode);
|
---|
1371 | }
|
---|
1372 | /* success response, append the rest of the parameters. */
|
---|
1373 | if (rcf == 0) {
|
---|
1374 | if (returnCode == TPM_SUCCESS) {
|
---|
1375 | /* checkpoint the beginning of the outParam's */
|
---|
1376 | outParamStart = response->buffer_current - response->buffer;
|
---|
1377 | /* 9. Return K1 */
|
---|
1378 | returnCode = TPM_SymmetricKey_Store(response, k1);
|
---|
1379 | /* checkpoint the end of the outParam's */
|
---|
1380 | outParamEnd = response->buffer_current - response->buffer;
|
---|
1381 | }
|
---|
1382 | /* digest the above the line output parameters */
|
---|
1383 | if (returnCode == TPM_SUCCESS) {
|
---|
1384 | returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */
|
---|
1385 | auditStatus, /* input audit status */
|
---|
1386 | transportEncrypt,
|
---|
1387 | tag,
|
---|
1388 | returnCode,
|
---|
1389 | ordinal, /* command ordinal */
|
---|
1390 | response->buffer + outParamStart, /* start */
|
---|
1391 | outParamEnd - outParamStart); /* length */
|
---|
1392 | }
|
---|
1393 | /* calculate and set the below the line parameters */
|
---|
1394 | if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) {
|
---|
1395 | returnCode = TPM_AuthParams_Set(response,
|
---|
1396 | *idKeyHmacKey, /* owner HMAC key */
|
---|
1397 | id_key_auth_session_data,
|
---|
1398 | outParamDigest,
|
---|
1399 | idKeynonceOdd,
|
---|
1400 | continueIdKeySession);
|
---|
1401 | }
|
---|
1402 | /* calculate and set the below the line parameters */
|
---|
1403 | if (returnCode == TPM_SUCCESS) {
|
---|
1404 | returnCode = TPM_AuthParams_Set(response,
|
---|
1405 | *hmacKey, /* owner HMAC key */
|
---|
1406 | auth_session_data,
|
---|
1407 | outParamDigest,
|
---|
1408 | nonceOdd,
|
---|
1409 | continueAuthSession);
|
---|
1410 | }
|
---|
1411 | /* audit if required */
|
---|
1412 | if ((returnCode == TPM_SUCCESS) && auditStatus) {
|
---|
1413 | returnCode = TPM_ProcessAudit(tpm_state,
|
---|
1414 | transportEncrypt,
|
---|
1415 | inParamDigest,
|
---|
1416 | outParamDigest,
|
---|
1417 | ordinal);
|
---|
1418 | }
|
---|
1419 | /* adjust the initial response */
|
---|
1420 | rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state);
|
---|
1421 | }
|
---|
1422 | /* if there was an error, or continueAuthSession is FALSE, terminate the session */
|
---|
1423 | if (((rcf != 0) ||
|
---|
1424 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
|
---|
1425 | !continueIdKeySession) &&
|
---|
1426 | idKeyAuthHandleValid) {
|
---|
1427 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, idKeyAuthHandle);
|
---|
1428 | }
|
---|
1429 | /* if there was an error, or continueAuthSession is FALSE, terminate the session */
|
---|
1430 | if (((rcf != 0) ||
|
---|
1431 | ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) ||
|
---|
1432 | !continueAuthSession) &&
|
---|
1433 | authHandleValid) {
|
---|
1434 | TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle);
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 |
|
---|
1438 | /*
|
---|
1439 | cleanup
|
---|
1440 | */
|
---|
1441 | TPM_SizedBuffer_Delete(&blob); /* @1 */
|
---|
1442 | TPM_SymmetricKey_Delete(&symmetricKey); /* @2 */
|
---|
1443 | free(b1Blob); /* @3 */
|
---|
1444 | TPM_AsymCaContents_Delete(&b1AsymCaContents); /* @4 */
|
---|
1445 | TPM_EKBlob_Delete(&b1EkBlob); /* @5 */
|
---|
1446 | TPM_EKBlobActivate_Delete(&a1); /* @6 */
|
---|
1447 | return rcf;
|
---|
1448 | }
|
---|