1 /** @file
2   Provide functions to provide tcg storage core spec related functions.
3 
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <Library/TcgStorageCoreLib.h>
10 
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 
15 typedef struct {
16     UINT16                                FeatureCode;
17     TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER  *Feature;
18     UINTN                                 FeatureSize;
19 } TCG_FIND_FEATURE_CTX;
20 
21 /**
22   Returns a human-readable string representing a method status return code.
23 
24   @param[in]  MethodStatus   Method status to translate to a string
25 
26 
27   @retval   return the string info.
28 **/
29 CHAR8*
30 EFIAPI
TcgMethodStatusString(UINT8 MethodStatus)31 TcgMethodStatusString(
32   UINT8 MethodStatus
33   )
34 {
35   switch (MethodStatus) {
36     #define C(status) case TCG_METHOD_STATUS_CODE_ ## status: return #status
37             C(SUCCESS);
38             C(NOT_AUTHORIZED);
39             C(OBSOLETE);
40             C(SP_BUSY);
41             C(SP_FAILED);
42             C(SP_DISABLED);
43             C(SP_FROZEN);
44             C(NO_SESSIONS_AVAILABLE);
45             C(UNIQUENESS_CONFLICT);
46             C(INSUFFICIENT_SPACE);
47             C(INSUFFICIENT_ROWS);
48             C(INVALID_PARAMETER);
49             C(OBSOLETE2);
50             C(OBSOLETE3);
51             C(TPER_MALFUNCTION);
52             C(TRANSACTION_FAILURE);
53             C(RESPONSE_OVERFLOW);
54             C(AUTHORITY_LOCKED_OUT);
55             C(FAIL);
56     #undef C
57   }
58   return "unknown";
59 }
60 
61 
62 /**
63   adds call token and method Header (invoking id, and method id).
64 
65   @param    CreateStruct             The input create structure.
66   @param    InvokingId               Invoking id.
67   @param    MethodId                 Method id.
68 
69 **/
70 TCG_RESULT
71 EFIAPI
TcgStartMethodCall(TCG_CREATE_STRUCT * CreateStruct,TCG_UID InvokingId,TCG_UID MethodId)72 TcgStartMethodCall(
73   TCG_CREATE_STRUCT   *CreateStruct,
74   TCG_UID             InvokingId,
75   TCG_UID             MethodId
76   )
77 {
78   NULL_CHECK(CreateStruct);
79 
80   if (CreateStruct->ComPacket == NULL ||
81       CreateStruct->CurPacket == NULL ||
82       CreateStruct->CurSubPacket == NULL
83      ) {
84     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
85     return (TcgResultFailureInvalidAction);
86   }
87 
88   ERROR_CHECK(TcgAddCall(CreateStruct));
89   ERROR_CHECK(TcgAddTcgUid(CreateStruct, InvokingId));
90   ERROR_CHECK(TcgAddTcgUid(CreateStruct, MethodId));
91 
92   return TcgResultSuccess;
93 }
94 
95 /**
96   Adds START LIST token.
97 
98   @param    CreateStruct        The input create structure.
99 
100 **/
101 TCG_RESULT
102 EFIAPI
TcgStartParameters(TCG_CREATE_STRUCT * CreateStruct)103 TcgStartParameters(
104   TCG_CREATE_STRUCT           *CreateStruct
105   )
106 {
107   NULL_CHECK(CreateStruct);
108 
109   if (CreateStruct->ComPacket == NULL ||
110       CreateStruct->CurPacket == NULL ||
111       CreateStruct->CurSubPacket == NULL
112      ) {
113     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
114     return (TcgResultFailureInvalidAction);
115   }
116 
117   return TcgAddStartList(CreateStruct);
118 }
119 
120 /**
121   Adds END LIST token.
122 
123   @param    CreateStruct        The input create structure.
124 
125 **/
126 TCG_RESULT
127 EFIAPI
TcgEndParameters(TCG_CREATE_STRUCT * CreateStruct)128 TcgEndParameters(
129   TCG_CREATE_STRUCT   *CreateStruct
130   )
131 {
132   NULL_CHECK(CreateStruct);
133 
134   if (CreateStruct->ComPacket == NULL ||
135       CreateStruct->CurPacket == NULL ||
136       CreateStruct->CurSubPacket == NULL
137      ) {
138     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
139     return (TcgResultFailureInvalidAction);
140   }
141 
142   return TcgAddEndList(CreateStruct);
143 }
144 
145 /**
146   Adds END Data token and method list.
147 
148   @param    CreateStruct        The input create structure.
149 
150 **/
151 TCG_RESULT
152 EFIAPI
TcgEndMethodCall(TCG_CREATE_STRUCT * CreateStruct)153 TcgEndMethodCall(
154   TCG_CREATE_STRUCT      *CreateStruct
155   )
156 {
157   NULL_CHECK(CreateStruct);
158 
159   if (CreateStruct->ComPacket == NULL ||
160       CreateStruct->CurPacket == NULL ||
161       CreateStruct->CurSubPacket == NULL
162      ) {
163     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
164     return (TcgResultFailureInvalidAction);
165   }
166 
167   ERROR_CHECK(TcgAddEndOfData(CreateStruct));
168 
169   ERROR_CHECK(TcgAddStartList(CreateStruct));
170   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00));   // expected to complete properly
171   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00));   // reserved
172   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00));   // reserved
173   ERROR_CHECK(TcgAddEndList(CreateStruct));
174 
175   return TcgResultSuccess;
176 }
177 
178 /**
179   Retrieves the comID and Extended comID of the ComPacket in the Tcg response.
180   It is intended to be used to confirm the received Tcg response is intended for user that received it.
181 
182   @param [in]        ParseStruct        Structure used to parse received TCG response.
183   @param [in/out]    ComId              comID retrieved from received ComPacket.
184   @param [in/out]    ComIdExtension     Extended comID retrieved from received ComPacket
185 
186 **/
187 TCG_RESULT
188 EFIAPI
TcgGetComIds(const TCG_PARSE_STRUCT * ParseStruct,UINT16 * ComId,UINT16 * ComIdExtension)189 TcgGetComIds(
190   const TCG_PARSE_STRUCT     *ParseStruct,
191   UINT16                     *ComId,
192   UINT16                     *ComIdExtension
193   )
194 {
195   NULL_CHECK(ParseStruct);
196   NULL_CHECK(ComId);
197   NULL_CHECK(ComIdExtension);
198 
199   if (ParseStruct->ComPacket == NULL) {
200     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p\n", ParseStruct->ComPacket));
201     return TcgResultFailureInvalidAction;
202   }
203 
204   *ComId = SwapBytes16(ParseStruct->ComPacket->ComIDBE);
205   *ComIdExtension = SwapBytes16(ParseStruct->ComPacket->ComIDExtensionBE);
206 
207   return TcgResultSuccess;
208 }
209 
210 /**
211   Checks if the ComIDs of the response match the expected values.
212 
213   @param[in]   ParseStruct               Structure used to parse received TCG response
214   @param[in]   ExpectedComId             Expected comID
215   @param[in]   ExpectedComIdExtension    Expected extended comID
216 
217 **/
218 TCG_RESULT
219 EFIAPI
TcgCheckComIds(const TCG_PARSE_STRUCT * ParseStruct,UINT16 ExpectedComId,UINT16 ExpectedComIdExtension)220 TcgCheckComIds(
221   const TCG_PARSE_STRUCT     *ParseStruct,
222   UINT16                     ExpectedComId,
223   UINT16                     ExpectedComIdExtension
224   )
225 {
226   UINT16 ParseComId;
227   UINT16 ParseComIdExtension;
228 
229   ERROR_CHECK(TcgGetComIds(ParseStruct, &ParseComId, &ParseComIdExtension));
230   if (ParseComId != ExpectedComId || ParseComIdExtension != ExpectedComIdExtension) {
231     DEBUG ((DEBUG_INFO, "Com ID: Actual 0x%02X Expected 0x%02X\n", ParseComId, ExpectedComId));
232     DEBUG ((DEBUG_INFO, "Extended Com ID: 0x%02X Expected 0x%02X\n", ParseComIdExtension, ExpectedComIdExtension));
233     return TcgResultFailure;
234   }
235   return TcgResultSuccess;
236 }
237 
238 /**
239  Returns the method status of the current subpacket.  Does not affect the current position
240  in the ComPacket.  In other words, it can be called whenever you have a valid SubPacket.
241 
242  @param [in/out]  ParseStruct       Structure used to parse received TCG response
243  @param [in/out]  MethodStatus      Method status retrieved of the current SubPacket
244 
245 **/
246 TCG_RESULT
247 EFIAPI
TcgGetMethodStatus(const TCG_PARSE_STRUCT * ParseStruct,UINT8 * MethodStatus)248 TcgGetMethodStatus(
249   const TCG_PARSE_STRUCT            *ParseStruct,
250   UINT8                             *MethodStatus
251   )
252 {
253   TCG_PARSE_STRUCT TmpParseStruct;
254   TCG_TOKEN TcgToken;
255   UINT8 Reserved1, Reserved2;
256 
257   NULL_CHECK(ParseStruct);
258   NULL_CHECK(MethodStatus);
259 
260   if (ParseStruct->ComPacket == NULL ||
261       ParseStruct->CurPacket == NULL ||
262       ParseStruct->CurSubPacket == NULL
263      ) {
264     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", ParseStruct->ComPacket, ParseStruct->CurPacket, ParseStruct->CurSubPacket));
265     return TcgResultFailureInvalidAction;
266   }
267 
268   // duplicate ParseStruct, then don't need to "reset" location cur ptr
269   CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT));
270 
271   // method status list exists after the end method call in the subpacket
272   // skip tokens until ENDDATA is found
273   do {
274     ERROR_CHECK(TcgGetNextToken(&TmpParseStruct, &TcgToken));
275   } while (TcgToken.Type != TcgTokenTypeEndOfData);
276 
277   // only reach here if enddata is found
278   // at this point, the curptr is pointing at method status list beginning
279   ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct));
280   ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, MethodStatus));
281   ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved1));
282   ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved2));
283   ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct));
284 
285   if (Reserved1 != 0) {
286     DEBUG ((DEBUG_INFO, "Method status reserved1 = 0x%02X (expected 0)\n", Reserved1));
287     return TcgResultFailure;
288   }
289 
290   if (Reserved2 != 0) {
291     DEBUG ((DEBUG_INFO, "Method status reserved2 = 0x%02X (expected 0)\n", Reserved1));
292     return TcgResultFailure;
293   }
294 
295   return TcgResultSuccess;
296 }
297 
298 /**
299   Return the toke type string info.
300 
301   @param    Type       Input the type info.
302 
303   @retval   Return the string for this type.
304 
305 **/
306 CHAR8*
307 EFIAPI
TcgTokenTypeString(TCG_TOKEN_TYPE Type)308 TcgTokenTypeString(
309   TCG_TOKEN_TYPE  Type
310   )
311 {
312   switch (Type) {
313     case TcgTokenTypeReserved: return "Reserved";
314     case TcgTokenTypeTinyAtom: return "Tiny Atom";
315     case TcgTokenTypeShortAtom: return "Short Atom";
316     case TcgTokenTypeMediumAtom: return "Medium Atom";
317     case TcgTokenTypeLongAtom: return "Long Atom";
318     case TcgTokenTypeStartList: return "Start List";
319     case TcgTokenTypeEndList: return "End List";
320     case TcgTokenTypeStartName: return "Start Name";
321     case TcgTokenTypeEndName: return "End Name";
322     case TcgTokenTypeCall: return "Call";
323     case TcgTokenTypeEndOfData: return "End of Data";
324     case TcgTokenTypeEndOfSession: return "End of Session";
325     case TcgTokenTypeStartTransaction: return "Start Transaction";
326     case TcgTokenTypeEndTransaction: return "End Transaction";
327     case TcgTokenTypeEmptyAtom: return "Empty atom";
328   }
329   return "Unknown";
330 }
331 
332 
333 /**
334 
335   Adds Start Session call to the data structure.  This creates the entire ComPacket structure and
336   returns the size of the entire compacket in the size parameter.
337 
338   @param [in/out]    CreateStruct               Structure used to add the start session call
339   @param [in/out]    Size                       Describes the size of the entire ComPacket (header and payload). Filled out by function.
340   @param [in]        ComId                      ComID for the ComPacket
341   @param [in]        ComIdExtension             Extended ComID for the ComPacket
342   @param [in]        HostSessionId              Host Session ID
343   @param [in]        SpId                       Security Provider to start session with
344   @param [in]        Write                      Write option for start session.  TRUE = start session requests write access
345   @param [in]        HostChallengeLength        Length of the host challenge.  Length should be 0 if hostChallenge is NULL
346   @param [in]        HostChallenge              Host challenge for Host Signing Authority.  If NULL, then no Host Challenge shall be sent.
347   @param [in]        HostSigningAuthority       Host Signing Authority used for start session.  If NULL, then no Host Signing Authority shall be sent.
348 
349 **/
350 TCG_RESULT
351 EFIAPI
TcgCreateStartSession(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size,UINT16 ComId,UINT16 ComIdExtension,UINT32 HostSessionId,TCG_UID SpId,BOOLEAN Write,UINT32 HostChallengeLength,const VOID * HostChallenge,TCG_UID HostSigningAuthority)352 TcgCreateStartSession(
353   TCG_CREATE_STRUCT     *CreateStruct,
354   UINT32                *Size,
355   UINT16                ComId,
356   UINT16                ComIdExtension,
357   UINT32                HostSessionId,
358   TCG_UID               SpId,
359   BOOLEAN               Write,
360   UINT32                HostChallengeLength,
361   const VOID            *HostChallenge,
362   TCG_UID               HostSigningAuthority
363   )
364 {
365   ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
366   ERROR_CHECK(TcgStartPacket(CreateStruct, 0x0, 0x0, 0x0, 0x0, 0x0)) ;
367   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
368   ERROR_CHECK(TcgStartMethodCall(CreateStruct, TCG_UID_SMUID, TCG_UID_SM_START_SESSION));
369   ERROR_CHECK(TcgStartParameters(CreateStruct));
370   ERROR_CHECK(TcgAddUINT32(CreateStruct, HostSessionId));
371   ERROR_CHECK(TcgAddTcgUid(CreateStruct, SpId));
372   ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Write));
373 
374   // optional parameters
375   if (HostChallenge != NULL && HostChallengeLength != 0) {
376     ERROR_CHECK(TcgAddStartName(CreateStruct));
377     ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00));   //TODO Create Enum for Method Optional Parameters?
378     ERROR_CHECK(TcgAddByteSequence(CreateStruct, HostChallenge, HostChallengeLength, FALSE));
379     ERROR_CHECK(TcgAddEndName(CreateStruct));
380   }
381   // optional parameters
382   if (HostSigningAuthority != 0) {
383     ERROR_CHECK(TcgAddStartName(CreateStruct));
384     ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x03));   //TODO Create Enum for Method Optional Parameters?
385     ERROR_CHECK(TcgAddTcgUid(CreateStruct, HostSigningAuthority));
386     ERROR_CHECK(TcgAddEndName(CreateStruct));
387   }
388 
389   ERROR_CHECK(TcgEndParameters(CreateStruct));
390   ERROR_CHECK(TcgEndMethodCall(CreateStruct));
391   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
392   ERROR_CHECK(TcgEndPacket(CreateStruct));
393   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
394 
395   return TcgResultSuccess;
396 }
397 
398 /**
399  Parses the Sync Session response contained in the parseStruct to retrieve Tper session ID.  If the Sync Session response
400  parameters do not match the comID, extended ComID and host session ID then a failure is returned.
401 
402  @param[in/out]   ParseStruct          Structure used to parse received TCG response, contains Sync Session response.
403  @param[in]       ComId                Expected ComID that is compared to actual ComID of response
404  @param[in]       ComIdExtension       Expected Extended ComID that is compared to actual Extended ComID of response
405  @param[in]       HostSessionId        Expected Host Session ID that is compared to actual  Host Session ID of response
406  @param[in/out]   TperSessionId        Tper Session ID retrieved from the Sync Session response.
407 
408 **/
409 TCG_RESULT
410 EFIAPI
TcgParseSyncSession(const TCG_PARSE_STRUCT * ParseStruct,UINT16 ComId,UINT16 ComIdExtension,UINT32 HostSessionId,UINT32 * TperSessionId)411 TcgParseSyncSession(
412   const TCG_PARSE_STRUCT  *ParseStruct,
413   UINT16                  ComId,
414   UINT16                  ComIdExtension,
415   UINT32                  HostSessionId,
416   UINT32                  *TperSessionId
417   )
418 {
419   UINT8 MethodStatus;
420   TCG_PARSE_STRUCT TmpParseStruct;
421   UINT16 ParseComId;
422   UINT16 ParseExtComId;
423   TCG_UID InvokingUID;
424   TCG_UID MethodUID;
425   UINT32 RecvHostSessionId;
426 
427   NULL_CHECK(ParseStruct);
428   NULL_CHECK(TperSessionId);
429 
430   CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT));
431 
432   // verify method status is good
433   ERROR_CHECK(TcgGetMethodStatus(&TmpParseStruct, &MethodStatus));
434   METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure);
435 
436   // verify comids
437   ERROR_CHECK(TcgGetComIds(&TmpParseStruct, &ParseComId, &ParseExtComId));
438 
439   if ((ComId != ParseComId) || (ComIdExtension != ParseExtComId)) {
440     DEBUG ((DEBUG_INFO, "unmatched comid (exp: 0x%X recv: 0x%X) or comid extension (exp: 0x%X recv: 0x%X)\n", ComId, ParseComId, ComIdExtension, ParseExtComId));
441     return TcgResultFailure;
442   }
443   ERROR_CHECK(TcgGetNextCall(&TmpParseStruct));
444   ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &InvokingUID));
445   ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &MethodUID));
446   ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct));
447   ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, &RecvHostSessionId));
448   ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, TperSessionId));
449   ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct));
450   ERROR_CHECK(TcgGetNextEndOfData(&TmpParseStruct));
451 
452   if (InvokingUID != TCG_UID_SMUID) {
453     DEBUG ((DEBUG_INFO, "Invoking UID did not match UID_SMUID\n"));
454     return TcgResultFailure;
455   }
456 
457   if (MethodUID != TCG_UID_SM_SYNC_SESSION) {
458     DEBUG ((DEBUG_INFO, "Method UID did not match UID_SM_SYNC_SESSION\n"));
459     return TcgResultFailure;
460   }
461 
462   if (HostSessionId != RecvHostSessionId) {
463     DEBUG ((DEBUG_INFO, "unmatched HostSessionId (exp: 0x%X recv: 0x%X)\n", HostSessionId, RecvHostSessionId));
464     return TcgResultFailure;
465   }
466 
467   return TcgResultSuccess;
468 }
469 
470 /**
471 
472   Creates ComPacket with EndSession.
473   This assumes a start session has already been opened.
474 
475   @param  [in/out]    CreateStruct        Structure used to add Endsession
476   @param  [in/out]    Size                Describes the size of the entire ComPacket (header and payload). Filled out by function.
477   @param  [in]        ComId               ComID for the ComPacket
478   @param  [in]        ComIdExtension      Extended ComID for the ComPacket
479   @param  [in]        HostSessionId         Host Session ID for the Packet
480   @param  [in]        TpSessionId         Tper Session ID for the Packet
481 
482 **/
483 TCG_RESULT
484 EFIAPI
TcgCreateEndSession(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size,UINT16 ComId,UINT16 ComIdExtension,UINT32 HostSessionId,UINT32 TpSessionId)485 TcgCreateEndSession(
486   TCG_CREATE_STRUCT   *CreateStruct,
487   UINT32              *Size,
488   UINT16              ComId,
489   UINT16              ComIdExtension,
490   UINT32              HostSessionId,
491   UINT32              TpSessionId
492   )
493 {
494   ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
495   ERROR_CHECK(TcgStartPacket(CreateStruct, TpSessionId, HostSessionId, 0x0, 0x0, 0x0));
496   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
497   ERROR_CHECK(TcgAddEndOfSession(CreateStruct));
498   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
499   ERROR_CHECK(TcgEndPacket(CreateStruct));
500   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
501 
502   return TcgResultSuccess;
503 }
504 
505 /**
506   Set start method.
507 
508   @param     CreateStruct   Input create structure.
509   @param     Row            Input the row info.
510   @param     ColumnNumber   the column info.
511 
512 **/
513 TCG_RESULT
514 EFIAPI
TcgStartMethodSet(TCG_CREATE_STRUCT * CreateStruct,TCG_UID Row,UINT32 ColumnNumber)515 TcgStartMethodSet(
516   TCG_CREATE_STRUCT        *CreateStruct,
517   TCG_UID                  Row,
518   UINT32                   ColumnNumber
519   )
520 {
521   ERROR_CHECK(TcgStartMethodCall(CreateStruct, Row, TCG_UID_METHOD_SET));
522   ERROR_CHECK(TcgStartParameters(CreateStruct));
523   ERROR_CHECK(TcgAddStartName(CreateStruct));
524   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x01)); // "Values"
525   ERROR_CHECK(TcgAddStartList(CreateStruct));
526   ERROR_CHECK(TcgAddStartName(CreateStruct));
527   ERROR_CHECK(TcgAddUINT32(CreateStruct, ColumnNumber));
528   return TcgResultSuccess;
529 }
530 
531 /**
532   Set end method.
533 
534   @param     CreateStruct  Input create structure.
535 
536 **/
537 TCG_RESULT
538 EFIAPI
TcgEndMethodSet(TCG_CREATE_STRUCT * CreateStruct)539 TcgEndMethodSet(
540   TCG_CREATE_STRUCT        *CreateStruct
541   )
542 {
543   ERROR_CHECK(TcgAddEndName(CreateStruct));
544   ERROR_CHECK(TcgAddEndList(CreateStruct));
545   ERROR_CHECK(TcgAddEndName(CreateStruct));
546   ERROR_CHECK(TcgEndParameters(CreateStruct));
547   ERROR_CHECK(TcgEndMethodCall(CreateStruct));
548   return TcgResultSuccess;
549 }
550 
551 /**
552   Creates ComPacket with a Method call that sets the PIN column for the row specified.
553   This assumes a start session has already been opened with the desired SP.
554 
555   @param [in/out]   CreateStruct           Structure used to add method call.
556   @param [in/out]   Size                   Describes the size of the entire ComPacket (header and payload). Filled out by function.
557   @param [in]       ComId                  ComID for the ComPacket
558   @param [in]       ComIdExtension         Extended ComID for the ComPacket
559   @param [in]       TperSession            Tper Session ID for the Packet
560   @param [in]       HostSession            Host Session ID for the Packet
561   @param [in]       SidRow                 UID of row of current SP to set PIN column
562   @param [in]       Password               value of PIN to set
563   @param [in]       PasswordSize           Size of PIN
564 
565 **/
566 TCG_RESULT
567 EFIAPI
TcgCreateSetCPin(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size,UINT16 ComId,UINT16 ComIdExtension,UINT32 TperSession,UINT32 HostSession,TCG_UID SidRow,const VOID * Password,UINT32 PasswordSize)568 TcgCreateSetCPin(
569   TCG_CREATE_STRUCT       *CreateStruct,
570   UINT32                  *Size,
571   UINT16                  ComId,
572   UINT16                  ComIdExtension,
573   UINT32                  TperSession,
574   UINT32                  HostSession,
575   TCG_UID                 SidRow,
576   const VOID              *Password,
577   UINT32                  PasswordSize
578   )
579 {
580   // set new SID Password
581   ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
582   ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
583   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
584   ERROR_CHECK(TcgStartMethodSet(CreateStruct, SidRow, 0x03)); // "PIN"
585   ERROR_CHECK(TcgAddByteSequence(CreateStruct, Password, PasswordSize, FALSE));
586   ERROR_CHECK(TcgEndMethodSet(CreateStruct));
587   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
588   ERROR_CHECK(TcgEndPacket(CreateStruct));
589   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
590   return TcgResultSuccess;
591 }
592 
593 /**
594  Creates ComPacket with a Method call that sets the "Enabled" column for the row specified using the value specified.
595  This assumes a start session has already been opened with the desired SP.
596 
597  @param [in/out]  CreateStruct          Structure used to add method call
598  @param [in/out]  Size                  Describes the size of the entire ComPacket (header and payload). Filled out by function.
599  @param [in]      ComId                 ComID for the ComPacket
600  @param [in]      ComIdExtension        Extended ComID for the ComPacket
601  @param [in]      TperSession           Tper Session ID for the Packet
602  @param [in]      HostSession           Host Session ID for the Packet
603  @param [in]      AuthorityUid          Authority UID to modify the "Enabled" column for
604  @param [in]      Enabled               Value to set the "Enabled" column to
605 
606 **/
607 TCG_RESULT
608 EFIAPI
TcgSetAuthorityEnabled(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size,UINT16 ComId,UINT16 ComIdExtension,UINT32 TperSession,UINT32 HostSession,TCG_UID AuthorityUid,BOOLEAN Enabled)609 TcgSetAuthorityEnabled(
610   TCG_CREATE_STRUCT           *CreateStruct,
611   UINT32                      *Size,
612   UINT16                      ComId,
613   UINT16                      ComIdExtension,
614   UINT32                      TperSession,
615   UINT32                      HostSession,
616   TCG_UID                     AuthorityUid,
617   BOOLEAN                     Enabled
618   )
619 {
620   ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
621   ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
622   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
623   ERROR_CHECK(TcgStartMethodSet(CreateStruct, AuthorityUid, 0x05)); // "Enabled"
624   ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Enabled));
625   ERROR_CHECK(TcgEndMethodSet(CreateStruct));
626   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
627   ERROR_CHECK(TcgEndPacket(CreateStruct));
628   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
629   return TcgResultSuccess;
630 }
631 
632 /**
633   Create set ace.
634 
635   @param     CreateStruct      Input create structure.
636   @param     Size              size info.
637   @param     ComId             ComId info.
638   @param     ComIdExtension    ComId extension info.
639   @param     TperSession       Tper session data.
640   @param     HostSession       Host session data.
641   @param     AceRow            Ace row info.
642   @param     Authority1        Authority 1 info.
643   @param     LogicalOperator   Logical operator info.
644   @param     Authority2        Authority 2 info.
645 
646   @retval    Return the action result.
647 
648 **/
649 TCG_RESULT
650 EFIAPI
TcgCreateSetAce(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size,UINT16 ComId,UINT16 ComIdExtension,UINT32 TperSession,UINT32 HostSession,TCG_UID AceRow,TCG_UID Authority1,BOOLEAN LogicalOperator,TCG_UID Authority2)651 TcgCreateSetAce(
652   TCG_CREATE_STRUCT        *CreateStruct,
653   UINT32                   *Size,
654   UINT16                   ComId,
655   UINT16                   ComIdExtension,
656   UINT32                   TperSession,
657   UINT32                   HostSession,
658   TCG_UID                  AceRow,
659   TCG_UID                  Authority1,
660   BOOLEAN                  LogicalOperator,
661   TCG_UID                  Authority2
662   )
663 {
664   UINT8 HalfUidAuthorityObjectRef[4];
665   UINT8 HalfUidBooleanAce[4];
666 
667   HalfUidAuthorityObjectRef[0] = 0x0;
668   HalfUidAuthorityObjectRef[1] = 0x0;
669   HalfUidAuthorityObjectRef[2] = 0xC;
670   HalfUidAuthorityObjectRef[3] = 0x5;
671 
672   HalfUidBooleanAce[0] = 0x0;
673   HalfUidBooleanAce[1] = 0x0;
674   HalfUidBooleanAce[2] = 0x4;
675   HalfUidBooleanAce[3] = 0xE;
676 
677   ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
678   ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
679   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
680   ERROR_CHECK(TcgStartMethodSet(CreateStruct, AceRow, 0x03));     // "BooleanExpr"
681   ERROR_CHECK(TcgAddStartList(CreateStruct));
682   ERROR_CHECK(TcgAddStartName(CreateStruct));
683   ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE));
684   ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority1));
685   ERROR_CHECK(TcgAddEndName(CreateStruct));
686   ERROR_CHECK(TcgAddStartName(CreateStruct));
687   ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE));
688   ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority2));
689   ERROR_CHECK(TcgAddEndName(CreateStruct));
690 
691   ERROR_CHECK(TcgAddStartName(CreateStruct));
692   ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidBooleanAce, sizeof(HalfUidBooleanAce), FALSE));
693   ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, LogicalOperator));
694   ERROR_CHECK(TcgAddEndName(CreateStruct));
695   ERROR_CHECK(TcgAddEndList(CreateStruct));
696   ERROR_CHECK(TcgEndMethodSet(CreateStruct));
697   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
698   ERROR_CHECK(TcgEndPacket(CreateStruct));
699   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
700   return TcgResultSuccess;
701 }
702 
703 /**
704   Enum level 0 discovery.
705 
706   @param     DiscoveryHeader   Discovery header.
707   @param     Callback          Callback function.
708   @param     Context           The context for the function.
709 
710   @retval    return true if the callback return TRUE, else return FALSE.
711 
712 **/
713 BOOLEAN
714 EFIAPI
TcgEnumLevel0Discovery(const TCG_LEVEL0_DISCOVERY_HEADER * DiscoveryHeader,TCG_LEVEL0_ENUM_CALLBACK Callback,VOID * Context)715 TcgEnumLevel0Discovery(
716   const TCG_LEVEL0_DISCOVERY_HEADER  *DiscoveryHeader,
717   TCG_LEVEL0_ENUM_CALLBACK           Callback,
718   VOID                               *Context
719   )
720 {
721   UINT32                                  BytesLeft;
722   const UINT8                             *DiscoveryBufferPtr;
723   UINT32                                  FeatLength;
724   TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER    *Feat;
725 
726   //
727   // Total bytes including descriptors but not including the Length field
728   //
729   BytesLeft = SwapBytes32(DiscoveryHeader->LengthBE);
730 
731   //
732   // If discovery Header is not valid, exit
733   //
734   if (BytesLeft == 0) {
735     return FALSE;
736   }
737 
738   //
739   // Subtract the Length of the Header, except the Length field, which is not included
740   //
741   BytesLeft -= (sizeof(TCG_LEVEL0_DISCOVERY_HEADER) - sizeof(DiscoveryHeader->LengthBE));
742 
743   //
744   // Move ptr to first descriptor
745   //
746   DiscoveryBufferPtr = (const UINT8*)DiscoveryHeader + sizeof(TCG_LEVEL0_DISCOVERY_HEADER);
747 
748   while (BytesLeft > sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER)) {
749     //
750     // Pointer to beginning of descriptor (including common Header)
751     //
752     Feat = (TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER*)DiscoveryBufferPtr;
753 
754     FeatLength = Feat->Length + sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER);
755 
756     //
757     // Not enough bytes left for Feature descriptor
758     //
759     if (BytesLeft < FeatLength) {
760       break;
761     }
762 
763     //
764     // Report the Feature to the callback
765     //
766     if (Callback(DiscoveryHeader, Feat, FeatLength, Context)) {
767       return TRUE;
768     }
769 
770     //
771     // Descriptor Length only describes Data after common Header
772     //
773     BytesLeft -= FeatLength;
774     DiscoveryBufferPtr += FeatLength;
775   }
776 
777   return FALSE;
778 }
779 
780 /**
781   The callback function for Get Feature function.
782 
783   @param     DiscoveryHeader   Input discovery header.
784   @param     Feature           Input Feature.
785   @param     FeatureSize       Input Feature size.
786   @param     Context           The context.
787 
788 **/
789 BOOLEAN
790 EFIAPI
TcgFindFeatureCallback(const TCG_LEVEL0_DISCOVERY_HEADER * DiscoveryHeader,TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER * Feature,UINTN FeatureSize,VOID * Context)791 TcgFindFeatureCallback(
792   const TCG_LEVEL0_DISCOVERY_HEADER           *DiscoveryHeader,
793   TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER        *Feature,
794   UINTN                                       FeatureSize,
795   VOID                                        *Context
796   )
797 {
798   TCG_FIND_FEATURE_CTX* FindCtx;
799 
800   FindCtx = (TCG_FIND_FEATURE_CTX*)Context;
801   if ( SwapBytes16( Feature->FeatureCode_BE ) == FindCtx->FeatureCode ) {
802     FindCtx->Feature = Feature;
803     FindCtx->FeatureSize = FeatureSize;
804     return TRUE; // done enumerating features
805   }
806   return FALSE; // continue enumerating
807 }
808 
809 /**
810   Get Feature code from the header.
811 
812   @param     DiscoveryHeader    The discovery header.
813   @param     FeatureCode        return the Feature code.
814   @param     FeatureSize        return the Feature size.
815 
816   @retval    return the Feature code data.
817 **/
818 TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER*
819 EFIAPI
TcgGetFeature(const TCG_LEVEL0_DISCOVERY_HEADER * DiscoveryHeader,UINT16 FeatureCode,UINTN * FeatureSize)820 TcgGetFeature(
821   const TCG_LEVEL0_DISCOVERY_HEADER  *DiscoveryHeader,
822   UINT16                             FeatureCode,
823   UINTN                              *FeatureSize
824   )
825 {
826   TCG_FIND_FEATURE_CTX FindCtx;
827 
828   FindCtx.FeatureCode = FeatureCode;
829   FindCtx.Feature = NULL;
830   FindCtx.FeatureSize = 0;
831 
832   TcgEnumLevel0Discovery(DiscoveryHeader, TcgFindFeatureCallback, &FindCtx);
833   if (FeatureSize != NULL) {
834     *FeatureSize = FindCtx.FeatureSize;
835   }
836   return FindCtx.Feature;
837 }
838 
839 /**
840   Determines if the protocol provided is part of the provided supported protocol list.
841 
842   @param[in]  ProtocolList     Supported protocol list to investigate
843   @param[in]  Protocol         Protocol value to determine if supported
844 
845   @return TRUE = protocol is supported, FALSE = protocol is not supported
846 **/
847 BOOLEAN
848 EFIAPI
TcgIsProtocolSupported(const TCG_SUPPORTED_SECURITY_PROTOCOLS * ProtocolList,UINT16 Protocol)849 TcgIsProtocolSupported(
850   const TCG_SUPPORTED_SECURITY_PROTOCOLS   *ProtocolList,
851   UINT16                                   Protocol
852   )
853 {
854   UINT16 Index;
855   UINT16 ListLength;
856 
857   ListLength = SwapBytes16(ProtocolList->ListLength_BE);
858 
859   if (ListLength > sizeof(ProtocolList->List)) {
860     DEBUG ((DEBUG_INFO, "WARNING: list Length is larger than max allowed Value; truncating\n"));
861     ListLength = sizeof(ProtocolList->List);
862   }
863 
864   for (Index = 0; Index < ListLength; Index++) {
865     if (ProtocolList->List[Index] == Protocol) {
866       return TRUE;
867     }
868   }
869 
870   return FALSE;
871 }
872 
873 /**
874   Check whether lock or not.
875 
876   @param     Discovery
877 
878   @retval    TRUE if lock, FALSE if not lock.
879 **/
880 BOOLEAN
881 EFIAPI
TcgIsLocked(const TCG_LEVEL0_DISCOVERY_HEADER * Discovery)882 TcgIsLocked(
883   const TCG_LEVEL0_DISCOVERY_HEADER         *Discovery
884   )
885 {
886   UINTN Size;
887   TCG_LOCKING_FEATURE_DESCRIPTOR     *LockDescriptor;
888 
889   Size = 0;
890   LockDescriptor =(TCG_LOCKING_FEATURE_DESCRIPTOR*) TcgGetFeature (Discovery, TCG_FEATURE_LOCKING, &Size);
891 
892   if (LockDescriptor != NULL && Size >= sizeof(*LockDescriptor)) {
893     DEBUG ((DEBUG_INFO, "locked: %d\n", LockDescriptor->Locked));
894     return LockDescriptor->Locked;
895   }
896 
897   //
898   // Descriptor was not found
899   //
900   return FALSE;
901 }
902