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