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