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