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