]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalUtil.c
SecurityPkg: Fix spelling errors
[mirror_edk2.git] / SecurityPkg / Library / TcgStorageOpalLib / TcgStorageOpalUtil.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }