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