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