]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecConfigImpl.c
NetworkPkg: Fix IpSec run into infinite loop issue in some case
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecConfigImpl.c
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->Action = SpdData->Action;
1172
1173 //
1174 // Fix the address of ProcessingPolicy and copy it if need, which is continous
1175 // memory and close to the base structure of SAD data.
1176 //
1177 if (SpdData->Action != EfiIPsecActionProtect) {
1178 SpdEntry->Data->ProcessingPolicy = NULL;
1179 } else {
1180 SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (
1181 SpdEntry->Data + 1,
1182 sizeof (UINTN)
1183 );
1184 IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy);
1185 }
1186 //
1187 // Update the sas list of the new SPD entry.
1188 //
1189 InitializeListHead (&SpdEntry->Data->Sas);
1190
1191 SadList = &mConfigData[IPsecConfigDataTypeSad];
1192
1193 NET_LIST_FOR_EACH (Entry, SadList) {
1194 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
1195
1196 for (Index = 0; Index < SpdData->SaIdCount; Index++) {
1197
1198 if (CompareSaId (
1199 (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index],
1200 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
1201 )) {
1202 if (SadEntry->Data->SpdEntry != NULL) {
1203 RemoveEntryList (&SadEntry->BySpd);
1204 }
1205 InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
1206 SadEntry->Data->SpdEntry = SpdEntry;
1207 DuplicateSpdSelector (
1208 (EFI_IPSEC_CONFIG_SELECTOR *)SadEntry->Data->SpdSelector,
1209 (EFI_IPSEC_CONFIG_SELECTOR *)SpdEntry->Selector,
1210 NULL
1211 );
1212 }
1213 }
1214 }
1215 //
1216 // Insert the new SPD entry.
1217 //
1218 InsertTailList (EntryInsertBefore, &SpdEntry->List);
1219
1220 return EFI_SUCCESS;
1221 }
1222
1223 /**
1224 Set the security association information for the EFI IPsec driver.
1225
1226 The IPsec configuration data has a unique selector/identifier separately to
1227 identify a data entry.
1228
1229 @param[in] Selector Pointer to an entry selector on operated
1230 configuration data specified by DataType.
1231 A NULL Selector causes the entire specified-type
1232 configuration information to be flushed.
1233 @param[in] Data The data buffer to be set. The structure
1234 of the data buffer should be EFI_IPSEC_SA_DATA.
1235 @param[in] Context Pointer to one entry selector which describes
1236 the expected position the new data entry will
1237 be added. If Context is NULL,the new entry will
1238 be appended the end of database.
1239
1240 @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
1241 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1242
1243 **/
1244 EFI_STATUS
1245 SetSadEntry (
1246 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1247 IN VOID *Data,
1248 IN VOID *Context OPTIONAL
1249 )
1250 {
1251 IPSEC_SAD_ENTRY *SadEntry;
1252 IPSEC_SPD_ENTRY *SpdEntry;
1253 LIST_ENTRY *Entry;
1254 LIST_ENTRY *NextEntry;
1255 LIST_ENTRY *SadList;
1256 LIST_ENTRY *SpdList;
1257 EFI_IPSEC_SA_ID *SaId;
1258 EFI_IPSEC_SA_DATA2 *SaData;
1259 EFI_IPSEC_SA_ID *InsertBefore;
1260 LIST_ENTRY *EntryInsertBefore;
1261 UINTN SadEntrySize;
1262
1263 SaId = (Selector == NULL) ? NULL : &Selector->SaId;
1264 SaData = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA2 *) Data;
1265 InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId;
1266 SadList = &mConfigData[IPsecConfigDataTypeSad];
1267
1268 //
1269 // The default behavior is to insert the node ahead of the header.
1270 //
1271 EntryInsertBefore = SadList;
1272
1273 //
1274 // Remove the existed SAD entry.
1275 //
1276 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) {
1277
1278 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
1279
1280 if (SaId == NULL ||
1281 CompareSaId (
1282 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
1283 (EFI_IPSEC_CONFIG_SELECTOR *) SaId
1284 )) {
1285 //
1286 // Record the existed entry position to keep the original order.
1287 //
1288 EntryInsertBefore = SadEntry->List.ForwardLink;
1289
1290 //
1291 // Update the related SAD.byspd field.
1292 //
1293 if (SadEntry->Data->SpdEntry != NULL) {
1294 RemoveEntryList (&SadEntry->BySpd);
1295 }
1296
1297 RemoveEntryList (&SadEntry->List);
1298 FreePool (SadEntry);
1299 }
1300 }
1301 //
1302 // Return success here if only want to remove the SAD entry
1303 //
1304 if (SaData == NULL || SaId == NULL) {
1305 return EFI_SUCCESS;
1306 }
1307 //
1308 // Search the appointed entry position if InsertBefore is not NULL.
1309 //
1310 if (InsertBefore != NULL) {
1311
1312 NET_LIST_FOR_EACH (Entry, SadList) {
1313 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
1314
1315 if (CompareSaId (
1316 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
1317 (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
1318 )) {
1319 EntryInsertBefore = Entry;
1320 break;
1321 }
1322 }
1323 }
1324
1325 //
1326 // Do Padding for different Arch.
1327 //
1328 SadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY));
1329 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_ID));
1330 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA));
1331
1332 if (SaId->Proto == EfiIPsecAH) {
1333 SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength;
1334 } else {
1335 SadEntrySize = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength);
1336 SadEntrySize += ALIGN_VARIABLE (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength);
1337 }
1338
1339 if (SaData->SpdSelector != NULL) {
1340 SadEntrySize += SadEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector);
1341 }
1342 SadEntry = AllocateZeroPool (SadEntrySize);
1343
1344 if (SadEntry == NULL) {
1345 return EFI_OUT_OF_RESOURCES;
1346 }
1347 //
1348 // Fix the address of Id and Data buffer and copy them, which is
1349 // continous memory and close to the base structure of SAD entry.
1350 //
1351 SadEntry->Id = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN));
1352 SadEntry->Data = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN));
1353
1354 CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID));
1355
1356 SadEntry->Data->Mode = SaData->Mode;
1357 SadEntry->Data->SequenceNumber = SaData->SNCount;
1358 SadEntry->Data->AntiReplayWindowSize = SaData->AntiReplayWindows;
1359
1360 ZeroMem (
1361 &SadEntry->Data->AntiReplayBitmap,
1362 sizeof (SadEntry->Data->AntiReplayBitmap)
1363 );
1364
1365 ZeroMem (
1366 &SadEntry->Data->AlgoInfo,
1367 sizeof (EFI_IPSEC_ALGO_INFO)
1368 );
1369
1370 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
1371 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
1372
1373 if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
1374 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN));
1375 CopyMem (
1376 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
1377 SaData->AlgoInfo.EspAlgoInfo.AuthKey,
1378 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength
1379 );
1380 }
1381
1382 if (SaId->Proto == EfiIPsecESP) {
1383 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId;
1384 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;
1385
1386 if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
1387 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
1388 ((UINT8 *) (SadEntry->Data + 1) +
1389 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength),
1390 sizeof (UINTN)
1391 );
1392 CopyMem (
1393 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
1394 SaData->AlgoInfo.EspAlgoInfo.EncKey,
1395 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength
1396 );
1397 }
1398 }
1399
1400 CopyMem (
1401 &SadEntry->Data->SaLifetime,
1402 &SaData->SaLifetime,
1403 sizeof (EFI_IPSEC_SA_LIFETIME)
1404 );
1405
1406 SadEntry->Data->PathMTU = SaData->PathMTU;
1407 SadEntry->Data->SpdSelector = NULL;
1408 SadEntry->Data->ESNEnabled = FALSE;
1409 SadEntry->Data->ManualSet = SaData->ManualSet;
1410
1411 //
1412 // Copy Tunnel Source/Destination Address
1413 //
1414 if (SaData->Mode == EfiIPsecTunnel) {
1415 CopyMem (
1416 &SadEntry->Data->TunnelDestAddress,
1417 &SaData->TunnelDestinationAddress,
1418 sizeof (EFI_IP_ADDRESS)
1419 );
1420 CopyMem (
1421 &SadEntry->Data->TunnelSourceAddress,
1422 &SaData->TunnelSourceAddress,
1423 sizeof (EFI_IP_ADDRESS)
1424 );
1425 }
1426 //
1427 // Update the spd.sas list of the spd entry specified by SAD selector
1428 //
1429 SpdList = &mConfigData[IPsecConfigDataTypeSpd];
1430
1431 for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) {
1432
1433 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
1434 if (IsSubSpdSelector (
1435 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
1436 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
1437 ) && SpdEntry->Data->Action == EfiIPsecActionProtect) {
1438 SadEntry->Data->SpdEntry = SpdEntry;
1439 SadEntry->Data->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *)((UINT8 *)SadEntry +
1440 SadEntrySize -
1441 (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector)
1442 );
1443 DuplicateSpdSelector (
1444 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
1445 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
1446 NULL
1447 );
1448 InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
1449 }
1450 }
1451 //
1452 // Insert the new SAD entry.
1453 //
1454 InsertTailList (EntryInsertBefore, &SadEntry->List);
1455
1456 return EFI_SUCCESS;
1457 }
1458
1459 /**
1460 Set the peer authorization configuration information for the EFI IPsec driver.
1461
1462 The IPsec configuration data has a unique selector/identifier separately to
1463 identify a data entry.
1464
1465 @param[in] Selector Pointer to an entry selector on operated
1466 configuration data specified by DataType.
1467 A NULL Selector causes the entire specified-type
1468 configuration information to be flushed.
1469 @param[in] Data The data buffer to be set. The structure
1470 of the data buffer should be EFI_IPSEC_PAD_DATA.
1471 @param[in] Context Pointer to one entry selector that describes
1472 the expected position the new data entry will
1473 be added. If Context is NULL, the new entry will
1474 be appended the end of database.
1475
1476 @retval EFI_OUT_OF_RESOURCES The required system resources could not be allocated.
1477 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1478
1479 **/
1480 EFI_STATUS
1481 SetPadEntry (
1482 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1483 IN VOID *Data,
1484 IN VOID *Context OPTIONAL
1485 )
1486 {
1487 IPSEC_PAD_ENTRY *PadEntry;
1488 EFI_IPSEC_PAD_ID *PadId;
1489 EFI_IPSEC_PAD_DATA *PadData;
1490 LIST_ENTRY *PadList;
1491 LIST_ENTRY *Entry;
1492 LIST_ENTRY *NextEntry;
1493 EFI_IPSEC_PAD_ID *InsertBefore;
1494 LIST_ENTRY *EntryInsertBefore;
1495 UINTN PadEntrySize;
1496
1497 PadId = (Selector == NULL) ? NULL : &Selector->PadId;
1498 PadData = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data;
1499 InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId;
1500 PadList = &mConfigData[IPsecConfigDataTypePad];
1501
1502 //
1503 // The default behavior is to insert the node ahead of the header.
1504 //
1505 EntryInsertBefore = PadList;
1506
1507 //
1508 // Remove the existed pad entry.
1509 //
1510 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) {
1511
1512 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
1513
1514 if (PadId == NULL ||
1515 ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId)
1516 ) {
1517 //
1518 // Record the existed entry position to keep the original order.
1519 //
1520 EntryInsertBefore = PadEntry->List.ForwardLink;
1521 RemoveEntryList (&PadEntry->List);
1522
1523 FreePool (PadEntry);
1524 }
1525 }
1526 //
1527 // Return success here if only want to remove the pad entry
1528 //
1529 if (PadData == NULL || PadId == NULL) {
1530 return EFI_SUCCESS;
1531 }
1532 //
1533 // Search the appointed entry position if InsertBefore is not NULL.
1534 //
1535 if (InsertBefore != NULL) {
1536
1537 NET_LIST_FOR_EACH (Entry, PadList) {
1538 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
1539
1540 if (ComparePadId (
1541 (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id,
1542 (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
1543 )) {
1544 EntryInsertBefore = Entry;
1545 break;
1546 }
1547 }
1548 }
1549
1550 //
1551 // Do PADDING for different arch.
1552 //
1553 PadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY));
1554 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID));
1555 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA));
1556 PadEntrySize = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0));
1557 PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0;
1558
1559 PadEntry = AllocateZeroPool (PadEntrySize);
1560
1561 if (PadEntry == NULL) {
1562 return EFI_OUT_OF_RESOURCES;
1563 }
1564 //
1565 // Fix the address of Id and Data buffer and copy them, which is
1566 // continous memory and close to the base structure of pad entry.
1567 //
1568 PadEntry->Id = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN));
1569 PadEntry->Data = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN));
1570
1571 CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID));
1572
1573 PadEntry->Data->AuthProtocol = PadData->AuthProtocol;
1574 PadEntry->Data->AuthMethod = PadData->AuthMethod;
1575 PadEntry->Data->IkeIdFlag = PadData->IkeIdFlag;
1576
1577 if (PadData->AuthData != NULL) {
1578 PadEntry->Data->AuthDataSize = PadData->AuthDataSize;
1579 PadEntry->Data->AuthData = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN));
1580 CopyMem (
1581 PadEntry->Data->AuthData,
1582 PadData->AuthData,
1583 PadData->AuthDataSize
1584 );
1585 } else {
1586 PadEntry->Data->AuthDataSize = 0;
1587 PadEntry->Data->AuthData = NULL;
1588 }
1589
1590 if (PadData->RevocationData != NULL) {
1591 PadEntry->Data->RevocationDataSize = PadData->RevocationDataSize;
1592 PadEntry->Data->RevocationData = (VOID *) ALIGN_POINTER (
1593 ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize),
1594 sizeof (UINTN)
1595 );
1596 CopyMem (
1597 PadEntry->Data->RevocationData,
1598 PadData->RevocationData,
1599 PadData->RevocationDataSize
1600 );
1601 } else {
1602 PadEntry->Data->RevocationDataSize = 0;
1603 PadEntry->Data->RevocationData = NULL;
1604 }
1605 //
1606 // Insert the new pad entry.
1607 //
1608 InsertTailList (EntryInsertBefore, &PadEntry->List);
1609
1610 return EFI_SUCCESS;
1611 }
1612
1613 /**
1614 This function lookup the data entry from IPsec SPD. Return the configuration
1615 value of the specified SPD Entry.
1616
1617 @param[in] Selector Pointer to an entry selector which is an identifier
1618 of the SPD entry.
1619 @param[in, out] DataSize On output the size of data returned in Data.
1620 @param[out] Data The buffer to return the contents of the IPsec
1621 configuration data. The type of the data buffer
1622 is associated with the DataType.
1623
1624 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1625 @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
1626 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
1627 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
1628 updated with the size needed to complete the request.
1629
1630 **/
1631 EFI_STATUS
1632 GetSpdEntry (
1633 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1634 IN OUT UINTN *DataSize,
1635 OUT VOID *Data
1636 )
1637 {
1638 IPSEC_SPD_ENTRY *SpdEntry;
1639 IPSEC_SAD_ENTRY *SadEntry;
1640 EFI_IPSEC_SPD_SELECTOR *SpdSel;
1641 EFI_IPSEC_SPD_DATA *SpdData;
1642 LIST_ENTRY *SpdList;
1643 LIST_ENTRY *SpdSas;
1644 LIST_ENTRY *Entry;
1645 UINTN RequiredSize;
1646
1647 SpdSel = &Selector->SpdSelector;
1648 SpdData = (EFI_IPSEC_SPD_DATA *) Data;
1649 SpdList = &mConfigData[IPsecConfigDataTypeSpd];
1650
1651 NET_LIST_FOR_EACH (Entry, SpdList) {
1652 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
1653
1654 //
1655 // Find the required SPD entry
1656 //
1657 if (CompareSpdSelector (
1658 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
1659 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
1660 )) {
1661
1662 RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data);
1663 if (*DataSize < RequiredSize) {
1664 *DataSize = RequiredSize;
1665 return EFI_BUFFER_TOO_SMALL;
1666 }
1667
1668 if (SpdData == NULL) {
1669 return EFI_INVALID_PARAMETER;
1670 }
1671
1672 *DataSize = RequiredSize;
1673
1674 //
1675 // Extract and fill all SaId array from the SPD.sas list
1676 //
1677 SpdSas = &SpdEntry->Data->Sas;
1678 SpdData->SaIdCount = 0;
1679
1680 NET_LIST_FOR_EACH (Entry, SpdSas) {
1681 SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
1682 CopyMem (
1683 &SpdData->SaId[SpdData->SaIdCount++],
1684 SadEntry->Id,
1685 sizeof (EFI_IPSEC_SA_ID)
1686 );
1687 }
1688 //
1689 // Fill the other fields in SPD data.
1690 //
1691 CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name));
1692
1693 SpdData->PackageFlag = SpdEntry->Data->PackageFlag;
1694 SpdData->Action = SpdEntry->Data->Action;
1695
1696 if (SpdData->Action != EfiIPsecActionProtect) {
1697 SpdData->ProcessingPolicy = NULL;
1698 } else {
1699 SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID));
1700
1701 IpSecDuplicateProcessPolicy (
1702 SpdData->ProcessingPolicy,
1703 SpdEntry->Data->ProcessingPolicy
1704 );
1705 }
1706
1707 return EFI_SUCCESS;
1708 }
1709 }
1710
1711 return EFI_NOT_FOUND;
1712 }
1713
1714 /**
1715 This function lookup the data entry from IPsec SAD. Return the configuration
1716 value of the specified SAD Entry.
1717
1718 @param[in] Selector Pointer to an entry selector which is an identifier
1719 of the SAD entry.
1720 @param[in, out] DataSize On output, the size of data returned in Data.
1721 @param[out] Data The buffer to return the contents of the IPsec
1722 configuration data. The type of the data buffer
1723 is associated with the DataType.
1724
1725 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1726 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
1727 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
1728 updated with the size needed to complete the request.
1729
1730 **/
1731 EFI_STATUS
1732 GetSadEntry (
1733 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1734 IN OUT UINTN *DataSize,
1735 OUT VOID *Data
1736 )
1737 {
1738 IPSEC_SAD_ENTRY *SadEntry;
1739 LIST_ENTRY *Entry;
1740 LIST_ENTRY *SadList;
1741 EFI_IPSEC_SA_ID *SaId;
1742 EFI_IPSEC_SA_DATA2 *SaData;
1743 UINTN RequiredSize;
1744
1745 SaId = &Selector->SaId;
1746 SaData = (EFI_IPSEC_SA_DATA2 *) Data;
1747 SadList = &mConfigData[IPsecConfigDataTypeSad];
1748
1749 NET_LIST_FOR_EACH (Entry, SadList) {
1750 SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
1751
1752 //
1753 // Find the required SAD entry.
1754 //
1755 if (CompareSaId (
1756 (EFI_IPSEC_CONFIG_SELECTOR *) SaId,
1757 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
1758 )) {
1759 //
1760 // Calculate the required size of the SAD entry.
1761 // Data Layout is follows:
1762 // |EFI_IPSEC_SA_DATA
1763 // |AuthKey
1764 // |EncryptKey (Optional)
1765 // |SpdSelector (Optional)
1766 //
1767 RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2));
1768
1769 if (SaId->Proto == EfiIPsecAH) {
1770 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength);
1771 } else {
1772 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);
1773 RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength);
1774 }
1775
1776 if (SadEntry->Data->SpdSelector != NULL) {
1777 RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector);
1778 }
1779
1780 if (*DataSize < RequiredSize) {
1781 *DataSize = RequiredSize;
1782 return EFI_BUFFER_TOO_SMALL;
1783 }
1784
1785 //
1786 // Fill the data fields of SAD entry.
1787 //
1788 *DataSize = RequiredSize;
1789 SaData->Mode = SadEntry->Data->Mode;
1790 SaData->SNCount = SadEntry->Data->SequenceNumber;
1791 SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize;
1792
1793 CopyMem (
1794 &SaData->SaLifetime,
1795 &SadEntry->Data->SaLifetime,
1796 sizeof (EFI_IPSEC_SA_LIFETIME)
1797 );
1798
1799 ZeroMem (
1800 &SaData->AlgoInfo,
1801 sizeof (EFI_IPSEC_ALGO_INFO)
1802 );
1803
1804 if (SaId->Proto == EfiIPsecAH) {
1805 //
1806 // Copy AH alogrithm INFO to SaData
1807 //
1808 SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId;
1809 SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength;
1810 if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) {
1811 SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
1812 CopyMem (
1813 SaData->AlgoInfo.AhAlgoInfo.AuthKey,
1814 SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey,
1815 SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength
1816 );
1817 }
1818 } else if (SaId->Proto == EfiIPsecESP) {
1819 //
1820 // Copy ESP alogrithem INFO to SaData
1821 //
1822 SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId;
1823 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength;
1824 if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
1825 SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
1826 CopyMem (
1827 SaData->AlgoInfo.EspAlgoInfo.AuthKey,
1828 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
1829 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength
1830 );
1831 }
1832
1833 SaData->AlgoInfo.EspAlgoInfo.EncAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId;
1834 SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength;
1835
1836 if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
1837 SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
1838 ((UINT8 *) (SaData + 1) +
1839 SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength),
1840 sizeof (UINTN)
1841 );
1842 CopyMem (
1843 SaData->AlgoInfo.EspAlgoInfo.EncKey,
1844 SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
1845 SaData->AlgoInfo.EspAlgoInfo.EncKeyLength
1846 );
1847 }
1848 }
1849
1850 SaData->PathMTU = SadEntry->Data->PathMTU;
1851
1852 //
1853 // Fill Tunnel Address if it is Tunnel Mode
1854 //
1855 if (SadEntry->Data->Mode == EfiIPsecTunnel) {
1856 CopyMem (
1857 &SaData->TunnelDestinationAddress,
1858 &SadEntry->Data->TunnelDestAddress,
1859 sizeof (EFI_IP_ADDRESS)
1860 );
1861 CopyMem (
1862 &SaData->TunnelSourceAddress,
1863 &SadEntry->Data->TunnelSourceAddress,
1864 sizeof (EFI_IP_ADDRESS)
1865 );
1866 }
1867 //
1868 // Fill the spd selector field of SAD data
1869 //
1870 if (SadEntry->Data->SpdSelector != NULL) {
1871
1872 SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) (
1873 (UINT8 *)SaData +
1874 RequiredSize -
1875 SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector)
1876 );
1877
1878 DuplicateSpdSelector (
1879 (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
1880 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
1881 NULL
1882 );
1883
1884 } else {
1885
1886 SaData->SpdSelector = NULL;
1887 }
1888
1889 SaData->ManualSet = SadEntry->Data->ManualSet;
1890
1891 return EFI_SUCCESS;
1892 }
1893 }
1894
1895 return EFI_NOT_FOUND;
1896 }
1897
1898 /**
1899 This function lookup the data entry from IPsec PAD. Return the configuration
1900 value of the specified PAD Entry.
1901
1902 @param[in] Selector Pointer to an entry selector which is an identifier
1903 of the PAD entry.
1904 @param[in, out] DataSize On output the size of data returned in Data.
1905 @param[out] Data The buffer to return the contents of the IPsec
1906 configuration data. The type of the data buffer
1907 is associated with the DataType.
1908
1909 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1910 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
1911 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
1912 updated with the size needed to complete the request.
1913
1914 **/
1915 EFI_STATUS
1916 GetPadEntry (
1917 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1918 IN OUT UINTN *DataSize,
1919 OUT VOID *Data
1920 )
1921 {
1922 IPSEC_PAD_ENTRY *PadEntry;
1923 LIST_ENTRY *PadList;
1924 LIST_ENTRY *Entry;
1925 EFI_IPSEC_PAD_ID *PadId;
1926 EFI_IPSEC_PAD_DATA *PadData;
1927 UINTN RequiredSize;
1928
1929 PadId = &Selector->PadId;
1930 PadData = (EFI_IPSEC_PAD_DATA *) Data;
1931 PadList = &mConfigData[IPsecConfigDataTypePad];
1932
1933 NET_LIST_FOR_EACH (Entry, PadList) {
1934 PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
1935
1936 //
1937 // Find the required pad entry.
1938 //
1939 if (ComparePadId (
1940 (EFI_IPSEC_CONFIG_SELECTOR *) PadId,
1941 (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id
1942 )) {
1943 //
1944 // Calculate the required size of the pad entry.
1945 //
1946 RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));
1947 RequiredSize = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize);
1948 RequiredSize += PadEntry->Data->RevocationDataSize;
1949
1950 if (*DataSize < RequiredSize) {
1951 *DataSize = RequiredSize;
1952 return EFI_BUFFER_TOO_SMALL;
1953 }
1954 //
1955 // Fill the data fields of pad entry
1956 //
1957 *DataSize = RequiredSize;
1958 PadData->AuthProtocol = PadEntry->Data->AuthProtocol;
1959 PadData->AuthMethod = PadEntry->Data->AuthMethod;
1960 PadData->IkeIdFlag = PadEntry->Data->IkeIdFlag;
1961
1962 //
1963 // Copy Authentication data.
1964 //
1965 if (PadEntry->Data->AuthData != NULL) {
1966
1967 PadData->AuthDataSize = PadEntry->Data->AuthDataSize;
1968 PadData->AuthData = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN));
1969 CopyMem (
1970 PadData->AuthData,
1971 PadEntry->Data->AuthData,
1972 PadData->AuthDataSize
1973 );
1974 } else {
1975
1976 PadData->AuthDataSize = 0;
1977 PadData->AuthData = NULL;
1978 }
1979 //
1980 // Copy Revocation Data.
1981 //
1982 if (PadEntry->Data->RevocationData != NULL) {
1983
1984 PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize;
1985 PadData->RevocationData = (VOID *) ALIGN_POINTER (
1986 ((UINT8 *) (PadData + 1) + PadData->AuthDataSize),
1987 sizeof (UINTN)
1988 );
1989 CopyMem (
1990 PadData->RevocationData,
1991 PadEntry->Data->RevocationData,
1992 PadData->RevocationDataSize
1993 );
1994 } else {
1995
1996 PadData->RevocationDataSize = 0;
1997 PadData->RevocationData = NULL;
1998 }
1999
2000 return EFI_SUCCESS;
2001 }
2002 }
2003
2004 return EFI_NOT_FOUND;
2005 }
2006
2007 /**
2008 Copy Source Process Policy to the Destination Process Policy.
2009
2010 @param[in] Dst Pointer to the Source Process Policy.
2011 @param[in] Src Pointer to the Destination Process Policy.
2012
2013 **/
2014 VOID
2015 IpSecDuplicateProcessPolicy (
2016 IN EFI_IPSEC_PROCESS_POLICY *Dst,
2017 IN EFI_IPSEC_PROCESS_POLICY *Src
2018 )
2019 {
2020 //
2021 // Firstly copy the structure content itself.
2022 //
2023 CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY));
2024
2025 //
2026 // Recursively copy the tunnel option if needed.
2027 //
2028 if (Dst->Mode != EfiIPsecTunnel) {
2029 ASSERT (Dst->TunnelOption == NULL);
2030 } else {
2031 Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN));
2032 CopyMem (
2033 Dst->TunnelOption,
2034 Src->TunnelOption,
2035 sizeof (EFI_IPSEC_TUNNEL_OPTION)
2036 );
2037 }
2038 }
2039
2040 /**
2041 Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
2042 to by the pointer members.
2043
2044 @param[in] SpdData Pointer to a specified EFI_IPSEC_SPD_DATA.
2045
2046 @return the whole size the specified EFI_IPSEC_SPD_DATA.
2047
2048 **/
2049 UINTN
2050 IpSecGetSizeOfEfiSpdData (
2051 IN EFI_IPSEC_SPD_DATA *SpdData
2052 )
2053 {
2054 UINTN Size;
2055
2056 Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA));
2057
2058 if (SpdData->Action == EfiIPsecActionProtect) {
2059 Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY));
2060
2061 if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
2062 Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION));
2063 }
2064 }
2065
2066 return Size;
2067 }
2068
2069 /**
2070 Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed
2071 to by the pointer members and the buffer size used by the Sa List.
2072
2073 @param[in] SpdData Pointer to the specified IPSEC_SPD_DATA.
2074
2075 @return the whole size of IPSEC_SPD_DATA.
2076
2077 **/
2078 UINTN
2079 IpSecGetSizeOfSpdData (
2080 IN IPSEC_SPD_DATA *SpdData
2081 )
2082 {
2083 UINTN Size;
2084 LIST_ENTRY *Link;
2085
2086 Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID);
2087
2088 if (SpdData->Action == EfiIPsecActionProtect) {
2089 Size += sizeof (EFI_IPSEC_PROCESS_POLICY);
2090
2091 if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
2092 Size += sizeof (EFI_IPSEC_TUNNEL_OPTION);
2093 }
2094 }
2095
2096 NET_LIST_FOR_EACH (Link, &SpdData->Sas) {
2097 Size += sizeof (EFI_IPSEC_SA_ID);
2098 }
2099
2100 return Size;
2101 }
2102
2103 /**
2104 Get the IPsec Variable.
2105
2106 Get the all variables which start with the string contained in VaraiableName.
2107 Since all IPsec related variable store in continual space, those kinds of
2108 variable can be searched by the EfiGetNextVariableName. Those variables also are
2109 returned in a continual buffer.
2110
2111 @param[in] VariableName Pointer to a specified Variable Name.
2112 @param[in] VendorGuid Pointer to a specified Vendor Guid.
2113 @param[in] Attributes Point to memory location to return the attributes
2114 of variable. If the point is NULL, the parameter
2115 would be ignored.
2116 @param[in, out] DataSize As input, point to the maximum size of return
2117 Data-Buffer. As output, point to the actual
2118 size of the returned Data-Buffer.
2119 @param[in] Data Point to return Data-Buffer.
2120
2121 @retval EFI_ABORTED If the Variable size which contained in the variable
2122 structure doesn't match the variable size obtained
2123 from the EFIGetVariable.
2124 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has
2125 been updated with the size needed to complete the request.
2126 @retval EFI_SUCCESS The function completed successfully.
2127 @retval others Other errors found during the variable getting.
2128 **/
2129 EFI_STATUS
2130 IpSecGetVariable (
2131 IN CHAR16 *VariableName,
2132 IN EFI_GUID *VendorGuid,
2133 IN UINT32 *Attributes, OPTIONAL
2134 IN OUT UINTN *DataSize,
2135 IN VOID *Data
2136 )
2137 {
2138 EFI_STATUS Status;
2139 EFI_GUID VendorGuidI;
2140 UINTN VariableNameLength;
2141 CHAR16 *VariableNameI;
2142 UINTN VariableNameISize;
2143 UINTN VariableNameISizeNew;
2144 UINTN VariableIndex;
2145 UINTN VariableCount;
2146 IP_SEC_VARIABLE_INFO IpSecVariableInfo;
2147 UINTN DataSizeI;
2148
2149 //
2150 // The variable name constructor is "VariableName + Info/0001/0002/... + NULL".
2151 // So the varialbe name is like "VariableNameInfo", "VariableName0001", ...
2152 // "VariableNameNULL".
2153 //
2154 VariableNameLength = StrLen (VariableName);
2155 VariableNameISize = (VariableNameLength + 5) * sizeof (CHAR16);
2156 VariableNameI = AllocateZeroPool (VariableNameISize);
2157 ASSERT (VariableNameI != NULL);
2158
2159 //
2160 // Construct the varible name of ipsecconfig meta data.
2161 //
2162 UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info");
2163
2164 DataSizeI = sizeof (IpSecVariableInfo);
2165
2166 Status = gRT->GetVariable (
2167 VariableNameI,
2168 VendorGuid,
2169 Attributes,
2170 &DataSizeI,
2171 &IpSecVariableInfo
2172 );
2173 if (EFI_ERROR (Status)) {
2174 goto ON_EXIT;
2175 }
2176
2177 if (*DataSize < IpSecVariableInfo.VariableSize) {
2178 *DataSize = IpSecVariableInfo.VariableSize;
2179 Status = EFI_BUFFER_TOO_SMALL;
2180 goto ON_EXIT;
2181 }
2182
2183 VariableCount = IpSecVariableInfo.VariableCount;
2184 VariableNameI[0] = L'\0';
2185
2186 while (VariableCount != 0) {
2187 //
2188 // Get the variable name one by one in the variable database.
2189 //
2190 VariableNameISizeNew = VariableNameISize;
2191 Status = gRT->GetNextVariableName (
2192 &VariableNameISizeNew,
2193 VariableNameI,
2194 &VendorGuidI
2195 );
2196 if (Status == EFI_BUFFER_TOO_SMALL) {
2197 VariableNameI = ReallocatePool (
2198 VariableNameISize,
2199 VariableNameISizeNew,
2200 VariableNameI
2201 );
2202 if (VariableNameI == NULL) {
2203 Status = EFI_OUT_OF_RESOURCES;
2204 break;
2205 }
2206 VariableNameISize = VariableNameISizeNew;
2207
2208 Status = gRT->GetNextVariableName (
2209 &VariableNameISizeNew,
2210 VariableNameI,
2211 &VendorGuidI
2212 );
2213 }
2214
2215 if (EFI_ERROR (Status)) {
2216 break;
2217 }
2218 //
2219 // Check whether the current variable is the required "ipsecconfig".
2220 //
2221 if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 ||
2222 CompareGuid (VendorGuid, &VendorGuidI)
2223 ) {
2224 //
2225 // Parse the variable count of the current ipsecconfig data.
2226 //
2227 VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength);
2228 if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) {
2229 //
2230 // Get the variable size of the current ipsecconfig data.
2231 //
2232 DataSizeI = 0;
2233 Status = gRT->GetVariable (
2234 VariableNameI,
2235 VendorGuid,
2236 Attributes,
2237 &DataSizeI,
2238 NULL
2239 );
2240 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
2241 //
2242 // Validate the variable count and variable size.
2243 //
2244 if (VariableIndex != IpSecVariableInfo.VariableCount) {
2245 //
2246 // If the varaibe is not the last one, its size should be the max
2247 // size of the single variable.
2248 //
2249 if (DataSizeI != IpSecVariableInfo.SingleVariableSize) {
2250 return EFI_ABORTED;
2251 }
2252 } else {
2253 if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) {
2254 return EFI_ABORTED;
2255 }
2256 }
2257 //
2258 // Get the variable data of the current ipsecconfig data and
2259 // store it into user buffer continously.
2260 //
2261 Status = gRT->GetVariable (
2262 VariableNameI,
2263 VendorGuid,
2264 Attributes,
2265 &DataSizeI,
2266 (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize
2267 );
2268 ASSERT_EFI_ERROR (Status);
2269 VariableCount--;
2270 }
2271 }
2272 }
2273 //
2274 // The VariableCount in "VariableNameInfo" varaible should have the correct
2275 // numbers of variables which name starts with VariableName.
2276 //
2277 if (VariableCount != 0) {
2278 Status = EFI_ABORTED;
2279 }
2280
2281 ON_EXIT:
2282 if (VariableNameI != NULL) {
2283 FreePool (VariableNameI);
2284 }
2285 return Status;
2286 }
2287
2288 /**
2289 Set the IPsec variables.
2290
2291 Set all IPsec variables which start with the specified variable name. Those variables
2292 are set one by one.
2293
2294 @param[in] VariableName The name of the vendor's variable. It is a
2295 Null-Terminated Unicode String.
2296 @param[in] VendorGuid Unify identifier for vendor.
2297 @param[in] Attributes Point to memory location to return the attributes of
2298 variable. If the point is NULL, the parameter would be ignored.
2299 @param[in] DataSize The size in bytes of Data-Buffer.
2300 @param[in] Data Points to the content of the variable.
2301
2302 @retval EFI_SUCCESS The firmware successfully stored the variable and its data, as
2303 defined by the Attributes.
2304 @retval others Storing the variables failed.
2305
2306 **/
2307 EFI_STATUS
2308 IpSecSetVariable (
2309 IN CHAR16 *VariableName,
2310 IN EFI_GUID *VendorGuid,
2311 IN UINT32 Attributes,
2312 IN UINTN DataSize,
2313 IN VOID *Data
2314 )
2315 {
2316 EFI_STATUS Status;
2317 CHAR16 *VariableNameI;
2318 UINTN VariableNameSize;
2319 UINTN VariableIndex;
2320 IP_SEC_VARIABLE_INFO IpSecVariableInfo;
2321 UINT64 MaximumVariableStorageSize;
2322 UINT64 RemainingVariableStorageSize;
2323 UINT64 MaximumVariableSize;
2324
2325 Status = gRT->QueryVariableInfo (
2326 Attributes,
2327 &MaximumVariableStorageSize,
2328 &RemainingVariableStorageSize,
2329 &MaximumVariableSize
2330 );
2331 if (EFI_ERROR (Status)) {
2332 return Status;
2333 }
2334
2335 //
2336 // "VariableName + Info/0001/0002/... + NULL"
2337 //
2338 VariableNameSize = (StrLen (VariableName) + 5) * sizeof (CHAR16);
2339 VariableNameI = AllocateZeroPool (VariableNameSize);
2340
2341 if (VariableNameI == NULL) {
2342 Status = EFI_OUT_OF_RESOURCES;
2343 goto ON_EXIT;
2344 }
2345 //
2346 // Construct the variable of ipsecconfig general information. Like the total
2347 // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables.
2348 //
2349 UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info");
2350 MaximumVariableSize -= VariableNameSize;
2351
2352 IpSecVariableInfo.VariableCount = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize);
2353 IpSecVariableInfo.VariableSize = (UINT32) DataSize;
2354 IpSecVariableInfo.SingleVariableSize = (UINT32) MaximumVariableSize;
2355
2356 //
2357 // Set the variable of ipsecconfig general information.
2358 //
2359 Status = gRT->SetVariable (
2360 VariableNameI,
2361 VendorGuid,
2362 Attributes,
2363 sizeof (IpSecVariableInfo),
2364 &IpSecVariableInfo
2365 );
2366 if (EFI_ERROR (Status)) {
2367 DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status));
2368 goto ON_EXIT;
2369 }
2370
2371 for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) {
2372 //
2373 // Construct and set the variable of ipsecconfig data one by one.
2374 // The index of variable name begin from 0001, and the varaible name
2375 // likes "VariableName0001", "VaraiableName0002"....
2376 //
2377 UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1);
2378 Status = gRT->SetVariable (
2379 VariableNameI,
2380 VendorGuid,
2381 Attributes,
2382 (VariableIndex == IpSecVariableInfo.VariableCount - 1) ?
2383 (DataSize % (UINTN) MaximumVariableSize) :
2384 (UINTN) MaximumVariableSize,
2385 (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize
2386 );
2387
2388 if (EFI_ERROR (Status)) {
2389 DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status));
2390 goto ON_EXIT;
2391 }
2392 }
2393
2394 ON_EXIT:
2395 if (VariableNameI != NULL) {
2396 FreePool (VariableNameI);
2397 }
2398
2399 return Status;
2400 }
2401
2402 /**
2403 Return the configuration value for the EFI IPsec driver.
2404
2405 This function lookup the data entry from IPsec database or IKEv2 configuration
2406 information. The expected data type and unique identification are described in
2407 DataType and Selector parameters.
2408
2409 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
2410 @param[in] DataType The type of data to retrieve.
2411 @param[in] Selector Pointer to an entry selector that is an identifier of the IPsec
2412 configuration data entry.
2413 @param[in, out] DataSize On output the size of data returned in Data.
2414 @param[out] Data The buffer to return the contents of the IPsec configuration data.
2415 The type of the data buffer associated with the DataType.
2416
2417 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
2418 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
2419 - This is NULL.
2420 - Selector is NULL.
2421 - DataSize is NULL.
2422 - Data is NULL and *DataSize is not zero
2423 @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.
2424 @retval EFI_UNSUPPORTED The specified DataType is not supported.
2425 @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been
2426 updated with the size needed to complete the request.
2427
2428 **/
2429 EFI_STATUS
2430 EFIAPI
2431 EfiIpSecConfigGetData (
2432 IN EFI_IPSEC_CONFIG_PROTOCOL *This,
2433 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2434 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
2435 IN OUT UINTN *DataSize,
2436 OUT VOID *Data
2437 )
2438 {
2439 if (This == NULL || Selector == NULL || DataSize == NULL) {
2440 return EFI_INVALID_PARAMETER;
2441 }
2442
2443 if (*DataSize != 0 && Data == NULL) {
2444 return EFI_INVALID_PARAMETER;
2445 }
2446
2447 if (DataType >= IPsecConfigDataTypeMaximum) {
2448 return EFI_UNSUPPORTED;
2449 }
2450
2451 return mGetPolicyEntry[DataType](Selector, DataSize, Data);
2452 }
2453
2454 /**
2455 Set the security association, security policy and peer authorization configuration
2456 information for the EFI IPsec driver.
2457
2458 This function is used to set the IPsec configuration information of type DataType for
2459 the EFI IPsec driver.
2460 The IPsec configuration data has a unique selector/identifier separately to identify
2461 a data entry. The selector structure depends on DataType's definition.
2462 Using SetData() with a Data of NULL causes the IPsec configuration data entry identified
2463 by DataType and Selector to be deleted.
2464
2465 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
2466 @param[in] DataType The type of data to be set.
2467 @param[in] Selector Pointer to an entry selector on operated configuration data
2468 specified by DataType. A NULL Selector causes the entire
2469 specified-type configuration information to be flushed.
2470 @param[in] Data The data buffer to be set. The structure of the data buffer is
2471 associated with the DataType.
2472 @param[in] InsertBefore Pointer to one entry selector which describes the expected
2473 position the new data entry will be added. If InsertBefore is NULL,
2474 the new entry will be appended to the end of the database.
2475
2476 @retval EFI_SUCCESS The specified configuration entry data was set successfully.
2477 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
2478 - This is NULL.
2479 @retval EFI_UNSUPPORTED The specified DataType is not supported.
2480 @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
2481
2482 **/
2483 EFI_STATUS
2484 EFIAPI
2485 EfiIpSecConfigSetData (
2486 IN EFI_IPSEC_CONFIG_PROTOCOL *This,
2487 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2488 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
2489 IN VOID *Data,
2490 IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL
2491 )
2492 {
2493 EFI_STATUS Status;
2494
2495 if (This == NULL) {
2496 return EFI_INVALID_PARAMETER;
2497 }
2498
2499 if (DataType >= IPsecConfigDataTypeMaximum) {
2500 return EFI_UNSUPPORTED;
2501 }
2502
2503 Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore);
2504
2505 if (!EFI_ERROR (Status) && !mSetBySelf) {
2506 //
2507 // Save the updated config data into variable.
2508 //
2509 IpSecConfigSave ();
2510 }
2511
2512 return Status;
2513 }
2514
2515 /**
2516 Enumerates the current selector for IPsec configuration data entry.
2517
2518 This function is called multiple times to retrieve the entry Selector in IPsec
2519 configuration database. On each call to GetNextSelector(), the next entry
2520 Selector are retrieved into the output interface.
2521
2522 If the entire IPsec configuration database has been iterated, the error
2523 EFI_NOT_FOUND is returned.
2524 If the Selector buffer is too small for the next Selector copy, an
2525 EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect
2526 the size of buffer needed.
2527
2528 On the initial call to GetNextSelector() to start the IPsec configuration database
2529 search, a pointer to the buffer with all zero value is passed in Selector. Calls
2530 to SetData() between calls to GetNextSelector may produce unpredictable results.
2531
2532 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
2533 @param[in] DataType The type of IPsec configuration data to retrieve.
2534 @param[in, out] SelectorSize The size of the Selector buffer.
2535 @param[in, out] Selector On input, supplies the pointer to last Selector that was
2536 returned by GetNextSelector().
2537 On output, returns one copy of the current entry Selector
2538 of a given DataType.
2539
2540 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
2541 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
2542 - This is NULL.
2543 - SelectorSize is NULL.
2544 - Selector is NULL.
2545 @retval EFI_NOT_FOUND The next configuration data entry was not found.
2546 @retval EFI_UNSUPPORTED The specified DataType is not supported.
2547 @retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter
2548 has been updated with the size needed to complete the search
2549 request.
2550
2551 **/
2552 EFI_STATUS
2553 EFIAPI
2554 EfiIpSecConfigGetNextSelector (
2555 IN EFI_IPSEC_CONFIG_PROTOCOL *This,
2556 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2557 IN OUT UINTN *SelectorSize,
2558 IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector
2559 )
2560 {
2561 LIST_ENTRY *Link;
2562 IPSEC_COMMON_POLICY_ENTRY *CommonEntry;
2563 BOOLEAN IsFound;
2564
2565 if (This == NULL || Selector == NULL || SelectorSize == NULL) {
2566 return EFI_INVALID_PARAMETER;
2567 }
2568
2569 if (DataType >= IPsecConfigDataTypeMaximum) {
2570 return EFI_UNSUPPORTED;
2571 }
2572
2573 IsFound = FALSE;
2574
2575 NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) {
2576 CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List);
2577
2578 if (IsFound || (BOOLEAN)(mIsZeroSelector[DataType](Selector))) {
2579 //
2580 // If found the appointed entry, then duplicate the next one and return,
2581 // or if the appointed entry is zero, then return the first one directly.
2582 //
2583 return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize);
2584 } else {
2585 //
2586 // Set the flag if find the appointed entry.
2587 //
2588 IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector);
2589 }
2590 }
2591
2592 return EFI_NOT_FOUND;
2593 }
2594
2595 /**
2596 Register an event that is to be signaled whenever a configuration process on the
2597 specified IPsec configuration information is done.
2598
2599 The register function is not surpport now and always returns EFI_UNSUPPORTED.
2600
2601 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
2602 @param[in] DataType The type of data to be registered the event for.
2603 @param[in] Event The event to be registered.
2604
2605 @retval EFI_SUCCESS The event is registered successfully.
2606 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2607 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2608 @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified
2609 DataType is not supported.
2610
2611 **/
2612 EFI_STATUS
2613 EFIAPI
2614 EfiIpSecConfigRegisterNotify (
2615 IN EFI_IPSEC_CONFIG_PROTOCOL *This,
2616 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2617 IN EFI_EVENT Event
2618 )
2619 {
2620 return EFI_UNSUPPORTED;
2621 }
2622
2623 /**
2624 Remove the specified event that was previously registered on the specified IPsec
2625 configuration data.
2626
2627 This function is not support now and alwasy return EFI_UNSUPPORTED.
2628
2629 @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
2630 @param[in] DataType The configuration data type to remove the registered event for.
2631 @param[in] Event The event to be unregistered.
2632
2633 @retval EFI_SUCCESS The event was removed successfully.
2634 @retval EFI_NOT_FOUND The Event specified by DataType could not be found in the
2635 database.
2636 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2637 @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified
2638 DataType is not supported.
2639
2640 **/
2641 EFI_STATUS
2642 EFIAPI
2643 EfiIpSecConfigUnregisterNotify (
2644 IN EFI_IPSEC_CONFIG_PROTOCOL *This,
2645 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2646 IN EFI_EVENT Event
2647 )
2648 {
2649 return EFI_UNSUPPORTED;
2650 }
2651
2652 /**
2653 Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer.
2654
2655 This function is a caller defined function, and it is called by the IpSecVisitConfigData().
2656 The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to
2657 copy all types of IPsec Config datas into one buffer and store this buffer into firmware in
2658 the form of several variables.
2659
2660 @param[in] Type A specified IPSEC_CONFIG_DATA_TYPE.
2661 @param[in] Selector Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied
2662 to the buffer.
2663 @param[in] Data Points to data to be copied to the buffer. The
2664 Data type is related to the Type.
2665 @param[in] SelectorSize The size of the Selector.
2666 @param[in] DataSize The size of the Data.
2667 @param[in, out] Buffer The buffer to store the Selector and Data.
2668
2669 @retval EFI_SUCCESS Copy the Selector and Data to a buffer successfully.
2670 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
2671
2672 **/
2673 EFI_STATUS
2674 IpSecCopyPolicyEntry (
2675 IN EFI_IPSEC_CONFIG_DATA_TYPE Type,
2676 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
2677 IN VOID *Data,
2678 IN UINTN SelectorSize,
2679 IN UINTN DataSize,
2680 IN OUT IPSEC_VARIABLE_BUFFER *Buffer
2681 )
2682 {
2683 IPSEC_VAR_ITEM_HEADER SelectorHeader;
2684 IPSEC_VAR_ITEM_HEADER DataHeader;
2685 UINTN EntrySize;
2686 UINT8 *TempPoint;
2687
2688 if (Type == IPsecConfigDataTypeSad) {
2689 //
2690 // Don't save automatically-generated SA entry into variable.
2691 //
2692 if (((EFI_IPSEC_SA_DATA2 *) Data)->ManualSet == FALSE) {
2693 return EFI_SUCCESS;
2694 }
2695 }
2696 //
2697 // Increase the capacity size of the buffer if needed.
2698 //
2699 EntrySize = ALIGN_VARIABLE (sizeof (SelectorHeader));
2700 EntrySize = ALIGN_VARIABLE (EntrySize + SelectorSize);
2701 EntrySize = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader));
2702 EntrySize = ALIGN_VARIABLE (EntrySize + DataSize);
2703
2704 //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader);
2705 if (Buffer->Capacity - Buffer->Size < EntrySize) {
2706 //
2707 // Calculate the required buffer
2708 //
2709 Buffer->Capacity += EntrySize;
2710 TempPoint = AllocatePool (Buffer->Capacity);
2711
2712 if (TempPoint == NULL) {
2713 return EFI_OUT_OF_RESOURCES;
2714 }
2715 //
2716 // Copy the old Buffer to new buffer and free the old one.
2717 //
2718 CopyMem (TempPoint, Buffer->Ptr, Buffer->Size);
2719 FreePool (Buffer->Ptr);
2720
2721 Buffer->Ptr = TempPoint;
2722 }
2723
2724 mFixPolicyEntry[Type](Selector, Data);
2725
2726 //
2727 // Fill the selector header and copy it into buffer.
2728 //
2729 SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT);
2730 SelectorHeader.Size = (UINT16) SelectorSize;
2731
2732 CopyMem (
2733 Buffer->Ptr + Buffer->Size,
2734 &SelectorHeader,
2735 sizeof (SelectorHeader)
2736 );
2737 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader));
2738
2739 //
2740 // Copy the selector into buffer.
2741 //
2742 CopyMem (
2743 Buffer->Ptr + Buffer->Size,
2744 Selector,
2745 SelectorSize
2746 );
2747 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + SelectorSize);
2748
2749 //
2750 // Fill the data header and copy it into buffer.
2751 //
2752 DataHeader.Type = (UINT8) Type;
2753 DataHeader.Size = (UINT16) DataSize;
2754
2755 CopyMem (
2756 Buffer->Ptr + Buffer->Size,
2757 &DataHeader,
2758 sizeof (DataHeader)
2759 );
2760 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader));
2761 //
2762 // Copy the data into buffer.
2763 //
2764 CopyMem (
2765 Buffer->Ptr + Buffer->Size,
2766 Data,
2767 DataSize
2768 );
2769 Buffer->Size = ALIGN_VARIABLE (Buffer->Size + DataSize);
2770
2771 mUnfixPolicyEntry[Type](Selector, Data);
2772
2773 return EFI_SUCCESS;
2774 }
2775
2776 /**
2777 Visit all IPsec Configurations of specified Type and call the caller defined
2778 interface.
2779
2780 @param[in] DataType The specified IPsec Config Data Type.
2781 @param[in] Routine The function defined by the caller.
2782 @param[in] Context The data passed to the Routine.
2783
2784 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated
2785 @retval EFI_SUCCESS This function completed successfully.
2786
2787 **/
2788 EFI_STATUS
2789 IpSecVisitConfigData (
2790 IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
2791 IN IPSEC_COPY_POLICY_ENTRY Routine,
2792 IN VOID *Context
2793 )
2794 {
2795 EFI_STATUS GetNextStatus;
2796 EFI_STATUS GetDataStatus;
2797 EFI_STATUS RoutineStatus;
2798 EFI_IPSEC_CONFIG_SELECTOR *Selector;
2799 VOID *Data;
2800 UINTN SelectorSize;
2801 UINTN DataSize;
2802 UINTN SelectorBufferSize;
2803 UINTN DataBufferSize;
2804 BOOLEAN FirstGetNext;
2805
2806 FirstGetNext = TRUE;
2807 DataBufferSize = 0;
2808 Data = NULL;
2809 SelectorBufferSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
2810 Selector = AllocateZeroPool (SelectorBufferSize);
2811
2812 if (Selector == NULL) {
2813 return EFI_OUT_OF_RESOURCES;
2814 }
2815
2816 while (TRUE) {
2817 //
2818 // Get the real size of the selector.
2819 //
2820 SelectorSize = SelectorBufferSize;
2821 GetNextStatus = EfiIpSecConfigGetNextSelector (
2822 &mIpSecConfigInstance,
2823 DataType,
2824 &SelectorSize,
2825 Selector
2826 );
2827 if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {
2828 FreePool (Selector);
2829 SelectorBufferSize = SelectorSize;
2830 //
2831 // Allocate zero pool for the first selector, while store the last
2832 // selector content for the other selectors.
2833 //
2834 if (FirstGetNext) {
2835 Selector = AllocateZeroPool (SelectorBufferSize);
2836 } else {
2837 Selector = AllocateCopyPool (SelectorBufferSize, Selector);
2838 }
2839
2840 if (Selector == NULL) {
2841 return EFI_OUT_OF_RESOURCES;
2842 }
2843 //
2844 // Get the content of the selector.
2845 //
2846 GetNextStatus = EfiIpSecConfigGetNextSelector (
2847 &mIpSecConfigInstance,
2848 DataType,
2849 &SelectorSize,
2850 Selector
2851 );
2852 }
2853
2854 if (EFI_ERROR (GetNextStatus)) {
2855 break;
2856 }
2857
2858 FirstGetNext = FALSE;
2859
2860 //
2861 // Get the real size of the policy entry according to the selector.
2862 //
2863 DataSize = DataBufferSize;
2864 GetDataStatus = EfiIpSecConfigGetData (
2865 &mIpSecConfigInstance,
2866 DataType,
2867 Selector,
2868 &DataSize,
2869 Data
2870 );
2871 if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {
2872 if (Data != NULL) {
2873 FreePool (Data);
2874 }
2875
2876 DataBufferSize = DataSize;
2877 Data = AllocateZeroPool (DataBufferSize);
2878
2879 if (Data == NULL) {
2880 return EFI_OUT_OF_RESOURCES;
2881 }
2882 //
2883 // Get the content of the policy entry according to the selector.
2884 //
2885 GetDataStatus = EfiIpSecConfigGetData (
2886 &mIpSecConfigInstance,
2887 DataType,
2888 Selector,
2889 &DataSize,
2890 Data
2891 );
2892 }
2893
2894 if (EFI_ERROR (GetDataStatus)) {
2895 break;
2896 }
2897 //
2898 // Prepare the buffer of updated policy entry, which is stored in
2899 // the continous memory, and then save into variable later.
2900 //
2901 RoutineStatus = Routine (
2902 DataType,
2903 Selector,
2904 Data,
2905 SelectorSize,
2906 DataSize,
2907 Context
2908 );
2909 if (EFI_ERROR (RoutineStatus)) {
2910 break;
2911 }
2912 }
2913
2914 if (Data != NULL) {
2915 FreePool (Data);
2916 }
2917
2918 if (Selector != NULL) {
2919 FreePool (Selector);
2920 }
2921
2922 return EFI_SUCCESS;
2923 }
2924
2925 /**
2926 This function is the subfunction of EFIIpSecConfigSetData.
2927
2928 This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.
2929
2930 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
2931 @retval EFI_SUCCESS Saved the configration successfully.
2932 @retval Others Other errors were found while obtaining the variable.
2933
2934 **/
2935 EFI_STATUS
2936 IpSecConfigSave (
2937 VOID
2938 )
2939 {
2940 IPSEC_VARIABLE_BUFFER Buffer;
2941 EFI_STATUS Status;
2942 EFI_IPSEC_CONFIG_DATA_TYPE Type;
2943
2944 Buffer.Size = 0;
2945 Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE;
2946 Buffer.Ptr = AllocateZeroPool (Buffer.Capacity);
2947
2948 if (Buffer.Ptr == NULL) {
2949 return EFI_OUT_OF_RESOURCES;
2950 }
2951 //
2952 // For each policy database, prepare the contious buffer to save into variable.
2953 //
2954 for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
2955 IpSecVisitConfigData (
2956 Type,
2957 (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry,
2958 &Buffer
2959 );
2960 }
2961 //
2962 // Save the updated policy database into variable.
2963 //
2964 Status = IpSecSetVariable (
2965 IPSECCONFIG_VARIABLE_NAME,
2966 &gEfiIpSecConfigProtocolGuid,
2967 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
2968 Buffer.Size,
2969 Buffer.Ptr
2970 );
2971
2972 FreePool (Buffer.Ptr);
2973
2974 return Status;
2975 }
2976
2977 /**
2978 Get the all IPSec configuration variables and store those variables
2979 to the internal data structure.
2980
2981 This founction is called by IpSecConfigInitialize() which is to intialize the
2982 IPsecConfiguration Protocol.
2983
2984 @param[in] Private Point to IPSEC_PRIVATE_DATA.
2985
2986 @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated
2987 @retval EFI_SUCCESS Restore the IPsec Configuration successfully.
2988 @retval others Other errors is found while obtaining the variable.
2989
2990 **/
2991 EFI_STATUS
2992 IpSecConfigRestore (
2993 IN IPSEC_PRIVATE_DATA *Private
2994 )
2995 {
2996 EFI_STATUS Status;
2997 UINTN BufferSize;
2998 UINT8 *Buffer;
2999 IPSEC_VAR_ITEM_HEADER *Header;
3000 UINT8 *Ptr;
3001 EFI_IPSEC_CONFIG_SELECTOR *Selector;
3002 EFI_IPSEC_CONFIG_DATA_TYPE Type;
3003 VOID *Data;
3004 UINT8 Value;
3005 UINTN Size;
3006
3007 Value = 0;
3008 Size = sizeof (Value);
3009 BufferSize = 0;
3010 Buffer = NULL;
3011
3012 Status = gRT->GetVariable (
3013 IPSECCONFIG_STATUS_NAME,
3014 &gEfiIpSecConfigProtocolGuid,
3015 NULL,
3016 &Size,
3017 &Value
3018 );
3019
3020 if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) {
3021 Private->IpSec.DisabledFlag = FALSE;
3022 }
3023 //
3024 // Get the real size of policy database in variable.
3025 //
3026 Status = IpSecGetVariable (
3027 IPSECCONFIG_VARIABLE_NAME,
3028 &gEfiIpSecConfigProtocolGuid,
3029 NULL,
3030 &BufferSize,
3031 Buffer
3032 );
3033 if (Status == EFI_BUFFER_TOO_SMALL) {
3034
3035 Buffer = AllocateZeroPool (BufferSize);
3036 if (Buffer == NULL) {
3037 return EFI_OUT_OF_RESOURCES;
3038 }
3039 //
3040 // Get the content of policy database in variable.
3041 //
3042 Status = IpSecGetVariable (
3043 IPSECCONFIG_VARIABLE_NAME,
3044 &gEfiIpSecConfigProtocolGuid,
3045 NULL,
3046 &BufferSize,
3047 Buffer
3048 );
3049 if (EFI_ERROR (Status)) {
3050 FreePool (Buffer);
3051 return Status;
3052 }
3053
3054 for (Ptr = Buffer; Ptr < Buffer + BufferSize;) {
3055
3056 Header = (IPSEC_VAR_ITEM_HEADER *) Ptr;
3057 Type = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT);
3058 ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum));
3059
3060 Selector = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN));
3061 Header = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER (
3062 (UINT8 *) Selector + Header->Size,
3063 sizeof (UINTN)
3064 );
3065 ASSERT (Header->Type == Type);
3066
3067 Data = ALIGN_POINTER (Header + 1, sizeof (UINTN));
3068
3069 mUnfixPolicyEntry[Type](Selector, Data);
3070
3071 //
3072 // Update each policy entry according to the content in variable.
3073 //
3074 mSetBySelf = TRUE;
3075 Status = EfiIpSecConfigSetData (
3076 &Private->IpSecConfig,
3077 Type,
3078 Selector,
3079 Data,
3080 NULL
3081 );
3082 mSetBySelf = FALSE;
3083
3084 if (EFI_ERROR (Status)) {
3085 FreePool (Buffer);
3086 return Status;
3087 }
3088
3089 Ptr = ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN));
3090 }
3091
3092 FreePool (Buffer);
3093 }
3094
3095 return EFI_SUCCESS;
3096 }
3097
3098 /**
3099 Install and Initialize IPsecConfig protocol
3100
3101 @param[in, out] Private Pointer to IPSEC_PRIVATE_DATA. After this function finish,
3102 the pointer of IPsecConfig Protocol implementation will copy
3103 into its IPsecConfig member.
3104
3105 @retval EFI_SUCCESS Initialized the IPsecConfig Protocol successfully.
3106 @retval Others Initializing the IPsecConfig Protocol failed.
3107 **/
3108 EFI_STATUS
3109 IpSecConfigInitialize (
3110 IN OUT IPSEC_PRIVATE_DATA *Private
3111 )
3112 {
3113 EFI_IPSEC_CONFIG_DATA_TYPE Type;
3114
3115 CopyMem (
3116 &Private->IpSecConfig,
3117 &mIpSecConfigInstance,
3118 sizeof (EFI_IPSEC_CONFIG_PROTOCOL)
3119 );
3120
3121 //
3122 // Initialize the list head of policy database.
3123 //
3124 for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
3125 InitializeListHead (&mConfigData[Type]);
3126 }
3127 //
3128 // Restore the content of policy database according to the variable.
3129 //
3130 IpSecConfigRestore (Private);
3131
3132 return gBS->InstallMultipleProtocolInterfaces (
3133 &Private->Handle,
3134 &gEfiIpSecConfigProtocolGuid,
3135 &Private->IpSecConfig,
3136 NULL
3137 );
3138 }