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 #include <Uefi.h>
9 #include <Library/BaseLib.h>
10 #include <Library/DebugLib.h>
11 #include <Library/TcgStorageOpalLib.h>
12 #include "TcgStorageOpalLibInternal.h"
13 
14 #define OPAL_MSID_LENGTH        128
15 
16 /**
17   Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.
18 
19   @param[in]      Session,           The session info for one opal device.
20   @param[in]      Psid               PSID of device to revert.
21   @param[in]      PsidLength         Length of PSID in bytes.
22 
23 **/
24 TCG_RESULT
25 EFIAPI
OpalUtilPsidRevert(OPAL_SESSION * Session,const VOID * Psid,UINT32 PsidLength)26 OpalUtilPsidRevert(
27   OPAL_SESSION   *Session,
28   const VOID     *Psid,
29   UINT32         PsidLength
30   )
31 {
32   UINT8        MethodStatus;
33   TCG_RESULT   Ret;
34   UINT32       RemovalTimeOut;
35 
36   NULL_CHECK(Session);
37   NULL_CHECK(Psid);
38 
39   RemovalTimeOut = GetRevertTimeOut (Session);
40   DEBUG ((DEBUG_INFO, "OpalUtilPsidRevert: Timeout value = %d\n", RemovalTimeOut));
41 
42   Ret = OpalStartSession(
43                       Session,
44                       OPAL_UID_ADMIN_SP,
45                       TRUE,
46                       PsidLength,
47                       Psid,
48                       OPAL_ADMIN_SP_PSID_AUTHORITY,
49                       &MethodStatus);
50   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
51     Ret = OpalPyrite2PsidRevert(Session, RemovalTimeOut);
52     if (Ret != TcgResultSuccess) {
53       //
54       // If revert was successful, session was already ended by TPer, so only end session on failure
55       //
56       OpalEndSession(Session);
57     }
58   }
59 
60   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
61     Ret = TcgResultFailure;
62   }
63 
64   return Ret;
65 }
66 
67 /**
68   Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY,
69   sets the OPAL_UID_ADMIN_SP_C_PIN_SID column with the new password,
70   and activates the locking SP to copy SID PIN to Admin1 Locking SP PIN
71 
72   @param[in]      Session,           The session info for one opal device.
73   @param[in]      GeneratedSid       Generated SID of disk
74   @param[in]      SidLength          Length of generatedSid in bytes
75   @param[in]      Password           New admin password to set
76   @param[in]      PassLength         Length of password in bytes
77 
78 **/
79 TCG_RESULT
80 EFIAPI
OpalUtilSetAdminPasswordAsSid(OPAL_SESSION * Session,const VOID * GeneratedSid,UINT32 SidLength,const VOID * Password,UINT32 PassLength)81 OpalUtilSetAdminPasswordAsSid(
82   OPAL_SESSION      *Session,
83   const VOID        *GeneratedSid,
84   UINT32            SidLength,
85   const VOID        *Password,
86   UINT32            PassLength
87   )
88 {
89   UINT8        MethodStatus;
90   TCG_RESULT   Ret;
91 
92   NULL_CHECK(Session);
93   NULL_CHECK(GeneratedSid);
94   NULL_CHECK(Password);
95 
96   Ret = OpalStartSession(
97                     Session,
98                     OPAL_UID_ADMIN_SP,
99                     TRUE,
100                     SidLength,
101                     GeneratedSid,
102                     OPAL_ADMIN_SP_SID_AUTHORITY,
103                     &MethodStatus
104                     );
105   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
106     DEBUG ((DEBUG_INFO, "start session with admin SP as SID authority failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));
107     goto done;
108   }
109 
110   //
111   // 1. Update SID = new Password
112   //
113   Ret = OpalSetPassword(
114                     Session,
115                     OPAL_UID_ADMIN_SP_C_PIN_SID,
116                     Password,
117                     PassLength,
118                     &MethodStatus
119                     );
120 
121   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
122     OpalEndSession(Session);
123     DEBUG ((DEBUG_INFO, "set Password failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));
124     goto done;
125   }
126 
127   //
128   // 2. Activate locking SP
129   //
130   Ret = OpalActivateLockingSp(Session, &MethodStatus);
131   OpalEndSession(Session);
132   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
133     DEBUG ((DEBUG_INFO, "activate locking SP failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));
134     goto done;
135   }
136 
137 done:
138   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
139     Ret = TcgResultFailure;
140   }
141   return Ret;
142 }
143 
144 /**
145 
146   Opens a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
147   and updates the specified locking range with the provided column values
148 
149   @param[in]      Session,               The session info for one opal device.
150   @param[in]      Password           New admin password to set
151   @param[in]      PassLength         Length of password in bytes
152   @param[in]      LockingRangeUid    Locking range UID to set values
153   @param[in]      RangeStart         Value to set RangeStart column for Locking Range
154   @param[in]      RangeLength        Value to set RangeLength column for Locking Range
155   @param[in]      ReadLockEnabled    Value to set readLockEnabled column for Locking Range
156   @param[in]      WriteLockEnabled   Value to set writeLockEnabled column for Locking Range
157   @param[in]      ReadLocked         Value to set ReadLocked column for Locking Range
158   @param[in]      WriteLocked        Value to set WriteLocked column for Locking Range
159 
160 **/
161 TCG_RESULT
162 EFIAPI
OpalUtilSetOpalLockingRange(OPAL_SESSION * Session,const VOID * Password,UINT32 PassLength,TCG_UID LockingRangeUid,UINT64 RangeStart,UINT64 RangeLength,BOOLEAN ReadLockEnabled,BOOLEAN WriteLockEnabled,BOOLEAN ReadLocked,BOOLEAN WriteLocked)163 OpalUtilSetOpalLockingRange(
164   OPAL_SESSION   *Session,
165   const VOID     *Password,
166   UINT32         PassLength,
167   TCG_UID        LockingRangeUid,
168   UINT64         RangeStart,
169   UINT64         RangeLength,
170   BOOLEAN        ReadLockEnabled,
171   BOOLEAN        WriteLockEnabled,
172   BOOLEAN        ReadLocked,
173   BOOLEAN        WriteLocked
174   )
175 {
176   UINT8        MethodStatus;
177   TCG_RESULT   Ret;
178 
179   NULL_CHECK(Session);
180   NULL_CHECK(Password);
181 
182   //
183   // Start session with Locking SP using current admin Password
184   //
185   Ret = OpalStartSession(
186                       Session,
187                       OPAL_UID_LOCKING_SP,
188                       TRUE,
189                       PassLength,
190                       Password,
191                       OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
192                       &MethodStatus);
193   if ((Ret != TcgResultSuccess) || (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS)) {
194     DEBUG ((DEBUG_INFO, "start session with locking SP failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));
195     goto done;
196   }
197 
198   //
199   // Enable locking range
200   //
201   Ret = OpalSetLockingRange(
202             Session,
203             LockingRangeUid,
204             RangeStart,
205             RangeLength,
206             ReadLockEnabled,
207             WriteLockEnabled,
208             ReadLocked,
209             WriteLocked,
210             &MethodStatus);
211 
212   OpalEndSession(Session);
213   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
214     DEBUG ((DEBUG_INFO, "set locking range failed: Ret=%d MethodStatus=0x%x\n", Ret, MethodStatus));
215   }
216 
217 done:
218   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
219     Ret = TcgResultFailure;
220   }
221   return Ret;
222 }
223 
224 /**
225   Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY,
226   sets OPAL_UID_ADMIN_SP_C_PIN_SID with the new password,
227   and sets OPAL_LOCKING_SP_C_PIN_ADMIN1 with the new password.
228 
229   @param[in]      Session,               The session info for one opal device.
230   @param[in]      OldPassword        Current admin password
231   @param[in]      OldPasswordLength  Length of current admin password in bytes
232   @param[in]      NewPassword        New admin password to set
233   @param[in]      NewPasswordLength  Length of new password in bytes
234 
235 **/
236 TCG_RESULT
237 EFIAPI
OpalUtilSetAdminPassword(OPAL_SESSION * Session,const VOID * OldPassword,UINT32 OldPasswordLength,const VOID * NewPassword,UINT32 NewPasswordLength)238 OpalUtilSetAdminPassword(
239   OPAL_SESSION  *Session,
240   const VOID    *OldPassword,
241   UINT32        OldPasswordLength,
242   const VOID    *NewPassword,
243   UINT32        NewPasswordLength
244   )
245 {
246   TCG_RESULT   Ret;
247   UINT8        MethodStatus;
248 
249   NULL_CHECK(Session);
250   NULL_CHECK(OldPassword);
251   NULL_CHECK(NewPassword);
252 
253   //
254   // Unknown ownership
255   //
256   Ret = OpalStartSession(
257                   Session,
258                   OPAL_UID_ADMIN_SP,
259                   TRUE,
260                   OldPasswordLength,
261                   OldPassword,
262                   OPAL_ADMIN_SP_SID_AUTHORITY,
263                   &MethodStatus
264                   );
265   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
266     DEBUG ((DEBUG_INFO, "start session with admin SP using old Password failed\n"));
267     goto done;
268   }
269 
270   //
271   // Update SID = new pw
272   //
273   Ret = OpalSetPassword(Session, OPAL_UID_ADMIN_SP_C_PIN_SID, NewPassword, NewPasswordLength, &MethodStatus);
274   OpalEndSession(Session);
275   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
276     DEBUG ((DEBUG_INFO, "set new admin SP Password failed\n"));
277     goto done;
278   }
279 
280   Ret = OpalStartSession(
281                   Session,
282                   OPAL_UID_LOCKING_SP,
283                   TRUE,
284                   OldPasswordLength,
285                   OldPassword,
286                   OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
287                   &MethodStatus
288                   );
289   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
290     DEBUG ((DEBUG_INFO, "start session with locking SP using old Password failed\n"));
291     goto done;
292   }
293 
294   //
295   // Update admin locking SP to new pw
296   //
297   Ret = OpalSetPassword(Session, OPAL_LOCKING_SP_C_PIN_ADMIN1, NewPassword, NewPasswordLength, &MethodStatus);
298   OpalEndSession(Session);
299   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
300     DEBUG ((DEBUG_INFO, "set new locking SP Password failed\n"));
301     goto done;
302   }
303 
304 done:
305   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
306     Ret = TcgResultFailure;
307   }
308   return Ret;
309 }
310 
311 /**
312   Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
313   and sets the User1 SP authority to enabled and sets the User1 password.
314 
315   @param[in]      Session,               The session info for one opal device.
316   @param[in]      OldPassword        Current admin password
317   @param[in]      OldPasswordLength  Length of current admin password in bytes
318   @param[in]      NewPassword        New admin password to set
319   @param[in]      NewPasswordLength  Length of new password in bytes
320 
321 **/
322 TCG_RESULT
323 EFIAPI
OpalUtilSetUserPassword(OPAL_SESSION * Session,const VOID * OldPassword,UINT32 OldPasswordLength,const VOID * NewPassword,UINT32 NewPasswordLength)324 OpalUtilSetUserPassword(
325   OPAL_SESSION    *Session,
326   const VOID      *OldPassword,
327   UINT32          OldPasswordLength,
328   const VOID      *NewPassword,
329   UINT32          NewPasswordLength
330   )
331 {
332   UINT8        MethodStatus;
333   TCG_RESULT   Ret;
334 
335   NULL_CHECK(Session);
336   NULL_CHECK(OldPassword);
337   NULL_CHECK(NewPassword);
338 
339   //
340   // See if updating user1 authority
341   //
342   Ret = OpalStartSession(
343                     Session,
344                     OPAL_UID_LOCKING_SP,
345                     TRUE,
346                     OldPasswordLength,
347                     OldPassword,
348                     OPAL_LOCKING_SP_USER1_AUTHORITY,
349                     &MethodStatus
350                     );
351   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
352     Ret = OpalSetPassword(
353                       Session,
354                       OPAL_LOCKING_SP_C_PIN_USER1,
355                       NewPassword,
356                       NewPasswordLength,
357                       &MethodStatus
358                       );
359     OpalEndSession(Session);
360     if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
361       return Ret;
362     }
363   }
364 
365   //
366   // Setting Password for first time or setting Password as admin
367   //
368 
369   //
370   // Start session with Locking SP using current admin Password
371   //
372   Ret = OpalStartSession(
373                     Session,
374                     OPAL_UID_LOCKING_SP,
375                     TRUE,
376                     OldPasswordLength,
377                     OldPassword,
378                     OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
379                     &MethodStatus
380                     );
381   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
382     DEBUG ((DEBUG_INFO, "StartSession with locking SP as admin1 authority failed\n"));
383     goto done;
384   }
385 
386   //
387   // Enable User1 and set its PIN
388   //
389   Ret = OpalSetLockingSpAuthorityEnabledAndPin(
390                                           Session,
391                                           OPAL_LOCKING_SP_C_PIN_USER1,
392                                           OPAL_LOCKING_SP_USER1_AUTHORITY,
393                                           NewPassword,
394                                           NewPasswordLength,
395                                           &MethodStatus
396                                           );
397   OpalEndSession(Session);
398   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
399     DEBUG ((DEBUG_INFO, "OpalSetLockingSpAuthorityEnabledAndPin failed\n"));
400     goto done;
401   }
402 
403 done:
404   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
405     Ret = TcgResultFailure;
406   }
407   return Ret;
408 }
409 
410 /**
411   Verify whether user input the correct password.
412 
413   @param[in]      Session,               The session info for one opal device.
414   @param[in]      Password                    Admin password
415   @param[in]      PasswordLength              Length of password in bytes
416   @param[in/out]  HostSigningAuthority        Use the Host signing authority type.
417 
418 **/
419 TCG_RESULT
420 EFIAPI
OpalUtilVerifyPassword(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,TCG_UID HostSigningAuthority)421 OpalUtilVerifyPassword (
422   OPAL_SESSION   *Session,
423   const VOID     *Password,
424   UINT32         PasswordLength,
425   TCG_UID        HostSigningAuthority
426   )
427 {
428   TCG_RESULT                    Ret;
429   UINT8                         MethodStatus;
430 
431   NULL_CHECK(Session);
432   NULL_CHECK(Password);
433 
434   Ret = OpalStartSession(
435             Session,
436             OPAL_UID_LOCKING_SP,
437             TRUE,
438             PasswordLength,
439             Password,
440             HostSigningAuthority,
441             &MethodStatus);
442   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
443     OpalEndSession(Session);
444     return TcgResultSuccess;
445   }
446 
447   return TcgResultFailure;
448 }
449 
450 /**
451   Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
452   and generates a new global locking range key to erase the Data.
453 
454   @param[in]      Session,               The session info for one opal device.
455   @param[in]      Password                   Admin or user password
456   @param[in]      PasswordLength         Length of password in bytes
457   @param[in/out]  PasswordFailed       indicates if password failed (start session didn't work)
458 
459 **/
460 TCG_RESULT
461 EFIAPI
OpalUtilSecureErase(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,BOOLEAN * PasswordFailed)462 OpalUtilSecureErase(
463   OPAL_SESSION     *Session,
464   const VOID       *Password,
465   UINT32           PasswordLength,
466   BOOLEAN          *PasswordFailed
467   )
468 {
469   UINT8        MethodStatus;
470   TCG_RESULT   Ret;
471 
472   NULL_CHECK(Session);
473   NULL_CHECK(Password);
474   NULL_CHECK(PasswordFailed);
475 
476   //
477   // Try to generate a new key with admin1
478   //
479   Ret = OpalStartSession(
480                       Session,
481                       OPAL_UID_LOCKING_SP,
482                       TRUE,
483                       PasswordLength,
484                       Password,
485                       OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
486                       &MethodStatus
487                       );
488 
489   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
490     Ret = OpalGlobalLockingRangeGenKey(Session, &MethodStatus);
491     *PasswordFailed = FALSE;
492     OpalEndSession(Session);
493   } else {
494     //
495     // Try to generate a new key with user1
496     //
497     Ret = OpalStartSession(
498                       Session,
499                       OPAL_UID_LOCKING_SP,
500                       TRUE,
501                       PasswordLength,
502                       Password,
503                       OPAL_LOCKING_SP_USER1_AUTHORITY,
504                       &MethodStatus
505                       );
506 
507     if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
508       Ret = OpalGlobalLockingRangeGenKey(Session, &MethodStatus);
509       *PasswordFailed = FALSE;
510       OpalEndSession(Session);
511     } else {
512       *PasswordFailed = TRUE;
513     }
514   }
515 
516   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
517     Ret = TcgResultFailure;
518   }
519   return Ret;
520 }
521 
522 /**
523   Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY and disables the User1 authority.
524 
525   @param[in]      Session,               The session info for one opal device.
526   @param[in]      Password               Admin password
527   @param[in]      PasswordLength         Length of password in bytes
528   @param[in/out]  PasswordFailed         indicates if password failed (start session didn't work)
529 
530 **/
531 TCG_RESULT
532 EFIAPI
OpalUtilDisableUser(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,BOOLEAN * PasswordFailed)533 OpalUtilDisableUser(
534   OPAL_SESSION   *Session,
535   const VOID     *Password,
536   UINT32         PasswordLength,
537   BOOLEAN        *PasswordFailed
538   )
539 {
540   UINT8        MethodStatus;
541   TCG_RESULT   Ret;
542 
543   NULL_CHECK(Session);
544   NULL_CHECK(Password);
545   NULL_CHECK(PasswordFailed);
546 
547   //
548   // Start session with Locking SP using current admin Password
549   //
550   Ret = OpalStartSession(
551                     Session,
552                     OPAL_UID_LOCKING_SP,
553                     TRUE,
554                     PasswordLength,
555                     Password,
556                     OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
557                     &MethodStatus
558                     );
559   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
560     DEBUG ((DEBUG_INFO, "StartSession with Locking SP as Admin1 failed\n"));
561     *PasswordFailed = TRUE;
562     goto done;
563   }
564 
565   *PasswordFailed = FALSE;
566   Ret = OpalDisableUser(Session, &MethodStatus);
567   OpalEndSession(Session);
568 
569 done:
570   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
571     Ret = TcgResultFailure;
572   }
573   return Ret;
574 }
575 
576 /**
577   Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts the device using the RevertSP method.
578 
579   @param[in]      Session,           The session info for one opal device.
580   @param[in]      KeepUserData       TRUE to keep existing Data on the disk, or FALSE to erase it
581   @param[in]      Password           Admin password
582   @param[in]      PasswordLength     Length of password in bytes
583   @param[in/out]  PasswordFailed     indicates if password failed (start session didn't work)
584   @param[in]      Msid               Msid info.
585   @param[in]      MsidLength         Msid data length.
586 
587 **/
588 TCG_RESULT
589 EFIAPI
OpalUtilRevert(OPAL_SESSION * Session,BOOLEAN KeepUserData,const VOID * Password,UINT32 PasswordLength,BOOLEAN * PasswordFailed,UINT8 * Msid,UINT32 MsidLength)590 OpalUtilRevert(
591   OPAL_SESSION     *Session,
592   BOOLEAN          KeepUserData,
593   const VOID       *Password,
594   UINT32           PasswordLength,
595   BOOLEAN          *PasswordFailed,
596   UINT8            *Msid,
597   UINT32           MsidLength
598   )
599 {
600   UINT8        MethodStatus;
601   TCG_RESULT   Ret;
602   UINT32       RemovalTimeOut;
603 
604   NULL_CHECK(Session);
605   NULL_CHECK(Msid);
606   NULL_CHECK(Password);
607   NULL_CHECK(PasswordFailed);
608 
609   RemovalTimeOut = GetRevertTimeOut (Session);
610   DEBUG ((DEBUG_INFO, "OpalUtilRevert: Timeout value = %d\n", RemovalTimeOut));
611 
612   Ret = OpalStartSession(
613                    Session,
614                    OPAL_UID_LOCKING_SP,
615                    TRUE,
616                    PasswordLength,
617                    Password,
618                    OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
619                    &MethodStatus
620                    );
621 
622   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
623     DEBUG ((DEBUG_INFO, "error starting session: Ret=%d, MethodStatus=%u\n", Ret, MethodStatus));
624     *PasswordFailed = TRUE;
625     goto done;
626   }
627 
628   *PasswordFailed = FALSE;
629   //
630   // Try to revert with admin1
631   //
632   Ret = OpalPyrite2AdminRevert(Session, KeepUserData, &MethodStatus, RemovalTimeOut);
633   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
634     //
635     // Device ends the session on successful revert, so only call OpalEndSession when fail.
636     //
637     DEBUG ((DEBUG_INFO, "OpalAdminRevert as admin failed\n"));
638     OpalEndSession(Session);
639   }
640 
641   Ret = OpalUtilSetSIDtoMSID (Session, Password, PasswordLength, Msid, MsidLength);
642 
643 done:
644   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
645     Ret = TcgResultFailure;
646   }
647   return Ret;
648 }
649 
650 /**
651   After revert success, set SID to MSID.
652 
653   @param          Session,           The session info for one opal device.
654   @param          Password,          Input password info.
655   @param          PasswordLength,    Input password length.
656   @param          Msid               Msid info.
657   @param          MsidLength         Msid data length.
658 
659 **/
660 TCG_RESULT
661 EFIAPI
OpalUtilSetSIDtoMSID(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,UINT8 * Msid,UINT32 MsidLength)662 OpalUtilSetSIDtoMSID (
663   OPAL_SESSION     *Session,
664   const VOID       *Password,
665   UINT32           PasswordLength,
666   UINT8            *Msid,
667   UINT32           MsidLength
668   )
669 {
670   TCG_RESULT                   Ret;
671   UINT8                        MethodStatus;
672 
673   NULL_CHECK(Session);
674   NULL_CHECK(Msid);
675   NULL_CHECK(Password);
676 
677   //
678   // Start session with admin sp to update SID to MSID
679   //
680   Ret = OpalStartSession(
681             Session,
682             OPAL_UID_ADMIN_SP,
683             TRUE,
684             PasswordLength,
685             Password,
686             OPAL_ADMIN_SP_SID_AUTHORITY,
687             &MethodStatus
688             );
689   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
690     goto done;
691   }
692 
693   //
694   // Update SID pin
695   //
696   Ret = OpalSetPassword(Session, OPAL_UID_ADMIN_SP_C_PIN_SID, Msid, MsidLength, &MethodStatus);
697   OpalEndSession(Session);
698 
699 done:
700   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
701     Ret = TcgResultFailure;
702   }
703 
704   return Ret;
705 }
706 
707 /**
708   Update global locking range.
709 
710   @param          Session,           The session info for one opal device.
711   @param          Password,          Input password info.
712   @param          PasswordLength,    Input password length.
713   @param          ReadLocked,        Read lock info.
714   @param          WriteLocked        write lock info.
715 
716 **/
717 TCG_RESULT
718 EFIAPI
OpalUtilUpdateGlobalLockingRange(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,BOOLEAN ReadLocked,BOOLEAN WriteLocked)719 OpalUtilUpdateGlobalLockingRange(
720   OPAL_SESSION    *Session,
721   const VOID      *Password,
722   UINT32          PasswordLength,
723   BOOLEAN         ReadLocked,
724   BOOLEAN         WriteLocked
725   )
726 {
727   UINT8        MethodStatus;
728   TCG_RESULT   Ret;
729 
730   NULL_CHECK(Session);
731   NULL_CHECK(Password);
732 
733   //
734   // Try to start session with Locking SP as admin1 authority
735   //
736   Ret = OpalStartSession(
737                     Session,
738                     OPAL_UID_LOCKING_SP,
739                     TRUE,
740                     PasswordLength,
741                     Password,
742                     OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
743                     &MethodStatus
744                     );
745   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
746     Ret = OpalUpdateGlobalLockingRange(
747                                 Session,
748                                 ReadLocked,
749                                 WriteLocked,
750                                 &MethodStatus
751                                 );
752     OpalEndSession(Session);
753     if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
754       goto done;
755     }
756   }
757 
758   if (MethodStatus == TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT) {
759     DEBUG ((DEBUG_INFO, "unlock as admin failed with AUTHORITY_LOCKED_OUT\n"));
760   }
761 
762   //
763   // Try user1 authority
764   //
765   Ret = OpalStartSession(
766                     Session,
767                     OPAL_UID_LOCKING_SP,
768                     TRUE,
769                     PasswordLength,
770                     Password,
771                     OPAL_LOCKING_SP_USER1_AUTHORITY,
772                     &MethodStatus
773                     );
774   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
775     DEBUG ((DEBUG_INFO, "StartSession with Locking SP as User1 failed\n"));
776     goto done;
777   }
778 
779   Ret = OpalUpdateGlobalLockingRange(Session, ReadLocked, WriteLocked, &MethodStatus);
780   OpalEndSession(Session);
781 
782 done:
783   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
784     if (MethodStatus == TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT) {
785       //
786       // Caller need to know this special error, but return status not has type for it.
787       // so here use TcgResultFailureInvalidType as an replacement.
788       //
789       Ret = TcgResultFailureInvalidType;
790     } else {
791       Ret = TcgResultFailure;
792     }
793   }
794   return Ret;
795 }
796 
797 /**
798   Update global locking range.
799 
800   @param          Session,           The session info for one opal device.
801   @param          Msid,              The data buffer to save Msid info.
802   @param          MsidBufferLength,  The data buffer length for Msid.
803   @param          MsidLength,        The actual data length for Msid.
804 
805 **/
806 TCG_RESULT
807 EFIAPI
OpalUtilGetMsid(OPAL_SESSION * Session,UINT8 * Msid,UINT32 MsidBufferLength,UINT32 * MsidLength)808 OpalUtilGetMsid(
809   OPAL_SESSION    *Session,
810   UINT8           *Msid,
811   UINT32          MsidBufferLength,
812   UINT32          *MsidLength
813   )
814 {
815   UINT8        MethodStatus;
816   TCG_RESULT   Ret;
817 
818   NULL_CHECK(Session);
819   NULL_CHECK(Msid);
820   NULL_CHECK(MsidLength);
821 
822   Ret = OpalStartSession(
823                    Session,
824                    OPAL_UID_ADMIN_SP,
825                    TRUE,
826                    0,
827                    NULL,
828                    TCG_UID_NULL,
829                    &MethodStatus
830                    );
831   if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) {
832     Ret = OpalGetMsid (Session, MsidBufferLength, Msid, MsidLength);
833     OpalEndSession (Session);
834   }
835 
836   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
837     Ret = TcgResultFailure;
838   }
839 
840   return Ret;
841 }
842 
843 /**
844 
845   The function determines who owns the device by attempting to start a session with different credentials.
846   If the SID PIN matches the MSID PIN, the no one owns the device.
847   If the SID PIN matches the ourSidPin, then "Us" owns the device.  Otherwise it is unknown.
848 
849 
850   @param[in]      Session            The session info for one opal device.
851   @param          Msid,              The Msid info.
852   @param          MsidLength,        The data length for Msid.
853 
854 **/
855 OPAL_OWNER_SHIP
856 EFIAPI
OpalUtilDetermineOwnership(OPAL_SESSION * Session,UINT8 * Msid,UINT32 MsidLength)857 OpalUtilDetermineOwnership(
858   OPAL_SESSION       *Session,
859   UINT8              *Msid,
860   UINT32             MsidLength
861   )
862 {
863   UINT8            MethodStatus;
864   TCG_RESULT       Ret;
865   OPAL_OWNER_SHIP  Owner;
866 
867   if ((Session == NULL) || (Msid == NULL)) {
868     return OpalOwnershipUnknown;
869   }
870 
871   Owner = OpalOwnershipUnknown;
872   //
873   // Start Session as SID_UID with ADMIN_SP using MSID PIN
874   //
875   Ret = OpalStartSession(
876                     Session,
877                     OPAL_UID_ADMIN_SP,
878                     TRUE,
879                     MsidLength,
880                     Msid,
881                     OPAL_ADMIN_SP_SID_AUTHORITY,
882                     &MethodStatus);
883   if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) {
884     //
885     // now we know that SID PIN == MSID PIN
886     //
887     Owner = OpalOwnershipNobody;
888 
889     OpalEndSession(Session);
890   }
891 
892   return Owner;
893 }
894 
895 /**
896 
897   The function returns if admin password exists.
898 
899   @param[in]      OwnerShip         The owner ship of the opal device.
900   @param[in]      LockingFeature    The locking info of the opal device.
901 
902   @retval         TRUE              Admin password existed.
903   @retval         FALSE             Admin password not existed.
904 
905 **/
906 BOOLEAN
907 EFIAPI
OpalUtilAdminPasswordExists(IN UINT16 OwnerShip,IN TCG_LOCKING_FEATURE_DESCRIPTOR * LockingFeature)908 OpalUtilAdminPasswordExists(
909   IN  UINT16                           OwnerShip,
910   IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature
911   )
912 {
913   NULL_CHECK(LockingFeature);
914 
915   // if it is Unknown who owns the device
916   // then someone has set password previously through our UI
917   // because the SID would no longer match the generated SID (ownership us)
918   // or someone has set password using 3rd party software
919 
920   //
921   // Locking sp enabled is checked b/c it must be enabled to change the PIN of the Admin1.
922   //
923   return (OwnerShip == OpalOwnershipUnknown && LockingFeature->LockingEnabled);
924 }
925 
926 /**
927   Get Active Data Removal Mechanism Value.
928 
929   @param[in]      Session                        The session info for one opal device.
930   @param[in]      GeneratedSid                   Generated SID of disk
931   @param[in]      SidLength                      Length of generatedSid in bytes
932   @param[out]     ActiveDataRemovalMechanism     Return the active data removal mechanism.
933 
934 **/
935 TCG_RESULT
936 EFIAPI
OpalUtilGetActiveDataRemovalMechanism(OPAL_SESSION * Session,const VOID * GeneratedSid,UINT32 SidLength,UINT8 * ActiveDataRemovalMechanism)937 OpalUtilGetActiveDataRemovalMechanism (
938   OPAL_SESSION      *Session,
939   const VOID        *GeneratedSid,
940   UINT32            SidLength,
941   UINT8             *ActiveDataRemovalMechanism
942   )
943 {
944   TCG_RESULT   Ret;
945   UINT8        MethodStatus;
946 
947   NULL_CHECK(Session);
948   NULL_CHECK(GeneratedSid);
949   NULL_CHECK(ActiveDataRemovalMechanism);
950 
951   Ret = OpalStartSession(
952                     Session,
953                     OPAL_UID_ADMIN_SP,
954                     TRUE,
955                     SidLength,
956                     GeneratedSid,
957                     OPAL_ADMIN_SP_ANYBODY_AUTHORITY,
958                     &MethodStatus
959                     );
960   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
961     DEBUG ((DEBUG_INFO, "Start session with admin SP as SID authority failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));
962     if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
963       Ret = TcgResultFailure;
964     }
965     return Ret;
966   }
967 
968   Ret = OpalPyrite2GetActiveDataRemovalMechanism (
969                     Session,
970                     ActiveDataRemovalMechanism
971                     );
972 
973   if (Ret != TcgResultSuccess) {
974     DEBUG ((DEBUG_INFO, "Pyrite2 Get Active Data Removal Mechanism failed: Ret=%d\n", Ret));
975   }
976 
977   OpalEndSession(Session);
978 
979   return Ret;
980 }
981 
982 /**
983   Calculate the estimated time.
984 
985   @param[in]      IsMinute               Whether the input time value is minute type or second type.
986   @param[in]      Time                   The input time value.
987 
988 **/
989 UINT32
CalculateDataRemovalTime(IN BOOLEAN IsMinute,IN UINT16 Time)990 CalculateDataRemovalTime (
991   IN BOOLEAN               IsMinute,
992   IN UINT16                Time
993   )
994 {
995   if (IsMinute) {
996     return Time * 2 * 60;
997   } else {
998     return Time * 2;
999   }
1000 }
1001 
1002 /**
1003   Return the estimated time for specific type.
1004 
1005   @param[in]      Index               The input data removal type.
1006   @param[in]      Descriptor          DATA_REMOVAL_FEATURE_DESCRIPTOR
1007 
1008 **/
1009 UINT32
GetDataRemovalTime(IN UINT8 Index,IN DATA_REMOVAL_FEATURE_DESCRIPTOR * Descriptor)1010 GetDataRemovalTime (
1011   IN  UINT8                            Index,
1012   IN  DATA_REMOVAL_FEATURE_DESCRIPTOR  *Descriptor
1013   )
1014 {
1015   switch (Index) {
1016   case OverwriteDataErase:
1017     return CalculateDataRemovalTime (Descriptor->FormatBit0, SwapBytes16 (Descriptor->TimeBit0));
1018 
1019   case BlockErase:
1020     return CalculateDataRemovalTime (Descriptor->FormatBit1, SwapBytes16 (Descriptor->TimeBit1));
1021 
1022   case CryptoErase:
1023     return CalculateDataRemovalTime (Descriptor->FormatBit2, SwapBytes16 (Descriptor->TimeBit2));
1024 
1025   case Unmap:
1026     return CalculateDataRemovalTime (Descriptor->FormatBit3, SwapBytes16 (Descriptor->TimeBit3));
1027 
1028   case ResetWritePointers:
1029     return CalculateDataRemovalTime (Descriptor->FormatBit4, SwapBytes16 (Descriptor->TimeBit4));
1030 
1031   case VendorSpecificErase:
1032     return CalculateDataRemovalTime (Descriptor->FormatBit5, SwapBytes16 (Descriptor->TimeBit5));
1033 
1034   default:
1035     return 0;
1036   }
1037 }
1038 
1039 /**
1040   Get the supported Data Removal Mechanism list.
1041 
1042   @param[in]      Session                        The session info for one opal device.
1043   @param[out]     RemovalMechanismLists          Return the supported data removal mechanism lists.
1044 
1045 **/
1046 TCG_RESULT
1047 EFIAPI
OpalUtilGetDataRemovalMechanismLists(IN OPAL_SESSION * Session,OUT UINT32 * RemovalMechanismLists)1048 OpalUtilGetDataRemovalMechanismLists (
1049   IN  OPAL_SESSION      *Session,
1050   OUT UINT32            *RemovalMechanismLists
1051   )
1052 {
1053   TCG_RESULT                       Ret;
1054   UINTN                            DataSize;
1055   DATA_REMOVAL_FEATURE_DESCRIPTOR  Descriptor;
1056   UINT8                            Index;
1057   UINT8                            BitValue;
1058 
1059   NULL_CHECK(Session);
1060   NULL_CHECK(RemovalMechanismLists);
1061 
1062   DataSize = sizeof (Descriptor);
1063   Ret = OpalGetFeatureDescriptor (Session, TCG_FEATURE_DATA_REMOVAL, &DataSize, &Descriptor);
1064   if (Ret != TcgResultSuccess) {
1065     return TcgResultFailure;
1066   }
1067 
1068   ASSERT (Descriptor.RemovalMechanism != 0);
1069 
1070   for (Index = 0; Index < ResearvedMechanism; Index ++) {
1071     BitValue = (BOOLEAN) BitFieldRead8 (Descriptor.RemovalMechanism, Index, Index);
1072 
1073     if (BitValue == 0) {
1074       RemovalMechanismLists[Index] = 0;
1075     } else {
1076       RemovalMechanismLists[Index] = GetDataRemovalTime (Index, &Descriptor);
1077     }
1078   }
1079 
1080   return TcgResultSuccess;
1081 }
1082 
1083 /**
1084   Get revert timeout value.
1085 
1086   @param[in]      Session                       The session info for one opal device.
1087 
1088 **/
1089 UINT32
GetRevertTimeOut(IN OPAL_SESSION * Session)1090 GetRevertTimeOut (
1091   IN OPAL_SESSION                *Session
1092   )
1093 {
1094   TCG_RESULT                   TcgResult;
1095   OPAL_DISK_SUPPORT_ATTRIBUTE  SupportedAttributes;
1096   UINT16                       BaseComId;
1097   UINT32                       MsidLength;
1098   UINT8                        Msid[OPAL_MSID_LENGTH];
1099   UINT32                       RemovalMechanishLists[ResearvedMechanism];
1100   UINT8                        ActiveDataRemovalMechanism;
1101 
1102   TcgResult = OpalGetSupportedAttributesInfo (Session, &SupportedAttributes, &BaseComId);
1103   if (TcgResult != TcgResultSuccess || SupportedAttributes.DataRemoval == 0) {
1104     return 0;
1105   }
1106 
1107   TcgResult = OpalUtilGetMsid (Session, Msid, OPAL_MSID_LENGTH, &MsidLength);
1108   if (TcgResult != TcgResultSuccess) {
1109     return 0;
1110   }
1111 
1112   TcgResult = OpalUtilGetDataRemovalMechanismLists (Session, RemovalMechanishLists);
1113   if (TcgResult != TcgResultSuccess) {
1114     return 0;
1115   }
1116 
1117   TcgResult = OpalUtilGetActiveDataRemovalMechanism (Session, Msid, MsidLength, &ActiveDataRemovalMechanism);
1118   if (TcgResult != TcgResultSuccess) {
1119     return 0;
1120   }
1121 
1122   return RemovalMechanishLists[ActiveDataRemovalMechanism];
1123 }
1124