]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c
SecurityPkg TcgStorageOpalLib: Remove the hard code debug build option.
[mirror_edk2.git] / SecurityPkg / Library / TcgStorageOpalLib / TcgStorageOpalCore.c
1 /** @file
2 Public API for Opal Core library.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <uefi.h>
16 #include <Library/BaseLib.h>
17 #include <Library/TimerLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/TcgStorageOpalLib.h>
21
22 #pragma pack(1)
23 typedef struct {
24 UINT8 HardwareReset : 1;
25 UINT8 Reserved : 7;
26 } TCG_BLOCK_SID_CLEAR_EVENTS;
27 #pragma pack()
28
29 #define TRUSTED_COMMAND_TIMEOUT_NS ((UINT64) 5 * ((UINT64)(1000000)) * 1000) // 5 seconds
30 #define BUFFER_SIZE 512
31
32 /**
33 The function performs a Trusted Send of a Buffer containing a TCG_COM_PACKET.
34
35 @param[in] Sscp The input Ssc Protocol.
36 @param[in] MediaId The input Media id info used by Ssc Protocol.
37 @param[in] SecurityProtocol Security Protocol
38 @param[in] SpSpecific Security Protocol Specific
39 @param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
40 @param[in] Buffer Address of Data to transfer
41 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
42
43 **/
44 TCG_RESULT
45 OpalTrustedSend(
46 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp,
47 UINT32 MediaId,
48 UINT8 SecurityProtocol,
49 UINT16 SpSpecific,
50 UINTN TransferLength,
51 VOID *Buffer,
52 UINTN BufferSize
53 )
54 {
55 UINTN TransferLength512;
56 EFI_STATUS Status;
57
58 //
59 // Round transferLength up to a 512-byte multiple
60 //
61 TransferLength512 = (TransferLength + 511) & ~(UINTN)511;
62
63 if (TransferLength512 > BufferSize) {
64 return TcgResultFailureBufferTooSmall;
65 }
66
67 ZeroMem((UINT8*)Buffer + TransferLength, TransferLength512 - TransferLength);
68
69 Status = Sscp->SendData(
70 Sscp,
71 MediaId,
72 TRUSTED_COMMAND_TIMEOUT_NS,
73 SecurityProtocol,
74 SwapBytes16(SpSpecific),
75 TransferLength512,
76 Buffer
77 );
78
79 return Status == EFI_SUCCESS ? TcgResultSuccess : TcgResultFailure;
80 }
81
82 /**
83
84 The function performs a Trusted Receive of a Buffer containing a TCG_COM_PACKET.
85
86 @param[in] Sscp The input Ssc Protocol.
87 @param[in] MediaId The input Media id info used by Ssc Protocol.
88 @param[in] SecurityProtocol Security Protocol
89 @param[in] SpSpecific Security Protocol Specific
90 @param[in] Buffer Address of Data to transfer
91 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
92
93 **/
94 TCG_RESULT
95 OpalTrustedRecv(
96 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp,
97 UINT32 MediaId,
98 UINT8 SecurityProtocol,
99 UINT16 SpSpecific,
100 VOID *Buffer,
101 UINTN BufferSize
102 )
103 {
104
105 UINTN TransferLength512;
106 UINT32 Tries;
107 TCG_COM_PACKET *ComPacket;
108 UINT32 Length;
109 UINT32 OutstandingData;
110 EFI_STATUS Status;
111 UINTN TransferSize;
112
113 //
114 // Round Buffer Size down to a 512-byte multiple
115 //
116 TransferLength512 = BufferSize & ~(UINTN)511;
117 Tries = 0;
118 ComPacket = NULL;
119 Length = 0;
120 OutstandingData = 0;
121
122 if (TransferLength512 < sizeof(TCG_COM_PACKET)) {
123 DEBUG ((DEBUG_INFO, "transferLength %u too small for ComPacket\n", TransferLength512));
124 return TcgResultFailureBufferTooSmall;
125 }
126
127 //
128 // Some devices respond with Length = 0 and OutstandingData = 1 to indicate that processing is not yet completed,
129 // so we need to retry the IF-RECV to get the actual Data.
130 // See TCG Core Spec v2 Table 45 IF-RECV ComPacket Field Values Summary
131 // This is an arbitrary number of retries, not from the spec.
132 // have a max timeout of 10 seconds, 5000 tries * 2ms = 10s
133 //
134 Tries = 5000;
135 while ((Tries--) > 0) {
136 ZeroMem( Buffer, BufferSize );
137 TransferSize = 0;
138
139 Status = Sscp->ReceiveData(
140 Sscp,
141 MediaId,
142 TRUSTED_COMMAND_TIMEOUT_NS,
143 SecurityProtocol,
144 SwapBytes16(SpSpecific),
145 TransferLength512,
146 Buffer,
147 &TransferSize
148 );
149
150 if (EFI_ERROR (Status)) {
151 return TcgResultFailure;
152 }
153
154 if (SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_1 && SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_2) {
155 return TcgResultSuccess;
156 }
157
158 if (SpSpecific == TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY) {
159 return TcgResultSuccess;
160 }
161
162 ComPacket = (TCG_COM_PACKET*) Buffer;
163 Length = SwapBytes32(ComPacket->LengthBE);
164 OutstandingData = SwapBytes32( ComPacket->OutstandingDataBE );
165
166 if (Length != 0 && OutstandingData == 0) {
167 return TcgResultSuccess;
168 }
169
170 //
171 // Delay for 2 ms
172 //
173 MicroSecondDelay (2000);
174 }
175
176 return TcgResultFailure;
177 }
178
179 /**
180 The function performs send, recv, check comIDs, check method status action.
181
182 @param[in] Session OPAL_SESSION related to this method..
183 @param[in] SendSize Transfer Length of Buffer (in bytes) - always a multiple of 512
184 @param[in] Buffer Address of Data to transfer
185 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
186 @param[in] ParseStruct Structure used to parse received TCG response.
187 @param[in] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
188
189 **/
190 TCG_RESULT
191 EFIAPI
192 OpalPerformMethod(
193 OPAL_SESSION *Session,
194 UINT32 SendSize,
195 VOID *Buffer,
196 UINT32 BufferSize,
197 TCG_PARSE_STRUCT *ParseStruct,
198 UINT8 *MethodStatus
199 )
200 {
201 NULL_CHECK(Session);
202 NULL_CHECK(MethodStatus);
203
204 ERROR_CHECK(OpalTrustedSend(
205 Session->Sscp,
206 Session->MediaId,
207 TCG_OPAL_SECURITY_PROTOCOL_1,
208 Session->OpalBaseComId,
209 SendSize,
210 Buffer,
211 BufferSize
212 ));
213
214 ERROR_CHECK(OpalTrustedRecv(
215 Session->Sscp,
216 Session->MediaId,
217 TCG_OPAL_SECURITY_PROTOCOL_1,
218 Session->OpalBaseComId,
219 Buffer,
220 BufferSize
221 ));
222
223 ERROR_CHECK(TcgInitTcgParseStruct(ParseStruct, Buffer, BufferSize));
224 ERROR_CHECK(TcgCheckComIds(ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
225 ERROR_CHECK(TcgGetMethodStatus(ParseStruct, MethodStatus));
226
227 return TcgResultSuccess;
228 }
229
230 /**
231 Trig the block sid action.
232
233 @param[in] Session OPAL_SESSION related to this method..
234 @param[in] HardwareReset Whether need to do hardware reset.
235
236 **/
237 TCG_RESULT
238 EFIAPI
239 OpalBlockSid(
240 OPAL_SESSION *Session,
241 BOOLEAN HardwareReset
242 )
243 {
244 UINT8 Buffer[BUFFER_SIZE];
245 TCG_BLOCK_SID_CLEAR_EVENTS *ClearEvents;
246
247 NULL_CHECK(Session);
248
249 //
250 // Set Hardware Reset bit
251 //
252 ClearEvents = (TCG_BLOCK_SID_CLEAR_EVENTS *) &Buffer[0];
253
254 ClearEvents->Reserved = 0;
255 ClearEvents->HardwareReset = HardwareReset;
256
257 return(OpalTrustedSend(
258 Session->Sscp,
259 Session->MediaId,
260 TCG_OPAL_SECURITY_PROTOCOL_2,
261 Session->OpalBaseComId,
262 1,
263 Buffer,
264 BUFFER_SIZE
265 ));
266 }
267
268 /**
269
270 Reverts device using Admin SP Revert method.
271
272 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
273
274 **/
275 TCG_RESULT
276 EFIAPI
277 OpalPsidRevert(
278 OPAL_SESSION *AdminSpSession
279 )
280 {
281 //
282 // Now that base comid is known, start Session
283 // we'll attempt to start Session as PSID authority
284 // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
285 //
286 TCG_CREATE_STRUCT CreateStruct;
287 TCG_PARSE_STRUCT ParseStruct;
288 UINT32 Size;
289 UINT8 Buffer[BUFFER_SIZE];
290 UINT8 MethodStatus;
291
292 NULL_CHECK(AdminSpSession);
293
294 //
295 // Send Revert action on Admin SP
296 //
297 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
298 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
299 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
300 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
301 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));
302 ERROR_CHECK(TcgStartParameters(&CreateStruct));
303 ERROR_CHECK(TcgEndParameters(&CreateStruct));
304 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
305 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
306 ERROR_CHECK(TcgEndPacket(&CreateStruct));
307 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
308
309 //
310 // Send Revert Method Call
311 //
312 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus));
313 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
314
315 return TcgResultSuccess;
316 }
317
318 /**
319
320 The function fills in the provided Buffer with the level 0 discovery Header
321 of the device specified.
322
323 @param[in] Session OPAL_SESSION data.
324 @param[in] BufferSize Size of Buffer provided (in bytes)
325 @param[in] BuffAddress Buffer address to fill with Level 0 Discovery response
326
327 **/
328 TCG_RESULT
329 EFIAPI
330 OpalRetrieveLevel0DiscoveryHeader(
331 OPAL_SESSION *Session,
332 UINTN BufferSize,
333 VOID *BuffAddress
334 )
335 {
336 return (OpalTrustedRecv(
337 Session->Sscp,
338 Session->MediaId,
339 TCG_OPAL_SECURITY_PROTOCOL_1, // SP
340 TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific
341 BuffAddress,
342 BufferSize
343 ));
344 }
345
346 /**
347
348 The function fills in the provided Buffer with the supported protocol list
349 of the device specified.
350
351 @param[in] Session OPAL_SESSION data.
352 @param[in] BufferSize Size of Buffer provided (in bytes)
353 @param[in] BuffAddress Buffer address to fill with security protocol list
354
355 **/
356 TCG_RESULT
357 EFIAPI
358 OpalRetrieveSupportedProtocolList(
359 OPAL_SESSION *Session,
360 UINTN BufferSize,
361 VOID *BuffAddress
362 )
363 {
364 return (OpalTrustedRecv(
365 Session->Sscp,
366 Session->MediaId,
367 TCG_SECURITY_PROTOCOL_INFO, // SP
368 TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific
369 BuffAddress,
370 BufferSize
371 ));
372 }
373
374 /**
375 Starts a session with a security provider (SP).
376
377 If a session is started successfully, the caller must end the session with OpalEndSession when finished
378 performing Opal actions.
379
380 @param[in/out] Session OPAL_SESSION to initialize.
381 @param[in] SpId Security provider ID to start the session with.
382 @param[in] Write Whether the session should be read-only (FALSE) or read/write (TRUE).
383 @param[in] HostChallengeLength Length of the host challenge. Length should be 0 if hostChallenge is NULL
384 @param[in] HostChallenge Host challenge for Host Signing Authority. If NULL, then no Host Challenge will be sent.
385 @param[in] HostSigningAuthority Host Signing Authority used for start session. If NULL, then no Host Signing Authority will be sent.
386 @param[in/out] MethodStatus Status of the StartSession method; only valid if TcgResultSuccess is returned.
387
388 @return TcgResultSuccess indicates that the function completed without any internal errors.
389 The caller must inspect the MethodStatus field to determine whether the method completed successfully.
390
391 **/
392 TCG_RESULT
393 EFIAPI
394 OpalStartSession(
395 OPAL_SESSION *Session,
396 TCG_UID SpId,
397 BOOLEAN Write,
398 UINT32 HostChallengeLength,
399 const VOID *HostChallenge,
400 TCG_UID HostSigningAuthority,
401 UINT8 *MethodStatus
402 )
403 {
404 TCG_CREATE_STRUCT CreateStruct;
405 TCG_PARSE_STRUCT ParseStruct;
406 UINT32 Size;
407 UINT8 Buf[BUFFER_SIZE];
408 UINT16 ComIdExtension;
409 UINT32 HostSessionId;
410
411 ComIdExtension = 0;
412 HostSessionId = 1;
413
414 NULL_CHECK(Session);
415 NULL_CHECK(MethodStatus);
416
417 Session->ComIdExtension = ComIdExtension;
418 Session->HostSessionId = HostSessionId;
419
420 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
421 ERROR_CHECK(TcgCreateStartSession(
422 &CreateStruct,
423 &Size,
424 Session->OpalBaseComId,
425 ComIdExtension,
426 HostSessionId,
427 SpId,
428 Write,
429 HostChallengeLength,
430 HostChallenge,
431 HostSigningAuthority
432 ));
433 ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
434 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
435 return TcgResultSuccess; // return early if method failed - user must check MethodStatus
436 }
437
438 if (TcgParseSyncSession(&ParseStruct, Session->OpalBaseComId, ComIdExtension, HostSessionId, &Session->TperSessionId) != TcgResultSuccess) {
439 OpalEndSession(Session);
440 return TcgResultFailure;
441 }
442
443 return TcgResultSuccess;
444 }
445
446 /**
447 Close a session opened with OpalStartSession.
448
449 @param[in/out] Session OPAL_SESSION to end.
450
451 **/
452 TCG_RESULT
453 EFIAPI
454 OpalEndSession(
455 OPAL_SESSION *Session
456 )
457 {
458 UINT8 Buffer[BUFFER_SIZE];
459 TCG_CREATE_STRUCT CreateStruct;
460 UINT32 Size;
461 TCG_PARSE_STRUCT ParseStruct;
462
463 NULL_CHECK(Session);
464 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, sizeof(Buffer)));
465 ERROR_CHECK(TcgCreateEndSession(
466 &CreateStruct,
467 &Size,
468 Session->OpalBaseComId,
469 Session->ComIdExtension,
470 Session->HostSessionId,
471 Session->TperSessionId
472 ));
473
474 ERROR_CHECK(OpalTrustedSend(
475 Session->Sscp,
476 Session->MediaId,
477 TCG_OPAL_SECURITY_PROTOCOL_1,
478 Session->OpalBaseComId,
479 Size,
480 Buffer,
481 sizeof(Buffer)
482 ));
483
484 ERROR_CHECK(OpalTrustedRecv(
485 Session->Sscp,
486 Session->MediaId,
487 TCG_OPAL_SECURITY_PROTOCOL_1,
488 Session->OpalBaseComId,
489 Buffer,
490 sizeof(Buffer)
491 ));
492
493 ERROR_CHECK(TcgInitTcgParseStruct(&ParseStruct, Buffer, sizeof(Buffer)));
494 ERROR_CHECK(TcgCheckComIds(&ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
495
496 ERROR_CHECK(TcgGetNextEndOfSession(&ParseStruct));
497 return TcgResultSuccess;
498 }
499
500 /**
501
502 The function retrieves the MSID from the device specified
503
504 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
505 @param[in] MsidBufferSize Allocated Buffer Size (in bytes) for MSID allocated by caller
506 @param[in] Msid Variable Length byte sequence representing MSID of device
507 @param[in] MsidLength Actual Length of MSID retrieved from device
508
509 **/
510 TCG_RESULT
511 EFIAPI
512 OpalGetMsid(
513 OPAL_SESSION *AdminSpSession,
514 UINT32 MsidBufferSize,
515 UINT8 *Msid,
516 UINT32 *MsidLength
517 )
518 {
519 //
520 // now that base comid is known, start Session
521 // we'll attempt to start Session as PSID authority
522 // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
523 //
524 TCG_CREATE_STRUCT CreateStruct;
525 TCG_PARSE_STRUCT ParseStruct;
526 UINT32 Size;
527 UINT8 MethodStatus;
528 UINT32 Col;
529 const VOID *RecvMsid;
530 UINT8 Buffer[BUFFER_SIZE];
531
532 NULL_CHECK(AdminSpSession);
533 NULL_CHECK(Msid);
534 NULL_CHECK(MsidLength);
535
536 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
537 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
538 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
539 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
540 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_C_PIN_MSID, TCG_UID_METHOD_GET));
541 ERROR_CHECK(TcgStartParameters(&CreateStruct));
542 ERROR_CHECK(TcgAddStartList(&CreateStruct));
543 ERROR_CHECK(TcgAddStartName(&CreateStruct));
544 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
545 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
546 ERROR_CHECK(TcgAddEndName(&CreateStruct));
547 ERROR_CHECK(TcgAddStartName(&CreateStruct));
548 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
549 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
550 ERROR_CHECK(TcgAddEndName(&CreateStruct));
551 ERROR_CHECK(TcgAddEndList(&CreateStruct));
552 ERROR_CHECK(TcgEndParameters(&CreateStruct));
553 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
554 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
555 ERROR_CHECK(TcgEndPacket(&CreateStruct));
556 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
557
558 //
559 // Send MSID Method Call
560 //
561 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus));
562 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
563
564 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
565 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
566 ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
567 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
568 ERROR_CHECK(TcgGetNextByteSequence(&ParseStruct, &RecvMsid, MsidLength));
569 ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
570 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
571 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
572 ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
573
574 if (Col != OPAL_ADMIN_SP_PIN_COL) {
575 DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_PIN_COL));
576 return TcgResultFailure;
577 }
578
579 if (RecvMsid == NULL) {
580 return TcgResultFailure;
581 }
582
583 if (MsidBufferSize < *MsidLength) {
584 DEBUG ((DEBUG_INFO, "Buffer too small MsidBufferSize: %d MsidLength: %d\n", MsidBufferSize, *MsidLength));
585 return TcgResultFailureBufferTooSmall;
586 }
587
588 //
589 // copy msid into Buffer
590 //
591 CopyMem(Msid, RecvMsid, *MsidLength);
592 return TcgResultSuccess;
593 }
594
595 /**
596
597 The function calls the Admin SP RevertSP method on the Locking SP. If KeepUserData is True, then the optional parameter
598 to keep the user Data is set to True, otherwise the optional parameter is not provided.
599
600 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP
601 @param[in] KeepUserData Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.
602 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
603
604 **/
605 TCG_RESULT
606 EFIAPI
607 OpalAdminRevert(
608 OPAL_SESSION *LockingSpSession,
609 BOOLEAN KeepUserData,
610 UINT8 *MethodStatus
611 )
612 {
613 UINT8 Buf[BUFFER_SIZE];
614 TCG_CREATE_STRUCT CreateStruct;
615 UINT32 Size;
616 TCG_PARSE_STRUCT ParseStruct;
617 TCG_RESULT Ret;
618
619 NULL_CHECK(LockingSpSession);
620 NULL_CHECK(MethodStatus);
621
622 //
623 // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data
624 //
625 if (KeepUserData) {
626 //
627 // set readlocked and writelocked to false
628 //
629 Ret = OpalUpdateGlobalLockingRange(
630 LockingSpSession,
631 FALSE,
632 FALSE,
633 MethodStatus);
634
635 if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
636 //
637 // bail out
638 //
639 return Ret;
640 }
641 }
642
643 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
644 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
645 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
646 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
647 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));
648 ERROR_CHECK(TcgStartParameters(&CreateStruct));
649
650 if (KeepUserData) {
651 //
652 // optional parameter to keep Data after revert
653 //
654 ERROR_CHECK(TcgAddStartName(&CreateStruct));
655 ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000)); // weird Value but that's what spec says
656 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));
657 ERROR_CHECK(TcgAddEndName(&CreateStruct));
658 }
659
660 ERROR_CHECK(TcgEndParameters(&CreateStruct));
661 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
662 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
663 ERROR_CHECK(TcgEndPacket(&CreateStruct));
664 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
665
666 //
667 // Send RevertSP method call
668 //
669 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
670
671 //
672 // Session is immediately ended by device after successful revertsp, so no need to end Session
673 //
674 if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
675 //
676 // Caller should take ownership again
677 //
678 return TcgResultSuccess;
679 } else {
680 //
681 // End Session
682 //
683 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
684 }
685
686 return TcgResultSuccess;
687 }
688
689 /**
690
691 The function activates the Locking SP.
692 Once activated, per Opal spec, the ADMIN SP SID PIN is copied over to the ADMIN1 LOCKING SP PIN.
693 If the Locking SP is already enabled, then TcgResultSuccess is returned and no action occurs.
694
695 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY to activate Locking SP
696 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
697
698 **/
699 TCG_RESULT
700 EFIAPI
701 OpalActivateLockingSp(
702 OPAL_SESSION *AdminSpSession,
703 UINT8 *MethodStatus
704 )
705 {
706 UINT8 Buf[BUFFER_SIZE];
707 TCG_CREATE_STRUCT CreateStruct;
708 UINT32 Size;
709 TCG_PARSE_STRUCT ParseStruct;
710
711 NULL_CHECK(AdminSpSession);
712 NULL_CHECK(MethodStatus);
713
714 //
715 // Call Activate method on Locking SP
716 //
717 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
718 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
719 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
720 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
721 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_LOCKING_SP, OPAL_ADMIN_SP_ACTIVATE_METHOD));
722 ERROR_CHECK(TcgStartParameters(&CreateStruct));
723 ERROR_CHECK(TcgEndParameters(&CreateStruct));
724 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
725 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
726 ERROR_CHECK(TcgEndPacket(&CreateStruct));
727 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
728
729 //
730 // Send Activate method call
731 //
732 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
733 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
734
735 return TcgResultSuccess;
736 }
737
738 /**
739
740 The function sets the PIN column of the specified cpinRowUid (authority) with the newPin Value.
741
742 @param[in/out] Session OPAL_SESSION to set password
743 @param[in] CpinRowUid UID of row (authority) to update PIN column
744 @param[in] NewPin New Pin to set for cpinRowUid specified
745 @param[in] NewPinLength Length in bytes of newPin
746 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
747
748 **/
749 TCG_RESULT
750 EFIAPI
751 OpalSetPassword(
752 OPAL_SESSION *Session,
753 TCG_UID CpinRowUid,
754 const VOID *NewPin,
755 UINT32 NewPinLength,
756 UINT8 *MethodStatus
757 )
758 {
759 UINT8 Buf[BUFFER_SIZE];
760 TCG_CREATE_STRUCT CreateStruct;
761 TCG_PARSE_STRUCT ParseStruct;
762 UINT32 Size;
763
764 NULL_CHECK(Session);
765 NULL_CHECK(NewPin);
766 NULL_CHECK(MethodStatus);
767
768 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
769 ERROR_CHECK(TcgCreateSetCPin(
770 &CreateStruct,
771 &Size,
772 Session->OpalBaseComId,
773 Session->ComIdExtension,
774 Session->TperSessionId,
775 Session->HostSessionId,
776 CpinRowUid,
777 NewPin,
778 NewPinLength
779 ));
780
781 ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
782 // exit with success on method failure - user must inspect MethodStatus
783 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
784
785 return TcgResultSuccess;
786 }
787
788 /**
789
790 The function sets the Enabled column to TRUE for the authorityUid provided and updates the PIN column for the cpinRowUid provided
791 using the newPin provided. AuthorityUid and cpinRowUid should describe the same authority.
792
793 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to update
794 @param[in] CpinRowUid Row UID of C_PIN table of Locking SP to update PIN
795 @param[in] AuthorityUid UID of Locking SP authority to update Pin column with
796 @param[in] NewPin New Password used to set Pin column
797 @param[in] NewPinLength Length in bytes of new password
798 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
799
800 **/
801 TCG_RESULT
802 EFIAPI
803 OpalSetLockingSpAuthorityEnabledAndPin(
804 OPAL_SESSION *LockingSpSession,
805 TCG_UID CpinRowUid,
806 TCG_UID AuthorityUid,
807 const VOID *NewPin,
808 UINT32 NewPinLength,
809 UINT8 *MethodStatus
810 )
811 {
812 UINT8 Buf[BUFFER_SIZE];
813 TCG_CREATE_STRUCT CreateStruct;
814 TCG_PARSE_STRUCT ParseStruct;
815 UINT32 Size;
816 TCG_UID ActiveKey;
817
818 NULL_CHECK(LockingSpSession);
819 NULL_CHECK(NewPin);
820 NULL_CHECK(MethodStatus);
821
822 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
823 ERROR_CHECK(TcgSetAuthorityEnabled(
824 &CreateStruct,
825 &Size,
826 LockingSpSession->OpalBaseComId,
827 LockingSpSession->ComIdExtension,
828 LockingSpSession->TperSessionId,
829 LockingSpSession->HostSessionId,
830 AuthorityUid,
831 TRUE));
832
833 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
834
835 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
836 DEBUG ((DEBUG_INFO, "Send Set Authority error\n"));
837 return TcgResultFailure;
838 }
839
840 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
841
842 ERROR_CHECK(TcgCreateSetCPin(
843 &CreateStruct,
844 &Size,
845 LockingSpSession->OpalBaseComId,
846 LockingSpSession->ComIdExtension,
847 LockingSpSession->TperSessionId,
848 LockingSpSession->HostSessionId,
849 CpinRowUid,
850 NewPin,
851 NewPinLength));
852
853 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
854
855 //
856 // allow user1 to set global range to unlocked/locked by modifying ACE_Locking_GlobalRange_SetRdLocked/SetWrLocked
857 //
858 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
859 ERROR_CHECK(TcgCreateSetAce(
860 &CreateStruct,
861 &Size,
862 LockingSpSession->OpalBaseComId,
863 LockingSpSession->ComIdExtension,
864 LockingSpSession->TperSessionId,
865 LockingSpSession->HostSessionId,
866 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_RDLOCKED,
867 OPAL_LOCKING_SP_USER1_AUTHORITY,
868 TCG_ACE_EXPRESSION_OR,
869 OPAL_LOCKING_SP_ADMINS_AUTHORITY
870 ));
871
872 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
873
874 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
875 DEBUG ((DEBUG_INFO, "Update ACE for RDLOCKED failed\n"));
876 return TcgResultFailure;
877 }
878
879 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
880 ERROR_CHECK(TcgCreateSetAce(
881 &CreateStruct,
882 &Size,
883 LockingSpSession->OpalBaseComId,
884 LockingSpSession->ComIdExtension,
885 LockingSpSession->TperSessionId,
886 LockingSpSession->HostSessionId,
887 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_WRLOCKED,
888 OPAL_LOCKING_SP_USER1_AUTHORITY,
889 TCG_ACE_EXPRESSION_OR,
890 OPAL_LOCKING_SP_ADMINS_AUTHORITY
891 ));
892
893 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
894
895 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
896 DEBUG ((DEBUG_INFO, "Update ACE for WRLOCKED failed\n"));
897 return TcgResultFailure;
898 }
899
900 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
901 ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
902 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
903
904 ERROR_CHECK(OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey));
905
906 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
907 ERROR_CHECK(TcgCreateSetAce(
908 &CreateStruct,
909 &Size,
910 LockingSpSession->OpalBaseComId,
911 LockingSpSession->ComIdExtension,
912 LockingSpSession->TperSessionId,
913 LockingSpSession->HostSessionId,
914 (ActiveKey == OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY) ? OPAL_LOCKING_SP_ACE_K_AES_256_GLOBALRANGE_GENKEY : OPAL_LOCKING_SP_ACE_K_AES_128_GLOBALRANGE_GENKEY,
915 OPAL_LOCKING_SP_USER1_AUTHORITY,
916 TCG_ACE_EXPRESSION_OR,
917 OPAL_LOCKING_SP_ADMINS_AUTHORITY
918 ));
919
920 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
921
922 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
923 DEBUG ((DEBUG_INFO, "Update ACE for GLOBALRANGE_GENKEY failed\n"));
924 //
925 //TODO do we want to disable user1 if all permissions are not granted
926 //
927 return TcgResultFailure;
928 }
929
930 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
931 ERROR_CHECK(TcgCreateSetAce(
932 &CreateStruct,
933 &Size,
934 LockingSpSession->OpalBaseComId,
935 LockingSpSession->ComIdExtension,
936 LockingSpSession->TperSessionId,
937 LockingSpSession->HostSessionId,
938 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL,
939 OPAL_LOCKING_SP_USER1_AUTHORITY,
940 TCG_ACE_EXPRESSION_OR,
941 OPAL_LOCKING_SP_ADMINS_AUTHORITY
942 ));
943
944 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
945
946 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
947 DEBUG ((DEBUG_INFO, "Update ACE for OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL failed\n"));
948 return TcgResultFailure;
949 }
950
951 return TcgResultSuccess;
952 }
953
954 /**
955
956 The function sets the Enabled column to FALSE for the USER1 authority.
957
958 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to disable User1
959 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
960
961 **/
962 TCG_RESULT
963 EFIAPI
964 OpalDisableUser(
965 OPAL_SESSION *LockingSpSession,
966 UINT8 *MethodStatus
967 )
968 {
969 UINT8 Buf[BUFFER_SIZE];
970 TCG_CREATE_STRUCT CreateStruct;
971 TCG_PARSE_STRUCT ParseStruct;
972 UINT32 Size;
973
974 NULL_CHECK(LockingSpSession);
975 NULL_CHECK(MethodStatus);
976
977 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
978 ERROR_CHECK(TcgSetAuthorityEnabled(
979 &CreateStruct,
980 &Size,
981 LockingSpSession->OpalBaseComId,
982 LockingSpSession->ComIdExtension,
983 LockingSpSession->TperSessionId,
984 LockingSpSession->HostSessionId,
985 OPAL_LOCKING_SP_USER1_AUTHORITY,
986 FALSE));
987
988 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
989
990 return TcgResultSuccess;
991 }
992
993 /**
994
995 The function retrieves the active key of the global locking range
996 and calls the GenKey method on the active key retrieved.
997
998 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
999 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1000
1001 **/
1002 TCG_RESULT
1003 EFIAPI
1004 OpalGlobalLockingRangeGenKey(
1005 OPAL_SESSION *LockingSpSession,
1006 UINT8 *MethodStatus
1007 )
1008 {
1009 UINT8 Buf[BUFFER_SIZE];
1010 TCG_CREATE_STRUCT CreateStruct;
1011 TCG_PARSE_STRUCT ParseStruct;
1012 UINT32 Size;
1013 TCG_UID ActiveKey;
1014
1015 NULL_CHECK(LockingSpSession);
1016 NULL_CHECK(MethodStatus);
1017
1018 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1019 //
1020 // retrieve the activekey in order to know which globalrange key to generate
1021 //
1022 ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
1023 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
1024
1025 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1026
1027 ERROR_CHECK(OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey));
1028
1029 //
1030 // call genkey on ActiveKey UID
1031 //
1032 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1033 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1034 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1035 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1036 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, ActiveKey, TCG_UID_METHOD_GEN_KEY));
1037 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1038 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1039 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1040 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1041 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1042 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1043
1044 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
1045
1046 return TcgResultSuccess;
1047 }
1048
1049 /**
1050
1051 The function updates the ReadLocked and WriteLocked columns of the Global Locking Range.
1052 This funciton is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns
1053 (not ReadLockEnabled and WriteLockEnabled columns).
1054
1055 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1056 @param[in] ReadLocked Value to set ReadLocked column for Global Locking Range
1057 @param[in] WriteLocked Value to set WriteLocked column for Global Locking Range
1058 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1059
1060 **/
1061 TCG_RESULT
1062 EFIAPI
1063 OpalUpdateGlobalLockingRange(
1064 OPAL_SESSION *LockingSpSession,
1065 BOOLEAN ReadLocked,
1066 BOOLEAN WriteLocked,
1067 UINT8 *MethodStatus
1068 )
1069 {
1070 UINT8 Buf[BUFFER_SIZE];
1071 TCG_CREATE_STRUCT CreateStruct;
1072 TCG_PARSE_STRUCT ParseStruct;
1073 UINT32 Size;
1074
1075 NULL_CHECK(LockingSpSession);
1076 NULL_CHECK(MethodStatus);
1077
1078 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1079
1080 //
1081 // set global locking range values
1082 //
1083 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1084 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1085 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1086 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_SET));
1087 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1088 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1089 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01)); // "Values"
1090 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1091
1092 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1093 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07)); // "ReadLocked"
1094 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1095 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1096
1097 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1098 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08)); // "WriteLocked"
1099 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1100 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1101
1102 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1103 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1104 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1105 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1106 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1107 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1108 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1109
1110 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
1111 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1112
1113 return TcgResultSuccess;
1114 }
1115
1116 /**
1117
1118 The function updates the RangeStart, RangeLength, ReadLockedEnabled, WriteLockedEnabled, ReadLocked and WriteLocked columns
1119 of the specified Locking Range. This function requires admin authority of a locking SP session.
1120
1121 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1122 @param[in] LockingRangeUid Locking range UID to set values
1123 @param[in] RangeStart Value to set RangeStart column for Locking Range
1124 @param[in] RangeLength Value to set RangeLength column for Locking Range
1125 @param[in] ReadLockEnabled Value to set readLockEnabled column for Locking Range
1126 @param[in] WriteLockEnabled Value to set writeLockEnabled column for Locking Range
1127 @param[in] ReadLocked Value to set ReadLocked column for Locking Range
1128 @param[in] WriteLocked Value to set WriteLocked column for Locking Range
1129 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1130
1131 **/
1132 TCG_RESULT
1133 EFIAPI
1134 OpalSetLockingRange(
1135 OPAL_SESSION *LockingSpSession,
1136 TCG_UID LockingRangeUid,
1137 UINT64 RangeStart,
1138 UINT64 RangeLength,
1139 BOOLEAN ReadLockEnabled,
1140 BOOLEAN WriteLockEnabled,
1141 BOOLEAN ReadLocked,
1142 BOOLEAN WriteLocked,
1143 UINT8 *MethodStatus
1144 )
1145 {
1146 UINT8 Buf[BUFFER_SIZE];
1147 TCG_CREATE_STRUCT CreateStruct;
1148 TCG_PARSE_STRUCT ParseStruct;
1149 UINT32 Size;
1150
1151 NULL_CHECK(LockingSpSession);
1152 NULL_CHECK(MethodStatus);
1153
1154 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1155
1156 //
1157 // set locking range values
1158 //
1159 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1160 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1161 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1162 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, LockingRangeUid, TCG_UID_METHOD_SET));
1163 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1164 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1165 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01)); // "Values"
1166 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1167
1168 //
1169 // range start and range Length only apply to non-global locking ranges
1170 //
1171 if (LockingRangeUid != OPAL_LOCKING_SP_LOCKING_GLOBALRANGE) {
1172 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1173 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x03)); // "RangeStart"
1174 ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeStart));
1175 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1176
1177 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1178 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x04)); // "RangeLength"
1179 ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeLength));
1180 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1181 }
1182
1183 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1184 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x05)); // "ReadLockEnabled"
1185 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLockEnabled));
1186 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1187
1188 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1189 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x06)); // "WriteLockEnabled"
1190 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLockEnabled));
1191 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1192
1193 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1194 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07)); // "ReadLocked"
1195 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1196 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1197
1198 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1199 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08)); // "WriteLocked"
1200 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1201 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1202
1203 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1204 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1205 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1206 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1207 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1208 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1209 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1210
1211 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));
1212 // Exit with success on method failure - user must inspect MethodStatus
1213 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1214
1215 return TcgResultSuccess;
1216 }
1217
1218 /**
1219
1220 The function populates the CreateStruct with a payload that will retrieve the global locking range active key.
1221 It is intended to be called with a session that is already started with a valid credential.
1222 The function does not send the payload.
1223
1224 @param[in] Session OPAL_SESSION to populate command for, needs ComId
1225 @param[in/out] CreateStruct Structure to populate with encoded TCG command
1226 @param[in/out] Size Size in bytes of the command created.
1227
1228 **/
1229 TCG_RESULT
1230 EFIAPI
1231 OpalCreateRetrieveGlobalLockingRangeActiveKey(
1232 const OPAL_SESSION *Session,
1233 TCG_CREATE_STRUCT *CreateStruct,
1234 UINT32 *Size
1235 )
1236 {
1237 NULL_CHECK(Session);
1238 NULL_CHECK(CreateStruct);
1239 NULL_CHECK(Size);
1240
1241 // Retrieve the activekey in order to know which globalrange key to generate
1242 ERROR_CHECK(TcgStartComPacket(CreateStruct, Session->OpalBaseComId, Session->ComIdExtension));
1243 ERROR_CHECK(TcgStartPacket(CreateStruct, Session->TperSessionId, Session->HostSessionId, 0x0, 0x0, 0x0));
1244 ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
1245 ERROR_CHECK(TcgStartMethodCall(CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_GET));
1246 ERROR_CHECK(TcgStartParameters(CreateStruct));
1247 ERROR_CHECK(TcgAddStartList(CreateStruct));
1248 ERROR_CHECK(TcgAddStartName(CreateStruct));
1249 ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1250 ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A)); // ActiveKey
1251 ERROR_CHECK(TcgAddEndName(CreateStruct));
1252 ERROR_CHECK(TcgAddStartName(CreateStruct));
1253 ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1254 ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A));
1255 ERROR_CHECK(TcgAddEndName(CreateStruct));
1256 ERROR_CHECK(TcgAddEndList(CreateStruct));
1257 ERROR_CHECK(TcgEndParameters(CreateStruct));
1258 ERROR_CHECK(TcgEndMethodCall(CreateStruct));
1259 ERROR_CHECK(TcgEndSubPacket(CreateStruct));
1260 ERROR_CHECK(TcgEndPacket(CreateStruct));
1261 ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
1262
1263 return TcgResultSuccess;
1264 }
1265
1266 /**
1267
1268 The function acquires the activeKey specified for the Global Locking Range from the ParseStruct.
1269
1270 @param[in] ParseStruct Structure that contains the device's response with the activekey
1271 @param[in/out] ActiveKey The UID of the active key retrieved
1272
1273 **/
1274 TCG_RESULT
1275 EFIAPI
1276 OpalParseRetrieveGlobalLockingRangeActiveKey(
1277 TCG_PARSE_STRUCT *ParseStruct,
1278 TCG_UID *ActiveKey
1279 )
1280 {
1281 UINT32 ColumnName;
1282
1283 NULL_CHECK(ParseStruct);
1284 NULL_CHECK(ActiveKey);
1285
1286 // parse response
1287 ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1288 ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1289 ERROR_CHECK(TcgGetNextStartName(ParseStruct));
1290 ERROR_CHECK(TcgGetNextUINT32(ParseStruct, &ColumnName));
1291 ERROR_CHECK(TcgGetNextTcgUid(ParseStruct, ActiveKey));
1292 ERROR_CHECK(TcgGetNextEndName(ParseStruct));
1293 ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1294 ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1295 ERROR_CHECK(TcgGetNextEndOfData(ParseStruct));
1296
1297 if (ColumnName != 0x0A) {
1298 DEBUG ((DEBUG_INFO, "Unexpected column name %u (exp 0x0A)\n", ColumnName));
1299 return TcgResultFailure;
1300 }
1301
1302 if (*ActiveKey != OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY && *ActiveKey != OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY) {
1303 DEBUG ((DEBUG_INFO, "Unexpected gen key %u (exp %u or %u)\n", *ActiveKey, OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY, OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY));
1304 return TcgResultFailure;
1305 }
1306
1307 return TcgResultSuccess;
1308 }
1309
1310 /**
1311
1312 The function retrieves the TryLimit column for the specified rowUid (authority).
1313
1314 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve try limit
1315 @param[in] RowUid Row UID of the Locking SP C_PIN table to retrieve TryLimit column
1316 @param[in/out] TryLimit Value from TryLimit column
1317
1318 **/
1319 TCG_RESULT
1320 EFIAPI
1321 OpalGetTryLimit(
1322 OPAL_SESSION *LockingSpSession,
1323 TCG_UID RowUid,
1324 UINT32 *TryLimit
1325 )
1326 {
1327 TCG_CREATE_STRUCT CreateStruct;
1328 TCG_PARSE_STRUCT ParseStruct;
1329 UINT32 Size;
1330 UINT8 MethodStatus;
1331 UINT8 Buf[BUFFER_SIZE];
1332 UINT32 Col;
1333
1334 NULL_CHECK(LockingSpSession);
1335 NULL_CHECK(TryLimit);
1336
1337 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1338 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1339 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1340 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1341 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, RowUid, TCG_UID_METHOD_GET));
1342 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1343 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1344 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1345 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1346 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1347 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1348 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1349 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1350 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1351 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1352 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1353 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1354 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1355 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1356 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1357 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1358
1359 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus));
1360 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
1361
1362 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1363 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1364 ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
1365 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
1366 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, TryLimit));
1367 ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
1368 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1369 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1370 ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
1371
1372 if (Col != OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL) {
1373 DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1374 return TcgResultFailure;
1375 }
1376
1377 return TcgResultSuccess;
1378 }
1379
1380 /**
1381
1382 Get the support attribute info.
1383
1384 @param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1385 @param[out] SupportedAttributes Return the support attribute info.
1386 @param[out] OpalBaseComId Return the base com id info.
1387
1388 **/
1389 TCG_RESULT
1390 EFIAPI
1391 OpalGetSupportedAttributesInfo(
1392 IN OPAL_SESSION *Session,
1393 OUT OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1394 OUT UINT16 *OpalBaseComId
1395 )
1396 {
1397 UINT8 Buffer[BUFFER_SIZE];
1398 TCG_SUPPORTED_SECURITY_PROTOCOLS *SupportedProtocols;
1399 TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader;
1400 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat;
1401 UINTN Size;
1402
1403 NULL_CHECK(Session);
1404 NULL_CHECK(SupportedAttributes);
1405 NULL_CHECK(OpalBaseComId);
1406
1407 ZeroMem(Buffer, BUFFER_SIZE);
1408 ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1409
1410 //
1411 // Retrieve supported protocols verify security protocol 1 is supported
1412 //
1413 SupportedProtocols = (TCG_SUPPORTED_SECURITY_PROTOCOLS*) Buffer;
1414
1415 //
1416 // Get list of supported protocols
1417 //
1418 if (OpalRetrieveSupportedProtocolList (Session, sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS), SupportedProtocols) == TcgResultFailure) {
1419 DEBUG ((DEBUG_INFO, "OpalRetrieveSupportedProtocolList failed\n"));
1420 return TcgResultFailure;
1421 }
1422
1423 SupportedAttributes->Sp1 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_1);
1424 SupportedAttributes->Sp2 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_2);
1425 SupportedAttributes->SpIeee1667 = TcgIsProtocolSupported (SupportedProtocols, TCG_SECURITY_PROTOCOL_IEEE_1667);
1426
1427 DEBUG ((DEBUG_INFO, "Supported Protocols: Sp1 %d Sp2: %d SpIeee1667 %d \n",
1428 SupportedAttributes->Sp1,
1429 SupportedAttributes->Sp2,
1430 SupportedAttributes->SpIeee1667
1431 ));
1432
1433 //
1434 // Perform level 0 discovery and assign desired feature info to Opal Disk structure
1435 //
1436 ZeroMem (Buffer, BUFFER_SIZE);
1437 if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1438 DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1439 return TcgResultFailure;
1440 }
1441
1442 //
1443 // Check for required feature descriptors
1444 //
1445 DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1446
1447 Size = 0;
1448 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V2_0_0, &Size);
1449 SupportedAttributes->OpalSsc2 = (Feat != NULL);
1450
1451 *OpalBaseComId = TCG_RESERVED_COMID;
1452
1453 //
1454 // Check Opal SCC V2 has valid settings for SID C_PIN on revert
1455 //
1456 if (SupportedAttributes->OpalSsc2 && Size >= sizeof (OPAL_SSCV2_FEATURE_DESCRIPTOR)) {
1457 //
1458 // Want opposite polarity b/c Value is greater than a bit, but we only care about non-zero vs zero
1459 //
1460 SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1461 SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1462 DEBUG ((DEBUG_INFO, "Opal SSC V2 InitCpinIndicator %d CpinUponRevert %d \n",
1463 SupportedAttributes->InitCpinIndicator,
1464 SupportedAttributes->CpinUponRevert
1465 ));
1466 *OpalBaseComId = SwapBytes16 (Feat->OpalSscV2.BaseComdIdBE);
1467 }
1468
1469 Size = 0;
1470 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_LITE, &Size);
1471 SupportedAttributes->OpalSscLite = (Feat != NULL);
1472
1473 if (Feat != NULL && Size >= sizeof (OPAL_SSCLITE_FEATURE_DESCRIPTOR)) {
1474 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1475 //
1476 // Pin values used always match up with ComId used
1477 //
1478 *OpalBaseComId = SwapBytes16 (Feat->OpalSscLite.BaseComdIdBE);
1479 SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1480 SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1481 DEBUG ((DEBUG_INFO, "Opal SSC Lite InitCpinIndicator %d CpinUponRevert %d \n",
1482 SupportedAttributes->InitCpinIndicator,
1483 SupportedAttributes->CpinUponRevert
1484 ));
1485 }
1486 }
1487
1488 Size = 0;
1489 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC, &Size);
1490 SupportedAttributes->PyriteSsc = (Feat != NULL);
1491 if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) {
1492 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1493 *OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE);
1494 SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0);
1495 SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0);
1496 DEBUG ((DEBUG_INFO, "Pyrite SSC InitCpinIndicator %d CpinUponRevert %d \n",
1497 SupportedAttributes->InitCpinIndicator,
1498 SupportedAttributes->CpinUponRevert
1499 ));
1500 }
1501 }
1502
1503 Size = 0;
1504 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V1_0_0, &Size);
1505 SupportedAttributes->OpalSsc1 = (Feat != NULL);
1506 if (Feat != NULL && Size >= sizeof (OPAL_SSCV1_FEATURE_DESCRIPTOR)) {
1507 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1508 *OpalBaseComId = SwapBytes16 (Feat->OpalSscV1.BaseComdIdBE);
1509 }
1510 }
1511
1512 Size = 0;
1513 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1514 if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1515 SupportedAttributes->MediaEncryption = Feat->Locking.MediaEncryption;
1516 }
1517
1518 DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId));
1519
1520
1521 return TcgResultSuccess;
1522 }
1523
1524 /**
1525
1526 Get the support attribute info.
1527
1528 @param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1529 @param[in/out] LockingFeature Return the Locking info.
1530
1531 **/
1532 TCG_RESULT
1533 EFIAPI
1534 OpalGetLockingInfo(
1535 OPAL_SESSION *Session,
1536 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1537 )
1538 {
1539 UINT8 Buffer[BUFFER_SIZE];
1540 TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader;
1541 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat;
1542 UINTN Size;
1543
1544 NULL_CHECK(Session);
1545 NULL_CHECK(LockingFeature);
1546
1547 ZeroMem(Buffer, BUFFER_SIZE);
1548 ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1549
1550 if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1551 DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1552 return TcgResultFailure;
1553 }
1554 DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1555
1556 Size = 0;
1557 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1558 if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1559 CopyMem (LockingFeature, &Feat->Locking, sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR));
1560 }
1561
1562 return TcgResultSuccess;
1563 }
1564
1565 /**
1566
1567 The function determines whether or not all of the requirements for the Opal Feature (not full specification)
1568 are met by the specified device.
1569
1570 @param[in] SupportedAttributes Opal device attribute.
1571
1572 **/
1573 BOOLEAN
1574 EFIAPI
1575 OpalFeatureSupported(
1576 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes
1577 )
1578 {
1579 NULL_CHECK(SupportedAttributes);
1580
1581 if (SupportedAttributes->Sp1 == 0) {
1582 return FALSE;
1583 }
1584
1585 if (SupportedAttributes->OpalSscLite == 0 &&
1586 SupportedAttributes->OpalSsc1 == 0 &&
1587 SupportedAttributes->OpalSsc2 == 0 &&
1588 SupportedAttributes->PyriteSsc == 0
1589 ) {
1590 return FALSE;
1591 }
1592
1593 return TRUE;
1594 }
1595
1596 /**
1597
1598 The function returns whether or not the device is Opal Enabled.
1599 TRUE means that the device is partially or fully locked.
1600 This will perform a Level 0 Discovery and parse the locking feature descriptor
1601
1602 @param[in] SupportedAttributes Opal device attribute.
1603 @param[in] LockingFeature Opal device locking status.
1604
1605
1606 **/
1607 BOOLEAN
1608 EFIAPI
1609 OpalFeatureEnabled(
1610 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1611 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1612 )
1613 {
1614 NULL_CHECK(SupportedAttributes);
1615 NULL_CHECK(LockingFeature);
1616
1617 if (!OpalFeatureSupported (SupportedAttributes)) {
1618 return FALSE;
1619 }
1620
1621 if (LockingFeature->LockingSupported && LockingFeature->LockingEnabled) {
1622 return TRUE;
1623 }
1624
1625 return FALSE;
1626 }
1627
1628 /**
1629
1630 The function returns whether or not the device is Opal Locked.
1631 TRUE means that the device is partially or fully locked.
1632 This will perform a Level 0 Discovery and parse the locking feature descriptor
1633
1634 @param[in] SupportedAttributes Opal device attribute.
1635 @param[in] LockingFeature Opal device locking status.
1636
1637 **/
1638 BOOLEAN
1639 OpalDeviceLocked(
1640 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1641 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1642 )
1643 {
1644 NULL_CHECK(SupportedAttributes);
1645 NULL_CHECK(LockingFeature);
1646
1647 if (!OpalFeatureEnabled (SupportedAttributes, LockingFeature)) {
1648 return FALSE;
1649 }
1650
1651 return LockingFeature->Locked;
1652 }
1653