1 /** @file
2   The implementation of policy entry operation function in IpSecConfig application.
3 
4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "IpSecConfig.h"
17 #include "Indexer.h"
18 #include "Match.h"
19 #include "Helper.h"
20 #include "ForEach.h"
21 #include "PolicyEntryOperation.h"
22 
23 /**
24   Fill in EFI_IPSEC_SPD_SELECTOR through ParamPackage list.
25 
26   @param[out]     Selector        The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
27   @param[in]      ParamPackage    The pointer to the ParamPackage list.
28   @param[in, out] Mask            The pointer to the Mask.
29 
30   @retval EFI_SUCCESS              Fill in EFI_IPSEC_SPD_SELECTOR successfully.
31   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
32 
33 **/
34 EFI_STATUS
CreateSpdSelector(OUT EFI_IPSEC_SPD_SELECTOR * Selector,IN LIST_ENTRY * ParamPackage,IN OUT UINT32 * Mask)35 CreateSpdSelector (
36      OUT EFI_IPSEC_SPD_SELECTOR    *Selector,
37   IN     LIST_ENTRY                *ParamPackage,
38   IN OUT UINT32                    *Mask
39   )
40 {
41   EFI_STATUS      Status;
42   EFI_STATUS      ReturnStatus;
43   CONST CHAR16    *ValueStr;
44 
45   Status       = EFI_SUCCESS;
46   ReturnStatus = EFI_SUCCESS;
47 
48   //
49   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
50   //
51   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--local");
52   if (ValueStr != NULL) {
53     Selector->LocalAddressCount = 1;
54     Status = EfiInetAddrRange ((CHAR16 *) ValueStr, Selector->LocalAddress);
55     if (EFI_ERROR (Status)) {
56       ShellPrintHiiEx (
57         -1,
58         -1,
59         NULL,
60         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
61         mHiiHandle,
62         mAppName,
63         L"--local",
64         ValueStr
65         );
66       ReturnStatus = EFI_INVALID_PARAMETER;
67     } else {
68       *Mask |= LOCAL;
69     }
70   }
71 
72   //
73   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
74   //
75   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--remote");
76   if (ValueStr != NULL) {
77     Selector->RemoteAddressCount = 1;
78     Status = EfiInetAddrRange ((CHAR16 *) ValueStr, Selector->RemoteAddress);
79     if (EFI_ERROR (Status)) {
80       ShellPrintHiiEx (
81         -1,
82         -1,
83         NULL,
84         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
85         mHiiHandle,
86         mAppName,
87         L"--remote",
88         ValueStr
89         );
90       ReturnStatus = EFI_INVALID_PARAMETER;
91     } else {
92       *Mask |= REMOTE;
93     }
94   }
95 
96   Selector->NextLayerProtocol = EFI_IPSEC_ANY_PROTOCOL;
97 
98   //
99   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
100   //
101   Status = GetNumber (
102              L"--proto",
103              (UINT16) -1,
104              &Selector->NextLayerProtocol,
105              sizeof (UINT16),
106              mMapIpProtocol,
107              ParamPackage,
108              FORMAT_NUMBER | FORMAT_STRING
109              );
110   if (!EFI_ERROR (Status)) {
111     *Mask |= PROTO;
112   }
113 
114   if (Status == EFI_INVALID_PARAMETER) {
115     ReturnStatus = EFI_INVALID_PARAMETER;
116   }
117 
118   Selector->LocalPort  = EFI_IPSEC_ANY_PORT;
119   Selector->RemotePort = EFI_IPSEC_ANY_PORT;
120 
121   //
122   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
123   //
124   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--local-port");
125   if (ValueStr != NULL) {
126     Status = EfiInetPortRange ((CHAR16 *) ValueStr, &Selector->LocalPort, &Selector->LocalPortRange);
127     if (EFI_ERROR (Status)) {
128       ShellPrintHiiEx (
129         -1,
130         -1,
131         NULL,
132         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
133         mHiiHandle,
134         mAppName,
135         L"--local-port",
136         ValueStr
137         );
138       ReturnStatus = EFI_INVALID_PARAMETER;
139     } else {
140       *Mask |= LOCAL_PORT;
141     }
142   }
143 
144   //
145   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
146   //
147   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--remote-port");
148   if (ValueStr != NULL) {
149     Status = EfiInetPortRange ((CHAR16 *) ValueStr, &Selector->RemotePort, &Selector->RemotePortRange);
150     if (EFI_ERROR (Status)) {
151       ShellPrintHiiEx (
152         -1,
153         -1,
154         NULL,
155         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
156         mHiiHandle,
157         mAppName,
158         L"--remote-port",
159         ValueStr
160         );
161       ReturnStatus = EFI_INVALID_PARAMETER;
162     } else {
163       *Mask |= REMOTE_PORT;
164     }
165   }
166 
167   //
168   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
169   //
170   Status = GetNumber (
171              L"--icmp-type",
172              (UINT8) -1,
173              &Selector->LocalPort,
174              sizeof (UINT16),
175              NULL,
176              ParamPackage,
177              FORMAT_NUMBER
178              );
179   if (!EFI_ERROR (Status)) {
180     *Mask |= ICMP_TYPE;
181   }
182 
183   if (Status == EFI_INVALID_PARAMETER) {
184     ReturnStatus = EFI_INVALID_PARAMETER;
185   }
186 
187   //
188   // Convert user imput from string to integer, and fill in the member in EFI_IPSEC_SPD_SELECTOR.
189   //
190   Status = GetNumber (
191              L"--icmp-code",
192              (UINT8) -1,
193              &Selector->RemotePort,
194              sizeof (UINT16),
195              NULL,
196              ParamPackage,
197              FORMAT_NUMBER
198              );
199   if (!EFI_ERROR (Status)) {
200     *Mask |= ICMP_CODE;
201   }
202 
203   if (Status == EFI_INVALID_PARAMETER) {
204     ReturnStatus = EFI_INVALID_PARAMETER;
205   }
206 
207   return ReturnStatus;
208 }
209 
210 /**
211   Fill in EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA through ParamPackage list.
212 
213   @param[out] Selector        The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
214   @param[out] Data            The pointer to the EFI_IPSEC_SPD_DATA structure.
215   @param[in]  ParamPackage    The pointer to the ParamPackage list.
216   @param[out] Mask            The pointer to the Mask.
217   @param[in]  CreateNew       The switch to create new.
218 
219   @retval EFI_SUCCESS              Fill in EFI_IPSEC_SPD_SELECTOR and EFI_IPSEC_SPD_DATA successfully.
220   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
221 
222 **/
223 EFI_STATUS
CreateSpdEntry(OUT EFI_IPSEC_SPD_SELECTOR ** Selector,OUT EFI_IPSEC_SPD_DATA ** Data,IN LIST_ENTRY * ParamPackage,OUT UINT32 * Mask,IN BOOLEAN CreateNew)224 CreateSpdEntry (
225   OUT EFI_IPSEC_SPD_SELECTOR    **Selector,
226   OUT EFI_IPSEC_SPD_DATA        **Data,
227   IN  LIST_ENTRY                *ParamPackage,
228   OUT UINT32                    *Mask,
229   IN  BOOLEAN                   CreateNew
230   )
231 {
232   EFI_STATUS      Status;
233   EFI_STATUS      ReturnStatus;
234   CONST CHAR16    *ValueStr;
235   UINTN           DataSize;
236 
237   Status    = EFI_SUCCESS;
238   *Mask     = 0;
239 
240   *Selector = AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR) + 2 * sizeof (EFI_IP_ADDRESS_INFO));
241   ASSERT (*Selector != NULL);
242 
243   (*Selector)->LocalAddress  = (EFI_IP_ADDRESS_INFO *) (*Selector + 1);
244   (*Selector)->RemoteAddress = (*Selector)->LocalAddress + 1;
245 
246   ReturnStatus = CreateSpdSelector (*Selector, ParamPackage, Mask);
247 
248   //
249   // SPD DATA
250   // NOTE: Allocate enough memory and add padding for different arch.
251   //
252   DataSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SPD_DATA));
253   DataSize  = ALIGN_VARIABLE (DataSize + sizeof (EFI_IPSEC_PROCESS_POLICY));
254   DataSize += sizeof (EFI_IPSEC_TUNNEL_OPTION);
255 
256   *Data = AllocateZeroPool (DataSize);
257   ASSERT (*Data != NULL);
258 
259   (*Data)->ProcessingPolicy               = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (
260                                                                            (*Data + 1),
261                                                                            sizeof (UINTN)
262                                                                            );
263   (*Data)->ProcessingPolicy->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER (
264                                                                           ((*Data)->ProcessingPolicy + 1),
265                                                                           sizeof (UINTN)
266                                                                           );
267 
268 
269   //
270   // Convert user imput from string to integer, and fill in the Name in EFI_IPSEC_SPD_DATA.
271   //
272   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--name");
273   if (ValueStr != NULL) {
274     UnicodeStrToAsciiStrS (ValueStr, (CHAR8 *) (*Data)->Name, sizeof ((*Data)->Name));
275     *Mask |= NAME;
276   }
277 
278   //
279   // Convert user imput from string to integer, and fill in the PackageFlag in EFI_IPSEC_SPD_DATA.
280   //
281   Status = GetNumber (
282              L"--packet-flag",
283              (UINT8) -1,
284              &(*Data)->PackageFlag,
285              sizeof (UINT32),
286              NULL,
287              ParamPackage,
288              FORMAT_NUMBER
289              );
290   if (!EFI_ERROR (Status)) {
291     *Mask |= PACKET_FLAG;
292   }
293 
294   if (Status == EFI_INVALID_PARAMETER) {
295     ReturnStatus = EFI_INVALID_PARAMETER;
296   }
297 
298   //
299   // Convert user imput from string to integer, and fill in the Action in EFI_IPSEC_SPD_DATA.
300   //
301   Status = GetNumber (
302              L"--action",
303              (UINT8) -1,
304              &(*Data)->Action,
305              sizeof (UINT32),
306              mMapIpSecAction,
307              ParamPackage,
308              FORMAT_STRING
309              );
310   if (!EFI_ERROR (Status)) {
311     *Mask |= ACTION;
312   }
313 
314   if (Status == EFI_INVALID_PARAMETER) {
315     ReturnStatus = EFI_INVALID_PARAMETER;
316   }
317 
318   //
319   // Convert user imput from string to integer, and fill in the ExtSeqNum in EFI_IPSEC_SPD_DATA.
320   //
321   if (ShellCommandLineGetFlag (ParamPackage, L"--ext-sequence")) {
322     (*Data)->ProcessingPolicy->ExtSeqNum   = TRUE;
323     *Mask |= EXT_SEQUENCE;
324   } else if (ShellCommandLineGetFlag (ParamPackage, L"--ext-sequence-")) {
325     (*Data)->ProcessingPolicy->ExtSeqNum   = FALSE;
326     *Mask |= EXT_SEQUENCE;
327   }
328 
329   //
330   // Convert user imput from string to integer, and fill in the SeqOverflow in EFI_IPSEC_SPD_DATA.
331   //
332   if (ShellCommandLineGetFlag (ParamPackage, L"--sequence-overflow")) {
333     (*Data)->ProcessingPolicy->SeqOverflow = TRUE;
334     *Mask |= SEQUENCE_OVERFLOW;
335   } else if (ShellCommandLineGetFlag (ParamPackage, L"--sequence-overflow-")) {
336     (*Data)->ProcessingPolicy->SeqOverflow = FALSE;
337     *Mask |= SEQUENCE_OVERFLOW;
338   }
339 
340   //
341   // Convert user imput from string to integer, and fill in the FragCheck in EFI_IPSEC_SPD_DATA.
342   //
343   if (ShellCommandLineGetFlag (ParamPackage, L"--fragment-check")) {
344     (*Data)->ProcessingPolicy->FragCheck   = TRUE;
345     *Mask |= FRAGMENT_CHECK;
346   } else if (ShellCommandLineGetFlag (ParamPackage, L"--fragment-check-")) {
347     (*Data)->ProcessingPolicy->FragCheck   = FALSE;
348     *Mask |= FRAGMENT_CHECK;
349   }
350 
351   //
352   // Convert user imput from string to integer, and fill in the ProcessingPolicy in EFI_IPSEC_SPD_DATA.
353   //
354   Status = GetNumber (
355              L"--lifebyte",
356              (UINT64) -1,
357              &(*Data)->ProcessingPolicy->SaLifetime.ByteCount,
358              sizeof (UINT64),
359              NULL,
360              ParamPackage,
361              FORMAT_NUMBER
362              );
363   if (!EFI_ERROR (Status)) {
364     *Mask |= LIFEBYTE;
365   }
366 
367   if (Status == EFI_INVALID_PARAMETER) {
368     ReturnStatus = EFI_INVALID_PARAMETER;
369   }
370 
371   Status = GetNumber (
372              L"--lifetime",
373              (UINT64) -1,
374              &(*Data)->ProcessingPolicy->SaLifetime.HardLifetime,
375              sizeof (UINT64),
376              NULL,
377              ParamPackage,
378              FORMAT_NUMBER
379              );
380   if (!EFI_ERROR (Status)) {
381     *Mask |= LIFETIME;
382   }
383   if (Status == EFI_INVALID_PARAMETER) {
384     ReturnStatus = EFI_INVALID_PARAMETER;
385   }
386 
387   Status = GetNumber (
388              L"--lifetime-soft",
389              (UINT64) -1,
390              &(*Data)->ProcessingPolicy->SaLifetime.SoftLifetime,
391              sizeof (UINT64),
392              NULL,
393              ParamPackage,
394              FORMAT_NUMBER
395              );
396   if (!EFI_ERROR (Status)) {
397     *Mask |= LIFETIME_SOFT;
398   }
399 
400   if (Status == EFI_INVALID_PARAMETER) {
401     ReturnStatus = EFI_INVALID_PARAMETER;
402   }
403 
404   (*Data)->ProcessingPolicy->Mode = EfiIPsecTransport;
405   Status = GetNumber (
406              L"--mode",
407              0,
408              &(*Data)->ProcessingPolicy->Mode,
409              sizeof (UINT32),
410              mMapIpSecMode,
411              ParamPackage,
412              FORMAT_STRING
413              );
414   if (!EFI_ERROR (Status)) {
415     *Mask |= MODE;
416   }
417 
418   if (Status == EFI_INVALID_PARAMETER) {
419     ReturnStatus = EFI_INVALID_PARAMETER;
420   }
421 
422   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-local");
423   if (ValueStr != NULL) {
424     Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->ProcessingPolicy->TunnelOption->LocalTunnelAddress);
425     if (EFI_ERROR (Status)) {
426       ShellPrintHiiEx (
427         -1,
428         -1,
429         NULL,
430         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
431         mHiiHandle,
432         mAppName,
433         L"--tunnel-local",
434         ValueStr
435         );
436       ReturnStatus = EFI_INVALID_PARAMETER;
437     } else {
438       *Mask |= TUNNEL_LOCAL;
439     }
440   }
441 
442   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-remote");
443   if (ValueStr != NULL) {
444     Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->ProcessingPolicy->TunnelOption->RemoteTunnelAddress);
445     if (EFI_ERROR (Status)) {
446       ShellPrintHiiEx (
447         -1,
448         -1,
449         NULL,
450         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
451         mHiiHandle,
452         mAppName,
453         L"--tunnel-remote",
454         ValueStr
455         );
456       ReturnStatus = EFI_INVALID_PARAMETER;
457     } else {
458       *Mask |= TUNNEL_REMOTE;
459     }
460   }
461 
462   (*Data)->ProcessingPolicy->TunnelOption->DF = EfiIPsecTunnelCopyDf;
463   Status = GetNumber (
464              L"--dont-fragment",
465              0,
466              &(*Data)->ProcessingPolicy->TunnelOption->DF,
467              sizeof (UINT32),
468              mMapDfOption,
469              ParamPackage,
470              FORMAT_STRING
471              );
472   if (!EFI_ERROR (Status)) {
473     *Mask |= DONT_FRAGMENT;
474   }
475 
476   if (Status == EFI_INVALID_PARAMETER) {
477     ReturnStatus = EFI_INVALID_PARAMETER;
478   }
479 
480   (*Data)->ProcessingPolicy->Proto = EfiIPsecESP;
481   Status = GetNumber (
482              L"--ipsec-proto",
483              0,
484              &(*Data)->ProcessingPolicy->Proto,
485              sizeof (UINT32),
486              mMapIpSecProtocol,
487              ParamPackage,
488              FORMAT_STRING
489              );
490   if (!EFI_ERROR (Status)) {
491     *Mask |= IPSEC_PROTO;
492   }
493 
494   if (Status == EFI_INVALID_PARAMETER) {
495     ReturnStatus = EFI_INVALID_PARAMETER;
496   }
497 
498   Status = GetNumber (
499              L"--encrypt-algo",
500              0,
501              &(*Data)->ProcessingPolicy->EncAlgoId,
502              sizeof (UINT8),
503              mMapEncAlgo,
504              ParamPackage,
505              FORMAT_STRING
506              );
507   if (!EFI_ERROR (Status)) {
508     *Mask |= ENCRYPT_ALGO;
509   }
510 
511   if (Status == EFI_INVALID_PARAMETER) {
512     ReturnStatus = EFI_INVALID_PARAMETER;
513   }
514 
515   Status = GetNumber (
516              L"--auth-algo",
517              0,
518              &(*Data)->ProcessingPolicy->AuthAlgoId,
519              sizeof (UINT8),
520              mMapAuthAlgo,
521              ParamPackage,
522              FORMAT_STRING
523              );
524   if (!EFI_ERROR (Status)) {
525     *Mask |= AUTH_ALGO;
526   }
527 
528   if (Status == EFI_INVALID_PARAMETER) {
529     ReturnStatus = EFI_INVALID_PARAMETER;
530   }
531 
532   //
533   // Cannot check Mode against EfiIPsecTunnel, because user may want to change tunnel_remote only so the Mode is not set.
534   //
535   if ((*Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE | DONT_FRAGMENT)) == 0) {
536     (*Data)->ProcessingPolicy->TunnelOption = NULL;
537   }
538 
539   if ((*Mask & (EXT_SEQUENCE | SEQUENCE_OVERFLOW | FRAGMENT_CHECK | LIFEBYTE |
540                 LIFETIME_SOFT | LIFETIME | MODE | TUNNEL_LOCAL | TUNNEL_REMOTE |
541                 DONT_FRAGMENT | IPSEC_PROTO | AUTH_ALGO | ENCRYPT_ALGO)) == 0) {
542     if ((*Data)->Action != EfiIPsecActionProtect) {
543       //
544       // User may not provide additional parameter for Protect action, so we cannot simply set ProcessingPolicy to NULL.
545       //
546       (*Data)->ProcessingPolicy = NULL;
547     }
548   }
549 
550   if (CreateNew) {
551     if ((*Mask & (LOCAL | REMOTE | PROTO | ACTION)) != (LOCAL | REMOTE | PROTO | ACTION)) {
552       ShellPrintHiiEx (
553         -1,
554         -1,
555         NULL,
556         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
557         mHiiHandle,
558         mAppName,
559         L"--local --remote --proto --action"
560         );
561       ReturnStatus = EFI_INVALID_PARAMETER;
562     } else if (((*Data)->Action == EfiIPsecActionProtect) &&
563                ((*Data)->ProcessingPolicy->Mode == EfiIPsecTunnel) &&
564                ((*Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE))) {
565       ShellPrintHiiEx (
566         -1,
567         -1,
568         NULL,
569         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
570         mHiiHandle,
571         mAppName,
572         L"--tunnel-local --tunnel-remote"
573         );
574       ReturnStatus = EFI_INVALID_PARAMETER;
575     }
576   }
577 
578   return ReturnStatus;
579 }
580 
581 /**
582   Fill in EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA2 through ParamPackage list.
583 
584   @param[out] SaId            The pointer to the EFI_IPSEC_SA_ID structure.
585   @param[out] Data            The pointer to the EFI_IPSEC_SA_DATA2 structure.
586   @param[in]  ParamPackage    The pointer to the ParamPackage list.
587   @param[out] Mask            The pointer to the Mask.
588   @param[in]  CreateNew       The switch to create new.
589 
590   @retval EFI_SUCCESS              Fill in EFI_IPSEC_SA_ID and EFI_IPSEC_SA_DATA2 successfully.
591   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
592 
593 **/
594 EFI_STATUS
CreateSadEntry(OUT EFI_IPSEC_SA_ID ** SaId,OUT EFI_IPSEC_SA_DATA2 ** Data,IN LIST_ENTRY * ParamPackage,OUT UINT32 * Mask,IN BOOLEAN CreateNew)595 CreateSadEntry (
596   OUT EFI_IPSEC_SA_ID      **SaId,
597   OUT EFI_IPSEC_SA_DATA2   **Data,
598   IN  LIST_ENTRY           *ParamPackage,
599   OUT UINT32               *Mask,
600   IN  BOOLEAN              CreateNew
601   )
602 {
603   EFI_STATUS      Status;
604   EFI_STATUS      ReturnStatus;
605   UINTN           AuthKeyLength;
606   UINTN           EncKeyLength;
607   CONST CHAR16    *ValueStr;
608   CHAR8           *AsciiStr;
609   UINTN           DataSize;
610 
611   Status        = EFI_SUCCESS;
612   ReturnStatus  = EFI_SUCCESS;
613   *Mask         = 0;
614   AuthKeyLength = 0;
615   EncKeyLength  = 0;
616 
617   *SaId = AllocateZeroPool (sizeof (EFI_IPSEC_SA_ID));
618   ASSERT (*SaId != NULL);
619 
620   //
621   // Convert user imput from string to integer, and fill in the Spi in EFI_IPSEC_SA_ID.
622   //
623   Status = GetNumber (L"--spi", (UINT32) -1, &(*SaId)->Spi, sizeof (UINT32), NULL, ParamPackage, FORMAT_NUMBER);
624   if (!EFI_ERROR (Status)) {
625     *Mask |= SPI;
626   }
627 
628   if (Status == EFI_INVALID_PARAMETER) {
629     ReturnStatus = EFI_INVALID_PARAMETER;
630   }
631 
632   //
633   // Convert user imput from string to integer, and fill in the Proto in EFI_IPSEC_SA_ID.
634   //
635   Status = GetNumber (
636              L"--ipsec-proto",
637              0,
638              &(*SaId)->Proto,
639              sizeof (EFI_IPSEC_PROTOCOL_TYPE),
640              mMapIpSecProtocol,
641              ParamPackage,
642              FORMAT_STRING
643              );
644   if (!EFI_ERROR (Status)) {
645     *Mask |= IPSEC_PROTO;
646   }
647 
648   if (Status == EFI_INVALID_PARAMETER) {
649     ReturnStatus = EFI_INVALID_PARAMETER;
650   }
651 
652   //
653   // Convert user imput from string to integer, and fill in EFI_IPSEC_SA_DATA2.
654   //
655   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-key");
656   if (ValueStr != NULL) {
657     AuthKeyLength = StrLen (ValueStr);
658   }
659 
660   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--encrypt-key");
661   if (ValueStr != NULL) {
662     EncKeyLength = StrLen (ValueStr);
663   }
664 
665   //
666   // EFI_IPSEC_SA_DATA2:
667   //   +------------
668   //   | EFI_IPSEC_SA_DATA2
669   //   +-----------------------
670   //   | AuthKey
671   //   +-------------------------
672   //   | EncKey
673   //   +-------------------------
674   //   | SpdSelector
675   //
676   // Notes: To make sure the address alignment add padding after each data if needed.
677   //
678   DataSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2));
679   DataSize  = ALIGN_VARIABLE (DataSize + AuthKeyLength);
680   DataSize  = ALIGN_VARIABLE (DataSize + EncKeyLength);
681   DataSize  = ALIGN_VARIABLE (DataSize + sizeof (EFI_IPSEC_SPD_SELECTOR));
682   DataSize  = ALIGN_VARIABLE (DataSize + sizeof (EFI_IP_ADDRESS_INFO));
683   DataSize += sizeof (EFI_IP_ADDRESS_INFO);
684 
685 
686 
687   *Data = AllocateZeroPool (DataSize);
688   ASSERT (*Data != NULL);
689 
690   (*Data)->ManualSet                    = TRUE;
691   (*Data)->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER (((*Data) + 1), sizeof (UINTN));
692   (*Data)->AlgoInfo.EspAlgoInfo.EncKey  = (VOID *) ALIGN_POINTER (
693                                                      ((UINT8 *) (*Data)->AlgoInfo.EspAlgoInfo.AuthKey + AuthKeyLength),
694                                                      sizeof (UINTN)
695                                                      );
696   (*Data)->SpdSelector                  = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER (
697                                                                        ((UINT8 *) (*Data)->AlgoInfo.EspAlgoInfo.EncKey + EncKeyLength),
698                                                                        sizeof (UINTN)
699                                                                        );
700   (*Data)->SpdSelector->LocalAddress    = (EFI_IP_ADDRESS_INFO *) ALIGN_POINTER (
701                                                                     ((UINT8 *) (*Data)->SpdSelector + sizeof (EFI_IPSEC_SPD_SELECTOR)),
702                                                                     sizeof (UINTN));
703   (*Data)->SpdSelector->RemoteAddress   = (EFI_IP_ADDRESS_INFO *) ALIGN_POINTER (
704                                                                     (*Data)->SpdSelector->LocalAddress + 1,
705                                                                     sizeof (UINTN)
706                                                                     );
707 
708   (*Data)->Mode = EfiIPsecTransport;
709   Status = GetNumber (
710              L"--mode",
711              0,
712              &(*Data)->Mode,
713              sizeof (EFI_IPSEC_MODE),
714              mMapIpSecMode,
715              ParamPackage,
716              FORMAT_STRING
717              );
718   if (!EFI_ERROR (Status)) {
719     *Mask |= MODE;
720   }
721 
722   if (Status == EFI_INVALID_PARAMETER) {
723     ReturnStatus = EFI_INVALID_PARAMETER;
724   }
725 
726   //
727   // According to RFC 4303-3.3.3. The first packet sent using a given SA
728   // will contain a sequence number of 1.
729   //
730   (*Data)->SNCount = 1;
731   Status = GetNumber (
732              L"--sequence-number",
733              (UINT64) -1,
734              &(*Data)->SNCount,
735              sizeof (UINT64),
736              NULL,
737              ParamPackage,
738              FORMAT_NUMBER
739              );
740   if (!EFI_ERROR (Status)) {
741     *Mask |= SEQUENCE_NUMBER;
742   }
743 
744   if (Status == EFI_INVALID_PARAMETER) {
745     ReturnStatus = EFI_INVALID_PARAMETER;
746   }
747 
748   (*Data)->AntiReplayWindows = 0;
749   Status = GetNumber (
750              L"--antireplay-window",
751              (UINT8) -1,
752              &(*Data)->AntiReplayWindows,
753              sizeof (UINT8),
754              NULL,
755              ParamPackage,
756              FORMAT_NUMBER
757              );
758   if (!EFI_ERROR (Status)) {
759     *Mask |= SEQUENCE_NUMBER;
760   }
761 
762   if (Status == EFI_INVALID_PARAMETER) {
763     ReturnStatus = EFI_INVALID_PARAMETER;
764   }
765 
766   Status = GetNumber (
767              L"--encrypt-algo",
768              0,
769              &(*Data)->AlgoInfo.EspAlgoInfo.EncAlgoId,
770              sizeof (UINT8),
771              mMapEncAlgo,
772              ParamPackage,
773              FORMAT_STRING
774              );
775   if (!EFI_ERROR (Status)) {
776     *Mask |= ENCRYPT_ALGO;
777   }
778 
779   if (Status == EFI_INVALID_PARAMETER) {
780     ReturnStatus = EFI_INVALID_PARAMETER;
781   }
782 
783   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--encrypt-key");
784   if (ValueStr != NULL ) {
785     (*Data)->AlgoInfo.EspAlgoInfo.EncKeyLength = EncKeyLength;
786     AsciiStr = AllocateZeroPool (EncKeyLength + 1);
787     ASSERT (AsciiStr != NULL);
788     UnicodeStrToAsciiStrS (ValueStr, AsciiStr, EncKeyLength + 1);
789     CopyMem ((*Data)->AlgoInfo.EspAlgoInfo.EncKey,  AsciiStr, EncKeyLength);
790     FreePool (AsciiStr);
791     *Mask |= ENCRYPT_KEY;
792   } else {
793     (*Data)->AlgoInfo.EspAlgoInfo.EncKey = NULL;
794   }
795 
796   Status = GetNumber (
797              L"--auth-algo",
798              0,
799              &(*Data)->AlgoInfo.EspAlgoInfo.AuthAlgoId,
800              sizeof (UINT8),
801              mMapAuthAlgo,
802              ParamPackage,
803              FORMAT_STRING
804              );
805   if (!EFI_ERROR (Status)) {
806     *Mask |= AUTH_ALGO;
807   }
808 
809   if (Status == EFI_INVALID_PARAMETER) {
810     ReturnStatus = EFI_INVALID_PARAMETER;
811   }
812 
813   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-key");
814   if (ValueStr != NULL) {
815     (*Data)->AlgoInfo.EspAlgoInfo.AuthKeyLength = AuthKeyLength;
816     AsciiStr = AllocateZeroPool (AuthKeyLength + 1);
817     ASSERT (AsciiStr != NULL);
818     UnicodeStrToAsciiStrS (ValueStr, AsciiStr, AuthKeyLength + 1);
819     CopyMem ((*Data)->AlgoInfo.EspAlgoInfo.AuthKey, AsciiStr, AuthKeyLength);
820     FreePool (AsciiStr);
821     *Mask |= AUTH_KEY;
822   } else {
823     (*Data)->AlgoInfo.EspAlgoInfo.AuthKey = NULL;
824   }
825 
826   Status = GetNumber (
827              L"--lifebyte",
828              (UINT64) -1,
829              &(*Data)->SaLifetime.ByteCount,
830              sizeof (UINT64),
831              NULL,
832              ParamPackage,
833              FORMAT_NUMBER
834              );
835   if (!EFI_ERROR (Status)) {
836     *Mask |= LIFEBYTE;
837   }
838 
839   if (Status == EFI_INVALID_PARAMETER) {
840     ReturnStatus = EFI_INVALID_PARAMETER;
841   }
842 
843   Status = GetNumber (
844              L"--lifetime",
845              (UINT64) -1,
846              &(*Data)->SaLifetime.HardLifetime,
847              sizeof (UINT64),
848              NULL,
849              ParamPackage,
850              FORMAT_NUMBER
851              );
852   if (!EFI_ERROR (Status)) {
853     *Mask |= LIFETIME;
854   }
855 
856   if (Status == EFI_INVALID_PARAMETER) {
857     ReturnStatus = EFI_INVALID_PARAMETER;
858   }
859 
860   Status = GetNumber (
861              L"--lifetime-soft",
862              (UINT64) -1,
863              &(*Data)->SaLifetime.SoftLifetime,
864              sizeof (UINT64),
865              NULL,
866              ParamPackage,
867              FORMAT_NUMBER
868              );
869   if (!EFI_ERROR (Status)) {
870     *Mask |= LIFETIME_SOFT;
871   }
872 
873   if (Status == EFI_INVALID_PARAMETER) {
874     ReturnStatus = EFI_INVALID_PARAMETER;
875   }
876 
877   Status = GetNumber (
878              L"--path-mtu",
879              (UINT32) -1,
880              &(*Data)->PathMTU,
881              sizeof (UINT32),
882              NULL,
883              ParamPackage,
884              FORMAT_NUMBER
885              );
886   if (!EFI_ERROR (Status)) {
887     *Mask |= PATH_MTU;
888   }
889 
890   if (Status == EFI_INVALID_PARAMETER) {
891     ReturnStatus = EFI_INVALID_PARAMETER;
892   }
893 
894   //
895   // Convert user imput from string to integer, and fill in the DestAddress in EFI_IPSEC_SA_ID.
896   //
897   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-dest");
898   if (ValueStr != NULL) {
899     Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->TunnelDestinationAddress);
900     if (EFI_ERROR (Status)) {
901       ShellPrintHiiEx (
902         -1,
903         -1,
904         NULL,
905         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
906         mHiiHandle,
907         mAppName,
908         L"--tunnel-dest",
909         ValueStr
910         );
911       ReturnStatus = EFI_INVALID_PARAMETER;
912     } else {
913       *Mask |= DEST;
914     }
915   }
916 
917   //
918   // Convert user input from string to integer, and fill in the DestAddress in EFI_IPSEC_SA_ID.
919   //
920   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--tunnel-source");
921   if (ValueStr != NULL) {
922     Status = EfiInetAddr2 ((CHAR16 *) ValueStr, &(*Data)->TunnelSourceAddress);
923     if (EFI_ERROR (Status)) {
924       ShellPrintHiiEx (
925         -1,
926         -1,
927         NULL,
928         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
929         mHiiHandle,
930         mAppName,
931         L"--tunnel-source",
932         ValueStr
933         );
934       ReturnStatus = EFI_INVALID_PARAMETER;
935     } else {
936       *Mask |= SOURCE;
937     }
938   }
939 
940   //
941   // If it is TunnelMode, then check if the tunnel-source and --tunnel-dest are set
942   //
943   if ((*Data)->Mode == EfiIPsecTunnel) {
944     if ((*Mask & (DEST|SOURCE)) != (DEST|SOURCE)) {
945       ShellPrintHiiEx (
946         -1,
947         -1,
948         NULL,
949         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
950         mHiiHandle,
951         mAppName,
952         L"--tunnel-source --tunnel-dest"
953         );
954       ReturnStatus = EFI_INVALID_PARAMETER;
955     }
956   }
957   ReturnStatus = CreateSpdSelector ((*Data)->SpdSelector, ParamPackage, Mask);
958 
959   if (CreateNew) {
960     if ((*Mask & (SPI|IPSEC_PROTO|LOCAL|REMOTE)) != (SPI|IPSEC_PROTO|LOCAL|REMOTE)) {
961       ShellPrintHiiEx (
962         -1,
963         -1,
964         NULL,
965         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
966         mHiiHandle,
967         mAppName,
968         L"--spi --ipsec-proto --local --remote"
969         );
970       ReturnStatus = EFI_INVALID_PARAMETER;
971     } else {
972       if ((*SaId)->Proto == EfiIPsecAH) {
973         if ((*Mask & AUTH_ALGO) == 0) {
974           ShellPrintHiiEx (
975             -1,
976             -1,
977             NULL,
978             STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
979             mHiiHandle,
980             mAppName,
981             L"--auth-algo"
982             );
983           ReturnStatus = EFI_INVALID_PARAMETER;
984         } else if ((*Data)->AlgoInfo.EspAlgoInfo.AuthAlgoId != IPSEC_AALG_NONE && (*Mask & AUTH_KEY) == 0) {
985           ShellPrintHiiEx (
986             -1,
987             -1,
988             NULL,
989             STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
990             mHiiHandle,
991             mAppName,
992             L"--auth-key"
993             );
994           ReturnStatus = EFI_INVALID_PARAMETER;
995         }
996       } else {
997         if ((*Mask & (ENCRYPT_ALGO|AUTH_ALGO)) != (ENCRYPT_ALGO|AUTH_ALGO) ) {
998           ShellPrintHiiEx (
999             -1,
1000             -1,
1001             NULL,
1002             STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
1003             mHiiHandle,
1004             mAppName,
1005             L"--encrypt-algo --auth-algo"
1006             );
1007           ReturnStatus = EFI_INVALID_PARAMETER;
1008         } else if ((*Data)->AlgoInfo.EspAlgoInfo.EncAlgoId != IPSEC_EALG_NONE && (*Mask & ENCRYPT_KEY) == 0) {
1009           ShellPrintHiiEx (
1010             -1,
1011             -1,
1012             NULL,
1013             STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
1014             mHiiHandle,
1015             mAppName,
1016             L"--encrypt-key"
1017             );
1018           ReturnStatus = EFI_INVALID_PARAMETER;
1019         } else if ((*Data)->AlgoInfo.EspAlgoInfo.AuthAlgoId != IPSEC_AALG_NONE && (*Mask & AUTH_KEY) == 0) {
1020           ShellPrintHiiEx (
1021             -1,
1022             -1,
1023             NULL,
1024             STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
1025             mHiiHandle,
1026             mAppName,
1027             L"--auth-key"
1028             );
1029           ReturnStatus = EFI_INVALID_PARAMETER;
1030         }
1031       }
1032     }
1033   }
1034 
1035   return ReturnStatus;
1036 }
1037 
1038 /**
1039   Fill in EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA through ParamPackage list.
1040 
1041   @param[out] PadId           The pointer to the EFI_IPSEC_PAD_ID structure.
1042   @param[out] Data            The pointer to the EFI_IPSEC_PAD_DATA structure.
1043   @param[in]  ParamPackage    The pointer to the ParamPackage list.
1044   @param[out] Mask            The pointer to the Mask.
1045   @param[in]  CreateNew       The switch to create new.
1046 
1047   @retval EFI_SUCCESS              Fill in EFI_IPSEC_PAD_ID and EFI_IPSEC_PAD_DATA successfully.
1048   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
1049 
1050 **/
1051 EFI_STATUS
CreatePadEntry(OUT EFI_IPSEC_PAD_ID ** PadId,OUT EFI_IPSEC_PAD_DATA ** Data,IN LIST_ENTRY * ParamPackage,OUT UINT32 * Mask,IN BOOLEAN CreateNew)1052 CreatePadEntry (
1053   OUT EFI_IPSEC_PAD_ID      **PadId,
1054   OUT EFI_IPSEC_PAD_DATA    **Data,
1055   IN  LIST_ENTRY            *ParamPackage,
1056   OUT UINT32                *Mask,
1057   IN  BOOLEAN               CreateNew
1058   )
1059 {
1060   EFI_STATUS         Status;
1061   EFI_STATUS         ReturnStatus;
1062   SHELL_FILE_HANDLE  FileHandle;
1063   UINT64             FileSize;
1064   UINTN              AuthDataLength;
1065   UINTN              RevocationDataLength;
1066   UINTN              DataLength;
1067   UINTN              Index;
1068   CONST CHAR16       *ValueStr;
1069   UINTN              DataSize;
1070 
1071   Status               = EFI_SUCCESS;
1072   ReturnStatus         = EFI_SUCCESS;
1073   *Mask                = 0;
1074   AuthDataLength       = 0;
1075   RevocationDataLength = 0;
1076 
1077   *PadId = AllocateZeroPool (sizeof (EFI_IPSEC_PAD_ID));
1078   ASSERT (*PadId != NULL);
1079 
1080   //
1081   // Convert user imput from string to integer, and fill in EFI_IPSEC_PAD_ID.
1082   //
1083   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--peer-address");
1084   if (ValueStr != NULL) {
1085     (*PadId)->PeerIdValid = FALSE;
1086     Status = EfiInetAddrRange ((CHAR16 *) ValueStr, &(*PadId)->Id.IpAddress);
1087     if (EFI_ERROR (Status)) {
1088       ShellPrintHiiEx (
1089         -1,
1090         -1,
1091         NULL,
1092         STRING_TOKEN (STR_IPSEC_CONFIG_INCORRECT_PARAMETER_VALUE),
1093         mHiiHandle,
1094         mAppName,
1095         L"--peer-address",
1096         ValueStr
1097         );
1098       ReturnStatus = EFI_INVALID_PARAMETER;
1099     } else {
1100       *Mask |= PEER_ADDRESS;
1101     }
1102   }
1103 
1104   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--peer-id");
1105   if (ValueStr != NULL) {
1106     (*PadId)->PeerIdValid = TRUE;
1107     StrnCpyS ((CHAR16 *) (*PadId)->Id.PeerId, MAX_PEERID_LEN / sizeof (CHAR16), ValueStr, MAX_PEERID_LEN / sizeof (CHAR16) - 1);
1108     *Mask |= PEER_ID;
1109   }
1110 
1111   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-data");
1112   if (ValueStr != NULL) {
1113     if (ValueStr[0] == L'@') {
1114       //
1115       // Input is a file: --auth-data "@fs1:\My Certificates\tom.dat"
1116       //
1117       Status = ShellOpenFileByName (&ValueStr[1], &FileHandle, EFI_FILE_MODE_READ, 0);
1118       if (EFI_ERROR (Status)) {
1119         ShellPrintHiiEx (
1120           -1,
1121           -1,
1122           NULL,
1123           STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED),
1124           mHiiHandle,
1125           mAppName,
1126           &ValueStr[1]
1127           );
1128         ReturnStatus = EFI_INVALID_PARAMETER;
1129       } else {
1130         Status = ShellGetFileSize (FileHandle, &FileSize);
1131         ShellCloseFile (&FileHandle);
1132         if (EFI_ERROR (Status)) {
1133           ShellPrintHiiEx (
1134             -1,
1135             -1,
1136             NULL,
1137             STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED),
1138             mHiiHandle,
1139             mAppName,
1140             &ValueStr[1]
1141             );
1142           ReturnStatus = EFI_INVALID_PARAMETER;
1143         } else {
1144           AuthDataLength = (UINTN) FileSize;
1145         }
1146       }
1147     } else {
1148       AuthDataLength = StrLen (ValueStr);
1149     }
1150   }
1151 
1152   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--revocation-data");
1153   if (ValueStr != NULL) {
1154     RevocationDataLength = (StrLen (ValueStr) + 1) * sizeof (CHAR16);
1155   }
1156 
1157   //
1158   // Allocate Buffer for Data. Add padding after each struct to make sure the alignment
1159   // in different Arch.
1160   //
1161   DataSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));
1162   DataSize  = ALIGN_VARIABLE (DataSize + AuthDataLength);
1163   DataSize += RevocationDataLength;
1164 
1165   *Data = AllocateZeroPool (DataSize);
1166   ASSERT (*Data != NULL);
1167 
1168   (*Data)->AuthData       = (VOID *) ALIGN_POINTER ((*Data + 1), sizeof (UINTN));
1169   (*Data)->RevocationData = (VOID *) ALIGN_POINTER (((UINT8 *) (*Data + 1) + AuthDataLength), sizeof (UINTN));
1170   (*Data)->AuthProtocol   = EfiIPsecAuthProtocolIKEv1;
1171 
1172   //
1173   // Convert user imput from string to integer, and fill in EFI_IPSEC_PAD_DATA.
1174   //
1175   Status = GetNumber (
1176              L"--auth-proto",
1177              0,
1178              &(*Data)->AuthProtocol,
1179              sizeof (EFI_IPSEC_AUTH_PROTOCOL_TYPE),
1180              mMapAuthProto,
1181              ParamPackage,
1182              FORMAT_STRING
1183              );
1184   if (!EFI_ERROR (Status)) {
1185     *Mask |= AUTH_PROTO;
1186   }
1187 
1188   if (Status == EFI_INVALID_PARAMETER) {
1189     ReturnStatus = EFI_INVALID_PARAMETER;
1190   }
1191 
1192   Status = GetNumber (
1193              L"--auth-method",
1194              0,
1195              &(*Data)->AuthMethod,
1196              sizeof (EFI_IPSEC_AUTH_METHOD),
1197              mMapAuthMethod,
1198              ParamPackage,
1199              FORMAT_STRING
1200              );
1201   if (!EFI_ERROR (Status)) {
1202     *Mask |= AUTH_METHOD;
1203   }
1204 
1205   if (Status == EFI_INVALID_PARAMETER) {
1206     ReturnStatus = EFI_INVALID_PARAMETER;
1207   }
1208 
1209   if (ShellCommandLineGetFlag (ParamPackage, L"--ike-id")) {
1210     (*Data)->IkeIdFlag = TRUE;
1211     *Mask |= IKE_ID;
1212   }
1213 
1214   if (ShellCommandLineGetFlag (ParamPackage, L"--ike-id-")) {
1215     (*Data)->IkeIdFlag = FALSE;
1216     *Mask |= IKE_ID;
1217   }
1218 
1219   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--auth-data");
1220   if (ValueStr != NULL) {
1221     if (ValueStr[0] == L'@') {
1222       //
1223       // Input is a file: --auth-data "@fs1:\My Certificates\tom.dat"
1224       //
1225 
1226       Status = ShellOpenFileByName (&ValueStr[1], &FileHandle, EFI_FILE_MODE_READ, 0);
1227       if (EFI_ERROR (Status)) {
1228         ShellPrintHiiEx (
1229           -1,
1230           -1,
1231           NULL,
1232           STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED),
1233           mHiiHandle,
1234           mAppName,
1235           &ValueStr[1]
1236           );
1237         ReturnStatus = EFI_INVALID_PARAMETER;
1238         (*Data)->AuthData = NULL;
1239       } else {
1240         DataLength = AuthDataLength;
1241         Status     = ShellReadFile (FileHandle, &DataLength, (*Data)->AuthData);
1242         ShellCloseFile (&FileHandle);
1243         if (EFI_ERROR (Status)) {
1244           ShellPrintHiiEx (
1245             -1,
1246             -1,
1247             NULL,
1248             STRING_TOKEN (STR_IPSEC_CONFIG_FILE_OPEN_FAILED),
1249             mHiiHandle,
1250             mAppName,
1251             &ValueStr[1]
1252             );
1253           ReturnStatus = EFI_INVALID_PARAMETER;
1254           (*Data)->AuthData = NULL;
1255         } else {
1256           ASSERT (DataLength == AuthDataLength);
1257           *Mask |= AUTH_DATA;
1258         }
1259       }
1260     } else {
1261       for (Index = 0; Index < AuthDataLength; Index++) {
1262         ((CHAR8 *) (*Data)->AuthData)[Index] = (CHAR8) ValueStr[Index];
1263       }
1264       (*Data)->AuthDataSize = AuthDataLength;
1265       *Mask |= AUTH_DATA;
1266     }
1267   }
1268 
1269   ValueStr = ShellCommandLineGetValue (ParamPackage, L"--revocation-data");
1270   if (ValueStr != NULL) {
1271     CopyMem ((*Data)->RevocationData, ValueStr, RevocationDataLength);
1272     (*Data)->RevocationDataSize = RevocationDataLength;
1273     *Mask |= REVOCATION_DATA;
1274   } else {
1275     (*Data)->RevocationData = NULL;
1276   }
1277 
1278   if (CreateNew) {
1279     if ((*Mask & (PEER_ID | PEER_ADDRESS)) == 0) {
1280       ShellPrintHiiEx (
1281         -1,
1282         -1,
1283         NULL,
1284         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
1285         mHiiHandle,
1286         mAppName,
1287         L"--peer-id --peer-address"
1288         );
1289       ReturnStatus = EFI_INVALID_PARAMETER;
1290     } else if ((*Mask & (AUTH_METHOD | AUTH_DATA)) != (AUTH_METHOD | AUTH_DATA)) {
1291       ShellPrintHiiEx (
1292         -1,
1293         -1,
1294         NULL,
1295         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
1296         mHiiHandle,
1297         mAppName,
1298         L"--auth-method --auth-data"
1299         );
1300       ReturnStatus = EFI_INVALID_PARAMETER;
1301     }
1302   }
1303 
1304   return ReturnStatus;
1305 }
1306 
1307 CREATE_POLICY_ENTRY mCreatePolicyEntry[] = {
1308   (CREATE_POLICY_ENTRY) CreateSpdEntry,
1309   (CREATE_POLICY_ENTRY) CreateSadEntry,
1310   (CREATE_POLICY_ENTRY) CreatePadEntry
1311 };
1312 
1313 /**
1314   Combine old SPD entry with new SPD entry.
1315 
1316   @param[in, out] OldSelector    The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
1317   @param[in, out] OldData        The pointer to the EFI_IPSEC_SPD_DATA structure.
1318   @param[in]      NewSelector    The pointer to the EFI_IPSEC_SPD_SELECTOR structure.
1319   @param[in]      NewData        The pointer to the EFI_IPSEC_SPD_DATA structure.
1320   @param[in]      Mask           The pointer to the Mask.
1321   @param[out]     CreateNew      The switch to create new.
1322 
1323   @retval EFI_SUCCESS              Combined successfully.
1324   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
1325 
1326 **/
1327 EFI_STATUS
CombineSpdEntry(IN OUT EFI_IPSEC_SPD_SELECTOR * OldSelector,IN OUT EFI_IPSEC_SPD_DATA * OldData,IN EFI_IPSEC_SPD_SELECTOR * NewSelector,IN EFI_IPSEC_SPD_DATA * NewData,IN UINT32 Mask,OUT BOOLEAN * CreateNew)1328 CombineSpdEntry (
1329   IN OUT EFI_IPSEC_SPD_SELECTOR    *OldSelector,
1330   IN OUT EFI_IPSEC_SPD_DATA        *OldData,
1331   IN     EFI_IPSEC_SPD_SELECTOR    *NewSelector,
1332   IN     EFI_IPSEC_SPD_DATA        *NewData,
1333   IN     UINT32                    Mask,
1334      OUT BOOLEAN                   *CreateNew
1335   )
1336 {
1337 
1338   //
1339   // Process Selector
1340   //
1341   *CreateNew = FALSE;
1342   if ((Mask & LOCAL) == 0) {
1343     NewSelector->LocalAddressCount = OldSelector->LocalAddressCount;
1344     NewSelector->LocalAddress      = OldSelector->LocalAddress;
1345   } else if ((NewSelector->LocalAddressCount != OldSelector->LocalAddressCount) ||
1346              (CompareMem (NewSelector->LocalAddress, OldSelector->LocalAddress, NewSelector->LocalAddressCount * sizeof (EFI_IP_ADDRESS_INFO)) != 0)) {
1347     *CreateNew = TRUE;
1348   }
1349 
1350   if ((Mask & REMOTE) == 0) {
1351     NewSelector->RemoteAddressCount = OldSelector->RemoteAddressCount;
1352     NewSelector->RemoteAddress      = OldSelector->RemoteAddress;
1353   } else if ((NewSelector->RemoteAddressCount != OldSelector->RemoteAddressCount) ||
1354              (CompareMem (NewSelector->RemoteAddress, OldSelector->RemoteAddress, NewSelector->RemoteAddressCount * sizeof (EFI_IP_ADDRESS_INFO)) != 0)) {
1355     *CreateNew = TRUE;
1356   }
1357 
1358   if ((Mask & PROTO) == 0) {
1359     NewSelector->NextLayerProtocol = OldSelector->NextLayerProtocol;
1360   } else if (NewSelector->NextLayerProtocol != OldSelector->NextLayerProtocol) {
1361     *CreateNew = TRUE;
1362   }
1363 
1364   switch (NewSelector->NextLayerProtocol) {
1365     case EFI_IP4_PROTO_TCP:
1366     case EFI_IP4_PROTO_UDP:
1367       if ((Mask & LOCAL_PORT) == 0) {
1368         NewSelector->LocalPort      = OldSelector->LocalPort;
1369         NewSelector->LocalPortRange = OldSelector->LocalPortRange;
1370       } else if ((NewSelector->LocalPort != OldSelector->LocalPort) ||
1371         (NewSelector->LocalPortRange != OldSelector->LocalPortRange)) {
1372         *CreateNew = TRUE;
1373       }
1374 
1375       if ((Mask & REMOTE_PORT) == 0) {
1376         NewSelector->RemotePort      = OldSelector->RemotePort;
1377         NewSelector->RemotePortRange = OldSelector->RemotePortRange;
1378       } else if ((NewSelector->RemotePort != OldSelector->RemotePort) ||
1379         (NewSelector->RemotePortRange != OldSelector->RemotePortRange)) {
1380         *CreateNew = TRUE;
1381       }
1382       break;
1383 
1384     case EFI_IP4_PROTO_ICMP:
1385       if ((Mask & ICMP_TYPE) == 0) {
1386         NewSelector->LocalPort = OldSelector->LocalPort;
1387       } else if (NewSelector->LocalPort != OldSelector->LocalPort) {
1388         *CreateNew = TRUE;
1389       }
1390 
1391       if ((Mask & ICMP_CODE) == 0) {
1392         NewSelector->RemotePort = OldSelector->RemotePort;
1393       } else if (NewSelector->RemotePort != OldSelector->RemotePort) {
1394         *CreateNew = TRUE;
1395       }
1396       break;
1397   }
1398   //
1399   // Process Data
1400   //
1401   OldData->SaIdCount = 0;
1402 
1403   if ((Mask & NAME) != 0) {
1404     AsciiStrCpyS ((CHAR8 *) OldData->Name, MAX_PEERID_LEN, (CHAR8 *) NewData->Name);
1405   }
1406 
1407   if ((Mask & PACKET_FLAG) != 0) {
1408     OldData->PackageFlag = NewData->PackageFlag;
1409   }
1410 
1411   if ((Mask & ACTION) != 0) {
1412     OldData->Action = NewData->Action;
1413   }
1414 
1415   if (OldData->Action != EfiIPsecActionProtect) {
1416     OldData->ProcessingPolicy = NULL;
1417   } else {
1418     //
1419     // Protect
1420     //
1421     if (OldData->ProcessingPolicy == NULL) {
1422       //
1423       // Just point to new data if originally NULL.
1424       //
1425       OldData->ProcessingPolicy = NewData->ProcessingPolicy;
1426       if (OldData->ProcessingPolicy->Mode == EfiIPsecTunnel &&
1427           (Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE)
1428         ) {
1429         //
1430         // Change to Protect action and Tunnel mode, but without providing local/remote tunnel address.
1431         //
1432         ShellPrintHiiEx (
1433           -1,
1434           -1,
1435           NULL,
1436           STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
1437           mHiiHandle,
1438           mAppName,
1439           L"--tunnel-local --tunnel-remote"
1440           );
1441         return EFI_INVALID_PARAMETER;
1442       }
1443     } else {
1444       //
1445       // Modify some of the data.
1446       //
1447       if ((Mask & EXT_SEQUENCE) != 0) {
1448         OldData->ProcessingPolicy->ExtSeqNum = NewData->ProcessingPolicy->ExtSeqNum;
1449       }
1450 
1451       if ((Mask & SEQUENCE_OVERFLOW) != 0) {
1452         OldData->ProcessingPolicy->SeqOverflow = NewData->ProcessingPolicy->SeqOverflow;
1453       }
1454 
1455       if ((Mask & FRAGMENT_CHECK) != 0) {
1456         OldData->ProcessingPolicy->FragCheck = NewData->ProcessingPolicy->FragCheck;
1457       }
1458 
1459       if ((Mask & LIFEBYTE) != 0) {
1460         OldData->ProcessingPolicy->SaLifetime.ByteCount = NewData->ProcessingPolicy->SaLifetime.ByteCount;
1461       }
1462 
1463       if ((Mask & LIFETIME_SOFT) != 0) {
1464         OldData->ProcessingPolicy->SaLifetime.SoftLifetime = NewData->ProcessingPolicy->SaLifetime.SoftLifetime;
1465       }
1466 
1467       if ((Mask & LIFETIME) != 0) {
1468         OldData->ProcessingPolicy->SaLifetime.HardLifetime = NewData->ProcessingPolicy->SaLifetime.HardLifetime;
1469       }
1470 
1471       if ((Mask & MODE) != 0) {
1472         OldData->ProcessingPolicy->Mode = NewData->ProcessingPolicy->Mode;
1473       }
1474 
1475       if ((Mask & IPSEC_PROTO) != 0) {
1476         OldData->ProcessingPolicy->Proto = NewData->ProcessingPolicy->Proto;
1477       }
1478 
1479       if ((Mask & AUTH_ALGO) != 0) {
1480         OldData->ProcessingPolicy->AuthAlgoId = NewData->ProcessingPolicy->AuthAlgoId;
1481       }
1482 
1483       if ((Mask & ENCRYPT_ALGO) != 0) {
1484         OldData->ProcessingPolicy->EncAlgoId = NewData->ProcessingPolicy->EncAlgoId;
1485       }
1486 
1487       if (OldData->ProcessingPolicy->Mode != EfiIPsecTunnel) {
1488         OldData->ProcessingPolicy->TunnelOption = NULL;
1489       } else {
1490         if (OldData->ProcessingPolicy->TunnelOption == NULL) {
1491           //
1492           // Set from Transport mode to Tunnel mode, should ensure TUNNEL_LOCAL & TUNNEL_REMOTE both exists.
1493           //
1494           if ((Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE)) {
1495             ShellPrintHiiEx (
1496               -1,
1497               -1,
1498               NULL,
1499               STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
1500               mHiiHandle,
1501               mAppName,
1502               L"--tunnel-local --tunnel-remote"
1503               );
1504             return EFI_INVALID_PARAMETER;
1505           }
1506 
1507           OldData->ProcessingPolicy->TunnelOption = NewData->ProcessingPolicy->TunnelOption;
1508         } else {
1509           if ((Mask & TUNNEL_LOCAL) != 0) {
1510             CopyMem (
1511               &OldData->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1512               &NewData->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1513               sizeof (EFI_IP_ADDRESS)
1514               );
1515           }
1516 
1517           if ((Mask & TUNNEL_REMOTE) != 0) {
1518             CopyMem (
1519               &OldData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1520               &NewData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1521               sizeof (EFI_IP_ADDRESS)
1522               );
1523           }
1524 
1525           if ((Mask & DONT_FRAGMENT) != 0) {
1526             OldData->ProcessingPolicy->TunnelOption->DF = NewData->ProcessingPolicy->TunnelOption->DF;
1527           }
1528         }
1529       }
1530     }
1531   }
1532 
1533   return EFI_SUCCESS;
1534 }
1535 
1536 /**
1537   Combine old SAD entry with new SAD entry.
1538 
1539   @param[in, out] OldSaId      The pointer to the EFI_IPSEC_SA_ID structure.
1540   @param[in, out] OldData      The pointer to the EFI_IPSEC_SA_DATA2 structure.
1541   @param[in]      NewSaId      The pointer to the EFI_IPSEC_SA_ID structure.
1542   @param[in]      NewData      The pointer to the EFI_IPSEC_SA_DATA2 structure.
1543   @param[in]      Mask         The pointer to the Mask.
1544   @param[out]     CreateNew    The switch to create new.
1545 
1546   @retval EFI_SUCCESS              Combined successfully.
1547   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
1548 
1549 **/
1550 EFI_STATUS
CombineSadEntry(IN OUT EFI_IPSEC_SA_ID * OldSaId,IN OUT EFI_IPSEC_SA_DATA2 * OldData,IN EFI_IPSEC_SA_ID * NewSaId,IN EFI_IPSEC_SA_DATA2 * NewData,IN UINT32 Mask,OUT BOOLEAN * CreateNew)1551 CombineSadEntry (
1552   IN OUT EFI_IPSEC_SA_ID      *OldSaId,
1553   IN OUT EFI_IPSEC_SA_DATA2   *OldData,
1554   IN     EFI_IPSEC_SA_ID      *NewSaId,
1555   IN     EFI_IPSEC_SA_DATA2   *NewData,
1556   IN     UINT32               Mask,
1557      OUT BOOLEAN              *CreateNew
1558   )
1559 {
1560 
1561   *CreateNew = FALSE;
1562 
1563   if ((Mask & SPI) == 0) {
1564     NewSaId->Spi = OldSaId->Spi;
1565   } else if (NewSaId->Spi != OldSaId->Spi) {
1566     *CreateNew = TRUE;
1567   }
1568 
1569   if ((Mask & IPSEC_PROTO) == 0) {
1570     NewSaId->Proto = OldSaId->Proto;
1571   } else if (NewSaId->Proto != OldSaId->Proto) {
1572     *CreateNew = TRUE;
1573   }
1574 
1575   if ((Mask & DEST) == 0) {
1576     CopyMem (&NewData->TunnelDestinationAddress, &OldData->TunnelDestinationAddress, sizeof (EFI_IP_ADDRESS));
1577   } else if (CompareMem (&NewData->TunnelDestinationAddress, &OldData->TunnelDestinationAddress, sizeof (EFI_IP_ADDRESS)) != 0) {
1578     *CreateNew = TRUE;
1579   }
1580 
1581   if ((Mask & SOURCE) == 0) {
1582     CopyMem (&NewData->TunnelSourceAddress, &OldData->TunnelSourceAddress, sizeof (EFI_IP_ADDRESS));
1583   } else if (CompareMem (&NewData->TunnelSourceAddress, &OldData->TunnelSourceAddress, sizeof (EFI_IP_ADDRESS)) != 0) {
1584     *CreateNew = TRUE;
1585   }
1586   //
1587   // Process SA_DATA.
1588   //
1589   if ((Mask & MODE) != 0) {
1590     OldData->Mode = NewData->Mode;
1591   }
1592 
1593   if ((Mask & SEQUENCE_NUMBER) != 0) {
1594     OldData->SNCount = NewData->SNCount;
1595   }
1596 
1597   if ((Mask & ANTIREPLAY_WINDOW) != 0) {
1598     OldData->AntiReplayWindows = NewData->AntiReplayWindows;
1599   }
1600 
1601   if ((Mask & AUTH_ALGO) != 0) {
1602     OldData->AlgoInfo.EspAlgoInfo.AuthAlgoId    = NewData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
1603   }
1604 
1605   if ((Mask & AUTH_KEY) != 0) {
1606     OldData->AlgoInfo.EspAlgoInfo.AuthKey       = NewData->AlgoInfo.EspAlgoInfo.AuthKey;
1607     OldData->AlgoInfo.EspAlgoInfo.AuthKeyLength = NewData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
1608   }
1609 
1610   if ((Mask & ENCRYPT_ALGO) != 0) {
1611     OldData->AlgoInfo.EspAlgoInfo.EncAlgoId     = NewData->AlgoInfo.EspAlgoInfo.EncAlgoId;
1612   }
1613 
1614   if ((Mask & ENCRYPT_KEY) != 0) {
1615     OldData->AlgoInfo.EspAlgoInfo.EncKey        = NewData->AlgoInfo.EspAlgoInfo.EncKey;
1616     OldData->AlgoInfo.EspAlgoInfo.EncKeyLength  = NewData->AlgoInfo.EspAlgoInfo.EncKeyLength;
1617   }
1618 
1619   if (NewSaId->Proto == EfiIPsecAH) {
1620     if ((Mask & (ENCRYPT_ALGO | ENCRYPT_KEY)) != 0) {
1621       //
1622       // Should not provide encrypt_* if AH.
1623       //
1624       ShellPrintHiiEx (
1625         -1,
1626         -1,
1627         NULL,
1628         STRING_TOKEN (STR_IPSEC_CONFIG_UNWANTED_PARAMETER),
1629         mHiiHandle,
1630         mAppName,
1631         L"--encrypt-algo --encrypt-key"
1632         );
1633       return EFI_INVALID_PARAMETER;
1634     }
1635   }
1636 
1637   if (NewSaId->Proto == EfiIPsecESP && OldSaId->Proto == EfiIPsecAH) {
1638     //
1639     // AH -> ESP
1640     // Should provide encrypt_algo at least.
1641     //
1642     if ((Mask & ENCRYPT_ALGO) == 0) {
1643       ShellPrintHiiEx (
1644         -1,
1645         -1,
1646         NULL,
1647         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
1648         mHiiHandle,
1649         mAppName,
1650         L"--encrypt-algo"
1651         );
1652       return EFI_INVALID_PARAMETER;
1653     }
1654 
1655     //
1656     // Encrypt_key should be provided if algorithm is not NONE.
1657     //
1658     if (NewData->AlgoInfo.EspAlgoInfo.EncAlgoId != IPSEC_EALG_NONE && (Mask & ENCRYPT_KEY) == 0) {
1659       ShellPrintHiiEx (
1660         -1,
1661         -1,
1662         NULL,
1663         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
1664         mHiiHandle,
1665         mAppName,
1666         L"--encrypt-algo"
1667         );
1668       return EFI_INVALID_PARAMETER;
1669     }
1670   }
1671 
1672   if ((Mask & LIFEBYTE) != 0) {
1673     OldData->SaLifetime.ByteCount    = NewData->SaLifetime.ByteCount;
1674   }
1675 
1676   if ((Mask & LIFETIME_SOFT) != 0) {
1677     OldData->SaLifetime.SoftLifetime = NewData->SaLifetime.SoftLifetime;
1678   }
1679 
1680   if ((Mask & LIFETIME) != 0) {
1681     OldData->SaLifetime.HardLifetime = NewData->SaLifetime.HardLifetime;
1682   }
1683 
1684   if ((Mask & PATH_MTU) != 0) {
1685     OldData->PathMTU                 = NewData->PathMTU;
1686   }
1687   //
1688   // Process SpdSelector.
1689   //
1690   if (OldData->SpdSelector == NULL) {
1691     if ((Mask & (LOCAL | REMOTE | PROTO | LOCAL_PORT | REMOTE_PORT | ICMP_TYPE | ICMP_CODE)) != 0) {
1692       if ((Mask & (LOCAL | REMOTE | PROTO)) != (LOCAL | REMOTE | PROTO)) {
1693         ShellPrintHiiEx (
1694           -1,
1695           -1,
1696           NULL,
1697           STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
1698           mHiiHandle,
1699           mAppName,
1700           L"--local --remote --proto"
1701           );
1702         return EFI_INVALID_PARAMETER;
1703       }
1704 
1705       OldData->SpdSelector = NewData->SpdSelector;
1706     }
1707   } else {
1708     if ((Mask & LOCAL) != 0) {
1709       OldData->SpdSelector->LocalAddressCount  = NewData->SpdSelector->LocalAddressCount;
1710       OldData->SpdSelector->LocalAddress       = NewData->SpdSelector->LocalAddress;
1711     }
1712 
1713     if ((Mask & REMOTE) != 0) {
1714       OldData->SpdSelector->RemoteAddressCount = NewData->SpdSelector->RemoteAddressCount;
1715       OldData->SpdSelector->RemoteAddress      = NewData->SpdSelector->RemoteAddress;
1716     }
1717 
1718     if ((Mask & PROTO) != 0) {
1719       OldData->SpdSelector->NextLayerProtocol  = NewData->SpdSelector->NextLayerProtocol;
1720     }
1721 
1722     if (OldData->SpdSelector != NULL) {
1723       switch (OldData->SpdSelector->NextLayerProtocol) {
1724         case EFI_IP4_PROTO_TCP:
1725         case EFI_IP4_PROTO_UDP:
1726           if ((Mask & LOCAL_PORT) != 0) {
1727             OldData->SpdSelector->LocalPort  = NewData->SpdSelector->LocalPort;
1728           }
1729 
1730           if ((Mask & REMOTE_PORT) != 0) {
1731             OldData->SpdSelector->RemotePort = NewData->SpdSelector->RemotePort;
1732           }
1733           break;
1734 
1735         case EFI_IP4_PROTO_ICMP:
1736           if ((Mask & ICMP_TYPE) != 0) {
1737             OldData->SpdSelector->LocalPort  = (UINT8) NewData->SpdSelector->LocalPort;
1738           }
1739 
1740           if ((Mask & ICMP_CODE) != 0) {
1741             OldData->SpdSelector->RemotePort = (UINT8) NewData->SpdSelector->RemotePort;
1742           }
1743           break;
1744       }
1745     }
1746   }
1747 
1748   return EFI_SUCCESS;
1749 }
1750 
1751 /**
1752   Combine old PAD entry with new PAD entry.
1753 
1754   @param[in, out] OldPadId     The pointer to the EFI_IPSEC_PAD_ID structure.
1755   @param[in, out] OldData      The pointer to the EFI_IPSEC_PAD_DATA structure.
1756   @param[in]      NewPadId     The pointer to the EFI_IPSEC_PAD_ID structure.
1757   @param[in]      NewData      The pointer to the EFI_IPSEC_PAD_DATA structure.
1758   @param[in]      Mask         The pointer to the Mask.
1759   @param[out]     CreateNew    The switch to create new.
1760 
1761   @retval EFI_SUCCESS              Combined successfully.
1762   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
1763 
1764 **/
1765 EFI_STATUS
CombinePadEntry(IN OUT EFI_IPSEC_PAD_ID * OldPadId,IN OUT EFI_IPSEC_PAD_DATA * OldData,IN EFI_IPSEC_PAD_ID * NewPadId,IN EFI_IPSEC_PAD_DATA * NewData,IN UINT32 Mask,OUT BOOLEAN * CreateNew)1766 CombinePadEntry (
1767   IN OUT EFI_IPSEC_PAD_ID      *OldPadId,
1768   IN OUT EFI_IPSEC_PAD_DATA    *OldData,
1769   IN     EFI_IPSEC_PAD_ID      *NewPadId,
1770   IN     EFI_IPSEC_PAD_DATA    *NewData,
1771   IN     UINT32                Mask,
1772      OUT BOOLEAN               *CreateNew
1773   )
1774 {
1775 
1776   *CreateNew = FALSE;
1777 
1778   if ((Mask & (PEER_ID | PEER_ADDRESS)) == 0) {
1779     CopyMem (NewPadId, OldPadId, sizeof (EFI_IPSEC_PAD_ID));
1780   } else {
1781     if ((Mask & PEER_ID) != 0) {
1782       if (OldPadId->PeerIdValid) {
1783         if (StrCmp ((CONST CHAR16 *) OldPadId->Id.PeerId, (CONST CHAR16 *) NewPadId->Id.PeerId) != 0) {
1784           *CreateNew = TRUE;
1785         }
1786       } else {
1787         *CreateNew = TRUE;
1788       }
1789     } else {
1790       //
1791       // MASK & PEER_ADDRESS
1792       //
1793       if (OldPadId->PeerIdValid) {
1794         *CreateNew = TRUE;
1795       } else {
1796         if ((CompareMem (&OldPadId->Id.IpAddress.Address, &NewPadId->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0) ||
1797             (OldPadId->Id.IpAddress.PrefixLength != NewPadId->Id.IpAddress.PrefixLength)) {
1798           *CreateNew = TRUE;
1799         }
1800       }
1801     }
1802   }
1803 
1804   if ((Mask & AUTH_PROTO) != 0) {
1805     OldData->AuthProtocol = NewData->AuthProtocol;
1806   }
1807 
1808   if ((Mask & AUTH_METHOD) != 0) {
1809     OldData->AuthMethod = NewData->AuthMethod;
1810   }
1811 
1812   if ((Mask & IKE_ID) != 0) {
1813     OldData->IkeIdFlag = NewData->IkeIdFlag;
1814   }
1815 
1816   if ((Mask & AUTH_DATA) != 0) {
1817     OldData->AuthDataSize = NewData->AuthDataSize;
1818     OldData->AuthData     = NewData->AuthData;
1819   }
1820 
1821   if ((Mask & REVOCATION_DATA) != 0) {
1822     OldData->RevocationDataSize = NewData->RevocationDataSize;
1823     OldData->RevocationData     = NewData->RevocationData;
1824   }
1825 
1826   return EFI_SUCCESS;
1827 }
1828 
1829 COMBINE_POLICY_ENTRY mCombinePolicyEntry[] = {
1830   (COMBINE_POLICY_ENTRY) CombineSpdEntry,
1831   (COMBINE_POLICY_ENTRY) CombineSadEntry,
1832   (COMBINE_POLICY_ENTRY) CombinePadEntry
1833 };
1834 
1835 /**
1836   Edit entry information in the database.
1837 
1838   @param[in] Selector    The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure.
1839   @param[in] Data        The pointer to the data.
1840   @param[in] Context     The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure.
1841 
1842   @retval EFI_SUCCESS    Continue the iteration.
1843   @retval EFI_ABORTED    Abort the iteration.
1844 **/
1845 EFI_STATUS
EditOperatePolicyEntry(IN EFI_IPSEC_CONFIG_SELECTOR * Selector,IN VOID * Data,IN EDIT_POLICY_ENTRY_CONTEXT * Context)1846 EditOperatePolicyEntry (
1847   IN EFI_IPSEC_CONFIG_SELECTOR    *Selector,
1848   IN VOID                         *Data,
1849   IN EDIT_POLICY_ENTRY_CONTEXT    *Context
1850   )
1851 {
1852   EFI_STATUS    Status;
1853   BOOLEAN       CreateNew;
1854 
1855   if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) {
1856     ASSERT (Context->DataType < 3);
1857 
1858     Status = mCombinePolicyEntry[Context->DataType] (
1859                Selector,
1860                Data,
1861                Context->Selector,
1862                Context->Data,
1863                Context->Mask,
1864                &CreateNew
1865                );
1866     if (!EFI_ERROR (Status)) {
1867       //
1868       // If the Selector already existed, this Entry will be updated by set data.
1869       //
1870       Status = mIpSecConfig->SetData (
1871                                mIpSecConfig,
1872                                Context->DataType,
1873                                Context->Selector, /// New created selector.
1874                                Data, /// Old date which has been modified, need to be set data.
1875                                Selector
1876                                );
1877       ASSERT_EFI_ERROR (Status);
1878 
1879       if (CreateNew) {
1880         //
1881         // Edit the entry to a new one. So, we need delete the old entry.
1882         //
1883         Status = mIpSecConfig->SetData (
1884                                  mIpSecConfig,
1885                                  Context->DataType,
1886                                  Selector, /// Old selector.
1887                                  NULL, /// NULL means to delete this Entry specified by Selector.
1888                                  NULL
1889                                  );
1890         ASSERT_EFI_ERROR (Status);
1891       }
1892     }
1893 
1894     Context->Status = Status;
1895     return EFI_ABORTED;
1896   }
1897 
1898   return EFI_SUCCESS;
1899 }
1900 
1901 /**
1902   Edit entry information in database according to datatype.
1903 
1904   @param[in] DataType        The value of EFI_IPSEC_CONFIG_DATA_TYPE.
1905   @param[in] ParamPackage    The pointer to the ParamPackage list.
1906 
1907   @retval EFI_SUCCESS             Edit entry information successfully.
1908   @retval EFI_NOT_FOUND           Can't find the specified entry.
1909   @retval Others                  Some mistaken case.
1910 **/
1911 EFI_STATUS
EditPolicyEntry(IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,IN LIST_ENTRY * ParamPackage)1912 EditPolicyEntry (
1913   IN EFI_IPSEC_CONFIG_DATA_TYPE    DataType,
1914   IN LIST_ENTRY                    *ParamPackage
1915   )
1916 {
1917   EFI_STATUS                   Status;
1918   EDIT_POLICY_ENTRY_CONTEXT    Context;
1919   CONST CHAR16                 *ValueStr;
1920 
1921   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
1922   if (ValueStr == NULL) {
1923     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr);
1924     return EFI_NOT_FOUND;
1925   }
1926 
1927   Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage);
1928   if (!EFI_ERROR (Status)) {
1929     Context.DataType = DataType;
1930     Context.Status   = EFI_NOT_FOUND;
1931     Status = mCreatePolicyEntry[DataType] (&Context.Selector, &Context.Data, ParamPackage, &Context.Mask, FALSE);
1932     if (!EFI_ERROR (Status)) {
1933       ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) EditOperatePolicyEntry, &Context);
1934       Status = Context.Status;
1935     }
1936 
1937     if (Context.Selector != NULL) {
1938       gBS->FreePool (Context.Selector);
1939     }
1940 
1941     if (Context.Data != NULL) {
1942       gBS->FreePool (Context.Data);
1943     }
1944   }
1945 
1946   if (Status == EFI_NOT_FOUND) {
1947     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr);
1948   } else if (EFI_ERROR (Status)) {
1949     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_EDIT_FAILED), mHiiHandle, mAppName);
1950   }
1951 
1952   return Status;
1953 
1954 }
1955 
1956 /**
1957   Insert entry information in database.
1958 
1959   @param[in] Selector    The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure.
1960   @param[in] Data        The pointer to the data.
1961   @param[in] Context     The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure.
1962 
1963   @retval EFI_SUCCESS    Continue the iteration.
1964   @retval EFI_ABORTED    Abort the iteration.
1965 **/
1966 EFI_STATUS
InsertPolicyEntry(IN EFI_IPSEC_CONFIG_SELECTOR * Selector,IN VOID * Data,IN INSERT_POLICY_ENTRY_CONTEXT * Context)1967 InsertPolicyEntry (
1968   IN EFI_IPSEC_CONFIG_SELECTOR      *Selector,
1969   IN VOID                           *Data,
1970   IN INSERT_POLICY_ENTRY_CONTEXT    *Context
1971   )
1972 {
1973   //
1974   // Found the entry which we want to insert before.
1975   //
1976   if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) {
1977 
1978     Context->Status = mIpSecConfig->SetData (
1979                                       mIpSecConfig,
1980                                       Context->DataType,
1981                                       Context->Selector,
1982                                       Context->Data,
1983                                       Selector
1984                                       );
1985     //
1986     // Abort the iteration after the insertion.
1987     //
1988     return EFI_ABORTED;
1989   }
1990 
1991   return EFI_SUCCESS;
1992 }
1993 
1994 /**
1995   Insert or add entry information in database according to datatype.
1996 
1997   @param[in] DataType        The value of EFI_IPSEC_CONFIG_DATA_TYPE.
1998   @param[in] ParamPackage    The pointer to the ParamPackage list.
1999 
2000   @retval EFI_SUCCESS             Insert or add entry information successfully.
2001   @retval EFI_NOT_FOUND           Can't find the specified entry.
2002   @retval EFI_BUFFER_TOO_SMALL    The entry already existed.
2003   @retval EFI_UNSUPPORTED         The operation is not supported.
2004   @retval Others                  Some mistaken case.
2005 **/
2006 EFI_STATUS
AddOrInsertPolicyEntry(IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,IN LIST_ENTRY * ParamPackage)2007 AddOrInsertPolicyEntry (
2008   IN EFI_IPSEC_CONFIG_DATA_TYPE    DataType,
2009   IN LIST_ENTRY                    *ParamPackage
2010   )
2011 {
2012   EFI_STATUS                     Status;
2013   EFI_IPSEC_CONFIG_SELECTOR      *Selector;
2014   VOID                           *Data;
2015   INSERT_POLICY_ENTRY_CONTEXT    Context;
2016   UINT32                         Mask;
2017   UINTN                          DataSize;
2018   CONST CHAR16                   *ValueStr;
2019 
2020   Status = mCreatePolicyEntry[DataType] (&Selector, &Data, ParamPackage, &Mask, TRUE);
2021   if (!EFI_ERROR (Status)) {
2022     //
2023     // Find if the Selector to be inserted already exists.
2024     //
2025     DataSize = 0;
2026     Status = mIpSecConfig->GetData (
2027                              mIpSecConfig,
2028                              DataType,
2029                              Selector,
2030                              &DataSize,
2031                              NULL
2032                              );
2033     if (Status == EFI_BUFFER_TOO_SMALL) {
2034       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_EXISTS), mHiiHandle, mAppName);
2035     } else if (ShellCommandLineGetFlag (ParamPackage, L"-a")) {
2036       Status = mIpSecConfig->SetData (
2037                                mIpSecConfig,
2038                                DataType,
2039                                Selector,
2040                                Data,
2041                                NULL
2042                                );
2043     } else {
2044       ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
2045       if (ValueStr == NULL) {
2046         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr);
2047         return EFI_NOT_FOUND;
2048       }
2049 
2050       Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage);
2051       if (!EFI_ERROR (Status)) {
2052         Context.DataType  = DataType;
2053         Context.Status    = EFI_NOT_FOUND;
2054         Context.Selector  = Selector;
2055         Context.Data      = Data;
2056 
2057         ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) InsertPolicyEntry, &Context);
2058         Status = Context.Status;
2059         if (Status == EFI_NOT_FOUND) {
2060           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr);
2061         }
2062       }
2063     }
2064 
2065     gBS->FreePool (Selector);
2066     gBS->FreePool (Data);
2067   }
2068 
2069   if (Status == EFI_UNSUPPORTED) {
2070     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_UNSUPPORT), mHiiHandle, mAppName);
2071   } else if (EFI_ERROR (Status)) {
2072     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_FAILED), mHiiHandle, mAppName);
2073   }
2074 
2075   return Status;
2076 }
2077