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