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