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**/
34EFI_STATUS
35CreateSpdSelector (
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**/
223EFI_STATUS
224CreateSpdEntry (
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**/
594EFI_STATUS
595CreateSadEntry (
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**/
1051EFI_STATUS
1052CreatePadEntry (
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
1307CREATE_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**/
1327EFI_STATUS
1328CombineSpdEntry (
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**/
1550EFI_STATUS
1551CombineSadEntry (
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**/
1765EFI_STATUS
1766CombinePadEntry (
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
1829COMBINE_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**/
1845EFI_STATUS
1846EditOperatePolicyEntry (
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**/
1911EFI_STATUS
1912EditPolicyEntry (
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**/
1966EFI_STATUS
1967InsertPolicyEntry (
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**/
2006EFI_STATUS
2007AddOrInsertPolicyEntry (
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