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