1 /** @file
2   Public API for Opal Core library.
3 
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <Uefi.h>
10 #include <Library/BaseLib.h>
11 #include <Library/TimerLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/TcgStorageOpalLib.h>
15 
16 #include "TcgStorageOpalLibInternal.h"
17 
18 #pragma pack(1)
19 typedef struct {
20     UINT8 HardwareReset : 1;
21     UINT8 Reserved : 7;
22 } TCG_BLOCK_SID_CLEAR_EVENTS;
23 #pragma pack()
24 
25 #define TRUSTED_COMMAND_TIMEOUT_NS      ((UINT64) 5 * ((UINT64)(1000000)) * 1000) // 5 seconds
26 #define BUFFER_SIZE                      512
27 
28 /**
29   The function performs a Trusted Send of a Buffer containing a TCG_COM_PACKET.
30 
31   @param[in]      Sscp                  The input Ssc Protocol.
32   @param[in]      MediaId               The input Media id info used by Ssc Protocol.
33   @param[in]      SecurityProtocol      Security Protocol
34   @param[in]      SpSpecific            Security Protocol Specific
35   @param[in]      TransferLength        Transfer Length of Buffer (in bytes) - always a multiple of 512
36   @param[in]      Buffer                Address of Data to transfer
37   @param[in]      BufferSize            Full Size of Buffer, including space that may be used for padding.
38 
39 **/
40 TCG_RESULT
OpalTrustedSend(EFI_STORAGE_SECURITY_COMMAND_PROTOCOL * Sscp,UINT32 MediaId,UINT8 SecurityProtocol,UINT16 SpSpecific,UINTN TransferLength,VOID * Buffer,UINTN BufferSize)41 OpalTrustedSend(
42   EFI_STORAGE_SECURITY_COMMAND_PROTOCOL  *Sscp,
43   UINT32                                 MediaId,
44   UINT8                                  SecurityProtocol,
45   UINT16                                 SpSpecific,
46   UINTN                                  TransferLength,
47   VOID                                   *Buffer,
48   UINTN                                  BufferSize
49   )
50 {
51   UINTN       TransferLength512;
52   EFI_STATUS  Status;
53 
54   //
55   // Round transferLength up to a 512-byte multiple
56   //
57   TransferLength512 = (TransferLength + 511) & ~(UINTN)511;
58 
59   if (TransferLength512 > BufferSize) {
60     return TcgResultFailureBufferTooSmall;
61   }
62 
63   ZeroMem((UINT8*)Buffer + TransferLength, TransferLength512 - TransferLength);
64 
65   Status = Sscp->SendData(
66                Sscp,
67                MediaId,
68                TRUSTED_COMMAND_TIMEOUT_NS,
69                SecurityProtocol,
70                SwapBytes16(SpSpecific),
71                TransferLength512,
72                Buffer
73                );
74 
75   return Status == EFI_SUCCESS ? TcgResultSuccess : TcgResultFailure;
76 }
77 
78 /**
79 
80   The function performs a Trusted Receive of a Buffer containing a TCG_COM_PACKET.
81 
82   @param[in]      Sscp                  The input Ssc Protocol.
83   @param[in]      MediaId               The input Media id info used by Ssc Protocol.
84   @param[in]      SecurityProtocol      Security Protocol
85   @param[in]      SpSpecific            Security Protocol Specific
86   @param[in]      Buffer                Address of Data to transfer
87   @param[in]      BufferSize            Full Size of Buffer, including space that may be used for padding.
88   @param[in]      EstimateTimeCost      Estimate the time needed.
89 
90 **/
91 TCG_RESULT
OpalTrustedRecv(EFI_STORAGE_SECURITY_COMMAND_PROTOCOL * Sscp,UINT32 MediaId,UINT8 SecurityProtocol,UINT16 SpSpecific,VOID * Buffer,UINTN BufferSize,UINT32 EstimateTimeCost)92 OpalTrustedRecv(
93   EFI_STORAGE_SECURITY_COMMAND_PROTOCOL  *Sscp,
94   UINT32                                 MediaId,
95   UINT8                                  SecurityProtocol,
96   UINT16                                 SpSpecific,
97   VOID                                   *Buffer,
98   UINTN                                  BufferSize,
99   UINT32                                 EstimateTimeCost
100   )
101 {
102   UINTN           TransferLength512;
103   UINT32          Tries;
104   TCG_COM_PACKET  *ComPacket;
105   UINT32          Length;
106   UINT32          OutstandingData;
107   EFI_STATUS      Status;
108   UINTN           TransferSize;
109 
110   //
111   // Round Buffer Size down to a 512-byte multiple
112   //
113   TransferLength512 = BufferSize & ~(UINTN)511;
114   Tries = 0;
115   ComPacket = NULL;
116   Length = 0;
117   OutstandingData = 0;
118 
119   if (TransferLength512 < sizeof(TCG_COM_PACKET)) {
120     DEBUG ((DEBUG_INFO, "transferLength %u too small for ComPacket\n", TransferLength512));
121     return TcgResultFailureBufferTooSmall;
122   }
123 
124   //
125   // Some devices respond with Length = 0 and OutstandingData = 1 to indicate that processing is not yet completed,
126   // so we need to retry the IF-RECV to get the actual Data.
127   // See TCG Core Spec v2 Table 45 IF-RECV ComPacket Field Values Summary
128   // This is an arbitrary number of retries, not from the spec.
129   //
130   // if user input estimate time cost(second level) value bigger than 10s, base on user input value to wait.
131   // Else, Use a max timeout of 10 seconds to wait, 5000 tries * 2ms = 10s
132   //
133   if (EstimateTimeCost > 10) {
134     Tries = EstimateTimeCost * 500; // 500 = 1000 * 1000 / 2000;
135   } else {
136     Tries = 5000;
137   }
138   while ((Tries--) > 0) {
139     ZeroMem( Buffer, BufferSize );
140     TransferSize = 0;
141 
142     Status = Sscp->ReceiveData(
143                  Sscp,
144                  MediaId,
145                  TRUSTED_COMMAND_TIMEOUT_NS,
146                  SecurityProtocol,
147                  SwapBytes16(SpSpecific),
148                  TransferLength512,
149                  Buffer,
150                  &TransferSize
151              );
152     if (EFI_ERROR (Status)) {
153       return TcgResultFailure;
154     }
155 
156     if (SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_1 && SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_2) {
157       return TcgResultSuccess;
158     }
159 
160     if (SpSpecific == TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY) {
161       return TcgResultSuccess;
162     }
163 
164     ComPacket = (TCG_COM_PACKET*) Buffer;
165     Length = SwapBytes32(ComPacket->LengthBE);
166     OutstandingData = SwapBytes32( ComPacket->OutstandingDataBE );
167 
168     if (Length != 0 && OutstandingData == 0) {
169       return TcgResultSuccess;
170     }
171 
172     //
173     // Delay for 2 ms
174     //
175     MicroSecondDelay (2000);
176   }
177 
178   return TcgResultFailure;
179 }
180 
181 /**
182   The function performs send, recv, check comIDs, check method status action.
183 
184   @param[in]      Session           OPAL_SESSION related to this method..
185   @param[in]      SendSize          Transfer Length of Buffer (in bytes) - always a multiple of 512
186   @param[in]      Buffer            Address of Data to transfer
187   @param[in]      BufferSize        Full Size of Buffer, including space that may be used for padding.
188   @param[in]      ParseStruct       Structure used to parse received TCG response.
189   @param[in]      MethodStatus      Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
190   @param[in]      EstimateTimeCost  Estimate the time need to for the method.
191 **/
192 TCG_RESULT
193 EFIAPI
OpalPerformMethod(OPAL_SESSION * Session,UINT32 SendSize,VOID * Buffer,UINT32 BufferSize,TCG_PARSE_STRUCT * ParseStruct,UINT8 * MethodStatus,UINT32 EstimateTimeCost)194 OpalPerformMethod (
195   OPAL_SESSION     *Session,
196   UINT32           SendSize,
197   VOID             *Buffer,
198   UINT32           BufferSize,
199   TCG_PARSE_STRUCT *ParseStruct,
200   UINT8            *MethodStatus,
201   UINT32           EstimateTimeCost
202   )
203 {
204   NULL_CHECK(Session);
205   NULL_CHECK(MethodStatus);
206 
207   ERROR_CHECK(OpalTrustedSend(
208                   Session->Sscp,
209                   Session->MediaId,
210                   TCG_OPAL_SECURITY_PROTOCOL_1,
211                   Session->OpalBaseComId,
212                   SendSize,
213                   Buffer,
214                   BufferSize
215               ));
216 
217   ERROR_CHECK(OpalTrustedRecv(
218                   Session->Sscp,
219                   Session->MediaId,
220                   TCG_OPAL_SECURITY_PROTOCOL_1,
221                   Session->OpalBaseComId,
222                   Buffer,
223                   BufferSize,
224                   EstimateTimeCost
225               ));
226 
227   ERROR_CHECK(TcgInitTcgParseStruct(ParseStruct, Buffer, BufferSize));
228   ERROR_CHECK(TcgCheckComIds(ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
229   ERROR_CHECK(TcgGetMethodStatus(ParseStruct, MethodStatus));
230 
231   return TcgResultSuccess;
232 }
233 
234 /**
235   Trig the block sid action.
236 
237   @param[in]      Session            OPAL_SESSION related to this method..
238   @param[in]      HardwareReset      Whether need to do hardware reset.
239 
240 **/
241 TCG_RESULT
242 EFIAPI
OpalBlockSid(OPAL_SESSION * Session,BOOLEAN HardwareReset)243 OpalBlockSid(
244   OPAL_SESSION                           *Session,
245   BOOLEAN                                HardwareReset
246   )
247 {
248   UINT8                      Buffer[BUFFER_SIZE];
249   TCG_BLOCK_SID_CLEAR_EVENTS *ClearEvents;
250 
251   NULL_CHECK(Session);
252 
253   //
254   // Set Hardware Reset bit
255   //
256   ClearEvents = (TCG_BLOCK_SID_CLEAR_EVENTS *) &Buffer[0];
257 
258   ClearEvents->Reserved = 0;
259   ClearEvents->HardwareReset = HardwareReset;
260 
261   return(OpalTrustedSend(
262                   Session->Sscp,
263                   Session->MediaId,
264                   TCG_OPAL_SECURITY_PROTOCOL_2,
265                   TCG_BLOCKSID_COMID,   // hardcode ComID 0x0005
266                   1,
267                   Buffer,
268                   BUFFER_SIZE
269               ));
270 }
271 
272 /**
273 
274   Reverts device using Admin SP Revert method.
275 
276   @param[in]  AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
277 
278 **/
279 TCG_RESULT
280 EFIAPI
OpalPsidRevert(OPAL_SESSION * AdminSpSession)281 OpalPsidRevert(
282   OPAL_SESSION              *AdminSpSession
283   )
284 {
285   //
286   // Now that base comid is known, start Session
287   // we'll attempt to start Session as PSID authority
288   // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
289   //
290   TCG_CREATE_STRUCT  CreateStruct;
291   TCG_PARSE_STRUCT   ParseStruct;
292   UINT32             Size;
293   UINT8              Buffer[BUFFER_SIZE];
294   UINT8              MethodStatus;
295 
296   NULL_CHECK(AdminSpSession);
297 
298   //
299   // Send Revert action on Admin SP
300   //
301   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
302   ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
303   ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
304   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
305   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));
306   ERROR_CHECK(TcgStartParameters(&CreateStruct));
307   ERROR_CHECK(TcgEndParameters(&CreateStruct));
308   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
309   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
310   ERROR_CHECK(TcgEndPacket(&CreateStruct));
311   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
312 
313   //
314   // Send Revert Method Call
315   //
316   ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
317   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
318 
319   return TcgResultSuccess;
320 }
321 
322 /**
323 
324   Reverts device using Admin SP Revert method.
325 
326   @param[in]  AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
327   @param[in]  EstimateTimeCost    Estimate the time needed.
328 
329 **/
330 TCG_RESULT
OpalPyrite2PsidRevert(OPAL_SESSION * AdminSpSession,UINT32 EstimateTimeCost)331 OpalPyrite2PsidRevert(
332   OPAL_SESSION              *AdminSpSession,
333   UINT32                    EstimateTimeCost
334   )
335 {
336   //
337   // Now that base comid is known, start Session
338   // we'll attempt to start Session as PSID authority
339   // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
340   //
341   TCG_CREATE_STRUCT  CreateStruct;
342   TCG_PARSE_STRUCT   ParseStruct;
343   UINT32             Size;
344   UINT8              Buffer[BUFFER_SIZE];
345   UINT8              MethodStatus;
346 
347 
348   NULL_CHECK(AdminSpSession);
349 
350   //
351   // Send Revert action on Admin SP
352   //
353   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
354   ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
355   ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
356   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
357   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));
358   ERROR_CHECK(TcgStartParameters(&CreateStruct));
359   ERROR_CHECK(TcgEndParameters(&CreateStruct));
360   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
361   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
362   ERROR_CHECK(TcgEndPacket(&CreateStruct));
363   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
364 
365   //
366   // Send Revert Method Call
367   //
368   ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, EstimateTimeCost));
369   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
370 
371   return TcgResultSuccess;
372 }
373 
374 /**
375 
376   The function fills in the provided Buffer with the level 0 discovery Header
377   of the device specified.
378 
379   @param[in]        Session         OPAL_SESSION data.
380   @param[in]        BufferSize      Size of Buffer provided (in bytes)
381   @param[in]        BuffAddress     Buffer address to fill with Level 0 Discovery response
382 
383 **/
384 TCG_RESULT
385 EFIAPI
OpalRetrieveLevel0DiscoveryHeader(OPAL_SESSION * Session,UINTN BufferSize,VOID * BuffAddress)386 OpalRetrieveLevel0DiscoveryHeader(
387   OPAL_SESSION     *Session,
388   UINTN            BufferSize,
389   VOID             *BuffAddress
390   )
391 {
392   return (OpalTrustedRecv(
393               Session->Sscp,
394               Session->MediaId,
395               TCG_OPAL_SECURITY_PROTOCOL_1,   // SP
396               TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific
397               BuffAddress,
398               BufferSize,
399               0
400             ));
401 }
402 
403 /**
404 
405   The function fills in the provided Buffer with the supported protocol list
406   of the device specified.
407 
408   @param[in]        Session         OPAL_SESSION data.
409   @param[in]        BufferSize      Size of Buffer provided (in bytes)
410   @param[in]        BuffAddress     Buffer address to fill with security protocol list
411 
412 **/
413 TCG_RESULT
414 EFIAPI
OpalRetrieveSupportedProtocolList(OPAL_SESSION * Session,UINTN BufferSize,VOID * BuffAddress)415 OpalRetrieveSupportedProtocolList(
416   OPAL_SESSION     *Session,
417   UINTN            BufferSize,
418   VOID             *BuffAddress
419   )
420 {
421   return (OpalTrustedRecv(
422               Session->Sscp,
423               Session->MediaId,
424               TCG_SECURITY_PROTOCOL_INFO, // SP
425               TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific
426               BuffAddress,
427               BufferSize,
428               0
429           ));
430 }
431 
432 /**
433   Starts a session with a security provider (SP).
434 
435   If a session is started successfully, the caller must end the session with OpalEndSession when finished
436   performing Opal actions.
437 
438   @param[in/out]  Session                 OPAL_SESSION to initialize.
439   @param[in]      SpId                    Security provider ID to start the session with.
440   @param[in]      Write                   Whether the session should be read-only (FALSE) or read/write (TRUE).
441   @param[in]      HostChallengeLength     Length of the host challenge.  Length should be 0 if hostChallenge is NULL
442   @param[in]      HostChallenge           Host challenge for Host Signing Authority.  If NULL, then no Host Challenge will be sent.
443   @param[in]      HostSigningAuthority    Host Signing Authority used for start session.  If NULL, then no Host Signing Authority will be sent.
444   @param[in/out]  MethodStatus            Status of the StartSession method; only valid if TcgResultSuccess is returned.
445 
446   @return TcgResultSuccess indicates that the function completed without any internal errors.
447   The caller must inspect the MethodStatus field to determine whether the method completed successfully.
448 
449 **/
450 TCG_RESULT
451 EFIAPI
OpalStartSession(OPAL_SESSION * Session,TCG_UID SpId,BOOLEAN Write,UINT32 HostChallengeLength,const VOID * HostChallenge,TCG_UID HostSigningAuthority,UINT8 * MethodStatus)452 OpalStartSession(
453   OPAL_SESSION     *Session,
454   TCG_UID          SpId,
455   BOOLEAN          Write,
456   UINT32           HostChallengeLength,
457   const VOID       *HostChallenge,
458   TCG_UID          HostSigningAuthority,
459   UINT8            *MethodStatus
460   )
461 {
462   TCG_CREATE_STRUCT CreateStruct;
463   TCG_PARSE_STRUCT  ParseStruct;
464   UINT32            Size;
465   UINT8             Buf[BUFFER_SIZE];
466   UINT16            ComIdExtension;
467   UINT32            HostSessionId;
468 
469   ComIdExtension = 0;
470   HostSessionId  = 1;
471 
472   NULL_CHECK(Session);
473   NULL_CHECK(MethodStatus);
474 
475   Session->ComIdExtension = ComIdExtension;
476   Session->HostSessionId = HostSessionId;
477 
478   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
479   ERROR_CHECK(TcgCreateStartSession(
480                     &CreateStruct,
481                     &Size,
482                     Session->OpalBaseComId,
483                     ComIdExtension,
484                     HostSessionId,
485                     SpId,
486                     Write,
487                     HostChallengeLength,
488                     HostChallenge,
489                     HostSigningAuthority
490                 ));
491   ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
492   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
493     return TcgResultSuccess; // return early if method failed - user must check MethodStatus
494   }
495 
496   if (TcgParseSyncSession(&ParseStruct, Session->OpalBaseComId, ComIdExtension, HostSessionId, &Session->TperSessionId) != TcgResultSuccess) {
497     OpalEndSession(Session);
498     return TcgResultFailure;
499   }
500 
501   return TcgResultSuccess;
502 }
503 
504 /**
505   Close a session opened with OpalStartSession.
506 
507   @param[in/out]  Session                 OPAL_SESSION to end.
508 
509 **/
510 TCG_RESULT
511 EFIAPI
OpalEndSession(OPAL_SESSION * Session)512 OpalEndSession(
513   OPAL_SESSION     *Session
514   )
515 {
516   UINT8             Buffer[BUFFER_SIZE];
517   TCG_CREATE_STRUCT CreateStruct;
518   UINT32            Size;
519   TCG_PARSE_STRUCT  ParseStruct;
520 
521   NULL_CHECK(Session);
522   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, sizeof(Buffer)));
523   ERROR_CHECK(TcgCreateEndSession(
524                   &CreateStruct,
525                   &Size,
526                   Session->OpalBaseComId,
527                   Session->ComIdExtension,
528                   Session->HostSessionId,
529                   Session->TperSessionId
530                 ));
531 
532   ERROR_CHECK(OpalTrustedSend(
533                   Session->Sscp,
534                   Session->MediaId,
535                   TCG_OPAL_SECURITY_PROTOCOL_1,
536                   Session->OpalBaseComId,
537                   Size,
538                   Buffer,
539                   sizeof(Buffer)
540               ));
541 
542   ERROR_CHECK(OpalTrustedRecv(
543                   Session->Sscp,
544                   Session->MediaId,
545                   TCG_OPAL_SECURITY_PROTOCOL_1,
546                   Session->OpalBaseComId,
547                   Buffer,
548                   sizeof(Buffer),
549                   0
550               ));
551 
552   ERROR_CHECK(TcgInitTcgParseStruct(&ParseStruct, Buffer, sizeof(Buffer)));
553   ERROR_CHECK(TcgCheckComIds(&ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
554 
555   ERROR_CHECK(TcgGetNextEndOfSession(&ParseStruct));
556   return TcgResultSuccess;
557 }
558 
559 /**
560 
561   The function retrieves the MSID from the device specified
562 
563   @param[in]  AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
564   @param[in]  MsidBufferSize      Allocated Buffer Size (in bytes) for MSID allocated by caller
565   @param[in]  Msid                Variable Length byte sequence representing MSID of device
566   @param[in]  MsidLength          Actual Length of MSID retrieved from device
567 
568 **/
569 TCG_RESULT
570 EFIAPI
OpalGetMsid(OPAL_SESSION * AdminSpSession,UINT32 MsidBufferSize,UINT8 * Msid,UINT32 * MsidLength)571 OpalGetMsid(
572   OPAL_SESSION    *AdminSpSession,
573   UINT32          MsidBufferSize,
574   UINT8           *Msid,
575   UINT32          *MsidLength
576   )
577 {
578   //
579   // now that base comid is known, start Session
580   // we'll attempt to start Session as PSID authority
581   // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
582   //
583   TCG_CREATE_STRUCT CreateStruct;
584   TCG_PARSE_STRUCT  ParseStruct;
585   UINT32            Size;
586   UINT8             MethodStatus;
587   UINT32            Col;
588   const VOID        *RecvMsid;
589   UINT8             Buffer[BUFFER_SIZE];
590 
591   NULL_CHECK(AdminSpSession);
592   NULL_CHECK(Msid);
593   NULL_CHECK(MsidLength);
594 
595   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
596   ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
597   ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
598   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
599   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_C_PIN_MSID, TCG_UID_METHOD_GET));
600   ERROR_CHECK(TcgStartParameters(&CreateStruct));
601   ERROR_CHECK(TcgAddStartList(&CreateStruct));
602   ERROR_CHECK(TcgAddStartName(&CreateStruct));
603   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
604   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
605   ERROR_CHECK(TcgAddEndName(&CreateStruct));
606   ERROR_CHECK(TcgAddStartName(&CreateStruct));
607   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
608   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
609   ERROR_CHECK(TcgAddEndName(&CreateStruct));
610   ERROR_CHECK(TcgAddEndList(&CreateStruct));
611   ERROR_CHECK(TcgEndParameters(&CreateStruct));
612   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
613   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
614   ERROR_CHECK(TcgEndPacket(&CreateStruct));
615   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
616 
617   //
618   // Send MSID Method Call
619   //
620   ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
621   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
622 
623   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
624   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
625   ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
626   ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
627   ERROR_CHECK(TcgGetNextByteSequence(&ParseStruct, &RecvMsid, MsidLength));
628   ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
629   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
630   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
631   ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
632 
633   if (Col != OPAL_ADMIN_SP_PIN_COL) {
634     DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_PIN_COL));
635     return TcgResultFailure;
636   }
637 
638   if (RecvMsid == NULL) {
639     return TcgResultFailure;
640   }
641 
642   if (MsidBufferSize < *MsidLength) {
643     DEBUG ((DEBUG_INFO, "Buffer too small MsidBufferSize: %d MsidLength: %d\n", MsidBufferSize, *MsidLength));
644     return TcgResultFailureBufferTooSmall;
645   }
646 
647   //
648   // copy msid into Buffer
649   //
650   CopyMem(Msid, RecvMsid, *MsidLength);
651   return TcgResultSuccess;
652 }
653 
654 /**
655 
656   The function retrieves the MSID from the device specified
657 
658   @param[in]  AdminSpSession              OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_ANYBODY_AUTHORITY
659   @param[out] ActiveDataRemovalMechanism  Active Data Removal Mechanism that the device will use for Revert/RevertSP calls.
660 
661 **/
662 TCG_RESULT
OpalPyrite2GetActiveDataRemovalMechanism(IN OPAL_SESSION * AdminSpSession,OUT UINT8 * ActiveDataRemovalMechanism)663 OpalPyrite2GetActiveDataRemovalMechanism (
664   IN  OPAL_SESSION    *AdminSpSession,
665   OUT UINT8           *ActiveDataRemovalMechanism
666   )
667 {
668   TCG_CREATE_STRUCT CreateStruct;
669   TCG_PARSE_STRUCT  ParseStruct;
670   UINT32            Size;
671   UINT8             MethodStatus;
672   UINT32            Col;
673   UINT8             RecvActiveDataRemovalMechanism;
674   UINT8             Buffer[BUFFER_SIZE];
675 
676   NULL_CHECK(AdminSpSession);
677   NULL_CHECK(ActiveDataRemovalMechanism);
678 
679   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
680   ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
681   ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
682   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
683   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_DATA_REMOVAL_MECHANISM, TCG_UID_METHOD_GET));
684   ERROR_CHECK(TcgStartParameters(&CreateStruct));
685   ERROR_CHECK(TcgAddStartList(&CreateStruct));
686   ERROR_CHECK(TcgAddStartName(&CreateStruct));
687   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
688   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
689   ERROR_CHECK(TcgAddEndName(&CreateStruct));
690   ERROR_CHECK(TcgAddStartName(&CreateStruct));
691   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
692   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
693   ERROR_CHECK(TcgAddEndName(&CreateStruct));
694   ERROR_CHECK(TcgAddEndList(&CreateStruct));
695   ERROR_CHECK(TcgEndParameters(&CreateStruct));
696   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
697   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
698   ERROR_CHECK(TcgEndPacket(&CreateStruct));
699   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
700 
701   //
702   // Send Get Active Data Removal Mechanism Method Call
703   //
704   ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
705   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
706 
707   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
708   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
709   ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
710   ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
711   ERROR_CHECK(TcgGetNextUINT8(&ParseStruct, &RecvActiveDataRemovalMechanism));
712   ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
713   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
714   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
715   ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
716 
717   if (Col != OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL) {
718     DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
719     return TcgResultFailure;
720   }
721 
722   if (RecvActiveDataRemovalMechanism >= ResearvedMechanism) {
723     return TcgResultFailure;
724   }
725 
726   //
727   // Copy active data removal mechanism into Buffer
728   //
729   CopyMem(ActiveDataRemovalMechanism, &RecvActiveDataRemovalMechanism, sizeof(RecvActiveDataRemovalMechanism));
730   return TcgResultSuccess;
731 }
732 
733 /**
734 
735   The function calls the Admin SP RevertSP method on the Locking SP.  If KeepUserData is True, then the optional parameter
736   to keep the user Data is set to True, otherwise the optional parameter is not provided.
737 
738   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP
739   @param[in]      KeepUserData        Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.
740   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
741 
742 **/
743 TCG_RESULT
744 EFIAPI
OpalAdminRevert(OPAL_SESSION * LockingSpSession,BOOLEAN KeepUserData,UINT8 * MethodStatus)745 OpalAdminRevert(
746   OPAL_SESSION    *LockingSpSession,
747   BOOLEAN         KeepUserData,
748   UINT8           *MethodStatus
749   )
750 {
751   UINT8             Buf[BUFFER_SIZE];
752   TCG_CREATE_STRUCT CreateStruct;
753   UINT32            Size;
754   TCG_PARSE_STRUCT  ParseStruct;
755   TCG_RESULT        Ret;
756 
757   NULL_CHECK(LockingSpSession);
758   NULL_CHECK(MethodStatus);
759 
760   //
761   // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data
762   //
763   if (KeepUserData) {
764     //
765     // set readlocked and writelocked to false
766     //
767     Ret = OpalUpdateGlobalLockingRange(
768                         LockingSpSession,
769                         FALSE,
770                         FALSE,
771                         MethodStatus);
772 
773     if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
774       //
775       // bail out
776       //
777       return Ret;
778     }
779   }
780 
781   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
782   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
783   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
784   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
785   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));
786   ERROR_CHECK(TcgStartParameters(&CreateStruct));
787 
788   if (KeepUserData) {
789     //
790     // optional parameter to keep Data after revert
791     //
792     ERROR_CHECK(TcgAddStartName(&CreateStruct));
793     ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000));      // weird Value but that's what spec says
794     ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));
795     ERROR_CHECK(TcgAddEndName(&CreateStruct));
796   }
797 
798   ERROR_CHECK(TcgEndParameters(&CreateStruct));
799   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
800   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
801   ERROR_CHECK(TcgEndPacket(&CreateStruct));
802   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
803 
804   //
805   // Send RevertSP method call
806   //
807   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
808 
809   //
810   // Session is immediately ended by device after successful revertsp, so no need to end Session
811   //
812   if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
813     //
814     // Caller should take ownership again
815     //
816     return TcgResultSuccess;
817   } else {
818     //
819     // End Session
820     //
821     METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);     // exit with success on method failure - user must inspect MethodStatus
822   }
823 
824   return TcgResultSuccess;
825 }
826 
827 
828 /**
829 
830   The function calls the Admin SP RevertSP method on the Locking SP.  If KeepUserData is True, then the optional parameter
831   to keep the user Data is set to True, otherwise the optional parameter is not provided.
832 
833   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP
834   @param[in]      KeepUserData        Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.
835   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
836   @param[in]      EstimateTimeCost    Estimate the time needed.
837 
838 **/
839 TCG_RESULT
OpalPyrite2AdminRevert(OPAL_SESSION * LockingSpSession,BOOLEAN KeepUserData,UINT8 * MethodStatus,UINT32 EstimateTimeCost)840 OpalPyrite2AdminRevert(
841   OPAL_SESSION    *LockingSpSession,
842   BOOLEAN         KeepUserData,
843   UINT8           *MethodStatus,
844   UINT32          EstimateTimeCost
845   )
846 {
847   UINT8             Buf[BUFFER_SIZE];
848   TCG_CREATE_STRUCT CreateStruct;
849   UINT32            Size;
850   TCG_PARSE_STRUCT  ParseStruct;
851   TCG_RESULT        Ret;
852 
853   NULL_CHECK(LockingSpSession);
854   NULL_CHECK(MethodStatus);
855 
856   //
857   // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data
858   //
859   if (KeepUserData) {
860     //
861     // set readlocked and writelocked to false
862     //
863     Ret = OpalUpdateGlobalLockingRange(
864                         LockingSpSession,
865                         FALSE,
866                         FALSE,
867                         MethodStatus);
868 
869     if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
870       //
871       // bail out
872       //
873       return Ret;
874     }
875   }
876 
877   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
878   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
879   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
880   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
881   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));
882   ERROR_CHECK(TcgStartParameters(&CreateStruct));
883 
884   if (KeepUserData) {
885     //
886     // optional parameter to keep Data after revert
887     //
888     ERROR_CHECK(TcgAddStartName(&CreateStruct));
889     ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000));      // weird Value but that's what spec says
890     ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));
891     ERROR_CHECK(TcgAddEndName(&CreateStruct));
892   }
893 
894   ERROR_CHECK(TcgEndParameters(&CreateStruct));
895   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
896   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
897   ERROR_CHECK(TcgEndPacket(&CreateStruct));
898   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
899 
900   //
901   // Send RevertSP method call
902   //
903   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, EstimateTimeCost));
904 
905   //
906   // Session is immediately ended by device after successful revertsp, so no need to end Session
907   //
908   if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
909     //
910     // Caller should take ownership again
911     //
912     return TcgResultSuccess;
913   } else {
914     //
915     // End Session
916     //
917     METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);     // exit with success on method failure - user must inspect MethodStatus
918   }
919 
920   return TcgResultSuccess;
921 }
922 
923 /**
924 
925   The function activates the Locking SP.
926   Once activated, per Opal spec, the ADMIN SP SID PIN is copied over to the ADMIN1 LOCKING SP PIN.
927   If the Locking SP is already enabled, then TcgResultSuccess is returned and no action occurs.
928 
929   @param[in]      AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY to activate Locking SP
930   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
931 
932 **/
933 TCG_RESULT
934 EFIAPI
OpalActivateLockingSp(OPAL_SESSION * AdminSpSession,UINT8 * MethodStatus)935 OpalActivateLockingSp(
936   OPAL_SESSION           *AdminSpSession,
937   UINT8                  *MethodStatus
938   )
939 {
940   UINT8             Buf[BUFFER_SIZE];
941   TCG_CREATE_STRUCT CreateStruct;
942   UINT32            Size;
943   TCG_PARSE_STRUCT  ParseStruct;
944 
945   NULL_CHECK(AdminSpSession);
946   NULL_CHECK(MethodStatus);
947 
948   //
949   // Call Activate method on Locking SP
950   //
951   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
952   ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
953   ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
954   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
955   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_LOCKING_SP, OPAL_ADMIN_SP_ACTIVATE_METHOD));
956   ERROR_CHECK(TcgStartParameters(&CreateStruct));
957   ERROR_CHECK(TcgEndParameters(&CreateStruct));
958   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
959   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
960   ERROR_CHECK(TcgEndPacket(&CreateStruct));
961   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
962 
963   //
964   // Send Activate method call
965   //
966   ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
967   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
968 
969   return TcgResultSuccess;
970 }
971 
972 /**
973 
974   The function sets the PIN column of the specified cpinRowUid (authority) with the newPin Value.
975 
976   @param[in/out]  Session                 OPAL_SESSION to set password
977   @param[in]      CpinRowUid              UID of row (authority) to update PIN column
978   @param[in]      NewPin                  New Pin to set for cpinRowUid specified
979   @param[in]      NewPinLength            Length in bytes of newPin
980   @param[in/out]  MethodStatus            Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
981 
982 **/
983 TCG_RESULT
984 EFIAPI
OpalSetPassword(OPAL_SESSION * Session,TCG_UID CpinRowUid,const VOID * NewPin,UINT32 NewPinLength,UINT8 * MethodStatus)985 OpalSetPassword(
986   OPAL_SESSION   *Session,
987   TCG_UID        CpinRowUid,
988   const VOID     *NewPin,
989   UINT32         NewPinLength,
990   UINT8          *MethodStatus
991   )
992 {
993   UINT8             Buf[BUFFER_SIZE];
994   TCG_CREATE_STRUCT CreateStruct;
995   TCG_PARSE_STRUCT  ParseStruct;
996   UINT32            Size;
997 
998   NULL_CHECK(Session);
999   NULL_CHECK(NewPin);
1000   NULL_CHECK(MethodStatus);
1001 
1002   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1003   ERROR_CHECK(TcgCreateSetCPin(
1004                          &CreateStruct,
1005                          &Size,
1006                          Session->OpalBaseComId,
1007                          Session->ComIdExtension,
1008                          Session->TperSessionId,
1009                          Session->HostSessionId,
1010                          CpinRowUid,
1011                          NewPin,
1012                          NewPinLength
1013                          ));
1014 
1015   ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1016   // exit with success on method failure - user must inspect MethodStatus
1017   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1018 
1019   return TcgResultSuccess;
1020 }
1021 
1022 /**
1023 
1024   The function sets the Enabled column to TRUE for the authorityUid provided and updates the PIN column for the cpinRowUid provided
1025   using the newPin provided.  AuthorityUid and cpinRowUid should describe the same authority.
1026 
1027   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to update
1028   @param[in]      CpinRowUid          Row UID of C_PIN table of Locking SP to update PIN
1029   @param[in]      AuthorityUid        UID of Locking SP authority to update Pin column with
1030   @param[in]      NewPin              New Password used to set Pin column
1031   @param[in]      NewPinLength        Length in bytes of new password
1032   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1033 
1034 **/
1035 TCG_RESULT
1036 EFIAPI
OpalSetLockingSpAuthorityEnabledAndPin(OPAL_SESSION * LockingSpSession,TCG_UID CpinRowUid,TCG_UID AuthorityUid,const VOID * NewPin,UINT32 NewPinLength,UINT8 * MethodStatus)1037 OpalSetLockingSpAuthorityEnabledAndPin(
1038   OPAL_SESSION    *LockingSpSession,
1039   TCG_UID         CpinRowUid,
1040   TCG_UID         AuthorityUid,
1041   const VOID      *NewPin,
1042   UINT32          NewPinLength,
1043   UINT8           *MethodStatus
1044   )
1045 {
1046   UINT8             Buf[BUFFER_SIZE];
1047   TCG_CREATE_STRUCT CreateStruct;
1048   TCG_PARSE_STRUCT  ParseStruct;
1049   UINT32            Size;
1050   TCG_UID           ActiveKey;
1051   TCG_RESULT        Ret;
1052 
1053   NULL_CHECK(LockingSpSession);
1054   NULL_CHECK(NewPin);
1055   NULL_CHECK(MethodStatus);
1056 
1057   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1058   ERROR_CHECK(TcgSetAuthorityEnabled(
1059                   &CreateStruct,
1060                   &Size,
1061                   LockingSpSession->OpalBaseComId,
1062                   LockingSpSession->ComIdExtension,
1063                   LockingSpSession->TperSessionId,
1064                   LockingSpSession->HostSessionId,
1065                   AuthorityUid,
1066                   TRUE));
1067 
1068   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1069 
1070   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1071     DEBUG ((DEBUG_INFO, "Send Set Authority error\n"));
1072     return TcgResultFailure;
1073   }
1074 
1075   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1076 
1077   ERROR_CHECK(TcgCreateSetCPin(
1078                   &CreateStruct,
1079                   &Size,
1080                   LockingSpSession->OpalBaseComId,
1081                   LockingSpSession->ComIdExtension,
1082                   LockingSpSession->TperSessionId,
1083                   LockingSpSession->HostSessionId,
1084                   CpinRowUid,
1085                   NewPin,
1086                   NewPinLength));
1087 
1088   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1089 
1090   //
1091   // allow user1 to set global range to unlocked/locked by modifying ACE_Locking_GlobalRange_SetRdLocked/SetWrLocked
1092   //
1093   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1094   ERROR_CHECK(TcgCreateSetAce(
1095                   &CreateStruct,
1096                   &Size,
1097                   LockingSpSession->OpalBaseComId,
1098                   LockingSpSession->ComIdExtension,
1099                   LockingSpSession->TperSessionId,
1100                   LockingSpSession->HostSessionId,
1101                   OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_RDLOCKED,
1102                   OPAL_LOCKING_SP_USER1_AUTHORITY,
1103                   TCG_ACE_EXPRESSION_OR,
1104                   OPAL_LOCKING_SP_ADMINS_AUTHORITY
1105               ));
1106 
1107   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1108 
1109   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1110     DEBUG ((DEBUG_INFO, "Update ACE for RDLOCKED failed\n"));
1111     return TcgResultFailure;
1112   }
1113 
1114   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1115   ERROR_CHECK(TcgCreateSetAce(
1116                   &CreateStruct,
1117                   &Size,
1118                   LockingSpSession->OpalBaseComId,
1119                   LockingSpSession->ComIdExtension,
1120                   LockingSpSession->TperSessionId,
1121                   LockingSpSession->HostSessionId,
1122                   OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_WRLOCKED,
1123                   OPAL_LOCKING_SP_USER1_AUTHORITY,
1124                   TCG_ACE_EXPRESSION_OR,
1125                   OPAL_LOCKING_SP_ADMINS_AUTHORITY
1126               ));
1127 
1128   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1129 
1130   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1131     DEBUG ((DEBUG_INFO, "Update ACE for WRLOCKED failed\n"));
1132     return TcgResultFailure;
1133   }
1134 
1135   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1136   ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
1137   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1138 
1139   //
1140   // For Pyrite type SSC, it not supports Active Key.
1141   // So here add check logic before enable it.
1142   //
1143   Ret = OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey);
1144   if (Ret == TcgResultSuccess) {
1145     ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1146     ERROR_CHECK(TcgCreateSetAce(
1147                     &CreateStruct,
1148                     &Size,
1149                     LockingSpSession->OpalBaseComId,
1150                     LockingSpSession->ComIdExtension,
1151                     LockingSpSession->TperSessionId,
1152                     LockingSpSession->HostSessionId,
1153                     (ActiveKey == OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY) ? OPAL_LOCKING_SP_ACE_K_AES_256_GLOBALRANGE_GENKEY : OPAL_LOCKING_SP_ACE_K_AES_128_GLOBALRANGE_GENKEY,
1154                     OPAL_LOCKING_SP_USER1_AUTHORITY,
1155                     TCG_ACE_EXPRESSION_OR,
1156                     OPAL_LOCKING_SP_ADMINS_AUTHORITY
1157                 ));
1158 
1159     ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1160 
1161     if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1162       DEBUG ((DEBUG_INFO, "Update ACE for GLOBALRANGE_GENKEY failed\n"));
1163       //
1164       // Disable user1 if all permissions are not granted.
1165       //
1166       return TcgResultFailure;
1167     }
1168   }
1169 
1170   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1171   ERROR_CHECK(TcgCreateSetAce(
1172                   &CreateStruct,
1173                   &Size,
1174                   LockingSpSession->OpalBaseComId,
1175                   LockingSpSession->ComIdExtension,
1176                   LockingSpSession->TperSessionId,
1177                   LockingSpSession->HostSessionId,
1178                   OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL,
1179                   OPAL_LOCKING_SP_USER1_AUTHORITY,
1180                   TCG_ACE_EXPRESSION_OR,
1181                   OPAL_LOCKING_SP_ADMINS_AUTHORITY
1182               ));
1183 
1184   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1185 
1186   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1187     DEBUG ((DEBUG_INFO, "Update ACE for OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL failed\n"));
1188     return TcgResultFailure;
1189   }
1190 
1191   return TcgResultSuccess;
1192 }
1193 
1194 /**
1195 
1196   The function sets the Enabled column to FALSE for the USER1 authority.
1197 
1198   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to disable User1
1199   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1200 
1201 **/
1202 TCG_RESULT
1203 EFIAPI
OpalDisableUser(OPAL_SESSION * LockingSpSession,UINT8 * MethodStatus)1204 OpalDisableUser(
1205   OPAL_SESSION     *LockingSpSession,
1206   UINT8            *MethodStatus
1207   )
1208 {
1209   UINT8             Buf[BUFFER_SIZE];
1210   TCG_CREATE_STRUCT CreateStruct;
1211   TCG_PARSE_STRUCT  ParseStruct;
1212   UINT32            Size;
1213 
1214   NULL_CHECK(LockingSpSession);
1215   NULL_CHECK(MethodStatus);
1216 
1217   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1218   ERROR_CHECK(TcgSetAuthorityEnabled(
1219                   &CreateStruct,
1220                   &Size,
1221                   LockingSpSession->OpalBaseComId,
1222                   LockingSpSession->ComIdExtension,
1223                   LockingSpSession->TperSessionId,
1224                   LockingSpSession->HostSessionId,
1225                   OPAL_LOCKING_SP_USER1_AUTHORITY,
1226                   FALSE));
1227 
1228   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1229 
1230   return TcgResultSuccess;
1231 }
1232 
1233 /**
1234 
1235   The function retrieves the active key of the global locking range
1236   and calls the GenKey method on the active key retrieved.
1237 
1238   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1239   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1240 
1241 **/
1242 TCG_RESULT
1243 EFIAPI
OpalGlobalLockingRangeGenKey(OPAL_SESSION * LockingSpSession,UINT8 * MethodStatus)1244 OpalGlobalLockingRangeGenKey(
1245   OPAL_SESSION   *LockingSpSession,
1246   UINT8          *MethodStatus
1247   )
1248 {
1249   UINT8             Buf[BUFFER_SIZE];
1250   TCG_CREATE_STRUCT CreateStruct;
1251   TCG_PARSE_STRUCT  ParseStruct;
1252   UINT32            Size;
1253   TCG_UID           ActiveKey;
1254 
1255   NULL_CHECK(LockingSpSession);
1256   NULL_CHECK(MethodStatus);
1257 
1258   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1259   //
1260   // retrieve the activekey in order to know which globalrange key to generate
1261   //
1262   ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
1263   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1264 
1265   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1266 
1267   ERROR_CHECK(OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey));
1268 
1269   //
1270   // call genkey on ActiveKey UID
1271   //
1272   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1273   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1274   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1275   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1276   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, ActiveKey, TCG_UID_METHOD_GEN_KEY));
1277   ERROR_CHECK(TcgStartParameters(&CreateStruct));
1278   ERROR_CHECK(TcgEndParameters(&CreateStruct));
1279   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1280   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1281   ERROR_CHECK(TcgEndPacket(&CreateStruct));
1282   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1283 
1284   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1285 
1286   return TcgResultSuccess;
1287 }
1288 
1289 /**
1290 
1291   The function updates the ReadLocked and WriteLocked columns of the Global Locking Range.
1292   This function is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns
1293   (not ReadLockEnabled and WriteLockEnabled columns).
1294 
1295   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1296   @param[in]      ReadLocked          Value to set ReadLocked column for Global Locking Range
1297   @param[in]      WriteLocked         Value to set WriteLocked column for Global Locking Range
1298   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1299 
1300 **/
1301 TCG_RESULT
1302 EFIAPI
OpalUpdateGlobalLockingRange(OPAL_SESSION * LockingSpSession,BOOLEAN ReadLocked,BOOLEAN WriteLocked,UINT8 * MethodStatus)1303 OpalUpdateGlobalLockingRange(
1304   OPAL_SESSION             *LockingSpSession,
1305   BOOLEAN                  ReadLocked,
1306   BOOLEAN                  WriteLocked,
1307   UINT8                    *MethodStatus
1308   )
1309 {
1310   UINT8             Buf[BUFFER_SIZE];
1311   TCG_CREATE_STRUCT CreateStruct;
1312   TCG_PARSE_STRUCT  ParseStruct;
1313   UINT32            Size;
1314 
1315   NULL_CHECK(LockingSpSession);
1316   NULL_CHECK(MethodStatus);
1317 
1318   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1319 
1320   //
1321   // set global locking range values
1322   //
1323   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1324   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1325   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1326   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_SET));
1327   ERROR_CHECK(TcgStartParameters(&CreateStruct));
1328   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1329   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01));                       // "Values"
1330   ERROR_CHECK(TcgAddStartList(&CreateStruct));
1331 
1332   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1333   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07));                       // "ReadLocked"
1334   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1335   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1336 
1337   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1338   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08));                       // "WriteLocked"
1339   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1340   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1341 
1342   ERROR_CHECK(TcgAddEndList(&CreateStruct));
1343   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1344   ERROR_CHECK(TcgEndParameters(&CreateStruct));
1345   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1346   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1347   ERROR_CHECK(TcgEndPacket(&CreateStruct));
1348   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1349 
1350   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1351   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1352 
1353   return TcgResultSuccess;
1354 }
1355 
1356 /**
1357 
1358   The function updates the RangeStart, RangeLength, ReadLockedEnabled, WriteLockedEnabled, ReadLocked and WriteLocked columns
1359   of the specified Locking Range.  This function requires admin authority of a locking SP session.
1360 
1361   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1362   @param[in]      LockingRangeUid     Locking range UID to set values
1363   @param[in]      RangeStart          Value to set RangeStart column for Locking Range
1364   @param[in]      RangeLength         Value to set RangeLength column for Locking Range
1365   @param[in]      ReadLockEnabled     Value to set readLockEnabled column for Locking Range
1366   @param[in]      WriteLockEnabled    Value to set writeLockEnabled column for Locking Range
1367   @param[in]      ReadLocked          Value to set ReadLocked column for Locking Range
1368   @param[in]      WriteLocked         Value to set WriteLocked column for Locking Range
1369   @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1370 
1371 **/
1372 TCG_RESULT
1373 EFIAPI
OpalSetLockingRange(OPAL_SESSION * LockingSpSession,TCG_UID LockingRangeUid,UINT64 RangeStart,UINT64 RangeLength,BOOLEAN ReadLockEnabled,BOOLEAN WriteLockEnabled,BOOLEAN ReadLocked,BOOLEAN WriteLocked,UINT8 * MethodStatus)1374 OpalSetLockingRange(
1375   OPAL_SESSION      *LockingSpSession,
1376   TCG_UID           LockingRangeUid,
1377   UINT64            RangeStart,
1378   UINT64            RangeLength,
1379   BOOLEAN           ReadLockEnabled,
1380   BOOLEAN           WriteLockEnabled,
1381   BOOLEAN           ReadLocked,
1382   BOOLEAN           WriteLocked,
1383   UINT8             *MethodStatus
1384   )
1385 {
1386   UINT8           Buf[BUFFER_SIZE];
1387   TCG_CREATE_STRUCT CreateStruct;
1388   TCG_PARSE_STRUCT  ParseStruct;
1389   UINT32          Size;
1390 
1391   NULL_CHECK(LockingSpSession);
1392   NULL_CHECK(MethodStatus);
1393 
1394   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1395 
1396   //
1397   // set locking range values
1398   //
1399   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1400   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1401   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1402   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, LockingRangeUid, TCG_UID_METHOD_SET));
1403   ERROR_CHECK(TcgStartParameters(&CreateStruct));
1404   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1405   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01));                        // "Values"
1406   ERROR_CHECK(TcgAddStartList(&CreateStruct));
1407 
1408   //
1409   // range start and range Length only apply to non-global locking ranges
1410   //
1411   if (LockingRangeUid != OPAL_LOCKING_SP_LOCKING_GLOBALRANGE) {
1412     ERROR_CHECK(TcgAddStartName(&CreateStruct));
1413     ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x03));                       // "RangeStart"
1414     ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeStart));
1415     ERROR_CHECK(TcgAddEndName(&CreateStruct));
1416 
1417     ERROR_CHECK(TcgAddStartName(&CreateStruct));
1418     ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x04));                       // "RangeLength"
1419     ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeLength));
1420     ERROR_CHECK(TcgAddEndName(&CreateStruct));
1421   }
1422 
1423   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1424   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x05));                       // "ReadLockEnabled"
1425   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLockEnabled));
1426   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1427 
1428   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1429   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x06));                       // "WriteLockEnabled"
1430   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLockEnabled));
1431   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1432 
1433   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1434   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07));                       // "ReadLocked"
1435   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1436   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1437 
1438   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1439   ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08));                       // "WriteLocked"
1440   ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1441   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1442 
1443   ERROR_CHECK(TcgAddEndList(&CreateStruct));
1444   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1445   ERROR_CHECK(TcgEndParameters(&CreateStruct));
1446   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1447   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1448   ERROR_CHECK(TcgEndPacket(&CreateStruct));
1449   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1450 
1451   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1452   // Exit with success on method failure - user must inspect MethodStatus
1453   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1454 
1455   return TcgResultSuccess;
1456 }
1457 
1458 /**
1459 
1460   The function populates the CreateStruct with a payload that will retrieve the global locking range active key.
1461   It is intended to be called with a session that is already started with a valid credential.
1462   The function does not send the payload.
1463 
1464   @param[in]      Session        OPAL_SESSION to populate command for, needs ComId
1465   @param[in/out]  CreateStruct   Structure to populate with encoded TCG command
1466   @param[in/out]  Size           Size in bytes of the command created.
1467 
1468 **/
1469 TCG_RESULT
1470 EFIAPI
OpalCreateRetrieveGlobalLockingRangeActiveKey(const OPAL_SESSION * Session,TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size)1471 OpalCreateRetrieveGlobalLockingRangeActiveKey(
1472   const OPAL_SESSION    *Session,
1473   TCG_CREATE_STRUCT     *CreateStruct,
1474   UINT32                *Size
1475   )
1476 {
1477   NULL_CHECK(Session);
1478   NULL_CHECK(CreateStruct);
1479   NULL_CHECK(Size);
1480 
1481   // Retrieve the activekey in order to know which globalrange key to generate
1482   ERROR_CHECK(TcgStartComPacket(CreateStruct, Session->OpalBaseComId, Session->ComIdExtension));
1483   ERROR_CHECK(TcgStartPacket(CreateStruct, Session->TperSessionId, Session->HostSessionId, 0x0, 0x0, 0x0));
1484   ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
1485   ERROR_CHECK(TcgStartMethodCall(CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_GET));
1486   ERROR_CHECK(TcgStartParameters(CreateStruct));
1487   ERROR_CHECK(TcgAddStartList(CreateStruct));
1488   ERROR_CHECK(TcgAddStartName(CreateStruct));
1489   ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1490   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A));         // ActiveKey
1491   ERROR_CHECK(TcgAddEndName(CreateStruct));
1492   ERROR_CHECK(TcgAddStartName(CreateStruct));
1493   ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1494   ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A));
1495   ERROR_CHECK(TcgAddEndName(CreateStruct));
1496   ERROR_CHECK(TcgAddEndList(CreateStruct));
1497   ERROR_CHECK(TcgEndParameters(CreateStruct));
1498   ERROR_CHECK(TcgEndMethodCall(CreateStruct));
1499   ERROR_CHECK(TcgEndSubPacket(CreateStruct));
1500   ERROR_CHECK(TcgEndPacket(CreateStruct));
1501   ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
1502 
1503   return TcgResultSuccess;
1504 }
1505 
1506 /**
1507 
1508   The function acquires the activeKey specified for the Global Locking Range from the ParseStruct.
1509 
1510   @param[in]      ParseStruct    Structure that contains the device's response with the activekey
1511   @param[in/out]  ActiveKey      The UID of the active key retrieved
1512 
1513 **/
1514 TCG_RESULT
1515 EFIAPI
OpalParseRetrieveGlobalLockingRangeActiveKey(TCG_PARSE_STRUCT * ParseStruct,TCG_UID * ActiveKey)1516 OpalParseRetrieveGlobalLockingRangeActiveKey(
1517   TCG_PARSE_STRUCT  *ParseStruct,
1518   TCG_UID           *ActiveKey
1519   )
1520 {
1521   UINT32 ColumnName;
1522 
1523   NULL_CHECK(ParseStruct);
1524   NULL_CHECK(ActiveKey);
1525 
1526   // parse response
1527   ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1528   ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1529   ERROR_CHECK(TcgGetNextStartName(ParseStruct));
1530   ERROR_CHECK(TcgGetNextUINT32(ParseStruct, &ColumnName));
1531   ERROR_CHECK(TcgGetNextTcgUid(ParseStruct, ActiveKey));
1532   ERROR_CHECK(TcgGetNextEndName(ParseStruct));
1533   ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1534   ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1535   ERROR_CHECK(TcgGetNextEndOfData(ParseStruct));
1536 
1537   if (ColumnName != 0x0A) {
1538     DEBUG ((DEBUG_INFO, "Unexpected column name %u (exp 0x0A)\n", ColumnName));
1539     return TcgResultFailure;
1540   }
1541 
1542   if (*ActiveKey != OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY && *ActiveKey != OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY) {
1543     DEBUG ((DEBUG_INFO, "Unexpected gen key %u (exp %u or %u)\n", *ActiveKey, OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY, OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY));
1544     return TcgResultFailure;
1545   }
1546 
1547   return TcgResultSuccess;
1548 }
1549 
1550 /**
1551 
1552   The function retrieves the TryLimit column for the specified rowUid (authority).
1553 
1554   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve try limit
1555   @param[in]      RowUid              Row UID of the Locking SP C_PIN table to retrieve TryLimit column
1556   @param[in/out]  TryLimit            Value from TryLimit column
1557 
1558 **/
1559 TCG_RESULT
1560 EFIAPI
OpalGetTryLimit(OPAL_SESSION * LockingSpSession,TCG_UID RowUid,UINT32 * TryLimit)1561 OpalGetTryLimit(
1562   OPAL_SESSION   *LockingSpSession,
1563   TCG_UID        RowUid,
1564   UINT32         *TryLimit
1565   )
1566 {
1567   TCG_CREATE_STRUCT CreateStruct;
1568   TCG_PARSE_STRUCT  ParseStruct;
1569   UINT32            Size;
1570   UINT8             MethodStatus;
1571   UINT8             Buf[BUFFER_SIZE];
1572   UINT32            Col;
1573 
1574   NULL_CHECK(LockingSpSession);
1575   NULL_CHECK(TryLimit);
1576 
1577   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1578   ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1579   ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1580   ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1581   ERROR_CHECK(TcgStartMethodCall(&CreateStruct, RowUid, TCG_UID_METHOD_GET));
1582   ERROR_CHECK(TcgStartParameters(&CreateStruct));
1583   ERROR_CHECK(TcgAddStartList(&CreateStruct));
1584   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1585   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1586   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1587   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1588   ERROR_CHECK(TcgAddStartName(&CreateStruct));
1589   ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1590   ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1591   ERROR_CHECK(TcgAddEndName(&CreateStruct));
1592   ERROR_CHECK(TcgAddEndList(&CreateStruct));
1593   ERROR_CHECK(TcgEndParameters(&CreateStruct));
1594   ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1595   ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1596   ERROR_CHECK(TcgEndPacket(&CreateStruct));
1597   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1598 
1599   ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus, 0));
1600   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
1601 
1602   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1603   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1604   ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
1605   ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
1606   ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, TryLimit));
1607   ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
1608   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1609   ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1610   ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
1611 
1612   if (Col != OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL) {
1613     DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1614     return TcgResultFailure;
1615   }
1616 
1617   return TcgResultSuccess;
1618 }
1619 
1620 /**
1621 
1622   Get the support attribute info.
1623 
1624   @param[in]      Session             OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1625   @param[out]     SupportedAttributes Return the support attribute info.
1626   @param[out]     OpalBaseComId       Return the base com id info.
1627 
1628 **/
1629 TCG_RESULT
1630 EFIAPI
OpalGetSupportedAttributesInfo(IN OPAL_SESSION * Session,OUT OPAL_DISK_SUPPORT_ATTRIBUTE * SupportedAttributes,OUT UINT16 * OpalBaseComId)1631 OpalGetSupportedAttributesInfo(
1632   IN  OPAL_SESSION                 *Session,
1633   OUT OPAL_DISK_SUPPORT_ATTRIBUTE  *SupportedAttributes,
1634   OUT UINT16                       *OpalBaseComId
1635   )
1636 {
1637   UINT8                              Buffer[BUFFER_SIZE];
1638   TCG_SUPPORTED_SECURITY_PROTOCOLS   *SupportedProtocols;
1639   TCG_LEVEL0_DISCOVERY_HEADER        *DiscoveryHeader;
1640   OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat;
1641   OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat2;
1642   UINTN                              Size;
1643   UINTN                              Size2;
1644 
1645   NULL_CHECK(Session);
1646   NULL_CHECK(SupportedAttributes);
1647   NULL_CHECK(OpalBaseComId);
1648 
1649   ZeroMem(Buffer, BUFFER_SIZE);
1650   ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1651 
1652   //
1653   // Retrieve supported protocols verify security protocol 1 is supported
1654   //
1655   SupportedProtocols = (TCG_SUPPORTED_SECURITY_PROTOCOLS*) Buffer;
1656 
1657   //
1658   // Get list of supported protocols
1659   //
1660   if (OpalRetrieveSupportedProtocolList (Session, sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS), SupportedProtocols) == TcgResultFailure) {
1661     DEBUG ((DEBUG_INFO, "OpalRetrieveSupportedProtocolList failed\n"));
1662     return TcgResultFailure;
1663   }
1664 
1665   SupportedAttributes->Sp1 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_1);
1666   SupportedAttributes->Sp2 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_2);
1667   SupportedAttributes->SpIeee1667 = TcgIsProtocolSupported (SupportedProtocols, TCG_SECURITY_PROTOCOL_IEEE_1667);
1668 
1669   DEBUG ((DEBUG_INFO, "Supported Protocols: Sp1 %d Sp2: %d SpIeee1667 %d \n",
1670               SupportedAttributes->Sp1,
1671               SupportedAttributes->Sp2,
1672               SupportedAttributes->SpIeee1667
1673               ));
1674 
1675   //
1676   // Perform level 0 discovery and assign desired feature info to Opal Disk structure
1677   //
1678   ZeroMem (Buffer, BUFFER_SIZE);
1679   if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1680     DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1681     return TcgResultFailure;
1682   }
1683 
1684   //
1685   // Check for required feature descriptors
1686   //
1687   DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1688 
1689   Size = 0;
1690   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V2_0_0, &Size);
1691   SupportedAttributes->OpalSsc2 = (Feat != NULL);
1692 
1693   *OpalBaseComId = TCG_RESERVED_COMID;
1694 
1695   //
1696   // Check Opal SCC V2 has valid settings for SID C_PIN on revert
1697   //
1698   if (SupportedAttributes->OpalSsc2 && Size >= sizeof (OPAL_SSCV2_FEATURE_DESCRIPTOR)) {
1699     //
1700     // Want opposite polarity b/c Value is greater than a bit, but we only care about non-zero vs zero
1701     //
1702     SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1703     SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1704     DEBUG ((DEBUG_INFO, "Opal SSC V2 InitCpinIndicator %d  CpinUponRevert %d \n",
1705              SupportedAttributes->InitCpinIndicator,
1706              SupportedAttributes->CpinUponRevert
1707             ));
1708     *OpalBaseComId = SwapBytes16 (Feat->OpalSscV2.BaseComdIdBE);
1709   }
1710 
1711   Size = 0;
1712   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_LITE, &Size);
1713   SupportedAttributes->OpalSscLite = (Feat != NULL);
1714 
1715   if (Feat != NULL && Size >= sizeof (OPAL_SSCLITE_FEATURE_DESCRIPTOR)) {
1716     if (*OpalBaseComId == TCG_RESERVED_COMID) {
1717       //
1718       // Pin values used always match up with ComId used
1719       //
1720       *OpalBaseComId = SwapBytes16 (Feat->OpalSscLite.BaseComdIdBE);
1721       SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1722       SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1723       DEBUG ((DEBUG_INFO, "Opal SSC Lite InitCpinIndicator %d  CpinUponRevert %d \n",
1724                SupportedAttributes->InitCpinIndicator,
1725                SupportedAttributes->CpinUponRevert
1726               ));
1727     }
1728   }
1729 
1730   //
1731   // For some pyrite 2.0 device, it contains both pyrite 1.0 and 2.0 feature data.
1732   // so here try to get data from pyrite 2.0 feature data first.
1733   //
1734   Size = 0;
1735   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC, &Size);
1736   Size2 = 0;
1737   Feat2 = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC_V2_0_0, &Size2);
1738   if (Feat2 != NULL && Size2 >= sizeof (PYRITE_SSCV2_FEATURE_DESCRIPTOR)) {
1739     SupportedAttributes->PyriteSscV2 = TRUE;
1740     if (*OpalBaseComId == TCG_RESERVED_COMID) {
1741       *OpalBaseComId = SwapBytes16 (Feat2->PyriteSscV2.BaseComdIdBE);
1742       SupportedAttributes->InitCpinIndicator = (Feat2->PyriteSscV2.InitialCPINSIDPIN == 0);
1743       SupportedAttributes->CpinUponRevert = (Feat2->PyriteSscV2.CPINSIDPINRevertBehavior == 0);
1744       DEBUG ((DEBUG_INFO, "Pyrite SSC V2 InitCpinIndicator %d  CpinUponRevert %d \n",
1745                SupportedAttributes->InitCpinIndicator,
1746                SupportedAttributes->CpinUponRevert
1747               ));
1748     }
1749   } else {
1750     SupportedAttributes->PyriteSsc = (Feat != NULL);
1751     if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) {
1752       if (*OpalBaseComId == TCG_RESERVED_COMID) {
1753         *OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE);
1754         SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0);
1755         SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0);
1756         DEBUG ((DEBUG_INFO, "Pyrite SSC InitCpinIndicator %d  CpinUponRevert %d \n",
1757                  SupportedAttributes->InitCpinIndicator,
1758                  SupportedAttributes->CpinUponRevert
1759                 ));
1760       }
1761     }
1762   }
1763 
1764   Size = 0;
1765   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V1_0_0, &Size);
1766   SupportedAttributes->OpalSsc1 = (Feat != NULL);
1767   if (Feat != NULL && Size >= sizeof (OPAL_SSCV1_FEATURE_DESCRIPTOR)) {
1768     if (*OpalBaseComId == TCG_RESERVED_COMID) {
1769       *OpalBaseComId = SwapBytes16 (Feat->OpalSscV1.BaseComdIdBE);
1770     }
1771   }
1772 
1773   Size = 0;
1774   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1775   if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1776     SupportedAttributes->MediaEncryption = Feat->Locking.MediaEncryption;
1777     DEBUG ((DEBUG_INFO, "SupportedAttributes->MediaEncryption 0x%X \n", SupportedAttributes->MediaEncryption));
1778   }
1779 
1780   Size = 0;
1781   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_BLOCK_SID, &Size);
1782   if (Feat != NULL && Size >= sizeof (TCG_BLOCK_SID_FEATURE_DESCRIPTOR)) {
1783     SupportedAttributes->BlockSid = TRUE;
1784     DEBUG ((DEBUG_INFO, "BlockSid Supported!!! Current Status is 0x%X \n", Feat->BlockSid.SIDBlockedState));
1785   } else {
1786     DEBUG ((DEBUG_INFO, "BlockSid Unsupported!!!"));
1787   }
1788 
1789   Size = 0;
1790   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_DATA_REMOVAL, &Size);
1791   if (Feat != NULL && Size >= sizeof (DATA_REMOVAL_FEATURE_DESCRIPTOR)) {
1792     SupportedAttributes->DataRemoval = TRUE;
1793     DEBUG ((DEBUG_INFO, "DataRemoval Feature Supported!\n"));
1794     DEBUG ((DEBUG_INFO, "Operation Processing = 0x%x\n", Feat->DataRemoval.OperationProcessing));
1795     DEBUG ((DEBUG_INFO, "RemovalMechanism = 0x%x\n", Feat->DataRemoval.RemovalMechanism));
1796     DEBUG ((DEBUG_INFO, "BIT0 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit0, SwapBytes16 (Feat->DataRemoval.TimeBit0)));
1797     DEBUG ((DEBUG_INFO, "BIT1 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit1, SwapBytes16 (Feat->DataRemoval.TimeBit1)));
1798     DEBUG ((DEBUG_INFO, "BIT2 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit2, SwapBytes16 (Feat->DataRemoval.TimeBit2)));
1799     DEBUG ((DEBUG_INFO, "BIT3 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit3, SwapBytes16 (Feat->DataRemoval.TimeBit3)));
1800     DEBUG ((DEBUG_INFO, "BIT4 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit4, SwapBytes16 (Feat->DataRemoval.TimeBit4)));
1801   }
1802 
1803   DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId));
1804 
1805   return TcgResultSuccess;
1806 }
1807 
1808 /**
1809 
1810   Get the support attribute info.
1811 
1812   @param[in]      Session             OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1813   @param[in/out]  LockingFeature      Return the Locking info.
1814 
1815 **/
1816 TCG_RESULT
1817 EFIAPI
OpalGetLockingInfo(OPAL_SESSION * Session,TCG_LOCKING_FEATURE_DESCRIPTOR * LockingFeature)1818 OpalGetLockingInfo(
1819   OPAL_SESSION                     *Session,
1820   TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature
1821   )
1822 {
1823   UINT8                              Buffer[BUFFER_SIZE];
1824   TCG_LEVEL0_DISCOVERY_HEADER        *DiscoveryHeader;
1825   OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat;
1826   UINTN                              Size;
1827 
1828   NULL_CHECK(Session);
1829   NULL_CHECK(LockingFeature);
1830 
1831   ZeroMem(Buffer, BUFFER_SIZE);
1832   ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1833 
1834   if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1835     DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1836     return TcgResultFailure;
1837   }
1838   DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1839 
1840   Size = 0;
1841   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1842   if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1843     CopyMem (LockingFeature, &Feat->Locking, sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR));
1844   }
1845 
1846   return TcgResultSuccess;
1847 }
1848 
1849 /**
1850 
1851   Get the descriptor for the specific feature code.
1852 
1853   @param[in]      Session             OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1854   @param[in]      FeatureCode         The feature code user request.
1855   @param[in, out] DataSize            The data size.
1856   @param[out]     Data                The data buffer used to save the feature descriptor.
1857 
1858 **/
1859 TCG_RESULT
OpalGetFeatureDescriptor(IN OPAL_SESSION * Session,IN UINT16 FeatureCode,IN OUT UINTN * DataSize,OUT VOID * Data)1860 OpalGetFeatureDescriptor (
1861   IN     OPAL_SESSION              *Session,
1862   IN     UINT16                    FeatureCode,
1863   IN OUT UINTN                     *DataSize,
1864   OUT    VOID                      *Data
1865   )
1866 {
1867   UINT8                              Buffer[BUFFER_SIZE];
1868   TCG_LEVEL0_DISCOVERY_HEADER        *DiscoveryHeader;
1869   OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat;
1870   UINTN                              Size;
1871 
1872   NULL_CHECK(Session);
1873   NULL_CHECK(DataSize);
1874   NULL_CHECK(Data);
1875 
1876   ZeroMem(Buffer, BUFFER_SIZE);
1877   ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1878 
1879   if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1880     DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1881     return TcgResultFailure;
1882   }
1883   DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1884 
1885   Size = 0;
1886   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, FeatureCode, &Size);
1887   if (Feat != NULL) {
1888     if (Size > *DataSize) {
1889       *DataSize = Size;
1890       return TcgResultFailureBufferTooSmall;
1891     }
1892 
1893     *DataSize = Size;
1894     CopyMem (Data, Feat, Size);
1895   }
1896 
1897   return TcgResultSuccess;
1898 }
1899 
1900 /**
1901 
1902   The function determines whether or not all of the requirements for the Opal Feature (not full specification)
1903   are met by the specified device.
1904 
1905   @param[in]      SupportedAttributes     Opal device attribute.
1906 
1907 **/
1908 BOOLEAN
1909 EFIAPI
OpalFeatureSupported(OPAL_DISK_SUPPORT_ATTRIBUTE * SupportedAttributes)1910 OpalFeatureSupported(
1911   OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes
1912   )
1913 {
1914   NULL_CHECK(SupportedAttributes);
1915 
1916   if (SupportedAttributes->Sp1 == 0) {
1917     return FALSE;
1918   }
1919 
1920   if (SupportedAttributes->OpalSscLite == 0 &&
1921       SupportedAttributes->OpalSsc1 == 0 &&
1922       SupportedAttributes->OpalSsc2 == 0 &&
1923       SupportedAttributes->PyriteSsc == 0 &&
1924       SupportedAttributes->PyriteSscV2 == 0
1925      ) {
1926     return FALSE;
1927   }
1928 
1929   return TRUE;
1930 }
1931 
1932 /**
1933 
1934   The function returns whether or not the device is Opal Enabled.
1935   TRUE means that the device is partially or fully locked.
1936   This will perform a Level 0 Discovery and parse the locking feature descriptor
1937 
1938   @param[in]      SupportedAttributes     Opal device attribute.
1939   @param[in]      LockingFeature          Opal device locking status.
1940 
1941 
1942 **/
1943 BOOLEAN
1944 EFIAPI
OpalFeatureEnabled(OPAL_DISK_SUPPORT_ATTRIBUTE * SupportedAttributes,TCG_LOCKING_FEATURE_DESCRIPTOR * LockingFeature)1945 OpalFeatureEnabled(
1946   OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
1947   TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature
1948   )
1949 {
1950   NULL_CHECK(SupportedAttributes);
1951   NULL_CHECK(LockingFeature);
1952 
1953   if (!OpalFeatureSupported (SupportedAttributes)) {
1954     return FALSE;
1955   }
1956 
1957   if (LockingFeature->LockingSupported && LockingFeature->LockingEnabled) {
1958     return TRUE;
1959   }
1960 
1961   return FALSE;
1962 }
1963 
1964 /**
1965 
1966   The function returns whether or not the device is Opal Locked.
1967   TRUE means that the device is partially or fully locked.
1968   This will perform a Level 0 Discovery and parse the locking feature descriptor
1969 
1970   @param[in]      SupportedAttributes     Opal device attribute.
1971   @param[in]      LockingFeature          Opal device locking status.
1972 
1973 **/
1974 BOOLEAN
OpalDeviceLocked(OPAL_DISK_SUPPORT_ATTRIBUTE * SupportedAttributes,TCG_LOCKING_FEATURE_DESCRIPTOR * LockingFeature)1975 OpalDeviceLocked(
1976   OPAL_DISK_SUPPORT_ATTRIBUTE      *SupportedAttributes,
1977   TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature
1978   )
1979 {
1980   NULL_CHECK(SupportedAttributes);
1981   NULL_CHECK(LockingFeature);
1982 
1983   if (!OpalFeatureEnabled (SupportedAttributes, LockingFeature)) {
1984     return FALSE;
1985   }
1986 
1987   return LockingFeature->Locked;
1988 }
1989 
1990