TianoCore EDK2 master
Loading...
Searching...
No Matches
IScsiCHAP.c
Go to the documentation of this file.
1
11#include "IScsiImpl.h"
12
13//
14// Supported CHAP hash algorithms, mapped to sets of BaseCryptLib APIs and
15// macros. CHAP_HASH structures at lower subscripts in the array are preferred
16// by the initiator.
17//
18STATIC CONST CHAP_HASH mChapHash[] = {
19 {
20 ISCSI_CHAP_ALGORITHM_SHA256,
26 },
27 #ifdef ENABLE_MD5_DEPRECATED_INTERFACES
28 //
29 // Keep the deprecated MD5 entry at the end of the array (making MD5 the
30 // least preferred choice of the initiator).
31 //
32 {
33 ISCSI_CHAP_ALGORITHM_MD5,
36 Md5Init,
39 },
40 #endif // ENABLE_MD5_DEPRECATED_INTERFACES
41};
42
43//
44// Ordered list of mChapHash[*].Algorithm values. It is formatted for the
45// CHAP_A=<A1,A2...> value string, by the IScsiCHAPInitHashList() function. It
46// is sent by the initiator in ISCSI_CHAP_STEP_ONE.
47//
48STATIC CHAR8 mChapHashListString[
49 3 + // UINT8 identifier in
50 // decimal
51 (1 + 3) * (ARRAY_SIZE (mChapHash) - 1) + // comma prepended for
52 // entries after the
53 // first
54 1 + // extra character for
55 // AsciiSPrint()
56 // truncation check
57 1 // terminating NUL
58];
59
86 IN UINT32 ChapIdentifier,
87 IN CHAR8 *ChapSecret,
88 IN UINT32 SecretLength,
89 IN UINT8 *ChapChallenge,
90 IN UINT32 ChallengeLength,
91 IN CONST CHAP_HASH *Hash,
92 OUT UINT8 *ChapResponse
93 )
94{
95 UINTN ContextSize;
96 VOID *Ctx;
97 CHAR8 IdByte[1];
98 EFI_STATUS Status;
99
100 if (SecretLength < ISCSI_CHAP_SECRET_MIN_LEN) {
101 return EFI_PROTOCOL_ERROR;
102 }
103
104 ASSERT (Hash != NULL);
105
106 ContextSize = Hash->GetContextSize ();
107 Ctx = AllocatePool (ContextSize);
108 if (Ctx == NULL) {
109 return EFI_OUT_OF_RESOURCES;
110 }
111
112 Status = EFI_PROTOCOL_ERROR;
113
114 if (!Hash->Init (Ctx)) {
115 goto Exit;
116 }
117
118 //
119 // Hash Identifier - Only calculate 1 byte data (RFC1994)
120 //
121 IdByte[0] = (CHAR8)ChapIdentifier;
122 if (!Hash->Update (Ctx, IdByte, 1)) {
123 goto Exit;
124 }
125
126 //
127 // Hash Secret
128 //
129 if (!Hash->Update (Ctx, ChapSecret, SecretLength)) {
130 goto Exit;
131 }
132
133 //
134 // Hash Challenge received from Target
135 //
136 if (!Hash->Update (Ctx, ChapChallenge, ChallengeLength)) {
137 goto Exit;
138 }
139
140 if (Hash->Final (Ctx, ChapResponse)) {
141 Status = EFI_SUCCESS;
142 }
143
144Exit:
145 FreePool (Ctx);
146 return Status;
147}
148
165 IN ISCSI_CHAP_AUTH_DATA *AuthData,
166 IN UINT8 *TargetResponse
167 )
168{
169 EFI_STATUS Status;
170 UINT32 SecretSize;
171 UINT8 VerifyRsp[ISCSI_CHAP_MAX_DIGEST_SIZE];
172 INTN Mismatch;
173
174 Status = EFI_SUCCESS;
175
176 SecretSize = (UINT32)AsciiStrLen (AuthData->AuthConfig->ReverseCHAPSecret);
177
178 ASSERT (AuthData->Hash != NULL);
179
181 AuthData->OutIdentifier,
182 AuthData->AuthConfig->ReverseCHAPSecret,
183 SecretSize,
184 AuthData->OutChallenge,
185 AuthData->Hash->DigestSize, // ChallengeLength
186 AuthData->Hash,
187 VerifyRsp
188 );
189
190 Mismatch = CompareMem (
191 VerifyRsp,
192 TargetResponse,
193 AuthData->Hash->DigestSize
194 );
195 if (Mismatch != 0) {
196 Status = EFI_SECURITY_VIOLATION;
197 }
198
199 return Status;
200}
201
216 IN ISCSI_CONNECTION *Conn
217 )
218{
219 EFI_STATUS Status;
220 ISCSI_SESSION *Session;
221 ISCSI_CHAP_AUTH_DATA *AuthData;
222 CHAR8 *Value;
223 UINT8 *Data;
224 UINT32 Len;
225 LIST_ENTRY *KeyValueList;
226 UINTN Algorithm;
227 CHAR8 *Identifier;
228 CHAR8 *Challenge;
229 CHAR8 *Name;
230 CHAR8 *Response;
231 UINT8 TargetRsp[ISCSI_CHAP_MAX_DIGEST_SIZE];
232 UINT32 RspLen;
233 UINTN Result;
234 UINTN HashIndex;
235
236 ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
237 ASSERT (Conn->RspQue.BufNum != 0);
238
239 Session = Conn->Session;
240 AuthData = &Session->AuthData.CHAP;
241 Len = Conn->RspQue.BufSize;
242 Data = AllocateZeroPool (Len);
243 if (Data == NULL) {
244 return EFI_OUT_OF_RESOURCES;
245 }
246
247 //
248 // Copy the data in case the data spans over multiple PDUs.
249 //
250 NetbufQueCopy (&Conn->RspQue, 0, Len, Data);
251
252 //
253 // Build the key-value list from the data segment of the Login Response.
254 //
255 KeyValueList = IScsiBuildKeyValueList ((CHAR8 *)Data, Len);
256 if (KeyValueList == NULL) {
257 Status = EFI_OUT_OF_RESOURCES;
258 goto ON_EXIT;
259 }
260
261 Status = EFI_PROTOCOL_ERROR;
262
263 switch (Conn->AuthStep) {
264 case ISCSI_AUTH_INITIAL:
265 //
266 // The first Login Response.
267 //
269 KeyValueList,
270 ISCSI_KEY_TARGET_PORTAL_GROUP_TAG
271 );
272 if (Value == NULL) {
273 goto ON_EXIT;
274 }
275
276 Result = IScsiNetNtoi (Value);
277 if (Result > 0xFFFF) {
278 goto ON_EXIT;
279 }
280
281 Session->TargetPortalGroupTag = (UINT16)Result;
282
284 KeyValueList,
285 ISCSI_KEY_AUTH_METHOD
286 );
287 if (Value == NULL) {
288 goto ON_EXIT;
289 }
290
291 //
292 // Initiator mandates CHAP authentication but target replies without
293 // "CHAP", or initiator suggets "None" but target replies with some kind of
294 // auth method.
295 //
296 if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) {
297 if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) != 0) {
298 goto ON_EXIT;
299 }
300 } else if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {
301 if (AsciiStrCmp (Value, ISCSI_AUTH_METHOD_CHAP) != 0) {
302 goto ON_EXIT;
303 }
304 } else {
305 goto ON_EXIT;
306 }
307
308 //
309 // Transit to CHAP step one.
310 //
311 Conn->AuthStep = ISCSI_CHAP_STEP_ONE;
312 Status = EFI_SUCCESS;
313 break;
314
315 case ISCSI_CHAP_STEP_TWO:
316 //
317 // The Target replies with CHAP_A=<A> CHAP_I=<I> CHAP_C=<C>
318 //
320 KeyValueList,
321 ISCSI_KEY_CHAP_ALGORITHM
322 );
323 if (Value == NULL) {
324 goto ON_EXIT;
325 }
326
327 Algorithm = IScsiNetNtoi (Value);
328 for (HashIndex = 0; HashIndex < ARRAY_SIZE (mChapHash); HashIndex++) {
329 if (Algorithm == mChapHash[HashIndex].Algorithm) {
330 break;
331 }
332 }
333
334 if (HashIndex == ARRAY_SIZE (mChapHash)) {
335 //
336 // Unsupported algorithm is chosen by target.
337 //
338 goto ON_EXIT;
339 }
340
341 //
342 // Remember the target's chosen hash algorithm.
343 //
344 ASSERT (AuthData->Hash == NULL);
345 AuthData->Hash = &mChapHash[HashIndex];
346
347 Identifier = IScsiGetValueByKeyFromList (
348 KeyValueList,
349 ISCSI_KEY_CHAP_IDENTIFIER
350 );
351 if (Identifier == NULL) {
352 goto ON_EXIT;
353 }
354
355 Challenge = IScsiGetValueByKeyFromList (
356 KeyValueList,
357 ISCSI_KEY_CHAP_CHALLENGE
358 );
359 if (Challenge == NULL) {
360 goto ON_EXIT;
361 }
362
363 //
364 // Process the CHAP identifier and CHAP Challenge from Target.
365 // Calculate Response value.
366 //
367 Result = IScsiNetNtoi (Identifier);
368 if (Result > 0xFF) {
369 goto ON_EXIT;
370 }
371
372 AuthData->InIdentifier = (UINT32)Result;
373 AuthData->InChallengeLength = (UINT32)sizeof (AuthData->InChallenge);
374 Status = IScsiHexToBin (
375 (UINT8 *)AuthData->InChallenge,
376 &AuthData->InChallengeLength,
377 Challenge
378 );
379 if (EFI_ERROR (Status)) {
380 Status = EFI_PROTOCOL_ERROR;
381 goto ON_EXIT;
382 }
383
385 AuthData->InIdentifier,
386 AuthData->AuthConfig->CHAPSecret,
387 (UINT32)AsciiStrLen (AuthData->AuthConfig->CHAPSecret),
388 AuthData->InChallenge,
389 AuthData->InChallengeLength,
390 AuthData->Hash,
391 AuthData->CHAPResponse
392 );
393
394 //
395 // Transit to next step.
396 //
397 Conn->AuthStep = ISCSI_CHAP_STEP_THREE;
398 break;
399
400 case ISCSI_CHAP_STEP_THREE:
401 //
402 // One way CHAP authentication and the target would like to
403 // authenticate us.
404 //
405 Status = EFI_SUCCESS;
406 break;
407
408 case ISCSI_CHAP_STEP_FOUR:
409 ASSERT (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL);
410 //
411 // The forth step, CHAP_N=<N> CHAP_R=<R> is received from Target.
412 //
413 Name = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_NAME);
414 if (Name == NULL) {
415 goto ON_EXIT;
416 }
417
418 Response = IScsiGetValueByKeyFromList (
419 KeyValueList,
420 ISCSI_KEY_CHAP_RESPONSE
421 );
422 if (Response == NULL) {
423 goto ON_EXIT;
424 }
425
426 ASSERT (AuthData->Hash != NULL);
427 RspLen = AuthData->Hash->DigestSize;
428 Status = IScsiHexToBin (TargetRsp, &RspLen, Response);
429 if (EFI_ERROR (Status) || (RspLen != AuthData->Hash->DigestSize)) {
430 Status = EFI_PROTOCOL_ERROR;
431 goto ON_EXIT;
432 }
433
434 //
435 // Check the CHAP Name and Response replied by Target.
436 //
437 Status = IScsiCHAPAuthTarget (AuthData, TargetRsp);
438 break;
439
440 default:
441 break;
442 }
443
444ON_EXIT:
445
446 if (KeyValueList != NULL) {
447 IScsiFreeKeyValueList (KeyValueList);
448 }
449
450 FreePool (Data);
451
452 return Status;
453}
454
471 IN ISCSI_CONNECTION *Conn,
472 IN OUT NET_BUF *Pdu
473 )
474{
475 EFI_STATUS Status;
476 ISCSI_SESSION *Session;
477 ISCSI_LOGIN_REQUEST *LoginReq;
478 ISCSI_CHAP_AUTH_DATA *AuthData;
479 CHAR8 *Value;
480 CHAR8 ValueStr[256];
481 CHAR8 *Response;
482 UINT32 RspLen;
483 CHAR8 *Challenge;
484 UINT32 ChallengeLen;
485 EFI_STATUS BinToHexStatus;
486
487 ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
488
489 Session = Conn->Session;
490 AuthData = &Session->AuthData.CHAP;
491 LoginReq = (ISCSI_LOGIN_REQUEST *)NetbufGetByte (Pdu, 0, 0);
492 if (LoginReq == NULL) {
493 return EFI_PROTOCOL_ERROR;
494 }
495
496 Status = EFI_SUCCESS;
497
498 RspLen = 2 * ISCSI_CHAP_MAX_DIGEST_SIZE + 3;
499 Response = AllocateZeroPool (RspLen);
500 if (Response == NULL) {
501 return EFI_OUT_OF_RESOURCES;
502 }
503
504 ChallengeLen = 2 * ISCSI_CHAP_MAX_DIGEST_SIZE + 3;
505 Challenge = AllocateZeroPool (ChallengeLen);
506 if (Challenge == NULL) {
507 FreePool (Response);
508 return EFI_OUT_OF_RESOURCES;
509 }
510
511 switch (Conn->AuthStep) {
512 case ISCSI_AUTH_INITIAL:
513 //
514 // It's the initial Login Request. Fill in the key=value pairs mandatory
515 // for the initial Login Request.
516 //
518 Pdu,
519 ISCSI_KEY_INITIATOR_NAME,
520 mPrivate->InitiatorName
521 );
522 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_SESSION_TYPE, "Normal");
524 Pdu,
525 ISCSI_KEY_TARGET_NAME,
526 Session->ConfigData->SessionConfigData.TargetName
527 );
528
529 if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) {
530 Value = ISCSI_KEY_VALUE_NONE;
531 ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
532 } else {
533 Value = ISCSI_AUTH_METHOD_CHAP;
534 }
535
536 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_AUTH_METHOD, Value);
537
538 break;
539
540 case ISCSI_CHAP_STEP_ONE:
541 //
542 // First step, send the Login Request with CHAP_A=<A1,A2...> key-value
543 // pair.
544 //
545 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_ALGORITHM, mChapHashListString);
546
547 Conn->AuthStep = ISCSI_CHAP_STEP_TWO;
548 break;
549
550 case ISCSI_CHAP_STEP_THREE:
551 //
552 // Third step, send the Login Request with CHAP_N=<N> CHAP_R=<R> or
553 // CHAP_N=<N> CHAP_R=<R> CHAP_I=<I> CHAP_C=<C> if target authentication is
554 // required too.
555 //
556 // CHAP_N=<N>
557 //
559 Pdu,
560 ISCSI_KEY_CHAP_NAME,
561 (CHAR8 *)&AuthData->AuthConfig->CHAPName
562 );
563 //
564 // CHAP_R=<R>
565 //
566 ASSERT (AuthData->Hash != NULL);
567 BinToHexStatus = IScsiBinToHex (
568 (UINT8 *)AuthData->CHAPResponse,
569 AuthData->Hash->DigestSize,
570 Response,
571 &RspLen
572 );
573 ASSERT_EFI_ERROR (BinToHexStatus);
574 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response);
575
576 if (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
577 //
578 // CHAP_I=<I>
579 //
580 Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
581 if (EFI_ERROR (Status)) {
582 break;
583 }
584
585 AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
586 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
587 //
588 // CHAP_C=<C>
589 //
590 Status = IScsiGenRandom (
591 (UINT8 *)AuthData->OutChallenge,
592 AuthData->Hash->DigestSize
593 );
594 if (EFI_ERROR (Status)) {
595 break;
596 }
597
598 BinToHexStatus = IScsiBinToHex (
599 (UINT8 *)AuthData->OutChallenge,
600 AuthData->Hash->DigestSize,
601 Challenge,
602 &ChallengeLen
603 );
604 ASSERT_EFI_ERROR (BinToHexStatus);
605 IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge);
606
607 Conn->AuthStep = ISCSI_CHAP_STEP_FOUR;
608 }
609
610 //
611 // Set the stage transition flag.
612 //
613 ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
614 break;
615
616 default:
617 Status = EFI_PROTOCOL_ERROR;
618 break;
619 }
620
621 FreePool (Response);
622 FreePool (Challenge);
623
624 return Status;
625}
626
634VOID
636 VOID
637 )
638{
639 CHAR8 *Position;
640 UINTN Left;
641 UINTN HashIndex;
642 CONST CHAP_HASH *Hash;
643 UINTN Printed;
644
645 Position = mChapHashListString;
646 Left = sizeof (mChapHashListString);
647 for (HashIndex = 0; HashIndex < ARRAY_SIZE (mChapHash); HashIndex++) {
648 Hash = &mChapHash[HashIndex];
649
650 //
651 // Format the next hash identifier.
652 //
653 // Assert that we can format at least one non-NUL character, i.e. that we
654 // can progress. Truncation is checked after printing.
655 //
656 ASSERT (Left >= 2);
657 Printed = AsciiSPrint (
658 Position,
659 Left,
660 "%a%d",
661 (HashIndex == 0) ? "" : ",",
662 Hash->Algorithm
663 );
664 //
665 // There's no way to differentiate between the "buffer filled to the brim,
666 // but not truncated" result and the "truncated" result of AsciiSPrint().
667 // This is why "mChapHashListString" has an extra byte allocated, and the
668 // reason why we use the less-than (rather than the less-than-or-equal-to)
669 // relational operator in the assertion below -- we enforce "no truncation"
670 // by excluding the "completely used up" case too.
671 //
672 ASSERT (Printed + 1 < Left);
673
674 Position += Printed;
675 Left -= Printed;
676
677 //
678 // Sanity-check the digest size for Hash.
679 //
680 ASSERT (Hash->DigestSize <= ISCSI_CHAP_MAX_DIGEST_SIZE);
681 }
682}
UINT64 UINTN
INT64 INTN
UINTN EFIAPI Sha256GetContextSize(VOID)
Definition: CryptSha256.c:20
BOOLEAN EFIAPI Sha256Init(OUT VOID *Sha256Context)
Definition: CryptSha256.c:44
BOOLEAN EFIAPI Sha256Final(IN OUT VOID *Sha256Context, OUT UINT8 *HashValue)
Definition: CryptSha256.c:161
#define SHA256_DIGEST_SIZE
Definition: BaseCryptLib.h:44
BOOLEAN EFIAPI Sha256Update(IN OUT VOID *Sha256Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha256.c:113
#define MD5_DIGEST_SIZE
Definition: BaseCryptLib.h:34
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
BOOLEAN EFIAPI Md5Final(IN OUT VOID *Md5Context, OUT UINT8 *HashValue)
Definition: CryptMd5Null.c:126
BOOLEAN EFIAPI Md5Update(IN OUT VOID *Md5Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptMd5Null.c:94
BOOLEAN EFIAPI Md5Init(OUT VOID *Md5Context)
Definition: CryptMd5Null.c:42
UINTN EFIAPI Md5GetContextSize(VOID)
Definition: CryptMd5Null.c:20
EFI_STATUS IScsiCHAPAuthTarget(IN ISCSI_CHAP_AUTH_DATA *AuthData, IN UINT8 *TargetResponse)
Definition: IScsiCHAP.c:164
EFI_STATUS IScsiCHAPToSendReq(IN ISCSI_CONNECTION *Conn, IN OUT NET_BUF *Pdu)
Definition: IScsiCHAP.c:470
VOID IScsiCHAPInitHashList(VOID)
Definition: IScsiCHAP.c:635
EFI_STATUS IScsiCHAPOnRspReceived(IN ISCSI_CONNECTION *Conn)
Definition: IScsiCHAP.c:215
EFI_STATUS IScsiCHAPCalculateResponse(IN UINT32 ChapIdentifier, IN CHAR8 *ChapSecret, IN UINT32 SecretLength, IN UINT8 *ChapChallenge, IN UINT32 ChallengeLength, IN CONST CHAP_HASH *Hash, OUT UINT8 *ChapResponse)
Definition: IScsiCHAP.c:85
UINTN IScsiNetNtoi(IN CHAR8 *Str)
Definition: IScsiMisc.c:459
EFI_STATUS IScsiHexToBin(IN OUT UINT8 *BinBuffer, IN OUT UINT32 *BinLength, IN CHAR8 *HexStr)
Definition: IScsiMisc.c:385
EFI_STATUS IScsiGenRandom(IN OUT UINT8 *Rand, IN UINTN RandLength)
Definition: IScsiMisc.c:483
EFI_STATUS IScsiBinToHex(IN UINT8 *BinBuffer, IN UINT32 BinLength, IN OUT CHAR8 *HexStr, IN OUT UINT32 *HexLength)
Definition: IScsiMisc.c:322
VOID IScsiFreeKeyValueList(IN LIST_ENTRY *KeyValueList)
Definition: IScsiProto.c:1978
CHAR8 * IScsiGetValueByKeyFromList(IN OUT LIST_ENTRY *KeyValueList, IN CHAR8 *Key)
Definition: IScsiProto.c:1945
LIST_ENTRY * IScsiBuildKeyValueList(IN CHAR8 *Data, IN UINT32 Len)
Definition: IScsiProto.c:1876
EFI_STATUS IScsiAddKeyValuePair(IN OUT NET_BUF *Pdu, IN CHAR8 *Key, IN CHAR8 *Value)
Definition: IScsiProto.c:677
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
Definition: PrintLib.c:813
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
UINT32 EFIAPI NetbufQueCopy(IN NET_BUF_QUEUE *NbufQue, IN UINT32 Offset, IN UINT32 Len, OUT UINT8 *Dest)
Definition: NetBuffer.c:1438
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112