1 /** @file 2 The implementation of IPSEC_CONFIG_PROTOCOL. 3 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "IpSecConfigImpl.h" 17 #include "IpSecDebug.h" 18 19 LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum]; 20 BOOLEAN mSetBySelf = FALSE; 21 22 // 23 // Common CompareSelector routine entry for SPD/SAD/PAD. 24 // 25 IPSEC_COMPARE_SELECTOR mCompareSelector[] = { 26 (IPSEC_COMPARE_SELECTOR) CompareSpdSelector, 27 (IPSEC_COMPARE_SELECTOR) CompareSaId, 28 (IPSEC_COMPARE_SELECTOR) ComparePadId 29 }; 30 31 // 32 // Common IsZeroSelector routine entry for SPD/SAD/PAD. 33 // 34 IPSEC_IS_ZERO_SELECTOR mIsZeroSelector[] = { 35 (IPSEC_IS_ZERO_SELECTOR) IsZeroSpdSelector, 36 (IPSEC_IS_ZERO_SELECTOR) IsZeroSaId, 37 (IPSEC_IS_ZERO_SELECTOR) IsZeroPadId 38 }; 39 40 // 41 // Common DuplicateSelector routine entry for SPD/SAD/PAD. 42 // 43 IPSEC_DUPLICATE_SELECTOR mDuplicateSelector[] = { 44 (IPSEC_DUPLICATE_SELECTOR) DuplicateSpdSelector, 45 (IPSEC_DUPLICATE_SELECTOR) DuplicateSaId, 46 (IPSEC_DUPLICATE_SELECTOR) DuplicatePadId 47 }; 48 49 // 50 // Common FixPolicyEntry routine entry for SPD/SAD/PAD. 51 // 52 IPSEC_FIX_POLICY_ENTRY mFixPolicyEntry[] = { 53 (IPSEC_FIX_POLICY_ENTRY) FixSpdEntry, 54 (IPSEC_FIX_POLICY_ENTRY) FixSadEntry, 55 (IPSEC_FIX_POLICY_ENTRY) FixPadEntry 56 }; 57 58 // 59 // Common UnfixPolicyEntry routine entry for SPD/SAD/PAD. 60 // 61 IPSEC_FIX_POLICY_ENTRY mUnfixPolicyEntry[] = { 62 (IPSEC_FIX_POLICY_ENTRY) UnfixSpdEntry, 63 (IPSEC_FIX_POLICY_ENTRY) UnfixSadEntry, 64 (IPSEC_FIX_POLICY_ENTRY) UnfixPadEntry 65 }; 66 67 // 68 // Common SetPolicyEntry routine entry for SPD/SAD/PAD. 69 // 70 IPSEC_SET_POLICY_ENTRY mSetPolicyEntry[] = { 71 (IPSEC_SET_POLICY_ENTRY) SetSpdEntry, 72 (IPSEC_SET_POLICY_ENTRY) SetSadEntry, 73 (IPSEC_SET_POLICY_ENTRY) SetPadEntry 74 }; 75 76 // 77 // Common GetPolicyEntry routine entry for SPD/SAD/PAD. 78 // 79 IPSEC_GET_POLICY_ENTRY mGetPolicyEntry[] = { 80 (IPSEC_GET_POLICY_ENTRY) GetSpdEntry, 81 (IPSEC_GET_POLICY_ENTRY) GetSadEntry, 82 (IPSEC_GET_POLICY_ENTRY) GetPadEntry 83 }; 84 85 // 86 // Routine entry for IpSecConfig protocol. 87 // 88 EFI_IPSEC_CONFIG_PROTOCOL mIpSecConfigInstance = { 89 EfiIpSecConfigSetData, 90 EfiIpSecConfigGetData, 91 EfiIpSecConfigGetNextSelector, 92 EfiIpSecConfigRegisterNotify, 93 EfiIpSecConfigUnregisterNotify 94 }; 95 96 /** 97 Get the all IPSec configuration variables and store those variables 98 to the internal data structure. 99 100 This founction is called by IpSecConfigInitialize() that is to intialize the 101 IPsecConfiguration Protocol. 102 103 @param[in] Private Point to IPSEC_PRIVATE_DATA. 104 105 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated. 106 @retval EFI_SUCCESS Restore the IPsec Configuration successfully. 107 @retval others Other errors is found during the variable getting. 108 109 **/ 110 EFI_STATUS 111 IpSecConfigRestore ( 112 IN IPSEC_PRIVATE_DATA *Private 113 ); 114 115 /** 116 Check if the specified EFI_IP_ADDRESS_INFO is in EFI_IP_ADDRESS_INFO list. 117 118 @param[in] AddressInfo Pointer of IP_ADDRESS_INFO to be search in AddressInfo list. 119 @param[in] AddressInfoList A list that contains IP_ADDRESS_INFOs. 120 @param[in] AddressCount Point out how many IP_ADDRESS_INFO in the list. 121 122 @retval TRUE The specified AddressInfo is in the AddressInfoList. 123 @retval FALSE The specified AddressInfo is not in the AddressInfoList. 124 125 **/ 126 BOOLEAN 127 IsInAddressInfoList( 128 IN EFI_IP_ADDRESS_INFO *AddressInfo, 129 IN EFI_IP_ADDRESS_INFO *AddressInfoList, 130 IN UINT32 AddressCount 131 ) 132 { 133 UINT8 Index; 134 EFI_IP_ADDRESS ZeroAddress; 135 136 ZeroMem(&ZeroAddress, sizeof (EFI_IP_ADDRESS)); 137 138 // 139 // Zero Address means any address is matched. 140 // 141 if (AddressCount == 1) { 142 if (CompareMem ( 143 &AddressInfoList[0].Address, 144 &ZeroAddress, 145 sizeof (EFI_IP_ADDRESS) 146 ) == 0) { 147 return TRUE; 148 } 149 } 150 for (Index = 0; Index < AddressCount ; Index++) { 151 if (CompareMem ( 152 AddressInfo, 153 &AddressInfoList[Index].Address, 154 sizeof (EFI_IP_ADDRESS) 155 ) == 0 && 156 AddressInfo->PrefixLength == AddressInfoList[Index].PrefixLength 157 ) { 158 return TRUE; 159 } 160 } 161 return FALSE; 162 } 163 164 /** 165 Compare two SPD Selectors. 166 167 Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/ 168 NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the 169 Local Addresses and remote Addresses. 170 171 @param[in] Selector1 Pointer of first SPD Selector. 172 @param[in] Selector2 Pointer of second SPD Selector. 173 174 @retval TRUE This two Selector have the same value in above fields. 175 @retval FALSE Not all above fields have the same value in these two Selectors. 176 177 **/ 178 BOOLEAN 179 CompareSpdSelector ( 180 IN EFI_IPSEC_CONFIG_SELECTOR *Selector1, 181 IN EFI_IPSEC_CONFIG_SELECTOR *Selector2 182 ) 183 { 184 EFI_IPSEC_SPD_SELECTOR *SpdSel1; 185 EFI_IPSEC_SPD_SELECTOR *SpdSel2; 186 BOOLEAN IsMatch; 187 UINTN Index; 188 189 SpdSel1 = &Selector1->SpdSelector; 190 SpdSel2 = &Selector2->SpdSelector; 191 IsMatch = TRUE; 192 193 // 194 // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/ 195 // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the 196 // two Spdselectors. Since the SPD supports two directions, it needs to 197 // compare two directions. 198 // 199 if ((SpdSel1->LocalAddressCount != SpdSel2->LocalAddressCount && 200 SpdSel1->LocalAddressCount != SpdSel2->RemoteAddressCount) || 201 (SpdSel1->RemoteAddressCount != SpdSel2->RemoteAddressCount && 202 SpdSel1->RemoteAddressCount != SpdSel2->LocalAddressCount) || 203 SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol || 204 SpdSel1->LocalPort != SpdSel2->LocalPort || 205 SpdSel1->LocalPortRange != SpdSel2->LocalPortRange || 206 SpdSel1->RemotePort != SpdSel2->RemotePort || 207 SpdSel1->RemotePortRange != SpdSel2->RemotePortRange 208 ) { 209 IsMatch = FALSE; 210 return IsMatch; 211 } 212 213 // 214 // Compare the all LocalAddress fields in the two Spdselectors. 215 // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare 216 // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return 217 // TRUE. 218 // 219 for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) { 220 if (!IsInAddressInfoList ( 221 &SpdSel1->LocalAddress[Index], 222 SpdSel2->LocalAddress, 223 SpdSel2->LocalAddressCount 224 )) { 225 IsMatch = FALSE; 226 break; 227 } 228 } 229 if (IsMatch) { 230 for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) { 231 if (!IsInAddressInfoList ( 232 &SpdSel2->LocalAddress[Index], 233 SpdSel1->LocalAddress, 234 SpdSel1->LocalAddressCount 235 )) { 236 IsMatch = FALSE; 237 break; 238 } 239 } 240 } 241 if (IsMatch) { 242 for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) { 243 if (!IsInAddressInfoList ( 244 &SpdSel1->RemoteAddress[Index], 245 SpdSel2->RemoteAddress, 246 SpdSel2->RemoteAddressCount 247 )) { 248 IsMatch = FALSE; 249 break; 250 } 251 } 252 } 253 if (IsMatch) { 254 for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) { 255 if (!IsInAddressInfoList ( 256 &SpdSel2->RemoteAddress[Index], 257 SpdSel1->RemoteAddress, 258 SpdSel1->RemoteAddressCount 259 )) { 260 IsMatch = FALSE; 261 break; 262 } 263 } 264 } 265 // 266 // Finish the one direction compare. If it is matched, return; otherwise, 267 // compare the other direction. 268 // 269 if (IsMatch) { 270 return IsMatch; 271 } 272 // 273 // Secondly, the SpdSel1->LocalAddress doesn't equal to SpdSel2->LocalAddress and 274 // SpdSel1->RemoteAddress doesn't equal to SpdSel2->RemoteAddress. Try to compare 275 // the RemoteAddress to LocalAddress. 276 // 277 IsMatch = TRUE; 278 for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) { 279 if (!IsInAddressInfoList ( 280 &SpdSel1->RemoteAddress[Index], 281 SpdSel2->LocalAddress, 282 SpdSel2->LocalAddressCount 283 )) { 284 IsMatch = FALSE; 285 break; 286 } 287 } 288 if (IsMatch) { 289 for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) { 290 if (!IsInAddressInfoList ( 291 &SpdSel2->RemoteAddress[Index], 292 SpdSel1->LocalAddress, 293 SpdSel1->LocalAddressCount 294 )) { 295 IsMatch = FALSE; 296 break; 297 } 298 } 299 } 300 if (IsMatch) { 301 for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) { 302 if (!IsInAddressInfoList ( 303 &SpdSel1->LocalAddress[Index], 304 SpdSel2->RemoteAddress, 305 SpdSel2->RemoteAddressCount 306 )) { 307 IsMatch = FALSE; 308 break; 309 } 310 } 311 } 312 if (IsMatch) { 313 for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) { 314 if (!IsInAddressInfoList ( 315 &SpdSel2->LocalAddress[Index], 316 SpdSel1->RemoteAddress, 317 SpdSel1->RemoteAddressCount 318 )) { 319 IsMatch = FALSE; 320 break; 321 } 322 } 323 } 324 return IsMatch; 325 } 326 327 /** 328 Find if the two SPD Selectors has subordinative. 329 330 Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/ 331 NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the 332 Local Addresses and remote Addresses. 333 334 @param[in] Selector1 Pointer of first SPD Selector. 335 @param[in] Selector2 Pointer of second SPD Selector. 336 337 @retval TRUE The first SPD Selector is subordinate Selector of second SPD Selector. 338 @retval FALSE The first SPD Selector is not subordinate Selector of second 339 SPD Selector. 340 341 **/ 342 BOOLEAN 343 IsSubSpdSelector ( 344 IN EFI_IPSEC_CONFIG_SELECTOR *Selector1, 345 IN EFI_IPSEC_CONFIG_SELECTOR *Selector2 346 ) 347 { 348 EFI_IPSEC_SPD_SELECTOR *SpdSel1; 349 EFI_IPSEC_SPD_SELECTOR *SpdSel2; 350 BOOLEAN IsMatch; 351 UINTN Index; 352 353 SpdSel1 = &Selector1->SpdSelector; 354 SpdSel2 = &Selector2->SpdSelector; 355 IsMatch = TRUE; 356 357 // 358 // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/ 359 // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the 360 // two Spdselectors. Since the SPD supports two directions, it needs to 361 // compare two directions. 362 // 363 if (SpdSel1->LocalAddressCount > SpdSel2->LocalAddressCount || 364 SpdSel1->RemoteAddressCount > SpdSel2->RemoteAddressCount || 365 (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) || 366 (SpdSel1->LocalPort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0)|| 367 (SpdSel1->LocalPortRange > SpdSel2->LocalPortRange && SpdSel1->LocalPort != 0)|| 368 (SpdSel1->RemotePort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0) || 369 (SpdSel1->RemotePortRange > SpdSel2->RemotePortRange && SpdSel2->RemotePort != 0) 370 ) { 371 IsMatch = FALSE; 372 } 373 374 // 375 // Compare the all LocalAddress fields in the two Spdselectors. 376 // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare 377 // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return 378 // TRUE. 379 // 380 if (IsMatch) { 381 for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) { 382 if (!IsInAddressInfoList ( 383 &SpdSel1->LocalAddress[Index], 384 SpdSel2->LocalAddress, 385 SpdSel2->LocalAddressCount 386 )) { 387 IsMatch = FALSE; 388 break; 389 } 390 } 391 392 if (IsMatch) { 393 for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) { 394 if (!IsInAddressInfoList ( 395 &SpdSel1->RemoteAddress[Index], 396 SpdSel2->RemoteAddress, 397 SpdSel2->RemoteAddressCount 398 )) { 399 IsMatch = FALSE; 400 break; 401 } 402 } 403 } 404 } 405 if (IsMatch) { 406 return IsMatch; 407 } 408 409 // 410 // 411 // The SPD selector in SPD entry is two way. 412 // 413 // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/ 414 // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the 415 // two Spdselectors. Since the SPD supports two directions, it needs to 416 // compare two directions. 417 // 418 IsMatch = TRUE; 419 if (SpdSel1->LocalAddressCount > SpdSel2->RemoteAddressCount || 420 SpdSel1->RemoteAddressCount > SpdSel2->LocalAddressCount || 421 (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) || 422 (SpdSel1->LocalPort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0)|| 423 (SpdSel1->LocalPortRange > SpdSel2->RemotePortRange && SpdSel1->RemotePort != 0)|| 424 (SpdSel1->RemotePort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0) || 425 (SpdSel1->RemotePortRange > SpdSel2->LocalPortRange && SpdSel2->LocalPort != 0) 426 ) { 427 IsMatch = FALSE; 428 return IsMatch; 429 } 430 431 // 432 // Compare the all LocalAddress fields in the two Spdselectors. 433 // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare 434 // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return 435 // TRUE. 436 // 437 for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) { 438 if (!IsInAddressInfoList ( 439 &SpdSel1->LocalAddress[Index], 440 SpdSel2->RemoteAddress, 441 SpdSel2->RemoteAddressCount 442 )) { 443 IsMatch = FALSE; 444 break; 445 } 446 } 447 448 if (IsMatch) { 449 for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) { 450 if (!IsInAddressInfoList ( 451 &SpdSel1->RemoteAddress[Index], 452 SpdSel2->LocalAddress, 453 SpdSel2->LocalAddressCount 454 )) { 455 IsMatch = FALSE; 456 break; 457 } 458 } 459 } 460 return IsMatch; 461 462 } 463 464 /** 465 Compare two SA IDs. 466 467 @param[in] Selector1 Pointer of first SA ID. 468 @param[in] Selector2 Pointer of second SA ID. 469 470 @retval TRUE This two Selectors have the same SA ID. 471 @retval FALSE This two Selecotrs don't have the same SA ID. 472 473 **/ 474 BOOLEAN 475 CompareSaId ( 476 IN EFI_IPSEC_CONFIG_SELECTOR *Selector1, 477 IN EFI_IPSEC_CONFIG_SELECTOR *Selector2 478 ) 479 { 480 EFI_IPSEC_SA_ID *SaId1; 481 EFI_IPSEC_SA_ID *SaId2; 482 BOOLEAN IsMatch; 483 484 SaId1 = &Selector1->SaId; 485 SaId2 = &Selector2->SaId; 486 IsMatch = TRUE; 487 488 if (CompareMem (SaId1, SaId2, sizeof (EFI_IPSEC_SA_ID)) != 0) { 489 IsMatch = FALSE; 490 } 491 492 return IsMatch; 493 } 494 495 /** 496 Compare two PAD IDs. 497 498 @param[in] Selector1 Pointer of first PAD ID. 499 @param[in] Selector2 Pointer of second PAD ID. 500 501 @retval TRUE This two Selectors have the same PAD ID. 502 @retval FALSE This two Selecotrs don't have the same PAD ID. 503 504 **/ 505 BOOLEAN 506 ComparePadId ( 507 IN EFI_IPSEC_CONFIG_SELECTOR *Selector1, 508 IN EFI_IPSEC_CONFIG_SELECTOR *Selector2 509 ) 510 { 511 EFI_IPSEC_PAD_ID *PadId1; 512 EFI_IPSEC_PAD_ID *PadId2; 513 BOOLEAN IsMatch; 514 515 PadId1 = &Selector1->PadId; 516 PadId2 = &Selector2->PadId; 517 IsMatch = TRUE; 518 519 // 520 // Compare the PeerIdValid fields in PadId. 521 // 522 if (PadId1->PeerIdValid != PadId2->PeerIdValid) { 523 IsMatch = FALSE; 524 } 525 // 526 // Compare the PeerId fields in PadId if PeerIdValid is true. 527 // 528 if (IsMatch && 529 PadId1->PeerIdValid && 530 AsciiStriCmp ((CONST CHAR8 *) PadId1->Id.PeerId, (CONST CHAR8 *) PadId2->Id.PeerId) != 0 531 ) { 532 IsMatch = FALSE; 533 } 534 // 535 // Compare the IpAddress fields in PadId if PeerIdValid is false. 536 // 537 if (IsMatch && 538 !PadId1->PeerIdValid && 539 (PadId1->Id.IpAddress.PrefixLength != PadId2->Id.IpAddress.PrefixLength || 540 CompareMem (&PadId1->Id.IpAddress.Address, &PadId2->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0) 541 ) { 542 IsMatch = FALSE; 543 } 544 545 return IsMatch; 546 } 547 548 /** 549 Check if the SPD Selector is Zero by its LocalAddressCount and RemoteAddressCount 550 fields. 551 552 @param[in] Selector Pointer of the SPD Selector. 553 554 @retval TRUE If the SPD Selector is Zero. 555 @retval FALSE If the SPD Selector is not Zero. 556 557 **/ 558 BOOLEAN 559 IsZeroSpdSelector ( 560 IN EFI_IPSEC_CONFIG_SELECTOR *Selector 561 ) 562 { 563 EFI_IPSEC_SPD_SELECTOR *SpdSel; 564 BOOLEAN IsZero; 565 566 SpdSel = &Selector->SpdSelector; 567 IsZero = FALSE; 568 569 if (SpdSel->LocalAddressCount == 0 && SpdSel->RemoteAddressCount == 0) { 570 IsZero = TRUE; 571 } 572 573 return IsZero; 574 } 575 576 /** 577 Check if the SA ID is Zero by its DestAddress. 578 579 @param[in] Selector Pointer of the SA ID. 580 581 @retval TRUE If the SA ID is Zero. 582 @retval FALSE If the SA ID is not Zero. 583 584 **/ 585 BOOLEAN 586 IsZeroSaId ( 587 IN EFI_IPSEC_CONFIG_SELECTOR *Selector 588 ) 589 { 590 BOOLEAN IsZero; 591 EFI_IPSEC_CONFIG_SELECTOR ZeroSelector; 592 593 IsZero = FALSE; 594 595 ZeroMem (&ZeroSelector, sizeof (EFI_IPSEC_CONFIG_SELECTOR)); 596 597 if (CompareMem (&ZeroSelector, Selector, sizeof (EFI_IPSEC_CONFIG_SELECTOR)) == 0) { 598 IsZero = TRUE; 599 } 600 601 return IsZero; 602 } 603 604 /** 605 Check if the PAD ID is Zero. 606 607 @param[in] Selector Pointer of the PAD ID. 608 609 @retval TRUE If the PAD ID is Zero. 610 @retval FALSE If the PAD ID is not Zero. 611 612 **/ 613 BOOLEAN 614 IsZeroPadId ( 615 IN EFI_IPSEC_CONFIG_SELECTOR *Selector 616 ) 617 { 618 EFI_IPSEC_PAD_ID *PadId; 619 EFI_IPSEC_PAD_ID ZeroId; 620 BOOLEAN IsZero; 621 622 PadId = &Selector->PadId; 623 IsZero = FALSE; 624 625 ZeroMem (&ZeroId, sizeof (EFI_IPSEC_PAD_ID)); 626 627 if (CompareMem (PadId, &ZeroId, sizeof (EFI_IPSEC_PAD_ID)) == 0) { 628 IsZero = TRUE; 629 } 630 631 return IsZero; 632 } 633 634 /** 635 Copy Source SPD Selector to the Destination SPD Selector. 636 637 @param[in, out] DstSel Pointer of Destination SPD Selector. 638 @param[in] SrcSel Pointer of Source SPD Selector. 639 @param[in, out] Size The size of the Destination SPD Selector. If it 640 not NULL and its value less than the size of 641 Source SPD Selector, the value of Source SPD 642 Selector's size will be passed to caller by this 643 parameter. 644 645 @retval EFI_INVALID_PARAMETER If the Destination or Source SPD Selector is NULL 646 @retval EFI_BUFFER_TOO_SMALL If the input Size is less than size of the Source SPD Selector. 647 @retval EFI_SUCCESS Copy Source SPD Selector to the Destination SPD 648 Selector successfully. 649 650 **/ 651 EFI_STATUS 652 DuplicateSpdSelector ( 653 IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel, 654 IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel, 655 IN OUT UINTN *Size 656 ) 657 { 658 EFI_IPSEC_SPD_SELECTOR *Dst; 659 EFI_IPSEC_SPD_SELECTOR *Src; 660 661 Dst = &DstSel->SpdSelector; 662 Src = &SrcSel->SpdSelector; 663 664 if (Dst == NULL || Src == NULL) { 665 return EFI_INVALID_PARAMETER; 666 } 667 668 if (Size != NULL && (*Size) < SIZE_OF_SPD_SELECTOR (Src)) { 669 *Size = SIZE_OF_SPD_SELECTOR (Src); 670 return EFI_BUFFER_TOO_SMALL; 671 } 672 // 673 // Copy the base structure of SPD selector. 674 // 675 CopyMem (Dst, Src, sizeof (EFI_IPSEC_SPD_SELECTOR)); 676 677 // 678 // Copy the local address array of SPD selector. 679 // 680 Dst->LocalAddress = (EFI_IP_ADDRESS_INFO *) (Dst + 1); 681 CopyMem ( 682 Dst->LocalAddress, 683 Src->LocalAddress, 684 sizeof (EFI_IP_ADDRESS_INFO) * Dst->LocalAddressCount 685 ); 686 687 // 688 // Copy the remote address array of SPD selector. 689 // 690 Dst->RemoteAddress = Dst->LocalAddress + Dst->LocalAddressCount; 691 CopyMem ( 692 Dst->RemoteAddress, 693 Src->RemoteAddress, 694 sizeof (EFI_IP_ADDRESS_INFO) * Dst->RemoteAddressCount 695 ); 696 697 return EFI_SUCCESS; 698 } 699 700 /** 701 Copy Source SA ID to the Destination SA ID. 702 703 @param[in, out] DstSel Pointer of Destination SA ID. 704 @param[in] SrcSel Pointer of Source SA ID. 705 @param[in, out] Size The size of the Destination SA ID. If it 706 not NULL and its value less than the size of 707 Source SA ID, the value of Source SA ID's size 708 will be passed to caller by this parameter. 709 710 @retval EFI_INVALID_PARAMETER If the Destination or Source SA ID is NULL. 711 @retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source SA ID. 712 @retval EFI_SUCCESS Copy Source SA ID to the Destination SA ID successfully. 713 714 **/ 715 EFI_STATUS 716 DuplicateSaId ( 717 IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel, 718 IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel, 719 IN OUT UINTN *Size 720 ) 721 { 722 EFI_IPSEC_SA_ID *Dst; 723 EFI_IPSEC_SA_ID *Src; 724 725 Dst = &DstSel->SaId; 726 Src = &SrcSel->SaId; 727 728 if (Dst == NULL || Src == NULL) { 729 return EFI_INVALID_PARAMETER; 730 } 731 732 if (Size != NULL && *Size < sizeof (EFI_IPSEC_SA_ID)) { 733 *Size = sizeof (EFI_IPSEC_SA_ID); 734 return EFI_BUFFER_TOO_SMALL; 735 } 736 737 CopyMem (Dst, Src, sizeof (EFI_IPSEC_SA_ID)); 738 739 return EFI_SUCCESS; 740 } 741 742 /** 743 Copy Source PAD ID to the Destination PAD ID. 744 745 @param[in, out] DstSel Pointer of Destination PAD ID. 746 @param[in] SrcSel Pointer of Source PAD ID. 747 @param[in, out] Size The size of the Destination PAD ID. If it 748 not NULL and its value less than the size of 749 Source PAD ID, the value of Source PAD ID's size 750 will be passed to caller by this parameter. 751 752 @retval EFI_INVALID_PARAMETER If the Destination or Source PAD ID is NULL. 753 @retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source PAD ID . 754 @retval EFI_SUCCESS Copy Source PAD ID to the Destination PAD ID successfully. 755 756 **/ 757 EFI_STATUS 758 DuplicatePadId ( 759 IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel, 760 IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel, 761 IN OUT UINTN *Size 762 ) 763 { 764 EFI_IPSEC_PAD_ID *Dst; 765 EFI_IPSEC_PAD_ID *Src; 766 767 Dst = &DstSel->PadId; 768 Src = &SrcSel->PadId; 769 770 if (Dst == NULL || Src == NULL) { 771 return EFI_INVALID_PARAMETER; 772 } 773 774 if (Size != NULL && *Size < sizeof (EFI_IPSEC_PAD_ID)) { 775 *Size = sizeof (EFI_IPSEC_PAD_ID); 776 return EFI_BUFFER_TOO_SMALL; 777 } 778 779 CopyMem (Dst, Src, sizeof (EFI_IPSEC_PAD_ID)); 780 781 return EFI_SUCCESS; 782 } 783 784 /** 785 Fix the value of some members of SPD Selector. 786 787 This function is called by IpSecCopyPolicyEntry()which copy the Policy 788 Entry into the Variable. Since some members in SPD Selector are pointers, 789 a physical address to relative address convertion is required before copying 790 this SPD entry into the variable. 791 792 @param[in] Selector Pointer of SPD Selector. 793 @param[in, out] Data Pointer of SPD Data. 794 795 **/ 796 VOID 797 FixSpdEntry ( 798 IN EFI_IPSEC_SPD_SELECTOR *Selector, 799 IN OUT EFI_IPSEC_SPD_DATA *Data 800 ) 801 { 802 // 803 // It assumes that all ref buffers in SPD selector and data are 804 // stored in the continous memory and close to the base structure. 805 // 806 FIX_REF_BUF_ADDR (Selector->LocalAddress, Selector); 807 FIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector); 808 809 if (Data->ProcessingPolicy != NULL) { 810 if (Data->ProcessingPolicy->TunnelOption != NULL) { 811 FIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data); 812 } 813 814 FIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data); 815 } 816 817 } 818 819 /** 820 Fix the value of some members of SA ID. 821 822 This function is called by IpSecCopyPolicyEntry()which copy the Policy 823 Entry into the Variable. Since some members in SA ID are pointers, 824 a physical address to relative address conversion is required before copying 825 this SAD into the variable. 826 827 @param[in] SaId Pointer of SA ID 828 @param[in, out] Data Pointer of SA Data. 829 830 **/ 831 VOID 832 FixSadEntry ( 833 IN EFI_IPSEC_SA_ID *SaId, 834 IN OUT EFI_IPSEC_SA_DATA2 *Data 835 ) 836 { 837 // 838 // It assumes that all ref buffers in SAD selector and data are 839 // stored in the continous memory and close to the base structure. 840 // 841 if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) { 842 FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data); 843 } 844 845 if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) { 846 FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data); 847 } 848 849 if (Data->SpdSelector != NULL) { 850 if (Data->SpdSelector->LocalAddress != NULL) { 851 FIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data); 852 } 853 854 FIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data); 855 FIX_REF_BUF_ADDR (Data->SpdSelector, Data); 856 } 857 858 } 859 860 /** 861 Fix the value of some members of PAD ID. 862 863 This function is called by IpSecCopyPolicyEntry()which copy the Policy 864 Entry into the Variable. Since some members in PAD ID are pointers, 865 a physical address to relative address conversion is required before copying 866 this PAD into the variable. 867 868 @param[in] PadId Pointer of PAD ID. 869 @param[in, out] Data Pointer of PAD Data. 870 871 **/ 872 VOID 873 FixPadEntry ( 874 IN EFI_IPSEC_PAD_ID *PadId, 875 IN OUT EFI_IPSEC_PAD_DATA *Data 876 ) 877 { 878 // 879 // It assumes that all ref buffers in pad selector and data are 880 // stored in the continous memory and close to the base structure. 881 // 882 if (Data->AuthData != NULL) { 883 FIX_REF_BUF_ADDR (Data->AuthData, Data); 884 } 885 886 if (Data->RevocationData != NULL) { 887 FIX_REF_BUF_ADDR (Data->RevocationData, Data); 888 } 889 890 } 891 892 /** 893 Recover the value of some members of SPD Selector. 894 895 This function is corresponding to FixSpdEntry(). It recovers the value of members 896 of SPD Selector that are fixed by FixSpdEntry(). 897 898 @param[in, out] Selector Pointer of SPD Selector. 899 @param[in, out] Data Pointer of SPD Data. 900 901 **/ 902 VOID 903 UnfixSpdEntry ( 904 IN OUT EFI_IPSEC_SPD_SELECTOR *Selector, 905 IN OUT EFI_IPSEC_SPD_DATA *Data 906 ) 907 { 908 // 909 // It assumes that all ref buffers in SPD selector and data are 910 // stored in the continous memory and close to the base structure. 911 // 912 UNFIX_REF_BUF_ADDR (Selector->LocalAddress, Selector); 913 UNFIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector); 914 915 if (Data->ProcessingPolicy != NULL) { 916 UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data); 917 if (Data->ProcessingPolicy->TunnelOption != NULL) { 918 UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data); 919 } 920 } 921 922 } 923 924 /** 925 Recover the value of some members of SA ID. 926 927 This function is corresponding to FixSadEntry(). It recovers the value of members 928 of SAD ID that are fixed by FixSadEntry(). 929 930 @param[in, out] SaId Pointer of SAD ID. 931 @param[in, out] Data Pointer of SAD Data. 932 933 **/ 934 VOID 935 UnfixSadEntry ( 936 IN OUT EFI_IPSEC_SA_ID *SaId, 937 IN OUT EFI_IPSEC_SA_DATA2 *Data 938 ) 939 { 940 // 941 // It assumes that all ref buffers in SAD selector and data are 942 // stored in the continous memory and close to the base structure. 943 // 944 if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) { 945 UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data); 946 } 947 948 if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) { 949 UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data); 950 } 951 952 if (Data->SpdSelector != NULL) { 953 UNFIX_REF_BUF_ADDR (Data->SpdSelector, Data); 954 if (Data->SpdSelector->LocalAddress != NULL) { 955 UNFIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data); 956 } 957 958 UNFIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data); 959 } 960 961 } 962 963 /** 964 Recover the value of some members of PAD ID. 965 966 This function is corresponding to FixPadEntry(). It recovers the value of members 967 of PAD ID that are fixed by FixPadEntry(). 968 969 @param[in] PadId Pointer of PAD ID. 970 @param[in, out] Data Pointer of PAD Data. 971 972 **/ 973 VOID 974 UnfixPadEntry ( 975 IN EFI_IPSEC_PAD_ID *PadId, 976 IN OUT EFI_IPSEC_PAD_DATA *Data 977 ) 978 { 979 // 980 // It assumes that all ref buffers in pad selector and data are 981 // stored in the continous memory and close to the base structure. 982 // 983 if (Data->AuthData != NULL) { 984 UNFIX_REF_BUF_ADDR (Data->AuthData, Data); 985 } 986 987 if (Data->RevocationData != NULL) { 988 UNFIX_REF_BUF_ADDR (Data->RevocationData, Data); 989 } 990 991 } 992 993 /** 994 Set the security policy information for the EFI IPsec driver. 995 996 The IPsec configuration data has a unique selector/identifier separately to 997 identify a data entry. 998 999 @param[in] Selector Pointer to an entry selector on operated 1000 configuration data specified by DataType. 1001 A NULL Selector causes the entire specified-type 1002 configuration information to be flushed. 1003 @param[in] Data The data buffer to be set. The structure 1004 of the data buffer should be EFI_IPSEC_SPD_DATA. 1005 @param[in] Context Pointer to one entry selector that describes 1006 the expected position the new data entry will 1007 be added. If Context is NULL, the new entry will 1008 be appended the end of database. 1009 1010 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: 1011 - Selector is not NULL and its LocalAddress 1012 is NULL or its RemoteAddress is NULL. 1013 - Data is not NULL and its Action is Protected 1014 and its plolicy is NULL. 1015 - Data is not NULL, its Action is not protected, 1016 and its policy is not NULL. 1017 - The Action of Data is Protected, its policy 1018 mode is Tunnel, and its tunnel option is NULL. 1019 - The Action of Data is protected and its policy 1020 mode is not Tunnel and it tunnel option is not NULL. 1021 @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated. 1022 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1023 1024 **/ 1025 EFI_STATUS 1026 SetSpdEntry ( 1027 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1028 IN VOID *Data, 1029 IN VOID *Context OPTIONAL 1030 ) 1031 { 1032 EFI_IPSEC_SPD_SELECTOR *SpdSel; 1033 EFI_IPSEC_SPD_DATA *SpdData; 1034 EFI_IPSEC_SPD_SELECTOR *InsertBefore; 1035 LIST_ENTRY *SpdList; 1036 LIST_ENTRY *SadList; 1037 LIST_ENTRY *SpdSas; 1038 LIST_ENTRY *EntryInsertBefore; 1039 LIST_ENTRY *Entry; 1040 LIST_ENTRY *Entry2; 1041 LIST_ENTRY *NextEntry; 1042 IPSEC_SPD_ENTRY *SpdEntry; 1043 IPSEC_SAD_ENTRY *SadEntry; 1044 UINTN SpdEntrySize; 1045 UINTN Index; 1046 1047 SpdSel = (Selector == NULL) ? NULL : &Selector->SpdSelector; 1048 SpdData = (Data == NULL) ? NULL : (EFI_IPSEC_SPD_DATA *) Data; 1049 InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SpdSelector; 1050 SpdList = &mConfigData[IPsecConfigDataTypeSpd]; 1051 1052 if (SpdSel != NULL) { 1053 if (SpdSel->LocalAddress == NULL || SpdSel->RemoteAddress == NULL) { 1054 return EFI_INVALID_PARAMETER; 1055 } 1056 } 1057 1058 if (SpdData != NULL) { 1059 if ((SpdData->Action == EfiIPsecActionProtect && SpdData->ProcessingPolicy == NULL) || 1060 (SpdData->Action != EfiIPsecActionProtect && SpdData->ProcessingPolicy != NULL) 1061 ) { 1062 return EFI_INVALID_PARAMETER; 1063 } 1064 1065 if (SpdData->Action == EfiIPsecActionProtect) { 1066 if ((SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption == NULL) || 1067 (SpdData->ProcessingPolicy->Mode != EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption != NULL) 1068 ) { 1069 return EFI_INVALID_PARAMETER; 1070 } 1071 } 1072 } 1073 // 1074 // The default behavior is to insert the node ahead of the header. 1075 // 1076 EntryInsertBefore = SpdList; 1077 1078 // 1079 // Remove the existed SPD entry. 1080 // 1081 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SpdList) { 1082 1083 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry); 1084 1085 if (SpdSel == NULL || 1086 CompareSpdSelector ((EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel) 1087 ) { 1088 // 1089 // Record the existed entry position to keep the original order. 1090 // 1091 EntryInsertBefore = SpdEntry->List.ForwardLink; 1092 RemoveEntryList (&SpdEntry->List); 1093 1094 // 1095 // Update the reverse ref of SAD entry in the SPD.sas list. 1096 // 1097 SpdSas = &SpdEntry->Data->Sas; 1098 1099 // 1100 // TODO: Deleted the related SAs. 1101 // 1102 NET_LIST_FOR_EACH (Entry2, SpdSas) { 1103 SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry2); 1104 SadEntry->Data->SpdEntry = NULL; 1105 } 1106 1107 // 1108 // Free the existed SPD entry 1109 // 1110 FreePool (SpdEntry); 1111 } 1112 } 1113 // 1114 // Return success here if only want to remove the SPD entry. 1115 // 1116 if (SpdData == NULL || SpdSel == NULL) { 1117 return EFI_SUCCESS; 1118 } 1119 // 1120 // Search the appointed entry position if InsertBefore is not NULL. 1121 // 1122 if (InsertBefore != NULL) { 1123 1124 NET_LIST_FOR_EACH (Entry, SpdList) { 1125 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry); 1126 1127 if (CompareSpdSelector ( 1128 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, 1129 (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore 1130 )) { 1131 EntryInsertBefore = Entry; 1132 break; 1133 } 1134 } 1135 } 1136 1137 // 1138 // Do Padding for the different Arch. 1139 // 1140 SpdEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_SPD_ENTRY)); 1141 SpdEntrySize = ALIGN_VARIABLE (SpdEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SpdSel)); 1142 SpdEntrySize += IpSecGetSizeOfEfiSpdData (SpdData); 1143 1144 SpdEntry = AllocateZeroPool (SpdEntrySize); 1145 1146 if (SpdEntry == NULL) { 1147 return EFI_OUT_OF_RESOURCES; 1148 } 1149 // 1150 // Fix the address of Selector and Data buffer and copy them, which is 1151 // continous memory and close to the base structure of SPD entry. 1152 // 1153 SpdEntry->Selector = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ((SpdEntry + 1), sizeof (UINTN)); 1154 SpdEntry->Data = (IPSEC_SPD_DATA *) ALIGN_POINTER ( 1155 ((UINT8 *) SpdEntry->Selector + SIZE_OF_SPD_SELECTOR (SpdSel)), 1156 sizeof (UINTN) 1157 ); 1158 1159 DuplicateSpdSelector ( 1160 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, 1161 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel, 1162 NULL 1163 ); 1164 1165 CopyMem ( 1166 SpdEntry->Data->Name, 1167 SpdData->Name, 1168 sizeof (SpdData->Name) 1169 ); 1170 SpdEntry->Data->PackageFlag = SpdData->PackageFlag; 1171 SpdEntry->Data->TrafficDirection = SpdData->TrafficDirection; 1172 SpdEntry->Data->Action = SpdData->Action; 1173 1174 // 1175 // Fix the address of ProcessingPolicy and copy it if need, which is continous 1176 // memory and close to the base structure of SAD data. 1177 // 1178 if (SpdData->Action != EfiIPsecActionProtect) { 1179 SpdEntry->Data->ProcessingPolicy = NULL; 1180 } else { 1181 SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER ( 1182 SpdEntry->Data + 1, 1183 sizeof (UINTN) 1184 ); 1185 IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy); 1186 } 1187 // 1188 // Update the sas list of the new SPD entry. 1189 // 1190 InitializeListHead (&SpdEntry->Data->Sas); 1191 1192 SadList = &mConfigData[IPsecConfigDataTypeSad]; 1193 1194 NET_LIST_FOR_EACH (Entry, SadList) { 1195 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry); 1196 1197 for (Index = 0; Index < SpdData->SaIdCount; Index++) { 1198 1199 if (CompareSaId ( 1200 (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index], 1201 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id 1202 )) { 1203 if (SadEntry->Data->SpdEntry != NULL) { 1204 RemoveEntryList (&SadEntry->BySpd); 1205 } 1206 InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd); 1207 SadEntry->Data->SpdEntry = SpdEntry; 1208 } 1209 } 1210 } 1211 // 1212 // Insert the new SPD entry. 1213 // 1214 InsertTailList (EntryInsertBefore, &SpdEntry->List); 1215 1216 return EFI_SUCCESS; 1217 } 1218 1219 /** 1220 Set the security association information for the EFI IPsec driver. 1221 1222 The IPsec configuration data has a unique selector/identifier separately to 1223 identify a data entry. 1224 1225 @param[in] Selector Pointer to an entry selector on operated 1226 configuration data specified by DataType. 1227 A NULL Selector causes the entire specified-type 1228 configuration information to be flushed. 1229 @param[in] Data The data buffer to be set. The structure 1230 of the data buffer should be EFI_IPSEC_SA_DATA. 1231 @param[in] Context Pointer to one entry selector which describes 1232 the expected position the new data entry will 1233 be added. If Context is NULL,the new entry will 1234 be appended the end of database. 1235 1236 @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated. 1237 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1238 1239 **/ 1240 EFI_STATUS 1241 SetSadEntry ( 1242 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1243 IN VOID *Data, 1244 IN VOID *Context OPTIONAL 1245 ) 1246 { 1247 IPSEC_SAD_ENTRY *SadEntry; 1248 IPSEC_SPD_ENTRY *SpdEntry; 1249 LIST_ENTRY *Entry; 1250 LIST_ENTRY *NextEntry; 1251 LIST_ENTRY *SadList; 1252 LIST_ENTRY *SpdList; 1253 EFI_IPSEC_SA_ID *SaId; 1254 EFI_IPSEC_SA_DATA2 *SaData; 1255 EFI_IPSEC_SA_ID *InsertBefore; 1256 LIST_ENTRY *EntryInsertBefore; 1257 UINTN SadEntrySize; 1258 1259 SaId = (Selector == NULL) ? NULL : &Selector->SaId; 1260 SaData = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA2 *) Data; 1261 InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId; 1262 SadList = &mConfigData[IPsecConfigDataTypeSad]; 1263 1264 // 1265 // The default behavior is to insert the node ahead of the header. 1266 // 1267 EntryInsertBefore = SadList; 1268 1269 // 1270 // Remove the existed SAD entry. 1271 // 1272 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) { 1273 1274 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry); 1275 1276 if (SaId == NULL || 1277 CompareSaId ( 1278 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id, 1279 (EFI_IPSEC_CONFIG_SELECTOR *) SaId 1280 )) { 1281 // 1282 // Record the existed entry position to keep the original order. 1283 // 1284 EntryInsertBefore = SadEntry->List.ForwardLink; 1285 1286 // 1287 // Update the related SAD.byspd field. 1288 // 1289 if (SadEntry->Data->SpdEntry != NULL) { 1290 RemoveEntryList (&SadEntry->BySpd); 1291 } 1292 1293 RemoveEntryList (&SadEntry->List); 1294 FreePool (SadEntry); 1295 } 1296 } 1297 // 1298 // Return success here if only want to remove the SAD entry 1299 // 1300 if (SaData == NULL || SaId == NULL) { 1301 return EFI_SUCCESS; 1302 } 1303 // 1304 // Search the appointed entry position if InsertBefore is not NULL. 1305 // 1306 if (InsertBefore != NULL) { 1307 1308 NET_LIST_FOR_EACH (Entry, SadList) { 1309 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry); 1310 1311 if (CompareSaId ( 1312 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id, 1313 (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore 1314 )) { 1315 EntryInsertBefore = Entry; 1316 break; 1317 } 1318 } 1319 } 1320 1321 // 1322 // Do Padding for different Arch. 1323 // 1324 SadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY)); 1325 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_ID)); 1326 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA)); 1327 1328 if (SaId->Proto == EfiIPsecAH) { 1329 SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength; 1330 } else { 1331 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength); 1332 SadEntrySize += ALIGN_VARIABLE (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength); 1333 } 1334 1335 if (SaData->SpdSelector != NULL) { 1336 SadEntrySize += SadEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector); 1337 } 1338 SadEntry = AllocateZeroPool (SadEntrySize); 1339 1340 if (SadEntry == NULL) { 1341 return EFI_OUT_OF_RESOURCES; 1342 } 1343 // 1344 // Fix the address of Id and Data buffer and copy them, which is 1345 // continous memory and close to the base structure of SAD entry. 1346 // 1347 SadEntry->Id = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN)); 1348 SadEntry->Data = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN)); 1349 1350 CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID)); 1351 1352 SadEntry->Data->Mode = SaData->Mode; 1353 SadEntry->Data->SequenceNumber = SaData->SNCount; 1354 SadEntry->Data->AntiReplayWindowSize = SaData->AntiReplayWindows; 1355 1356 ZeroMem ( 1357 &SadEntry->Data->AntiReplayBitmap, 1358 sizeof (SadEntry->Data->AntiReplayBitmap) 1359 ); 1360 1361 ZeroMem ( 1362 &SadEntry->Data->AlgoInfo, 1363 sizeof (EFI_IPSEC_ALGO_INFO) 1364 ); 1365 1366 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId; 1367 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength; 1368 1369 if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) { 1370 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN)); 1371 CopyMem ( 1372 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey, 1373 SaData->AlgoInfo.EspAlgoInfo.AuthKey, 1374 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength 1375 ); 1376 } 1377 1378 if (SaId->Proto == EfiIPsecESP) { 1379 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId; 1380 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength; 1381 1382 if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) { 1383 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER ( 1384 ((UINT8 *) (SadEntry->Data + 1) + 1385 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength), 1386 sizeof (UINTN) 1387 ); 1388 CopyMem ( 1389 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey, 1390 SaData->AlgoInfo.EspAlgoInfo.EncKey, 1391 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength 1392 ); 1393 } 1394 } 1395 1396 CopyMem ( 1397 &SadEntry->Data->SaLifetime, 1398 &SaData->SaLifetime, 1399 sizeof (EFI_IPSEC_SA_LIFETIME) 1400 ); 1401 1402 SadEntry->Data->PathMTU = SaData->PathMTU; 1403 SadEntry->Data->SpdSelector = NULL; 1404 SadEntry->Data->ESNEnabled = FALSE; 1405 SadEntry->Data->ManualSet = SaData->ManualSet; 1406 1407 // 1408 // Copy Tunnel Source/Destination Address 1409 // 1410 if (SaData->Mode == EfiIPsecTunnel) { 1411 CopyMem ( 1412 &SadEntry->Data->TunnelDestAddress, 1413 &SaData->TunnelDestinationAddress, 1414 sizeof (EFI_IP_ADDRESS) 1415 ); 1416 CopyMem ( 1417 &SadEntry->Data->TunnelSourceAddress, 1418 &SaData->TunnelSourceAddress, 1419 sizeof (EFI_IP_ADDRESS) 1420 ); 1421 } 1422 // 1423 // Update the spd.sas list of the spd entry specified by SAD selector 1424 // 1425 SpdList = &mConfigData[IPsecConfigDataTypeSpd]; 1426 1427 for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) { 1428 1429 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry); 1430 if (IsSubSpdSelector ( 1431 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector, 1432 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector 1433 ) && SpdEntry->Data->Action == EfiIPsecActionProtect) { 1434 SadEntry->Data->SpdEntry = SpdEntry; 1435 SadEntry->Data->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *)((UINT8 *)SadEntry + 1436 SadEntrySize - 1437 (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector) 1438 ); 1439 DuplicateSpdSelector ( 1440 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector, 1441 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector, 1442 NULL 1443 ); 1444 InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd); 1445 } 1446 } 1447 // 1448 // Insert the new SAD entry. 1449 // 1450 InsertTailList (EntryInsertBefore, &SadEntry->List); 1451 1452 return EFI_SUCCESS; 1453 } 1454 1455 /** 1456 Set the peer authorization configuration information for the EFI IPsec driver. 1457 1458 The IPsec configuration data has a unique selector/identifier separately to 1459 identify a data entry. 1460 1461 @param[in] Selector Pointer to an entry selector on operated 1462 configuration data specified by DataType. 1463 A NULL Selector causes the entire specified-type 1464 configuration information to be flushed. 1465 @param[in] Data The data buffer to be set. The structure 1466 of the data buffer should be EFI_IPSEC_PAD_DATA. 1467 @param[in] Context Pointer to one entry selector that describes 1468 the expected position the new data entry will 1469 be added. If Context is NULL, the new entry will 1470 be appended the end of database. 1471 1472 @retval EFI_OUT_OF_RESOURCES The required system resources could not be allocated. 1473 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1474 1475 **/ 1476 EFI_STATUS 1477 SetPadEntry ( 1478 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1479 IN VOID *Data, 1480 IN VOID *Context OPTIONAL 1481 ) 1482 { 1483 IPSEC_PAD_ENTRY *PadEntry; 1484 EFI_IPSEC_PAD_ID *PadId; 1485 EFI_IPSEC_PAD_DATA *PadData; 1486 LIST_ENTRY *PadList; 1487 LIST_ENTRY *Entry; 1488 LIST_ENTRY *NextEntry; 1489 EFI_IPSEC_PAD_ID *InsertBefore; 1490 LIST_ENTRY *EntryInsertBefore; 1491 UINTN PadEntrySize; 1492 1493 PadId = (Selector == NULL) ? NULL : &Selector->PadId; 1494 PadData = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data; 1495 InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId; 1496 PadList = &mConfigData[IPsecConfigDataTypePad]; 1497 1498 // 1499 // The default behavior is to insert the node ahead of the header. 1500 // 1501 EntryInsertBefore = PadList; 1502 1503 // 1504 // Remove the existed pad entry. 1505 // 1506 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) { 1507 1508 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry); 1509 1510 if (PadId == NULL || 1511 ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId) 1512 ) { 1513 // 1514 // Record the existed entry position to keep the original order. 1515 // 1516 EntryInsertBefore = PadEntry->List.ForwardLink; 1517 RemoveEntryList (&PadEntry->List); 1518 1519 FreePool (PadEntry); 1520 } 1521 } 1522 // 1523 // Return success here if only want to remove the pad entry 1524 // 1525 if (PadData == NULL || PadId == NULL) { 1526 return EFI_SUCCESS; 1527 } 1528 // 1529 // Search the appointed entry position if InsertBefore is not NULL. 1530 // 1531 if (InsertBefore != NULL) { 1532 1533 NET_LIST_FOR_EACH (Entry, PadList) { 1534 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry); 1535 1536 if (ComparePadId ( 1537 (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, 1538 (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore 1539 )) { 1540 EntryInsertBefore = Entry; 1541 break; 1542 } 1543 } 1544 } 1545 1546 // 1547 // Do PADDING for different arch. 1548 // 1549 PadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY)); 1550 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID)); 1551 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA)); 1552 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0)); 1553 PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0; 1554 1555 PadEntry = AllocateZeroPool (PadEntrySize); 1556 1557 if (PadEntry == NULL) { 1558 return EFI_OUT_OF_RESOURCES; 1559 } 1560 // 1561 // Fix the address of Id and Data buffer and copy them, which is 1562 // continous memory and close to the base structure of pad entry. 1563 // 1564 PadEntry->Id = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN)); 1565 PadEntry->Data = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN)); 1566 1567 CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID)); 1568 1569 PadEntry->Data->AuthProtocol = PadData->AuthProtocol; 1570 PadEntry->Data->AuthMethod = PadData->AuthMethod; 1571 PadEntry->Data->IkeIdFlag = PadData->IkeIdFlag; 1572 1573 if (PadData->AuthData != NULL) { 1574 PadEntry->Data->AuthDataSize = PadData->AuthDataSize; 1575 PadEntry->Data->AuthData = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN)); 1576 CopyMem ( 1577 PadEntry->Data->AuthData, 1578 PadData->AuthData, 1579 PadData->AuthDataSize 1580 ); 1581 } else { 1582 PadEntry->Data->AuthDataSize = 0; 1583 PadEntry->Data->AuthData = NULL; 1584 } 1585 1586 if (PadData->RevocationData != NULL) { 1587 PadEntry->Data->RevocationDataSize = PadData->RevocationDataSize; 1588 PadEntry->Data->RevocationData = (VOID *) ALIGN_POINTER ( 1589 ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize), 1590 sizeof (UINTN) 1591 ); 1592 CopyMem ( 1593 PadEntry->Data->RevocationData, 1594 PadData->RevocationData, 1595 PadData->RevocationDataSize 1596 ); 1597 } else { 1598 PadEntry->Data->RevocationDataSize = 0; 1599 PadEntry->Data->RevocationData = NULL; 1600 } 1601 // 1602 // Insert the new pad entry. 1603 // 1604 InsertTailList (EntryInsertBefore, &PadEntry->List); 1605 1606 return EFI_SUCCESS; 1607 } 1608 1609 /** 1610 This function lookup the data entry from IPsec SPD. Return the configuration 1611 value of the specified SPD Entry. 1612 1613 @param[in] Selector Pointer to an entry selector which is an identifier 1614 of the SPD entry. 1615 @param[in, out] DataSize On output the size of data returned in Data. 1616 @param[out] Data The buffer to return the contents of the IPsec 1617 configuration data. The type of the data buffer 1618 is associated with the DataType. 1619 1620 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1621 @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero. 1622 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. 1623 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been 1624 updated with the size needed to complete the request. 1625 1626 **/ 1627 EFI_STATUS 1628 GetSpdEntry ( 1629 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1630 IN OUT UINTN *DataSize, 1631 OUT VOID *Data 1632 ) 1633 { 1634 IPSEC_SPD_ENTRY *SpdEntry; 1635 IPSEC_SAD_ENTRY *SadEntry; 1636 EFI_IPSEC_SPD_SELECTOR *SpdSel; 1637 EFI_IPSEC_SPD_DATA *SpdData; 1638 LIST_ENTRY *SpdList; 1639 LIST_ENTRY *SpdSas; 1640 LIST_ENTRY *Entry; 1641 UINTN RequiredSize; 1642 1643 SpdSel = &Selector->SpdSelector; 1644 SpdData = (EFI_IPSEC_SPD_DATA *) Data; 1645 SpdList = &mConfigData[IPsecConfigDataTypeSpd]; 1646 1647 NET_LIST_FOR_EACH (Entry, SpdList) { 1648 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry); 1649 1650 // 1651 // Find the required SPD entry 1652 // 1653 if (CompareSpdSelector ( 1654 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel, 1655 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector 1656 )) { 1657 1658 RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data); 1659 if (*DataSize < RequiredSize) { 1660 *DataSize = RequiredSize; 1661 return EFI_BUFFER_TOO_SMALL; 1662 } 1663 1664 if (SpdData == NULL) { 1665 return EFI_INVALID_PARAMETER; 1666 } 1667 1668 *DataSize = RequiredSize; 1669 1670 // 1671 // Extract and fill all SaId array from the SPD.sas list 1672 // 1673 SpdSas = &SpdEntry->Data->Sas; 1674 SpdData->SaIdCount = 0; 1675 1676 NET_LIST_FOR_EACH (Entry, SpdSas) { 1677 SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry); 1678 CopyMem ( 1679 &SpdData->SaId[SpdData->SaIdCount++], 1680 SadEntry->Id, 1681 sizeof (EFI_IPSEC_SA_ID) 1682 ); 1683 } 1684 // 1685 // Fill the other fields in SPD data. 1686 // 1687 CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name)); 1688 1689 SpdData->PackageFlag = SpdEntry->Data->PackageFlag; 1690 SpdData->TrafficDirection = SpdEntry->Data->TrafficDirection; 1691 SpdData->Action = SpdEntry->Data->Action; 1692 1693 if (SpdData->Action != EfiIPsecActionProtect) { 1694 SpdData->ProcessingPolicy = NULL; 1695 } else { 1696 SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID)); 1697 1698 IpSecDuplicateProcessPolicy ( 1699 SpdData->ProcessingPolicy, 1700 SpdEntry->Data->ProcessingPolicy 1701 ); 1702 } 1703 1704 return EFI_SUCCESS; 1705 } 1706 } 1707 1708 return EFI_NOT_FOUND; 1709 } 1710 1711 /** 1712 This function lookup the data entry from IPsec SAD. Return the configuration 1713 value of the specified SAD Entry. 1714 1715 @param[in] Selector Pointer to an entry selector which is an identifier 1716 of the SAD entry. 1717 @param[in, out] DataSize On output, the size of data returned in Data. 1718 @param[out] Data The buffer to return the contents of the IPsec 1719 configuration data. The type of the data buffer 1720 is associated with the DataType. 1721 1722 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1723 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. 1724 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been 1725 updated with the size needed to complete the request. 1726 1727 **/ 1728 EFI_STATUS 1729 GetSadEntry ( 1730 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1731 IN OUT UINTN *DataSize, 1732 OUT VOID *Data 1733 ) 1734 { 1735 IPSEC_SAD_ENTRY *SadEntry; 1736 LIST_ENTRY *Entry; 1737 LIST_ENTRY *SadList; 1738 EFI_IPSEC_SA_ID *SaId; 1739 EFI_IPSEC_SA_DATA2 *SaData; 1740 UINTN RequiredSize; 1741 1742 SaId = &Selector->SaId; 1743 SaData = (EFI_IPSEC_SA_DATA2 *) Data; 1744 SadList = &mConfigData[IPsecConfigDataTypeSad]; 1745 1746 NET_LIST_FOR_EACH (Entry, SadList) { 1747 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry); 1748 1749 // 1750 // Find the required SAD entry. 1751 // 1752 if (CompareSaId ( 1753 (EFI_IPSEC_CONFIG_SELECTOR *) SaId, 1754 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id 1755 )) { 1756 // 1757 // Calculate the required size of the SAD entry. 1758 // Data Layout is follows: 1759 // |EFI_IPSEC_SA_DATA 1760 // |AuthKey 1761 // |EncryptKey (Optional) 1762 // |SpdSelector (Optional) 1763 // 1764 RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2)); 1765 1766 if (SaId->Proto == EfiIPsecAH) { 1767 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength); 1768 } else { 1769 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength); 1770 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength); 1771 } 1772 1773 if (SadEntry->Data->SpdSelector != NULL) { 1774 RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector); 1775 } 1776 1777 if (*DataSize < RequiredSize) { 1778 *DataSize = RequiredSize; 1779 return EFI_BUFFER_TOO_SMALL; 1780 } 1781 1782 // 1783 // Fill the data fields of SAD entry. 1784 // 1785 *DataSize = RequiredSize; 1786 SaData->Mode = SadEntry->Data->Mode; 1787 SaData->SNCount = SadEntry->Data->SequenceNumber; 1788 SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize; 1789 1790 CopyMem ( 1791 &SaData->SaLifetime, 1792 &SadEntry->Data->SaLifetime, 1793 sizeof (EFI_IPSEC_SA_LIFETIME) 1794 ); 1795 1796 ZeroMem ( 1797 &SaData->AlgoInfo, 1798 sizeof (EFI_IPSEC_ALGO_INFO) 1799 ); 1800 1801 if (SaId->Proto == EfiIPsecAH) { 1802 // 1803 // Copy AH alogrithm INFO to SaData 1804 // 1805 SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId; 1806 SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength; 1807 if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) { 1808 SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN)); 1809 CopyMem ( 1810 SaData->AlgoInfo.AhAlgoInfo.AuthKey, 1811 SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey, 1812 SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength 1813 ); 1814 } 1815 } else if (SaId->Proto == EfiIPsecESP) { 1816 // 1817 // Copy ESP alogrithem INFO to SaData 1818 // 1819 SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId; 1820 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength; 1821 if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) { 1822 SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN)); 1823 CopyMem ( 1824 SaData->AlgoInfo.EspAlgoInfo.AuthKey, 1825 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey, 1826 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength 1827 ); 1828 } 1829 1830 SaData->AlgoInfo.EspAlgoInfo.EncAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId; 1831 SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength; 1832 1833 if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) { 1834 SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER ( 1835 ((UINT8 *) (SaData + 1) + 1836 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength), 1837 sizeof (UINTN) 1838 ); 1839 CopyMem ( 1840 SaData->AlgoInfo.EspAlgoInfo.EncKey, 1841 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey, 1842 SaData->AlgoInfo.EspAlgoInfo.EncKeyLength 1843 ); 1844 } 1845 } 1846 1847 SaData->PathMTU = SadEntry->Data->PathMTU; 1848 1849 // 1850 // Fill Tunnel Address if it is Tunnel Mode 1851 // 1852 if (SadEntry->Data->Mode == EfiIPsecTunnel) { 1853 CopyMem ( 1854 &SaData->TunnelDestinationAddress, 1855 &SadEntry->Data->TunnelDestAddress, 1856 sizeof (EFI_IP_ADDRESS) 1857 ); 1858 CopyMem ( 1859 &SaData->TunnelSourceAddress, 1860 &SadEntry->Data->TunnelSourceAddress, 1861 sizeof (EFI_IP_ADDRESS) 1862 ); 1863 } 1864 // 1865 // Fill the spd selector field of SAD data 1866 // 1867 if (SadEntry->Data->SpdSelector != NULL) { 1868 1869 SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) ( 1870 (UINT8 *)SaData + 1871 RequiredSize - 1872 SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector) 1873 ); 1874 1875 DuplicateSpdSelector ( 1876 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector, 1877 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector, 1878 NULL 1879 ); 1880 1881 } else { 1882 1883 SaData->SpdSelector = NULL; 1884 } 1885 1886 SaData->ManualSet = SadEntry->Data->ManualSet; 1887 1888 return EFI_SUCCESS; 1889 } 1890 } 1891 1892 return EFI_NOT_FOUND; 1893 } 1894 1895 /** 1896 This function lookup the data entry from IPsec PAD. Return the configuration 1897 value of the specified PAD Entry. 1898 1899 @param[in] Selector Pointer to an entry selector which is an identifier 1900 of the PAD entry. 1901 @param[in, out] DataSize On output the size of data returned in Data. 1902 @param[out] Data The buffer to return the contents of the IPsec 1903 configuration data. The type of the data buffer 1904 is associated with the DataType. 1905 1906 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 1907 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. 1908 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been 1909 updated with the size needed to complete the request. 1910 1911 **/ 1912 EFI_STATUS 1913 GetPadEntry ( 1914 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 1915 IN OUT UINTN *DataSize, 1916 OUT VOID *Data 1917 ) 1918 { 1919 IPSEC_PAD_ENTRY *PadEntry; 1920 LIST_ENTRY *PadList; 1921 LIST_ENTRY *Entry; 1922 EFI_IPSEC_PAD_ID *PadId; 1923 EFI_IPSEC_PAD_DATA *PadData; 1924 UINTN RequiredSize; 1925 1926 PadId = &Selector->PadId; 1927 PadData = (EFI_IPSEC_PAD_DATA *) Data; 1928 PadList = &mConfigData[IPsecConfigDataTypePad]; 1929 1930 NET_LIST_FOR_EACH (Entry, PadList) { 1931 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry); 1932 1933 // 1934 // Find the required pad entry. 1935 // 1936 if (ComparePadId ( 1937 (EFI_IPSEC_CONFIG_SELECTOR *) PadId, 1938 (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id 1939 )) { 1940 // 1941 // Calculate the required size of the pad entry. 1942 // 1943 RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA)); 1944 RequiredSize = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize); 1945 RequiredSize += PadEntry->Data->RevocationDataSize; 1946 1947 if (*DataSize < RequiredSize) { 1948 *DataSize = RequiredSize; 1949 return EFI_BUFFER_TOO_SMALL; 1950 } 1951 // 1952 // Fill the data fields of pad entry 1953 // 1954 *DataSize = RequiredSize; 1955 PadData->AuthProtocol = PadEntry->Data->AuthProtocol; 1956 PadData->AuthMethod = PadEntry->Data->AuthMethod; 1957 PadData->IkeIdFlag = PadEntry->Data->IkeIdFlag; 1958 1959 // 1960 // Copy Authentication data. 1961 // 1962 if (PadEntry->Data->AuthData != NULL) { 1963 1964 PadData->AuthDataSize = PadEntry->Data->AuthDataSize; 1965 PadData->AuthData = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN)); 1966 CopyMem ( 1967 PadData->AuthData, 1968 PadEntry->Data->AuthData, 1969 PadData->AuthDataSize 1970 ); 1971 } else { 1972 1973 PadData->AuthDataSize = 0; 1974 PadData->AuthData = NULL; 1975 } 1976 // 1977 // Copy Revocation Data. 1978 // 1979 if (PadEntry->Data->RevocationData != NULL) { 1980 1981 PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize; 1982 PadData->RevocationData = (VOID *) ALIGN_POINTER ( 1983 ((UINT8 *) (PadData + 1) + PadData->AuthDataSize), 1984 sizeof (UINTN) 1985 ); 1986 CopyMem ( 1987 PadData->RevocationData, 1988 PadEntry->Data->RevocationData, 1989 PadData->RevocationDataSize 1990 ); 1991 } else { 1992 1993 PadData->RevocationDataSize = 0; 1994 PadData->RevocationData = NULL; 1995 } 1996 1997 return EFI_SUCCESS; 1998 } 1999 } 2000 2001 return EFI_NOT_FOUND; 2002 } 2003 2004 /** 2005 Copy Source Process Policy to the Destination Process Policy. 2006 2007 @param[in] Dst Pointer to the Source Process Policy. 2008 @param[in] Src Pointer to the Destination Process Policy. 2009 2010 **/ 2011 VOID 2012 IpSecDuplicateProcessPolicy ( 2013 IN EFI_IPSEC_PROCESS_POLICY *Dst, 2014 IN EFI_IPSEC_PROCESS_POLICY *Src 2015 ) 2016 { 2017 // 2018 // Firstly copy the structure content itself. 2019 // 2020 CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY)); 2021 2022 // 2023 // Recursively copy the tunnel option if needed. 2024 // 2025 if (Dst->Mode != EfiIPsecTunnel) { 2026 ASSERT (Dst->TunnelOption == NULL); 2027 } else { 2028 Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN)); 2029 CopyMem ( 2030 Dst->TunnelOption, 2031 Src->TunnelOption, 2032 sizeof (EFI_IPSEC_TUNNEL_OPTION) 2033 ); 2034 } 2035 } 2036 2037 /** 2038 Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed 2039 to by the pointer members. 2040 2041 @param[in] SpdData Pointer to a specified EFI_IPSEC_SPD_DATA. 2042 2043 @return the whole size the specified EFI_IPSEC_SPD_DATA. 2044 2045 **/ 2046 UINTN 2047 IpSecGetSizeOfEfiSpdData ( 2048 IN EFI_IPSEC_SPD_DATA *SpdData 2049 ) 2050 { 2051 UINTN Size; 2052 2053 Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA)); 2054 2055 if (SpdData->Action == EfiIPsecActionProtect) { 2056 Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY)); 2057 2058 if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) { 2059 Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION)); 2060 } 2061 } 2062 2063 return Size; 2064 } 2065 2066 /** 2067 Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed 2068 to by the pointer members and the buffer size used by the Sa List. 2069 2070 @param[in] SpdData Pointer to the specified IPSEC_SPD_DATA. 2071 2072 @return the whole size of IPSEC_SPD_DATA. 2073 2074 **/ 2075 UINTN 2076 IpSecGetSizeOfSpdData ( 2077 IN IPSEC_SPD_DATA *SpdData 2078 ) 2079 { 2080 UINTN Size; 2081 LIST_ENTRY *Link; 2082 2083 Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID); 2084 2085 if (SpdData->Action == EfiIPsecActionProtect) { 2086 Size += sizeof (EFI_IPSEC_PROCESS_POLICY); 2087 2088 if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) { 2089 Size += sizeof (EFI_IPSEC_TUNNEL_OPTION); 2090 } 2091 } 2092 2093 NET_LIST_FOR_EACH (Link, &SpdData->Sas) { 2094 Size += sizeof (EFI_IPSEC_SA_ID); 2095 } 2096 2097 return Size; 2098 } 2099 2100 /** 2101 Get the IPsec Variable. 2102 2103 Get the all variables which start with the string contained in VaraiableName. 2104 Since all IPsec related variable store in continual space, those kinds of 2105 variable can be searched by the EfiGetNextVariableName. Those variables also are 2106 returned in a continual buffer. 2107 2108 @param[in] VariableName Pointer to a specified Variable Name. 2109 @param[in] VendorGuid Pointer to a specified Vendor Guid. 2110 @param[in] Attributes Point to memory location to return the attributes 2111 of variable. If the point is NULL, the parameter 2112 would be ignored. 2113 @param[in, out] DataSize As input, point to the maximum size of return 2114 Data-Buffer. As output, point to the actual 2115 size of the returned Data-Buffer. 2116 @param[in] Data Point to return Data-Buffer. 2117 2118 @retval EFI_ABORTED If the Variable size which contained in the variable 2119 structure doesn't match the variable size obtained 2120 from the EFIGetVariable. 2121 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has 2122 been updated with the size needed to complete the request. 2123 @retval EFI_SUCCESS The function completed successfully. 2124 @retval others Other errors found during the variable getting. 2125 **/ 2126 EFI_STATUS 2127 IpSecGetVariable ( 2128 IN CHAR16 *VariableName, 2129 IN EFI_GUID *VendorGuid, 2130 IN UINT32 *Attributes, OPTIONAL 2131 IN OUT UINTN *DataSize, 2132 IN VOID *Data 2133 ) 2134 { 2135 EFI_STATUS Status; 2136 EFI_GUID VendorGuidI; 2137 UINTN VariableNameLength; 2138 CHAR16 *VariableNameI; 2139 UINTN VariableNameISize; 2140 UINTN VariableNameISizeNew; 2141 UINTN VariableIndex; 2142 UINTN VariableCount; 2143 IP_SEC_VARIABLE_INFO IpSecVariableInfo; 2144 UINTN DataSizeI; 2145 2146 // 2147 // The variable name constructor is "VariableName + Info/0001/0002/... + NULL". 2148 // So the varialbe name is like "VariableNameInfo", "VariableName0001", ... 2149 // "VariableNameNULL". 2150 // 2151 VariableNameLength = StrLen (VariableName); 2152 VariableNameISize = (VariableNameLength + 5) * sizeof (CHAR16); 2153 VariableNameI = AllocateZeroPool (VariableNameISize); 2154 ASSERT (VariableNameI != NULL); 2155 2156 // 2157 // Construct the varible name of ipsecconfig meta data. 2158 // 2159 UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info"); 2160 2161 DataSizeI = sizeof (IpSecVariableInfo); 2162 2163 Status = gRT->GetVariable ( 2164 VariableNameI, 2165 VendorGuid, 2166 Attributes, 2167 &DataSizeI, 2168 &IpSecVariableInfo 2169 ); 2170 if (EFI_ERROR (Status)) { 2171 goto ON_EXIT; 2172 } 2173 2174 if (*DataSize < IpSecVariableInfo.VariableSize) { 2175 *DataSize = IpSecVariableInfo.VariableSize; 2176 Status = EFI_BUFFER_TOO_SMALL; 2177 goto ON_EXIT; 2178 } 2179 2180 VariableCount = IpSecVariableInfo.VariableCount; 2181 VariableNameI[0] = L'\0'; 2182 2183 while (VariableCount != 0) { 2184 // 2185 // Get the variable name one by one in the variable database. 2186 // 2187 VariableNameISizeNew = VariableNameISize; 2188 Status = gRT->GetNextVariableName ( 2189 &VariableNameISizeNew, 2190 VariableNameI, 2191 &VendorGuidI 2192 ); 2193 if (Status == EFI_BUFFER_TOO_SMALL) { 2194 VariableNameI = ReallocatePool ( 2195 VariableNameISize, 2196 VariableNameISizeNew, 2197 VariableNameI 2198 ); 2199 if (VariableNameI == NULL) { 2200 Status = EFI_OUT_OF_RESOURCES; 2201 break; 2202 } 2203 VariableNameISize = VariableNameISizeNew; 2204 2205 Status = gRT->GetNextVariableName ( 2206 &VariableNameISizeNew, 2207 VariableNameI, 2208 &VendorGuidI 2209 ); 2210 } 2211 2212 if (EFI_ERROR (Status)) { 2213 break; 2214 } 2215 // 2216 // Check whether the current variable is the required "ipsecconfig". 2217 // 2218 if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 || 2219 CompareGuid (VendorGuid, &VendorGuidI) 2220 ) { 2221 // 2222 // Parse the variable count of the current ipsecconfig data. 2223 // 2224 VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength); 2225 if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) { 2226 // 2227 // Get the variable size of the current ipsecconfig data. 2228 // 2229 DataSizeI = 0; 2230 Status = gRT->GetVariable ( 2231 VariableNameI, 2232 VendorGuid, 2233 Attributes, 2234 &DataSizeI, 2235 NULL 2236 ); 2237 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 2238 // 2239 // Validate the variable count and variable size. 2240 // 2241 if (VariableIndex != IpSecVariableInfo.VariableCount) { 2242 // 2243 // If the varaibe is not the last one, its size should be the max 2244 // size of the single variable. 2245 // 2246 if (DataSizeI != IpSecVariableInfo.SingleVariableSize) { 2247 return EFI_ABORTED; 2248 } 2249 } else { 2250 if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) { 2251 return EFI_ABORTED; 2252 } 2253 } 2254 // 2255 // Get the variable data of the current ipsecconfig data and 2256 // store it into user buffer continously. 2257 // 2258 Status = gRT->GetVariable ( 2259 VariableNameI, 2260 VendorGuid, 2261 Attributes, 2262 &DataSizeI, 2263 (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize 2264 ); 2265 ASSERT_EFI_ERROR (Status); 2266 VariableCount--; 2267 } 2268 } 2269 } 2270 // 2271 // The VariableCount in "VariableNameInfo" varaible should have the correct 2272 // numbers of variables which name starts with VariableName. 2273 // 2274 if (VariableCount != 0) { 2275 Status = EFI_ABORTED; 2276 } 2277 2278 ON_EXIT: 2279 if (VariableNameI != NULL) { 2280 FreePool (VariableNameI); 2281 } 2282 return Status; 2283 } 2284 2285 /** 2286 Set the IPsec variables. 2287 2288 Set all IPsec variables which start with the specified variable name. Those variables 2289 are set one by one. 2290 2291 @param[in] VariableName The name of the vendor's variable. It is a 2292 Null-Terminated Unicode String. 2293 @param[in] VendorGuid Unify identifier for vendor. 2294 @param[in] Attributes Point to memory location to return the attributes of 2295 variable. If the point is NULL, the parameter would be ignored. 2296 @param[in] DataSize The size in bytes of Data-Buffer. 2297 @param[in] Data Points to the content of the variable. 2298 2299 @retval EFI_SUCCESS The firmware successfully stored the variable and its data, as 2300 defined by the Attributes. 2301 @retval others Storing the variables failed. 2302 2303 **/ 2304 EFI_STATUS 2305 IpSecSetVariable ( 2306 IN CHAR16 *VariableName, 2307 IN EFI_GUID *VendorGuid, 2308 IN UINT32 Attributes, 2309 IN UINTN DataSize, 2310 IN VOID *Data 2311 ) 2312 { 2313 EFI_STATUS Status; 2314 CHAR16 *VariableNameI; 2315 UINTN VariableNameSize; 2316 UINTN VariableIndex; 2317 IP_SEC_VARIABLE_INFO IpSecVariableInfo; 2318 UINT64 MaximumVariableStorageSize; 2319 UINT64 RemainingVariableStorageSize; 2320 UINT64 MaximumVariableSize; 2321 2322 Status = gRT->QueryVariableInfo ( 2323 Attributes, 2324 &MaximumVariableStorageSize, 2325 &RemainingVariableStorageSize, 2326 &MaximumVariableSize 2327 ); 2328 if (EFI_ERROR (Status)) { 2329 return Status; 2330 } 2331 2332 // 2333 // "VariableName + Info/0001/0002/... + NULL" 2334 // 2335 VariableNameSize = (StrLen (VariableName) + 5) * sizeof (CHAR16); 2336 VariableNameI = AllocateZeroPool (VariableNameSize); 2337 2338 if (VariableNameI == NULL) { 2339 Status = EFI_OUT_OF_RESOURCES; 2340 goto ON_EXIT; 2341 } 2342 // 2343 // Construct the variable of ipsecconfig general information. Like the total 2344 // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables. 2345 // 2346 UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info"); 2347 MaximumVariableSize -= VariableNameSize; 2348 2349 IpSecVariableInfo.VariableCount = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize); 2350 IpSecVariableInfo.VariableSize = (UINT32) DataSize; 2351 IpSecVariableInfo.SingleVariableSize = (UINT32) MaximumVariableSize; 2352 2353 // 2354 // Set the variable of ipsecconfig general information. 2355 // 2356 Status = gRT->SetVariable ( 2357 VariableNameI, 2358 VendorGuid, 2359 Attributes, 2360 sizeof (IpSecVariableInfo), 2361 &IpSecVariableInfo 2362 ); 2363 if (EFI_ERROR (Status)) { 2364 DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status)); 2365 goto ON_EXIT; 2366 } 2367 2368 for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) { 2369 // 2370 // Construct and set the variable of ipsecconfig data one by one. 2371 // The index of variable name begin from 0001, and the varaible name 2372 // likes "VariableName0001", "VaraiableName0002".... 2373 // 2374 UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1); 2375 Status = gRT->SetVariable ( 2376 VariableNameI, 2377 VendorGuid, 2378 Attributes, 2379 (VariableIndex == IpSecVariableInfo.VariableCount - 1) ? 2380 (DataSize % (UINTN) MaximumVariableSize) : 2381 (UINTN) MaximumVariableSize, 2382 (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize 2383 ); 2384 2385 if (EFI_ERROR (Status)) { 2386 DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status)); 2387 goto ON_EXIT; 2388 } 2389 } 2390 2391 ON_EXIT: 2392 if (VariableNameI != NULL) { 2393 FreePool (VariableNameI); 2394 } 2395 2396 return Status; 2397 } 2398 2399 /** 2400 Return the configuration value for the EFI IPsec driver. 2401 2402 This function lookup the data entry from IPsec database or IKEv2 configuration 2403 information. The expected data type and unique identification are described in 2404 DataType and Selector parameters. 2405 2406 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. 2407 @param[in] DataType The type of data to retrieve. 2408 @param[in] Selector Pointer to an entry selector that is an identifier of the IPsec 2409 configuration data entry. 2410 @param[in, out] DataSize On output the size of data returned in Data. 2411 @param[out] Data The buffer to return the contents of the IPsec configuration data. 2412 The type of the data buffer associated with the DataType. 2413 2414 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 2415 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: 2416 - This is NULL. 2417 - Selector is NULL. 2418 - DataSize is NULL. 2419 - Data is NULL and *DataSize is not zero 2420 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. 2421 @retval EFI_UNSUPPORTED The specified DataType is not supported. 2422 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been 2423 updated with the size needed to complete the request. 2424 2425 **/ 2426 EFI_STATUS 2427 EFIAPI 2428 EfiIpSecConfigGetData ( 2429 IN EFI_IPSEC_CONFIG_PROTOCOL *This, 2430 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2431 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 2432 IN OUT UINTN *DataSize, 2433 OUT VOID *Data 2434 ) 2435 { 2436 if (This == NULL || Selector == NULL || DataSize == NULL) { 2437 return EFI_INVALID_PARAMETER; 2438 } 2439 2440 if (*DataSize != 0 && Data == NULL) { 2441 return EFI_INVALID_PARAMETER; 2442 } 2443 2444 if (DataType >= IPsecConfigDataTypeMaximum) { 2445 return EFI_UNSUPPORTED; 2446 } 2447 2448 return mGetPolicyEntry[DataType](Selector, DataSize, Data); 2449 } 2450 2451 /** 2452 Set the security association, security policy and peer authorization configuration 2453 information for the EFI IPsec driver. 2454 2455 This function is used to set the IPsec configuration information of type DataType for 2456 the EFI IPsec driver. 2457 The IPsec configuration data has a unique selector/identifier separately to identify 2458 a data entry. The selector structure depends on DataType's definition. 2459 Using SetData() with a Data of NULL causes the IPsec configuration data entry identified 2460 by DataType and Selector to be deleted. 2461 2462 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. 2463 @param[in] DataType The type of data to be set. 2464 @param[in] Selector Pointer to an entry selector on operated configuration data 2465 specified by DataType. A NULL Selector causes the entire 2466 specified-type configuration information to be flushed. 2467 @param[in] Data The data buffer to be set. The structure of the data buffer is 2468 associated with the DataType. 2469 @param[in] InsertBefore Pointer to one entry selector which describes the expected 2470 position the new data entry will be added. If InsertBefore is NULL, 2471 the new entry will be appended to the end of the database. 2472 2473 @retval EFI_SUCCESS The specified configuration entry data was set successfully. 2474 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: 2475 - This is NULL. 2476 @retval EFI_UNSUPPORTED The specified DataType is not supported. 2477 @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated. 2478 2479 **/ 2480 EFI_STATUS 2481 EFIAPI 2482 EfiIpSecConfigSetData ( 2483 IN EFI_IPSEC_CONFIG_PROTOCOL *This, 2484 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2485 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 2486 IN VOID *Data, 2487 IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL 2488 ) 2489 { 2490 EFI_STATUS Status; 2491 2492 if (This == NULL) { 2493 return EFI_INVALID_PARAMETER; 2494 } 2495 2496 if (DataType >= IPsecConfigDataTypeMaximum) { 2497 return EFI_UNSUPPORTED; 2498 } 2499 2500 Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore); 2501 2502 if (!EFI_ERROR (Status) && !mSetBySelf) { 2503 // 2504 // Save the updated config data into variable. 2505 // 2506 IpSecConfigSave (); 2507 } 2508 2509 return Status; 2510 } 2511 2512 /** 2513 Enumerates the current selector for IPsec configuration data entry. 2514 2515 This function is called multiple times to retrieve the entry Selector in IPsec 2516 configuration database. On each call to GetNextSelector(), the next entry 2517 Selector are retrieved into the output interface. 2518 2519 If the entire IPsec configuration database has been iterated, the error 2520 EFI_NOT_FOUND is returned. 2521 If the Selector buffer is too small for the next Selector copy, an 2522 EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect 2523 the size of buffer needed. 2524 2525 On the initial call to GetNextSelector() to start the IPsec configuration database 2526 search, a pointer to the buffer with all zero value is passed in Selector. Calls 2527 to SetData() between calls to GetNextSelector may produce unpredictable results. 2528 2529 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. 2530 @param[in] DataType The type of IPsec configuration data to retrieve. 2531 @param[in, out] SelectorSize The size of the Selector buffer. 2532 @param[in, out] Selector On input, supplies the pointer to last Selector that was 2533 returned by GetNextSelector(). 2534 On output, returns one copy of the current entry Selector 2535 of a given DataType. 2536 2537 @retval EFI_SUCCESS The specified configuration data was obtained successfully. 2538 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: 2539 - This is NULL. 2540 - SelectorSize is NULL. 2541 - Selector is NULL. 2542 @retval EFI_NOT_FOUND The next configuration data entry was not found. 2543 @retval EFI_UNSUPPORTED The specified DataType is not supported. 2544 @retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter 2545 has been updated with the size needed to complete the search 2546 request. 2547 2548 **/ 2549 EFI_STATUS 2550 EFIAPI 2551 EfiIpSecConfigGetNextSelector ( 2552 IN EFI_IPSEC_CONFIG_PROTOCOL *This, 2553 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2554 IN OUT UINTN *SelectorSize, 2555 IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector 2556 ) 2557 { 2558 LIST_ENTRY *Link; 2559 IPSEC_COMMON_POLICY_ENTRY *CommonEntry; 2560 BOOLEAN IsFound; 2561 2562 if (This == NULL || Selector == NULL || SelectorSize == NULL) { 2563 return EFI_INVALID_PARAMETER; 2564 } 2565 2566 if (DataType >= IPsecConfigDataTypeMaximum) { 2567 return EFI_UNSUPPORTED; 2568 } 2569 2570 IsFound = FALSE; 2571 2572 NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) { 2573 CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List); 2574 2575 if (IsFound || (BOOLEAN)(mIsZeroSelector[DataType](Selector))) { 2576 // 2577 // If found the appointed entry, then duplicate the next one and return, 2578 // or if the appointed entry is zero, then return the first one directly. 2579 // 2580 return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize); 2581 } else { 2582 // 2583 // Set the flag if find the appointed entry. 2584 // 2585 IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector); 2586 } 2587 } 2588 2589 return EFI_NOT_FOUND; 2590 } 2591 2592 /** 2593 Register an event that is to be signaled whenever a configuration process on the 2594 specified IPsec configuration information is done. 2595 2596 The register function is not surpport now and always returns EFI_UNSUPPORTED. 2597 2598 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. 2599 @param[in] DataType The type of data to be registered the event for. 2600 @param[in] Event The event to be registered. 2601 2602 @retval EFI_SUCCESS The event is registered successfully. 2603 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. 2604 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. 2605 @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified 2606 DataType is not supported. 2607 2608 **/ 2609 EFI_STATUS 2610 EFIAPI 2611 EfiIpSecConfigRegisterNotify ( 2612 IN EFI_IPSEC_CONFIG_PROTOCOL *This, 2613 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2614 IN EFI_EVENT Event 2615 ) 2616 { 2617 return EFI_UNSUPPORTED; 2618 } 2619 2620 /** 2621 Remove the specified event that was previously registered on the specified IPsec 2622 configuration data. 2623 2624 This function is not support now and alwasy return EFI_UNSUPPORTED. 2625 2626 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. 2627 @param[in] DataType The configuration data type to remove the registered event for. 2628 @param[in] Event The event to be unregistered. 2629 2630 @retval EFI_SUCCESS The event was removed successfully. 2631 @retval EFI_NOT_FOUND The Event specified by DataType could not be found in the 2632 database. 2633 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. 2634 @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified 2635 DataType is not supported. 2636 2637 **/ 2638 EFI_STATUS 2639 EFIAPI 2640 EfiIpSecConfigUnregisterNotify ( 2641 IN EFI_IPSEC_CONFIG_PROTOCOL *This, 2642 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2643 IN EFI_EVENT Event 2644 ) 2645 { 2646 return EFI_UNSUPPORTED; 2647 } 2648 2649 /** 2650 Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer. 2651 2652 This function is a caller defined function, and it is called by the IpSecVisitConfigData(). 2653 The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to 2654 copy all types of IPsec Config datas into one buffer and store this buffer into firmware in 2655 the form of several variables. 2656 2657 @param[in] Type A specified IPSEC_CONFIG_DATA_TYPE. 2658 @param[in] Selector Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied 2659 to the buffer. 2660 @param[in] Data Points to data to be copied to the buffer. The 2661 Data type is related to the Type. 2662 @param[in] SelectorSize The size of the Selector. 2663 @param[in] DataSize The size of the Data. 2664 @param[in, out] Buffer The buffer to store the Selector and Data. 2665 2666 @retval EFI_SUCCESS Copy the Selector and Data to a buffer successfully. 2667 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated. 2668 2669 **/ 2670 EFI_STATUS 2671 IpSecCopyPolicyEntry ( 2672 IN EFI_IPSEC_CONFIG_DATA_TYPE Type, 2673 IN EFI_IPSEC_CONFIG_SELECTOR *Selector, 2674 IN VOID *Data, 2675 IN UINTN SelectorSize, 2676 IN UINTN DataSize, 2677 IN OUT IPSEC_VARIABLE_BUFFER *Buffer 2678 ) 2679 { 2680 IPSEC_VAR_ITEM_HEADER SelectorHeader; 2681 IPSEC_VAR_ITEM_HEADER DataHeader; 2682 UINTN EntrySize; 2683 UINT8 *TempPoint; 2684 2685 if (Type == IPsecConfigDataTypeSad) { 2686 // 2687 // Don't save automatically-generated SA entry into variable. 2688 // 2689 if (((EFI_IPSEC_SA_DATA2 *) Data)->ManualSet == FALSE) { 2690 return EFI_SUCCESS; 2691 } 2692 } 2693 // 2694 // Increase the capacity size of the buffer if needed. 2695 // 2696 EntrySize = ALIGN_VARIABLE (sizeof (SelectorHeader)); 2697 EntrySize = ALIGN_VARIABLE (EntrySize + SelectorSize); 2698 EntrySize = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader)); 2699 EntrySize = ALIGN_VARIABLE (EntrySize + DataSize); 2700 2701 //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader); 2702 if (Buffer->Capacity - Buffer->Size < EntrySize) { 2703 // 2704 // Calculate the required buffer 2705 // 2706 Buffer->Capacity += EntrySize; 2707 TempPoint = AllocatePool (Buffer->Capacity); 2708 2709 if (TempPoint == NULL) { 2710 return EFI_OUT_OF_RESOURCES; 2711 } 2712 // 2713 // Copy the old Buffer to new buffer and free the old one. 2714 // 2715 CopyMem (TempPoint, Buffer->Ptr, Buffer->Size); 2716 FreePool (Buffer->Ptr); 2717 2718 Buffer->Ptr = TempPoint; 2719 } 2720 2721 mFixPolicyEntry[Type](Selector, Data); 2722 2723 // 2724 // Fill the selector header and copy it into buffer. 2725 // 2726 SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT); 2727 SelectorHeader.Size = (UINT16) SelectorSize; 2728 2729 CopyMem ( 2730 Buffer->Ptr + Buffer->Size, 2731 &SelectorHeader, 2732 sizeof (SelectorHeader) 2733 ); 2734 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader)); 2735 2736 // 2737 // Copy the selector into buffer. 2738 // 2739 CopyMem ( 2740 Buffer->Ptr + Buffer->Size, 2741 Selector, 2742 SelectorSize 2743 ); 2744 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + SelectorSize); 2745 2746 // 2747 // Fill the data header and copy it into buffer. 2748 // 2749 DataHeader.Type = (UINT8) Type; 2750 DataHeader.Size = (UINT16) DataSize; 2751 2752 CopyMem ( 2753 Buffer->Ptr + Buffer->Size, 2754 &DataHeader, 2755 sizeof (DataHeader) 2756 ); 2757 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader)); 2758 // 2759 // Copy the data into buffer. 2760 // 2761 CopyMem ( 2762 Buffer->Ptr + Buffer->Size, 2763 Data, 2764 DataSize 2765 ); 2766 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + DataSize); 2767 2768 mUnfixPolicyEntry[Type](Selector, Data); 2769 2770 return EFI_SUCCESS; 2771 } 2772 2773 /** 2774 Visit all IPsec Configurations of specified Type and call the caller defined 2775 interface. 2776 2777 @param[in] DataType The specified IPsec Config Data Type. 2778 @param[in] Routine The function defined by the caller. 2779 @param[in] Context The data passed to the Routine. 2780 2781 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated 2782 @retval EFI_SUCCESS This function completed successfully. 2783 2784 **/ 2785 EFI_STATUS 2786 IpSecVisitConfigData ( 2787 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, 2788 IN IPSEC_COPY_POLICY_ENTRY Routine, 2789 IN VOID *Context 2790 ) 2791 { 2792 EFI_STATUS GetNextStatus; 2793 EFI_STATUS GetDataStatus; 2794 EFI_STATUS RoutineStatus; 2795 EFI_IPSEC_CONFIG_SELECTOR *Selector; 2796 VOID *Data; 2797 UINTN SelectorSize; 2798 UINTN DataSize; 2799 UINTN SelectorBufferSize; 2800 UINTN DataBufferSize; 2801 BOOLEAN FirstGetNext; 2802 2803 FirstGetNext = TRUE; 2804 DataBufferSize = 0; 2805 Data = NULL; 2806 SelectorBufferSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR); 2807 Selector = AllocateZeroPool (SelectorBufferSize); 2808 2809 if (Selector == NULL) { 2810 return EFI_OUT_OF_RESOURCES; 2811 } 2812 2813 while (TRUE) { 2814 // 2815 // Get the real size of the selector. 2816 // 2817 SelectorSize = SelectorBufferSize; 2818 GetNextStatus = EfiIpSecConfigGetNextSelector ( 2819 &mIpSecConfigInstance, 2820 DataType, 2821 &SelectorSize, 2822 Selector 2823 ); 2824 if (GetNextStatus == EFI_BUFFER_TOO_SMALL) { 2825 FreePool (Selector); 2826 SelectorBufferSize = SelectorSize; 2827 // 2828 // Allocate zero pool for the first selector, while store the last 2829 // selector content for the other selectors. 2830 // 2831 if (FirstGetNext) { 2832 Selector = AllocateZeroPool (SelectorBufferSize); 2833 } else { 2834 Selector = AllocateCopyPool (SelectorBufferSize, Selector); 2835 } 2836 2837 if (Selector == NULL) { 2838 return EFI_OUT_OF_RESOURCES; 2839 } 2840 // 2841 // Get the content of the selector. 2842 // 2843 GetNextStatus = EfiIpSecConfigGetNextSelector ( 2844 &mIpSecConfigInstance, 2845 DataType, 2846 &SelectorSize, 2847 Selector 2848 ); 2849 } 2850 2851 if (EFI_ERROR (GetNextStatus)) { 2852 break; 2853 } 2854 2855 FirstGetNext = FALSE; 2856 2857 // 2858 // Get the real size of the policy entry according to the selector. 2859 // 2860 DataSize = DataBufferSize; 2861 GetDataStatus = EfiIpSecConfigGetData ( 2862 &mIpSecConfigInstance, 2863 DataType, 2864 Selector, 2865 &DataSize, 2866 Data 2867 ); 2868 if (GetDataStatus == EFI_BUFFER_TOO_SMALL) { 2869 if (Data != NULL) { 2870 FreePool (Data); 2871 } 2872 2873 DataBufferSize = DataSize; 2874 Data = AllocateZeroPool (DataBufferSize); 2875 2876 if (Data == NULL) { 2877 return EFI_OUT_OF_RESOURCES; 2878 } 2879 // 2880 // Get the content of the policy entry according to the selector. 2881 // 2882 GetDataStatus = EfiIpSecConfigGetData ( 2883 &mIpSecConfigInstance, 2884 DataType, 2885 Selector, 2886 &DataSize, 2887 Data 2888 ); 2889 } 2890 2891 if (EFI_ERROR (GetDataStatus)) { 2892 break; 2893 } 2894 // 2895 // Prepare the buffer of updated policy entry, which is stored in 2896 // the continous memory, and then save into variable later. 2897 // 2898 RoutineStatus = Routine ( 2899 DataType, 2900 Selector, 2901 Data, 2902 SelectorSize, 2903 DataSize, 2904 Context 2905 ); 2906 if (EFI_ERROR (RoutineStatus)) { 2907 break; 2908 } 2909 } 2910 2911 if (Data != NULL) { 2912 FreePool (Data); 2913 } 2914 2915 if (Selector != NULL) { 2916 FreePool (Selector); 2917 } 2918 2919 return EFI_SUCCESS; 2920 } 2921 2922 /** 2923 This function is the subfunction of EFIIpSecConfigSetData. 2924 2925 This function call IpSecSetVaraible to set the IPsec Configuration into the firmware. 2926 2927 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated. 2928 @retval EFI_SUCCESS Saved the configration successfully. 2929 @retval Others Other errors were found while obtaining the variable. 2930 2931 **/ 2932 EFI_STATUS 2933 IpSecConfigSave ( 2934 VOID 2935 ) 2936 { 2937 IPSEC_VARIABLE_BUFFER Buffer; 2938 EFI_STATUS Status; 2939 EFI_IPSEC_CONFIG_DATA_TYPE Type; 2940 2941 Buffer.Size = 0; 2942 Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE; 2943 Buffer.Ptr = AllocateZeroPool (Buffer.Capacity); 2944 2945 if (Buffer.Ptr == NULL) { 2946 return EFI_OUT_OF_RESOURCES; 2947 } 2948 // 2949 // For each policy database, prepare the contious buffer to save into variable. 2950 // 2951 for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) { 2952 IpSecVisitConfigData ( 2953 Type, 2954 (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry, 2955 &Buffer 2956 ); 2957 } 2958 // 2959 // Save the updated policy database into variable. 2960 // 2961 Status = IpSecSetVariable ( 2962 IPSECCONFIG_VARIABLE_NAME, 2963 &gEfiIpSecConfigProtocolGuid, 2964 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 2965 Buffer.Size, 2966 Buffer.Ptr 2967 ); 2968 2969 FreePool (Buffer.Ptr); 2970 2971 return Status; 2972 } 2973 2974 /** 2975 Get the all IPSec configuration variables and store those variables 2976 to the internal data structure. 2977 2978 This founction is called by IpSecConfigInitialize() which is to intialize the 2979 IPsecConfiguration Protocol. 2980 2981 @param[in] Private Point to IPSEC_PRIVATE_DATA. 2982 2983 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated 2984 @retval EFI_SUCCESS Restore the IPsec Configuration successfully. 2985 @retval others Other errors is found while obtaining the variable. 2986 2987 **/ 2988 EFI_STATUS 2989 IpSecConfigRestore ( 2990 IN IPSEC_PRIVATE_DATA *Private 2991 ) 2992 { 2993 EFI_STATUS Status; 2994 UINTN BufferSize; 2995 UINT8 *Buffer; 2996 IPSEC_VAR_ITEM_HEADER *Header; 2997 UINT8 *Ptr; 2998 EFI_IPSEC_CONFIG_SELECTOR *Selector; 2999 EFI_IPSEC_CONFIG_DATA_TYPE Type; 3000 VOID *Data; 3001 UINT8 Value; 3002 UINTN Size; 3003 3004 Value = 0; 3005 Size = sizeof (Value); 3006 BufferSize = 0; 3007 Buffer = NULL; 3008 3009 Status = gRT->GetVariable ( 3010 IPSECCONFIG_STATUS_NAME, 3011 &gEfiIpSecConfigProtocolGuid, 3012 NULL, 3013 &Size, 3014 &Value 3015 ); 3016 3017 if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) { 3018 Private->IpSec.DisabledFlag = FALSE; 3019 } 3020 // 3021 // Get the real size of policy database in variable. 3022 // 3023 Status = IpSecGetVariable ( 3024 IPSECCONFIG_VARIABLE_NAME, 3025 &gEfiIpSecConfigProtocolGuid, 3026 NULL, 3027 &BufferSize, 3028 Buffer 3029 ); 3030 if (Status == EFI_BUFFER_TOO_SMALL) { 3031 3032 Buffer = AllocateZeroPool (BufferSize); 3033 if (Buffer == NULL) { 3034 return EFI_OUT_OF_RESOURCES; 3035 } 3036 // 3037 // Get the content of policy database in variable. 3038 // 3039 Status = IpSecGetVariable ( 3040 IPSECCONFIG_VARIABLE_NAME, 3041 &gEfiIpSecConfigProtocolGuid, 3042 NULL, 3043 &BufferSize, 3044 Buffer 3045 ); 3046 if (EFI_ERROR (Status)) { 3047 FreePool (Buffer); 3048 return Status; 3049 } 3050 3051 for (Ptr = Buffer; Ptr < Buffer + BufferSize;) { 3052 3053 Header = (IPSEC_VAR_ITEM_HEADER *) Ptr; 3054 Type = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT); 3055 ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum)); 3056 3057 Selector = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN)); 3058 Header = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER ( 3059 (UINT8 *) Selector + Header->Size, 3060 sizeof (UINTN) 3061 ); 3062 ASSERT (Header->Type == Type); 3063 3064 Data = ALIGN_POINTER (Header + 1, sizeof (UINTN)); 3065 3066 mUnfixPolicyEntry[Type](Selector, Data); 3067 3068 // 3069 // Update each policy entry according to the content in variable. 3070 // 3071 mSetBySelf = TRUE; 3072 Status = EfiIpSecConfigSetData ( 3073 &Private->IpSecConfig, 3074 Type, 3075 Selector, 3076 Data, 3077 NULL 3078 ); 3079 mSetBySelf = FALSE; 3080 3081 if (EFI_ERROR (Status)) { 3082 FreePool (Buffer); 3083 return Status; 3084 } 3085 3086 Ptr = ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN)); 3087 } 3088 3089 FreePool (Buffer); 3090 } 3091 3092 return EFI_SUCCESS; 3093 } 3094 3095 /** 3096 Install and Initialize IPsecConfig protocol 3097 3098 @param[in, out] Private Pointer to IPSEC_PRIVATE_DATA. After this function finish, 3099 the pointer of IPsecConfig Protocol implementation will copy 3100 into its IPsecConfig member. 3101 3102 @retval EFI_SUCCESS Initialized the IPsecConfig Protocol successfully. 3103 @retval Others Initializing the IPsecConfig Protocol failed. 3104 **/ 3105 EFI_STATUS 3106 IpSecConfigInitialize ( 3107 IN OUT IPSEC_PRIVATE_DATA *Private 3108 ) 3109 { 3110 EFI_IPSEC_CONFIG_DATA_TYPE Type; 3111 3112 CopyMem ( 3113 &Private->IpSecConfig, 3114 &mIpSecConfigInstance, 3115 sizeof (EFI_IPSEC_CONFIG_PROTOCOL) 3116 ); 3117 3118 // 3119 // Initialize the list head of policy database. 3120 // 3121 for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) { 3122 InitializeListHead (&mConfigData[Type]); 3123 } 3124 // 3125 // Restore the content of policy database according to the variable. 3126 // 3127 IpSecConfigRestore (Private); 3128 3129 return gBS->InstallMultipleProtocolInterfaces ( 3130 &Private->Handle, 3131 &gEfiIpSecConfigProtocolGuid, 3132 &Private->IpSecConfig, 3133 NULL 3134 ); 3135 } 3136