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