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