1 /* IBM_PROLOG_BEGIN_TAG */
2 /* This is an automatically generated prolog. */
3 /* */
4 /* $Source: src/usr/secureboot/trusted/trustedbootCmds.C $ */
5 /* */
6 /* OpenPOWER HostBoot Project */
7 /* */
8 /* Contributors Listed Below - COPYRIGHT 2015,2016 */
9 /* [+] International Business Machines Corp. */
10 /* */
11 /* */
12 /* Licensed under the Apache License, Version 2.0 (the "License"); */
13 /* you may not use this file except in compliance with the License. */
14 /* You may obtain a copy of the License at */
15 /* */
16 /* http://www.apache.org/licenses/LICENSE-2.0 */
17 /* */
18 /* Unless required by applicable law or agreed to in writing, software */
19 /* distributed under the License is distributed on an "AS IS" BASIS, */
20 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
21 /* implied. See the License for the specific language governing */
22 /* permissions and limitations under the License. */
23 /* */
24 /* IBM_PROLOG_END_TAG */
25 /**
26 * @file trustedbootCmds.C
27 *
28 * @brief Trusted boot TPM command interfaces
29 */
30
31 /////////////////////////////////////////////////////////////////
32 // NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
33 /////////////////////////////////////////////////////////////////
34
35 // ----------------------------------------------
36 // Includes
37 // ----------------------------------------------
38 #include <string.h>
39 #include <stdlib.h>
40 #ifdef __HOSTBOOT_MODULE
41 #include <secureboot/trustedboot_reasoncodes.H>
42 #else
43 #include "trustedboot_reasoncodes.H"
44 #endif
45 #include "trustedbootCmds.H"
46 #include "trustedbootUtils.H"
47 #include "trustedboot.H"
48 #include "trustedTypes.H"
49
50 #ifdef __cplusplus
51 namespace TRUSTEDBOOT
52 {
53 #endif
54
tpmTransmitCommand(TpmTarget * io_target,uint8_t * io_buffer,size_t i_bufsize)55 errlHndl_t tpmTransmitCommand(TpmTarget * io_target,
56 uint8_t* io_buffer,
57 size_t i_bufsize )
58 {
59 errlHndl_t err = TB_SUCCESS;
60 uint8_t* transmitBuf = NULL;
61 size_t cmdSize = 0;
62 size_t dataSize = 0;
63 TPM2_BaseIn* cmd = (TPM2_BaseIn*)io_buffer;
64 TPM2_BaseOut* resp = (TPM2_BaseOut*)io_buffer;
65
66 TRACUCOMP( g_trac_trustedboot,
67 ">>TPM TRANSMIT CMD START : BufLen %d : %016llx",
68 (int)i_bufsize,
69 *((uint64_t*)io_buffer) );
70
71 do
72 {
73 transmitBuf = (uint8_t*)malloc(MAX_TRANSMIT_SIZE);
74
75 // Marshal the data into a byte array for transfer to the TPM
76 err = tpmMarshalCommandData(cmd,
77 transmitBuf,
78 MAX_TRANSMIT_SIZE,
79 &cmdSize);
80 if (TB_SUCCESS != err)
81 {
82 break;
83 }
84
85 // Send to the TPM
86 dataSize = MAX_TRANSMIT_SIZE;
87 err = tpmTransmit(io_target,
88 transmitBuf,
89 cmdSize,
90 dataSize);
91
92 if (TB_SUCCESS != err)
93 {
94 break;
95 }
96
97 // Unmarshal the response
98 err = tpmUnmarshalResponseData(cmd->commandCode,
99 transmitBuf,
100 dataSize,
101 resp,
102 i_bufsize);
103
104
105 } while ( 0 );
106
107
108 free(transmitBuf);
109
110 TRACUCOMP( g_trac_trustedboot,
111 "<<tpmTransmitCommand() - %s",
112 ((TB_SUCCESS == err) ? "No Error" : "With Error") );
113 return err;
114 }
115
tpmMarshalCommandData(TPM2_BaseIn * i_cmd,uint8_t * o_outbuf,size_t i_bufsize,size_t * o_cmdSize)116 errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd,
117 uint8_t* o_outbuf,
118 size_t i_bufsize,
119 size_t* o_cmdSize)
120 {
121 errlHndl_t err = TB_SUCCESS;
122 uint8_t* sBuf = o_outbuf;
123 uint32_t* sSizePtr = NULL;
124 size_t curSize = 0;
125 int stage = 0;
126 TPM2_BaseIn* baseCmd =
127 (TPM2_BaseIn*)o_outbuf;
128 TPMS_AUTH_COMMAND cmdAuth;
129
130 *o_cmdSize = 0;
131
132 TRACDCOMP( g_trac_trustedboot,
133 ">>tpmMarshalCommandData()" );
134 do
135 {
136
137 TRACUCOMP( g_trac_trustedboot,
138 "TPM MARSHAL START : BufLen %d : %016llx",
139 (int)i_bufsize,
140 *((uint64_t*)i_cmd) );
141
142 // Start with the command header
143 sBuf = TPM2_BaseIn_marshal(i_cmd, sBuf, i_bufsize, o_cmdSize);
144 if (NULL == sBuf)
145 {
146 break;
147 }
148
149 // Marshal the handles
150 stage = 1;
151 if (TPM_CC_PCR_Extend == i_cmd->commandCode)
152 {
153 TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
154 sBuf = TPM2_ExtendIn_marshalHandle(cmdPtr,
155 sBuf,
156 i_bufsize,
157 o_cmdSize);
158 if (NULL == sBuf)
159 {
160 break;
161 }
162 }
163
164 // Marshal the authorizations
165 stage = 2;
166 if (TPM_CC_PCR_Extend == i_cmd->commandCode)
167 {
168 // Insert a password authorization with a null pw
169 // Make room for the 4 byte size field at the beginning
170 sSizePtr = (uint32_t*)sBuf;
171 sBuf += sizeof(uint32_t);
172 *o_cmdSize += sizeof(uint32_t);
173 i_bufsize -= sizeof(uint32_t);
174 curSize = *o_cmdSize;
175
176 cmdAuth.sessionHandle = TPM_RS_PW;
177 cmdAuth.nonceSize = 0;
178 cmdAuth.sessionAttributes = 0;
179 cmdAuth.hmacSize = 0;
180
181 sBuf = TPMS_AUTH_COMMAND_marshal(&cmdAuth, sBuf, i_bufsize,
182 o_cmdSize);
183
184 if (NULL == sBuf)
185 {
186 break;
187 }
188 // Put in the size of the auth area
189 *sSizePtr = (*o_cmdSize - curSize);
190
191 }
192
193 // Marshal the command parameters
194 stage = 3;
195 switch (i_cmd->commandCode)
196 {
197 // Two byte parm fields
198 case TPM_CC_Startup:
199 {
200 TPM2_2ByteIn* cmdPtr =
201 (TPM2_2ByteIn*)i_cmd;
202 sBuf = TPM2_2ByteIn_marshal(cmdPtr, sBuf,
203 i_bufsize, o_cmdSize);
204 }
205 break;
206
207 case TPM_CC_GetCapability:
208 {
209 TPM2_GetCapabilityIn* cmdPtr =
210 (TPM2_GetCapabilityIn*)i_cmd;
211 sBuf = TPM2_GetCapabilityIn_marshal(cmdPtr,sBuf,
212 i_bufsize, o_cmdSize);
213 }
214 break;
215 case TPM_CC_PCR_Read:
216 {
217 TPM2_PcrReadIn* cmdPtr = (TPM2_PcrReadIn*)i_cmd;
218 sBuf = TPM2_PcrReadIn_marshal(cmdPtr, sBuf,
219 i_bufsize - (sBuf - o_outbuf),
220 o_cmdSize);
221 }
222 break;
223
224 case TPM_CC_PCR_Extend:
225 {
226 TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
227 sBuf = TPM2_ExtendIn_marshalParms(cmdPtr, sBuf,
228 i_bufsize, o_cmdSize);
229 }
230 break;
231
232 default:
233 {
234 // Command code not supported
235 TRACFCOMP( g_trac_trustedboot,
236 "TPM MARSHAL INVALID COMMAND : %X",
237 i_cmd->commandCode );
238 sBuf = NULL;
239 /*@
240 * @errortype
241 * @reasoncode RC_TPM_MARSHAL_INVALID_CMD
242 * @severity ERRL_SEV_UNRECOVERABLE
243 * @moduleid MOD_TPM_MARSHALCMDDATA
244 * @userdata1 Command Code
245 * @userdata2 0
246 * @devdesc Unsupported command code during marshal
247 */
248 err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
249 RC_TPM_MARSHAL_INVALID_CMD,
250 i_cmd->commandCode,
251 0);
252 }
253 break;
254 };
255
256 if (TB_SUCCESS != err || NULL == sBuf)
257 {
258 break;
259 }
260
261 // Do a verification that the cmdSize equals what we used
262 if (((size_t)(sBuf - o_outbuf)) != *o_cmdSize)
263 {
264 TRACFCOMP( g_trac_trustedboot,
265 "TPM MARSHAL MARSHAL SIZE MISMATCH : %d %d",
266 (int)(sBuf - o_outbuf), (int)(*o_cmdSize) );
267 sBuf = NULL;
268 }
269
270 // Lastly now that we know the size update the byte stream
271 baseCmd->commandSize = *o_cmdSize;
272
273 } while ( 0 );
274
275 if (NULL == sBuf && TB_SUCCESS == err)
276 {
277 TRACFCOMP( g_trac_trustedboot,
278 "TPM MARSHAL FAILURE : Stage %d", stage);
279 /*@
280 * @errortype
281 * @reasoncode RC_TPM_MARSHALING_FAIL
282 * @severity ERRL_SEV_UNRECOVERABLE
283 * @moduleid MOD_TPM_MARSHALCMDDATA
284 * @userdata1 stage
285 * @userdata2 0
286 * @devdesc Marshaling error detected
287 */
288 err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
289 RC_TPM_MARSHALING_FAIL,
290 stage,
291 0 );
292
293 }
294
295 TRACUBIN(g_trac_trustedboot, "Marshal Out",
296 o_outbuf, *o_cmdSize);
297
298 TRACUCOMP( g_trac_trustedboot,
299 "TPM MARSHAL END : CmdSize: %d : %016llx ",
300 (int)(*o_cmdSize),
301 *((uint64_t*)o_outbuf) );
302
303 TRACDCOMP( g_trac_trustedboot,
304 "<<tpmMarshalCommandData()" );
305
306 return err;
307 }
308
tpmUnmarshalResponseData(uint32_t i_commandCode,uint8_t * i_respBuf,size_t i_respBufSize,TPM2_BaseOut * o_outBuf,size_t i_outBufSize)309 errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
310 uint8_t* i_respBuf,
311 size_t i_respBufSize,
312 TPM2_BaseOut* o_outBuf,
313 size_t i_outBufSize)
314 {
315 errlHndl_t err = TB_SUCCESS;
316 const uint8_t* sBuf = i_respBuf;
317 int stage = 0;
318
319 TRACDCOMP( g_trac_trustedboot,
320 ">>tpmUnmarshalResponseData()" );
321
322 do {
323
324 TRACUCOMP( g_trac_trustedboot,
325 "TPM UNMARSHAL START : RespBufLen %d : OutBufLen %d",
326 (int)i_respBufSize, (int)i_outBufSize);
327 TRACUBIN(g_trac_trustedboot,"Unmarshal In",
328 i_respBuf, i_respBufSize);
329
330
331 // Start with the response header
332 stage = 1;
333 sBuf = TPM2_BaseOut_unmarshal(o_outBuf, sBuf,
334 &i_respBufSize, i_outBufSize);
335 if (NULL == sBuf)
336 {
337 break;
338 }
339
340 // If the TPM returned a failure it will not send the rest
341 // Let the caller deal with the RC
342 if (TPM_SUCCESS != o_outBuf->responseCode)
343 {
344 break;
345 }
346
347
348 // Unmarshal the parameters
349 stage = 2;
350 switch (i_commandCode)
351 {
352 // Empty response commands
353 case TPM_CC_Startup:
354 case TPM_CC_PCR_Extend:
355 // Nothing to do
356 break;
357
358 case TPM_CC_GetCapability:
359 {
360 TPM2_GetCapabilityOut* respPtr =
361 (TPM2_GetCapabilityOut*)o_outBuf;
362 sBuf = TPM2_GetCapabilityOut_unmarshal(respPtr, sBuf,
363 &i_respBufSize,
364 i_outBufSize);
365
366 }
367 break;
368
369 case TPM_CC_PCR_Read:
370 {
371 TPM2_PcrReadOut* respPtr = (TPM2_PcrReadOut*)o_outBuf;
372 sBuf = TPM2_PcrReadOut_unmarshal(respPtr, sBuf,
373 &i_respBufSize,
374 i_outBufSize);
375 }
376 break;
377
378 default:
379 {
380 // Command code not supported
381 TRACFCOMP( g_trac_trustedboot,
382 "TPM UNMARSHAL INVALID COMMAND : %X",
383 i_commandCode );
384 sBuf = NULL;
385
386 /*@
387 * @errortype
388 * @reasoncode RC_TPM_UNMARSHAL_INVALID_CMD
389 * @severity ERRL_SEV_UNRECOVERABLE
390 * @moduleid MOD_TPM_UNMARSHALRESPDATA
391 * @userdata1 commandcode
392 * @userdata2 stage
393 * @devdesc Unsupported command code during unmarshal
394 */
395 err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
396 RC_TPM_UNMARSHAL_INVALID_CMD,
397 i_commandCode,
398 stage);
399 }
400 break;
401 }
402
403
404 } while ( 0 );
405
406 if (NULL == sBuf && TB_SUCCESS == err)
407 {
408 TRACFCOMP( g_trac_trustedboot,
409 "TPM UNMARSHAL FAILURE : Stage %d", stage);
410 /*@
411 * @errortype
412 * @reasoncode RC_TPM_UNMARSHALING_FAIL
413 * @severity ERRL_SEV_UNRECOVERABLE
414 * @moduleid MOD_TPM_UNMARSHALRESPDATA
415 * @userdata1 Stage
416 * @userdata2 Remaining response buffer size
417 * @devdesc Unmarshaling error detected
418 */
419 err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
420 RC_TPM_UNMARSHALING_FAIL,
421 stage,
422 i_respBufSize);
423
424
425
426 }
427
428 TRACUCOMP( g_trac_trustedboot,
429 "TPM UNMARSHAL END : %016llx ",
430 *((uint64_t*)o_outBuf) );
431
432 TRACDCOMP( g_trac_trustedboot,
433 "<<tpmUnmarshalResponseData()" );
434
435 return err;
436 }
437
tpmCmdStartup(TpmTarget * io_target)438 errlHndl_t tpmCmdStartup(TpmTarget* io_target)
439 {
440 errlHndl_t err = TB_SUCCESS;
441 uint8_t dataBuf[BUFSIZE];
442
443 TPM2_BaseOut* resp =
444 (TPM2_BaseOut*)(dataBuf);
445
446 TPM2_2ByteIn* cmd =
447 (TPM2_2ByteIn*)(dataBuf);
448
449 TRACUCOMP( g_trac_trustedboot,
450 ">>tpmCmdStartup()" );
451
452 do
453 {
454 // Send the TPM startup command
455 // Build our command block for a startup
456 memset(dataBuf, 0, sizeof(dataBuf));
457
458
459 cmd->base.tag = TPM_ST_NO_SESSIONS;
460 cmd->base.commandCode = TPM_CC_Startup;
461 cmd->param = TPM_SU_CLEAR;
462
463 err = tpmTransmitCommand(io_target,
464 dataBuf,
465 sizeof(dataBuf));
466
467 if (TB_SUCCESS != err)
468 {
469 TRACFCOMP( g_trac_trustedboot,
470 "TPM STARTUP transmit Fail");
471 break;
472
473 }
474 else if (TPM_SUCCESS != resp->responseCode)
475 {
476 TRACFCOMP( g_trac_trustedboot,
477 "TPM STARTUP OP Fail %X : ",
478 resp->responseCode);
479
480 /*@
481 * @errortype
482 * @reasoncode RC_TPM_START_FAIL
483 * @severity ERRL_SEV_UNRECOVERABLE
484 * @moduleid MOD_TPM_CMD_STARTUP
485 * @userdata1 responseCode
486 * @userdata2 0
487 * @devdesc Invalid operation type.
488 */
489 err = tpmCreateErrorLog(MOD_TPM_CMD_STARTUP,
490 RC_TPM_START_FAIL,
491 resp->responseCode,
492 0);
493
494 break;
495 }
496
497
498 } while ( 0 );
499
500
501 TRACUCOMP( g_trac_trustedboot,
502 "<<tpmCmdStartup() - %s",
503 ((TB_SUCCESS == err) ? "No Error" : "With Error") );
504 return err;
505 }
506
tpmCmdGetCapFwVersion(TpmTarget * io_target)507 errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target)
508 {
509 errlHndl_t err = TB_SUCCESS;
510 uint8_t dataBuf[BUFSIZE];
511 size_t dataSize = BUFSIZE;
512 uint16_t fwVersion[4] = {0xFF, 0xFF, 0xFF, 0xFF};
513 TPM2_GetCapabilityOut* resp =
514 (TPM2_GetCapabilityOut*)dataBuf;
515 TPM2_GetCapabilityIn* cmd =
516 (TPM2_GetCapabilityIn*)dataBuf;
517
518
519 TRACUCOMP( g_trac_trustedboot,
520 ">>tpmCmdGetCapFwVersion()" );
521
522 do
523 {
524
525 // Build our command block for a get capability of the FW version
526 memset(dataBuf, 0, dataSize);
527
528 cmd->base.tag = TPM_ST_NO_SESSIONS;
529 cmd->base.commandCode = TPM_CC_GetCapability;
530 cmd->capability = TPM_CAP_TPM_PROPERTIES;
531 cmd->property = TPM_PT_FIRMWARE_VERSION_1;
532 cmd->propertyCount = 1;
533
534 err = tpmTransmitCommand(io_target,
535 dataBuf,
536 sizeof(dataBuf));
537
538 if (TB_SUCCESS != err)
539 {
540 TRACFCOMP( g_trac_trustedboot,
541 "TPM GETCAP Transmit Fail");
542 break;
543
544 }
545
546 if (TPM_SUCCESS != resp->base.responseCode)
547 {
548 TRACFCOMP( g_trac_trustedboot,
549 "TPM GETCAP OP Fail %X Size(%d) ",
550 resp->base.responseCode,
551 (int)dataSize);
552
553 /*@
554 * @errortype
555 * @reasoncode RC_TPM_GETCAP_FAIL
556 * @severity ERRL_SEV_UNRECOVERABLE
557 * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
558 * @userdata1 responseCode
559 * @userdata2 0
560 * @devdesc Command failure reading TPM FW version.
561 */
562 err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
563 RC_TPM_GETCAP_FAIL,
564 resp->base.responseCode,
565 0);
566
567 break;
568 }
569 else
570 {
571 // Walk the reponse data to pull the high order bytes out
572
573 if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
574 resp->capData.data.tpmProperties.count != 1 ||
575 resp->capData.data.tpmProperties.tpmProperty[0].property !=
576 TPM_PT_FIRMWARE_VERSION_1) {
577
578 TRACFCOMP( g_trac_trustedboot,
579 "TPM GETCAP FW INVALID DATA "
580 "Cap(%X) Cnt(%X) Prop(%X)",
581 resp->capData.capability,
582 resp->capData.data.tpmProperties.count,
583 resp->capData.data.tpmProperties.
584 tpmProperty[0].property);
585
586 /*@
587 * @errortype
588 * @reasoncode RC_TPM_GETCAP_FW_INVALID_RESP
589 * @severity ERRL_SEV_UNRECOVERABLE
590 * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
591 * @userdata1 capability
592 * @userdata2 property
593 * @devdesc Command failure reading TPM FW version.
594 */
595 err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
596 RC_TPM_GETCAP_FW_INVALID_RESP,
597 resp->capData.capability,
598 resp->capData.data.tpmProperties.
599 tpmProperty[0].property);
600
601 break;
602 }
603 else
604 {
605 fwVersion[0] =
606 (resp->capData.data.
607 tpmProperties.tpmProperty[0].value >> 16);
608 fwVersion[1] =
609 (resp->capData.data.
610 tpmProperties.tpmProperty[0].value & 0xFFFF);
611 }
612
613 }
614
615 // Read part 2 of the version
616 dataSize = BUFSIZE;
617 memset(dataBuf, 0, dataSize);
618
619 cmd->base.tag = TPM_ST_NO_SESSIONS;
620 cmd->base.commandCode = TPM_CC_GetCapability;
621 cmd->capability = TPM_CAP_TPM_PROPERTIES;
622 cmd->property = TPM_PT_FIRMWARE_VERSION_2;
623 cmd->propertyCount = 1;
624
625
626 err = tpmTransmitCommand(io_target,
627 dataBuf,
628 sizeof(dataBuf));
629
630 if (TB_SUCCESS != err)
631 {
632 TRACFCOMP( g_trac_trustedboot,
633 "TPM GETCAP2 Transmit Fail");
634 break;
635
636 }
637
638 if ((sizeof(TPM2_GetCapabilityOut) > dataSize) ||
639 (TPM_SUCCESS != resp->base.responseCode))
640 {
641 TRACFCOMP( g_trac_trustedboot,
642 "TPM GETCAP2 OP Fail %X Size(%d) ",
643 resp->base.responseCode,
644 (int)dataSize);
645
646 /*@
647 * @errortype
648 * @reasoncode RC_TPM_GETCAP2_FAIL
649 * @severity ERRL_SEV_UNRECOVERABLE
650 * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
651 * @userdata1 responseCode
652 * @userdata2 0
653 * @devdesc Command failure reading TPM FW version.
654 */
655 err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
656 RC_TPM_GETCAP2_FAIL,
657 resp->base.responseCode,
658 0);
659
660 break;
661 }
662 else
663 {
664 // Walk the reponse data to pull the high order bytes out
665
666 if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
667 resp->capData.data.tpmProperties.count != 1 ||
668 resp->capData.data.tpmProperties.tpmProperty[0].property !=
669 TPM_PT_FIRMWARE_VERSION_2) {
670
671 TRACFCOMP( g_trac_trustedboot,
672 "TPM GETCAP2 FW INVALID DATA "
673 "Cap(%X) Cnt(%X) Prop(%X)",
674 resp->capData.capability,
675 resp->capData.data.tpmProperties.count,
676 resp->capData.data.tpmProperties.
677 tpmProperty[0].property);
678
679 /*@
680 * @errortype
681 * @reasoncode RC_TPM_GETCAP2_FW_INVALID_RESP
682 * @severity ERRL_SEV_UNRECOVERABLE
683 * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
684 * @userdata1 capability
685 * @userdata2 property
686 * @devdesc Command failure reading TPM FW version.
687 */
688 err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
689 RC_TPM_GETCAP2_FW_INVALID_RESP,
690 resp->capData.capability,
691 resp->capData.data.tpmProperties.
692 tpmProperty[0].property);
693 break;
694 }
695 else
696 {
697 fwVersion[2] =
698 (resp->capData.data.tpmProperties.
699 tpmProperty[0].value >> 16);
700 fwVersion[3] =
701 (resp->capData.data.tpmProperties.
702 tpmProperty[0].value & 0xFFFF);
703 }
704 // Trace the response
705 TRACFCOMP( g_trac_trustedboot,
706 "TPM GETCAP FW Level %d.%d.%d.%d",
707 fwVersion[0],fwVersion[1],fwVersion[2],fwVersion[3]
708 );
709 }
710
711
712 } while ( 0 );
713
714
715 TRACDCOMP( g_trac_trustedboot,
716 "<<tpmCmdGetCapFwVersion() - %s",
717 ((TB_SUCCESS == err) ? "No Error" : "With Error") );
718 return err;
719 }
720
721
tpmCmdPcrExtend(TpmTarget * io_target,TPM_Pcr i_pcr,TPM_Alg_Id i_algId,const uint8_t * i_digest,size_t i_digestSize)722 errlHndl_t tpmCmdPcrExtend(TpmTarget * io_target,
723 TPM_Pcr i_pcr,
724 TPM_Alg_Id i_algId,
725 const uint8_t* i_digest,
726 size_t i_digestSize)
727 {
728 return tpmCmdPcrExtend2Hash(io_target, i_pcr,
729 i_algId, i_digest, i_digestSize,
730 TPM_ALG_INVALID_ID, NULL, 0);
731 }
732
tpmCmdPcrExtend2Hash(TpmTarget * io_target,TPM_Pcr i_pcr,TPM_Alg_Id i_algId_1,const uint8_t * i_digest_1,size_t i_digestSize_1,TPM_Alg_Id i_algId_2,const uint8_t * i_digest_2,size_t i_digestSize_2)733 errlHndl_t tpmCmdPcrExtend2Hash(TpmTarget * io_target,
734 TPM_Pcr i_pcr,
735 TPM_Alg_Id i_algId_1,
736 const uint8_t* i_digest_1,
737 size_t i_digestSize_1,
738 TPM_Alg_Id i_algId_2,
739 const uint8_t* i_digest_2,
740 size_t i_digestSize_2)
741 {
742 errlHndl_t err = 0;
743 uint8_t dataBuf[sizeof(TPM2_ExtendIn)];
744 size_t dataSize = sizeof(dataBuf);
745 size_t fullDigestSize_1 = 0;
746 size_t fullDigestSize_2 = 0;
747 TPM2_BaseOut* resp = (TPM2_BaseOut*)dataBuf;
748 TPM2_ExtendIn* cmd = (TPM2_ExtendIn*)dataBuf;
749
750
751 TRACDCOMP( g_trac_trustedboot,
752 ">>tpmCmdPcrExtend2Hash()" );
753 if (NULL == i_digest_2)
754 {
755 TRACUCOMP( g_trac_trustedboot,
756 ">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X) DS(%d)",
757 i_pcr, i_algId_1, (int)i_digestSize_1);
758 }
759 else
760 {
761 TRACUCOMP( g_trac_trustedboot,
762 ">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X:%X) DS(%d:%d)",
763 i_pcr, i_algId_1, i_algId_2,
764 (int)i_digestSize_1, (int)i_digestSize_2);
765 }
766
767 do
768 {
769
770 fullDigestSize_1 = getDigestSize(i_algId_1);
771 if (NULL != i_digest_2)
772 {
773 fullDigestSize_2 = getDigestSize(i_algId_2);
774 }
775
776 // Build our command block
777 memset(dataBuf, 0, sizeof(dataBuf));
778
779 // Argument verification
780 if (fullDigestSize_1 == 0 ||
781 NULL == i_digest_1 ||
782 IMPLEMENTATION_PCR < i_pcr ||
783 (NULL != i_digest_2 && fullDigestSize_2 == 0)
784 )
785 {
786 TRACFCOMP( g_trac_trustedboot,
787 "TPM PCR EXTEND ARG FAILURE FDS(%d:%d) DS(%d:%d) "
788 "PCR(%d)",
789 (int)fullDigestSize_1, (int)fullDigestSize_2,
790 (int)i_digestSize_1, (int)i_digestSize_2, i_pcr);
791 /*@
792 * @errortype
793 * @reasoncode RC_TPM_INVALID_ARGS
794 * @severity ERRL_SEV_UNRECOVERABLE
795 * @moduleid MOD_TPM_CMD_PCREXTEND
796 * @userdata1 Digest Ptr
797 * @userdata2[0:15] Full Digest Size 1
798 * @userdata2[16:31] Full Digest Size 2
799 * @userdata2[32:63] PCR
800 * @devdesc Unmarshaling error detected
801 */
802 err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
803 RC_TPM_INVALID_ARGS,
804 (uint64_t)i_digest_1,
805 (fullDigestSize_1 << 48) |
806 (fullDigestSize_2 << 32) |
807 i_pcr);
808 break;
809 }
810
811 // Log the input PCR value
812 TRACUBIN(g_trac_trustedboot, "PCR In",
813 i_digest_1, fullDigestSize_1);
814
815 cmd->base.tag = TPM_ST_SESSIONS;
816 cmd->base.commandCode = TPM_CC_PCR_Extend;
817 cmd->pcrHandle = i_pcr;
818 cmd->digests.count = 1;
819 cmd->digests.digests[0].algorithmId = i_algId_1;
820 memcpy(&(cmd->digests.digests[0].digest), i_digest_1,
821 (i_digestSize_1 < fullDigestSize_1 ?
822 i_digestSize_1 : fullDigestSize_1) );
823 if (NULL != i_digest_2)
824 {
825 cmd->digests.count = 2;
826 cmd->digests.digests[1].algorithmId = i_algId_2;
827 memcpy(&(cmd->digests.digests[1].digest), i_digest_2,
828 (i_digestSize_2 < fullDigestSize_2 ?
829 i_digestSize_2 : fullDigestSize_2));
830 }
831
832 err = tpmTransmitCommand(io_target,
833 dataBuf,
834 sizeof(dataBuf));
835
836 if (TB_SUCCESS != err)
837 {
838 TRACFCOMP( g_trac_trustedboot,
839 "TPM PCRExtend Transmit Fail");
840 break;
841
842 }
843 else if ((sizeof(TPM2_BaseOut) > dataSize)
844 || (TPM_SUCCESS != resp->responseCode))
845 {
846 TRACFCOMP( g_trac_trustedboot,
847 "TPM PCRExtend OP Fail Ret(%X) ExSize(%d) Size(%d) ",
848 resp->responseCode,
849 (int)sizeof(TPM2_BaseOut),
850 (int)dataSize);
851
852 /*@
853 * @errortype
854 * @reasoncode RC_TPM_COMMAND_FAIL
855 * @severity ERRL_SEV_UNRECOVERABLE
856 * @moduleid MOD_TPM_CMD_PCREXTEND
857 * @userdata1 responseCode
858 * @userdata2 dataSize
859 * @devdesc Command failure reading TPM FW version.
860 */
861 err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
862 RC_TPM_COMMAND_FAIL,
863 resp->responseCode,
864 dataSize);
865 break;
866
867 }
868
869 } while ( 0 );
870
871
872 TRACUCOMP( g_trac_trustedboot,
873 "<<tpmCmdPcrExtend() - %s",
874 ((TB_SUCCESS == err) ? "No Error" : "With Error") );
875 return err;
876
877 }
878
tpmCmdPcrRead(TpmTarget * io_target,TPM_Pcr i_pcr,TPM_Alg_Id i_algId,uint8_t * o_digest,size_t i_digestSize)879 errlHndl_t tpmCmdPcrRead(TpmTarget* io_target,
880 TPM_Pcr i_pcr,
881 TPM_Alg_Id i_algId,
882 uint8_t* o_digest,
883 size_t i_digestSize)
884 {
885 errlHndl_t err = 0;
886 uint8_t dataBuf[sizeof(TPM2_PcrReadOut)];
887 size_t dataSize = sizeof(dataBuf);
888 size_t fullDigestSize = 0;
889 TPM2_PcrReadOut* resp = (TPM2_PcrReadOut*)dataBuf;
890 TPM2_PcrReadIn* cmd = (TPM2_PcrReadIn*)dataBuf;
891
892
893 TRACDCOMP( g_trac_trustedboot,
894 ">>tpmCmdPcrRead()" );
895 TRACUCOMP( g_trac_trustedboot,
896 ">>tpmCmdPcrRead() Pcr(%d) DS(%d)",
897 i_pcr, (int)i_digestSize);
898
899 do
900 {
901
902 fullDigestSize = getDigestSize(i_algId);
903
904 // Build our command block
905 memset(dataBuf, 0, sizeof(dataBuf));
906
907 // Argument verification
908 if (fullDigestSize > i_digestSize ||
909 NULL == o_digest ||
910 IMPLEMENTATION_PCR < i_pcr
911 )
912 {
913 TRACFCOMP( g_trac_trustedboot,
914 "TPM PCR READ ARG FAILURE FDS(%d) DS(%d) PCR(%d)",
915 (int)fullDigestSize, (int)i_digestSize, i_pcr);
916 /*@
917 * @errortype
918 * @reasoncode RC_TPM_INVALID_ARGS
919 * @severity ERRL_SEV_UNRECOVERABLE
920 * @moduleid MOD_TPM_CMD_PCRREAD
921 * @userdata1 Digest Ptr
922 * @userdata2[0:31] Full Digest Size
923 * @userdata2[32:63] PCR
924 * @devdesc Unmarshaling error detected
925 */
926 err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
927 RC_TPM_INVALID_ARGS,
928 (uint64_t)o_digest,
929 (fullDigestSize << 32) |
930 i_pcr);
931
932 break;
933 }
934
935 cmd->base.tag = TPM_ST_NO_SESSIONS;
936 cmd->base.commandCode = TPM_CC_PCR_Read;
937 cmd->pcrSelectionIn.count = 1; // One algorithm
938 cmd->pcrSelectionIn.pcrSelections[0].algorithmId = i_algId;
939 cmd->pcrSelectionIn.pcrSelections[0].sizeOfSelect = PCR_SELECT_MAX;
940 memset(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect, 0,
941 sizeof(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect));
942 cmd->pcrSelectionIn.pcrSelections[0].pcrSelect[i_pcr / 8] =
943 0x01 << (i_pcr % 8);
944
945 err = tpmTransmitCommand(io_target,
946 dataBuf,
947 sizeof(dataBuf));
948
949 if (TB_SUCCESS != err)
950 {
951 TRACFCOMP( g_trac_trustedboot,
952 "TPM PCRRead Transmit Fail ");
953 break;
954
955 }
956 else if ((sizeof(TPM2_BaseOut) > dataSize) ||
957 (TPM_SUCCESS != resp->base.responseCode) ||
958 (resp->pcrValues.count != 1) ||
959 (resp->pcrValues.digests[0].size != fullDigestSize))
960 {
961 TRACFCOMP( g_trac_trustedboot,
962 "TPM PCRRead OP Fail Ret(%X) ExSize(%d) "
963 "Size(%d) Cnt(%d) DSize(%d)",
964 resp->base.responseCode,
965 (int)sizeof(TPM2_BaseOut),
966 (int)dataSize,
967 resp->pcrValues.count,
968 resp->pcrValues.digests[0].size);
969
970 /*@
971 * @errortype
972 * @reasoncode RC_TPM_COMMAND_FAIL
973 * @severity ERRL_SEV_UNRECOVERABLE
974 * @moduleid MOD_TPM_CMD_PCRREAD
975 * @userdata1 responseCode
976 * @userdata2 dataSize
977 * @devdesc Command failure reading TPM FW version.
978 */
979 err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
980 RC_TPM_COMMAND_FAIL,
981 resp->base.responseCode,
982 dataSize);
983 break;
984 }
985 else
986 {
987
988 memcpy(o_digest, resp->pcrValues.digests[0].buffer, fullDigestSize);
989
990 // Log the PCR value
991 TRACUBIN(g_trac_trustedboot, "PCR Out",
992 o_digest, fullDigestSize);
993
994 }
995
996 } while ( 0 );
997
998
999 TRACUCOMP( g_trac_trustedboot,
1000 "<<tpmCmdPcrRead() - %s",
1001 ((TB_SUCCESS == err) ? "No Error" : "With Error") );
1002 return err;
1003
1004 }
1005
1006
1007 #ifdef __cplusplus
1008 } // end TRUSTEDBOOT
1009 #endif
1010