• 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 #include <Uefi.h>
15 #include <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/TcgStorageOpalLib.h>
18 
19 
20 /**
21   Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.
22 
23   @param[in]      Session,           The session info for one opal device.
24   @param[in]      Psid               PSID of device to revert.
25   @param[in]      PsidLength         Length of PSID in bytes.
26 
27 **/
28 TCG_RESULT
29 EFIAPI
OpalUtilPsidRevert(OPAL_SESSION * Session,const VOID * Psid,UINT32 PsidLength)30 OpalUtilPsidRevert(
31   OPAL_SESSION   *Session,
32   const VOID     *Psid,
33   UINT32         PsidLength
34   )
35 {
36   UINT8        MethodStatus;
37   TCG_RESULT   Ret;
38 
39   NULL_CHECK(Session);
40   NULL_CHECK(Psid);
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 = OpalPsidRevert(Session);
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 
603   NULL_CHECK(Session);
604   NULL_CHECK(Msid);
605   NULL_CHECK(Password);
606   NULL_CHECK(PasswordFailed);
607 
608   Ret = OpalStartSession(
609                    Session,
610                    OPAL_UID_LOCKING_SP,
611                    TRUE,
612                    PasswordLength,
613                    Password,
614                    OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
615                    &MethodStatus
616                    );
617 
618   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
619     DEBUG ((DEBUG_INFO, "error starting session: Ret=%d, MethodStatus=%u\n", Ret, MethodStatus));
620     *PasswordFailed = TRUE;
621     goto done;
622   }
623 
624   *PasswordFailed = FALSE;
625   //
626   // Try to revert with admin1
627   //
628   Ret = OpalAdminRevert(Session, KeepUserData, &MethodStatus);
629   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
630     //
631     // Device ends the session on successful revert, so only call OpalEndSession when fail.
632     //
633     DEBUG ((DEBUG_INFO, "OpalAdminRevert as admin failed\n"));
634     OpalEndSession(Session);
635   }
636 
637   Ret = OpalUtilSetSIDtoMSID (Session, Password, PasswordLength, Msid, MsidLength);
638 
639 done:
640   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
641     Ret = TcgResultFailure;
642   }
643   return Ret;
644 }
645 
646 /**
647   After revert success, set SID to MSID.
648 
649   @param          Session,           The session info for one opal device.
650   @param          Password,          Input password info.
651   @param          PasswordLength,    Input password length.
652   @param          Msid               Msid info.
653   @param          MsidLength         Msid data length.
654 
655 **/
656 TCG_RESULT
657 EFIAPI
OpalUtilSetSIDtoMSID(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,UINT8 * Msid,UINT32 MsidLength)658 OpalUtilSetSIDtoMSID (
659   OPAL_SESSION     *Session,
660   const VOID       *Password,
661   UINT32           PasswordLength,
662   UINT8            *Msid,
663   UINT32           MsidLength
664   )
665 {
666   TCG_RESULT                   Ret;
667   UINT8                        MethodStatus;
668 
669   NULL_CHECK(Session);
670   NULL_CHECK(Msid);
671   NULL_CHECK(Password);
672 
673   //
674   // Start session with admin sp to update SID to MSID
675   //
676   Ret = OpalStartSession(
677             Session,
678             OPAL_UID_ADMIN_SP,
679             TRUE,
680             PasswordLength,
681             Password,
682             OPAL_ADMIN_SP_SID_AUTHORITY,
683             &MethodStatus
684             );
685   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
686     goto done;
687   }
688 
689   //
690   // Update SID pin
691   //
692   Ret = OpalSetPassword(Session, OPAL_UID_ADMIN_SP_C_PIN_SID, Msid, MsidLength, &MethodStatus);
693   OpalEndSession(Session);
694 
695 done:
696   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
697     Ret = TcgResultFailure;
698   }
699 
700   return Ret;
701 }
702 
703 /**
704   Update global locking range.
705 
706   @param          Session,           The session info for one opal device.
707   @param          Password,          Input password info.
708   @param          PasswordLength,    Input password length.
709   @param          ReadLocked,        Read lock info.
710   @param          WriteLocked        write lock info.
711 
712 **/
713 TCG_RESULT
714 EFIAPI
OpalUtilUpdateGlobalLockingRange(OPAL_SESSION * Session,const VOID * Password,UINT32 PasswordLength,BOOLEAN ReadLocked,BOOLEAN WriteLocked)715 OpalUtilUpdateGlobalLockingRange(
716   OPAL_SESSION    *Session,
717   const VOID      *Password,
718   UINT32          PasswordLength,
719   BOOLEAN         ReadLocked,
720   BOOLEAN         WriteLocked
721   )
722 {
723   UINT8        MethodStatus;
724   TCG_RESULT   Ret;
725 
726   NULL_CHECK(Session);
727   NULL_CHECK(Password);
728 
729   //
730   // Try to start session with Locking SP as admin1 authority
731   //
732   Ret = OpalStartSession(
733                     Session,
734                     OPAL_UID_LOCKING_SP,
735                     TRUE,
736                     PasswordLength,
737                     Password,
738                     OPAL_LOCKING_SP_ADMIN1_AUTHORITY,
739                     &MethodStatus
740                     );
741   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
742     Ret = OpalUpdateGlobalLockingRange(
743                                 Session,
744                                 ReadLocked,
745                                 WriteLocked,
746                                 &MethodStatus
747                                 );
748     OpalEndSession(Session);
749     if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
750       goto done;
751     }
752   }
753 
754   if (MethodStatus == TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT) {
755     DEBUG ((DEBUG_INFO, "unlock as admin failed with AUTHORITY_LOCKED_OUT\n"));
756     goto done;
757   }
758 
759   //
760   // Try user1 authority
761   //
762   Ret = OpalStartSession(
763                     Session,
764                     OPAL_UID_LOCKING_SP,
765                     TRUE,
766                     PasswordLength,
767                     Password,
768                     OPAL_LOCKING_SP_USER1_AUTHORITY,
769                     &MethodStatus
770                     );
771   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
772     DEBUG ((DEBUG_INFO, "StartSession with Locking SP as User1 failed\n"));
773     goto done;
774   }
775 
776   Ret = OpalUpdateGlobalLockingRange(Session, ReadLocked, WriteLocked, &MethodStatus);
777   OpalEndSession(Session);
778 
779 done:
780   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
781     Ret = TcgResultFailure;
782   }
783   return Ret;
784 }
785 
786 /**
787   Update global locking range.
788 
789   @param          Session,           The session info for one opal device.
790   @param          Msid,              The data buffer to save Msid info.
791   @param          MsidBufferLength,  The data buffer length for Msid.
792   @param          MsidLength,        The actual data length for Msid.
793 
794 **/
795 TCG_RESULT
796 EFIAPI
OpalUtilGetMsid(OPAL_SESSION * Session,UINT8 * Msid,UINT32 MsidBufferLength,UINT32 * MsidLength)797 OpalUtilGetMsid(
798   OPAL_SESSION    *Session,
799   UINT8           *Msid,
800   UINT32          MsidBufferLength,
801   UINT32          *MsidLength
802   )
803 {
804   UINT8        MethodStatus;
805   TCG_RESULT   Ret;
806 
807   NULL_CHECK(Session);
808   NULL_CHECK(Msid);
809   NULL_CHECK(MsidLength);
810 
811   Ret = OpalStartSession(
812                    Session,
813                    OPAL_UID_ADMIN_SP,
814                    TRUE,
815                    0,
816                    NULL,
817                    TCG_UID_NULL,
818                    &MethodStatus
819                    );
820   if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) {
821     Ret = OpalGetMsid (Session, MsidBufferLength, Msid, MsidLength);
822     OpalEndSession (Session);
823   }
824 
825   if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
826     Ret = TcgResultFailure;
827   }
828 
829   return Ret;
830 }
831 
832 /**
833 
834   The function determines who owns the device by attempting to start a session with different credentials.
835   If the SID PIN matches the MSID PIN, the no one owns the device.
836   If the SID PIN matches the ourSidPin, then "Us" owns the device.  Otherwise it is unknown.
837 
838 
839   @param[in]      Session            The session info for one opal device.
840   @param          Msid,              The Msid info.
841   @param          MsidLength,        The data length for Msid.
842 
843 **/
844 OPAL_OWNER_SHIP
845 EFIAPI
OpalUtilDetermineOwnership(OPAL_SESSION * Session,UINT8 * Msid,UINT32 MsidLength)846 OpalUtilDetermineOwnership(
847   OPAL_SESSION       *Session,
848   UINT8              *Msid,
849   UINT32             MsidLength
850   )
851 {
852   UINT8            MethodStatus;
853   TCG_RESULT       Ret;
854   OPAL_OWNER_SHIP  Owner;
855 
856   if ((Session == NULL) || (Msid == NULL)) {
857     return OpalOwnershipUnknown;
858   }
859 
860   Owner = OpalOwnershipUnknown;
861   //
862   // Start Session as SID_UID with ADMIN_SP using MSID PIN
863   //
864   Ret = OpalStartSession(
865                     Session,
866                     OPAL_UID_ADMIN_SP,
867                     TRUE,
868                     MsidLength,
869                     Msid,
870                     OPAL_ADMIN_SP_SID_AUTHORITY,
871                     &MethodStatus);
872   if ((Ret == TcgResultSuccess) && (MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS)) {
873     //
874     // now we know that SID PIN == MSID PIN
875     //
876     Owner = OpalOwnershipNobody;
877 
878     OpalEndSession(Session);
879   }
880 
881   return Owner;
882 }
883 
884 /**
885 
886   The function returns if admin password exists.
887 
888   @param[in]      OwnerShip         The owner ship of the opal device.
889   @param[in]      LockingFeature    The locking info of the opal device.
890 
891   @retval         TRUE              Admin password existed.
892   @retval         FALSE             Admin password not existed.
893 
894 **/
895 BOOLEAN
896 EFIAPI
OpalUtilAdminPasswordExists(IN UINT16 OwnerShip,IN TCG_LOCKING_FEATURE_DESCRIPTOR * LockingFeature)897 OpalUtilAdminPasswordExists(
898   IN  UINT16                           OwnerShip,
899   IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature
900   )
901 {
902   NULL_CHECK(LockingFeature);
903 
904   // if it is Unknown who owns the device
905   // then someone has set password previously through our UI
906   // because the SID would no longer match the generated SID (ownership us)
907   // or someone has set password using 3rd party software
908 
909   //
910   // Locking sp enabled is checked b/c it must be enabled to change the PIN of the Admin1.
911   //
912   return (OwnerShip == OpalOwnershipUnknown && LockingFeature->LockingEnabled);
913 }
914 
915