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