Home | History | Annotate | Download | only in IpsecConfig
      1 /** @file
      2   The implementation of policy entry operation function in IpSecConfig application.
      3 
      4   Copyright (c) 2009 - 2015, 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
     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
    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     UnicodeStrToAsciiStr (ValueStr, (CHAR8 *) (*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
    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     UnicodeStrToAsciiStr (ValueStr, AsciiStr);
    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     UnicodeStrToAsciiStr (ValueStr, AsciiStr);
    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
   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
   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   if ((Mask & NAME) != 0) {
   1402     AsciiStrCpyS ((CHAR8 *) OldData->Name, MAX_PEERID_LEN, (CHAR8 *) NewData->Name);
   1403   }
   1404 
   1405   if ((Mask & PACKET_FLAG) != 0) {
   1406     OldData->PackageFlag = NewData->PackageFlag;
   1407   }
   1408 
   1409   if ((Mask & ACTION) != 0) {
   1410     OldData->Action = NewData->Action;
   1411   }
   1412 
   1413   if (OldData->Action != EfiIPsecActionProtect) {
   1414     OldData->ProcessingPolicy = NULL;
   1415   } else {
   1416     //
   1417     // Protect
   1418     //
   1419     if (OldData->ProcessingPolicy == NULL) {
   1420       //
   1421       // Just point to new data if originally NULL.
   1422       //
   1423       OldData->ProcessingPolicy = NewData->ProcessingPolicy;
   1424       if (OldData->ProcessingPolicy->Mode == EfiIPsecTunnel &&
   1425           (Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE)
   1426         ) {
   1427         //
   1428         // Change to Protect action and Tunnel mode, but without providing local/remote tunnel address.
   1429         //
   1430         ShellPrintHiiEx (
   1431           -1,
   1432           -1,
   1433           NULL,
   1434           STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
   1435           mHiiHandle,
   1436           mAppName,
   1437           L"--tunnel-local --tunnel-remote"
   1438           );
   1439         return EFI_INVALID_PARAMETER;
   1440       }
   1441     } else {
   1442       //
   1443       // Modify some of the data.
   1444       //
   1445       if ((Mask & EXT_SEQUENCE) != 0) {
   1446         OldData->ProcessingPolicy->ExtSeqNum = NewData->ProcessingPolicy->ExtSeqNum;
   1447       }
   1448 
   1449       if ((Mask & SEQUENCE_OVERFLOW) != 0) {
   1450         OldData->ProcessingPolicy->SeqOverflow = NewData->ProcessingPolicy->SeqOverflow;
   1451       }
   1452 
   1453       if ((Mask & FRAGMENT_CHECK) != 0) {
   1454         OldData->ProcessingPolicy->FragCheck = NewData->ProcessingPolicy->FragCheck;
   1455       }
   1456 
   1457       if ((Mask & LIFEBYTE) != 0) {
   1458         OldData->ProcessingPolicy->SaLifetime.ByteCount = NewData->ProcessingPolicy->SaLifetime.ByteCount;
   1459       }
   1460 
   1461       if ((Mask & LIFETIME_SOFT) != 0) {
   1462         OldData->ProcessingPolicy->SaLifetime.SoftLifetime = NewData->ProcessingPolicy->SaLifetime.SoftLifetime;
   1463       }
   1464 
   1465       if ((Mask & LIFETIME) != 0) {
   1466         OldData->ProcessingPolicy->SaLifetime.HardLifetime = NewData->ProcessingPolicy->SaLifetime.HardLifetime;
   1467       }
   1468 
   1469       if ((Mask & MODE) != 0) {
   1470         OldData->ProcessingPolicy->Mode = NewData->ProcessingPolicy->Mode;
   1471       }
   1472 
   1473       if ((Mask & IPSEC_PROTO) != 0) {
   1474         OldData->ProcessingPolicy->Proto = NewData->ProcessingPolicy->Proto;
   1475       }
   1476 
   1477       if ((Mask & AUTH_ALGO) != 0) {
   1478         OldData->ProcessingPolicy->AuthAlgoId = NewData->ProcessingPolicy->AuthAlgoId;
   1479       }
   1480 
   1481       if ((Mask & ENCRYPT_ALGO) != 0) {
   1482         OldData->ProcessingPolicy->EncAlgoId = NewData->ProcessingPolicy->EncAlgoId;
   1483       }
   1484 
   1485       if (OldData->ProcessingPolicy->Mode != EfiIPsecTunnel) {
   1486         OldData->ProcessingPolicy->TunnelOption = NULL;
   1487       } else {
   1488         if (OldData->ProcessingPolicy->TunnelOption == NULL) {
   1489           //
   1490           // Set from Transport mode to Tunnel mode, should ensure TUNNEL_LOCAL & TUNNEL_REMOTE both exists.
   1491           //
   1492           if ((Mask & (TUNNEL_LOCAL | TUNNEL_REMOTE)) != (TUNNEL_LOCAL | TUNNEL_REMOTE)) {
   1493             ShellPrintHiiEx (
   1494               -1,
   1495               -1,
   1496               NULL,
   1497               STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
   1498               mHiiHandle,
   1499               mAppName,
   1500               L"--tunnel-local --tunnel-remote"
   1501               );
   1502             return EFI_INVALID_PARAMETER;
   1503           }
   1504 
   1505           OldData->ProcessingPolicy->TunnelOption = NewData->ProcessingPolicy->TunnelOption;
   1506         } else {
   1507           if ((Mask & TUNNEL_LOCAL) != 0) {
   1508             CopyMem (
   1509               &OldData->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
   1510               &NewData->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
   1511               sizeof (EFI_IP_ADDRESS)
   1512               );
   1513           }
   1514 
   1515           if ((Mask & TUNNEL_REMOTE) != 0) {
   1516             CopyMem (
   1517               &OldData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
   1518               &NewData->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
   1519               sizeof (EFI_IP_ADDRESS)
   1520               );
   1521           }
   1522 
   1523           if ((Mask & DONT_FRAGMENT) != 0) {
   1524             OldData->ProcessingPolicy->TunnelOption->DF = NewData->ProcessingPolicy->TunnelOption->DF;
   1525           }
   1526         }
   1527       }
   1528     }
   1529   }
   1530 
   1531   return EFI_SUCCESS;
   1532 }
   1533 
   1534 /**
   1535   Combine old SAD entry with new SAD entry.
   1536 
   1537   @param[in, out] OldSaId      The pointer to the EFI_IPSEC_SA_ID structure.
   1538   @param[in, out] OldData      The pointer to the EFI_IPSEC_SA_DATA2 structure.
   1539   @param[in]      NewSaId      The pointer to the EFI_IPSEC_SA_ID structure.
   1540   @param[in]      NewData      The pointer to the EFI_IPSEC_SA_DATA2 structure.
   1541   @param[in]      Mask         The pointer to the Mask.
   1542   @param[out]     CreateNew    The switch to create new.
   1543 
   1544   @retval EFI_SUCCESS              Combined successfully.
   1545   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
   1546 
   1547 **/
   1548 EFI_STATUS
   1549 CombineSadEntry (
   1550   IN OUT EFI_IPSEC_SA_ID      *OldSaId,
   1551   IN OUT EFI_IPSEC_SA_DATA2   *OldData,
   1552   IN     EFI_IPSEC_SA_ID      *NewSaId,
   1553   IN     EFI_IPSEC_SA_DATA2   *NewData,
   1554   IN     UINT32               Mask,
   1555      OUT BOOLEAN              *CreateNew
   1556   )
   1557 {
   1558 
   1559   *CreateNew = FALSE;
   1560 
   1561   if ((Mask & SPI) == 0) {
   1562     NewSaId->Spi = OldSaId->Spi;
   1563   } else if (NewSaId->Spi != OldSaId->Spi) {
   1564     *CreateNew = TRUE;
   1565   }
   1566 
   1567   if ((Mask & IPSEC_PROTO) == 0) {
   1568     NewSaId->Proto = OldSaId->Proto;
   1569   } else if (NewSaId->Proto != OldSaId->Proto) {
   1570     *CreateNew = TRUE;
   1571   }
   1572 
   1573   if ((Mask & DEST) == 0) {
   1574     CopyMem (&NewData->TunnelDestinationAddress, &OldData->TunnelDestinationAddress, sizeof (EFI_IP_ADDRESS));
   1575   } else if (CompareMem (&NewData->TunnelDestinationAddress, &OldData->TunnelDestinationAddress, sizeof (EFI_IP_ADDRESS)) != 0) {
   1576     *CreateNew = TRUE;
   1577   }
   1578 
   1579   if ((Mask & SOURCE) == 0) {
   1580     CopyMem (&NewData->TunnelSourceAddress, &OldData->TunnelSourceAddress, sizeof (EFI_IP_ADDRESS));
   1581   } else if (CompareMem (&NewData->TunnelSourceAddress, &OldData->TunnelSourceAddress, sizeof (EFI_IP_ADDRESS)) != 0) {
   1582     *CreateNew = TRUE;
   1583   }
   1584   //
   1585   // Process SA_DATA.
   1586   //
   1587   if ((Mask & MODE) != 0) {
   1588     OldData->Mode = NewData->Mode;
   1589   }
   1590 
   1591   if ((Mask & SEQUENCE_NUMBER) != 0) {
   1592     OldData->SNCount = NewData->SNCount;
   1593   }
   1594 
   1595   if ((Mask & ANTIREPLAY_WINDOW) != 0) {
   1596     OldData->AntiReplayWindows = NewData->AntiReplayWindows;
   1597   }
   1598 
   1599   if ((Mask & AUTH_ALGO) != 0) {
   1600     OldData->AlgoInfo.EspAlgoInfo.AuthAlgoId    = NewData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
   1601   }
   1602 
   1603   if ((Mask & AUTH_KEY) != 0) {
   1604     OldData->AlgoInfo.EspAlgoInfo.AuthKey       = NewData->AlgoInfo.EspAlgoInfo.AuthKey;
   1605     OldData->AlgoInfo.EspAlgoInfo.AuthKeyLength = NewData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
   1606   }
   1607 
   1608   if ((Mask & ENCRYPT_ALGO) != 0) {
   1609     OldData->AlgoInfo.EspAlgoInfo.EncAlgoId     = NewData->AlgoInfo.EspAlgoInfo.EncAlgoId;
   1610   }
   1611 
   1612   if ((Mask & ENCRYPT_KEY) != 0) {
   1613     OldData->AlgoInfo.EspAlgoInfo.EncKey        = NewData->AlgoInfo.EspAlgoInfo.EncKey;
   1614     OldData->AlgoInfo.EspAlgoInfo.EncKeyLength  = NewData->AlgoInfo.EspAlgoInfo.EncKeyLength;
   1615   }
   1616 
   1617   if (NewSaId->Proto == EfiIPsecAH) {
   1618     if ((Mask & (ENCRYPT_ALGO | ENCRYPT_KEY)) != 0) {
   1619       //
   1620       // Should not provide encrypt_* if AH.
   1621       //
   1622       ShellPrintHiiEx (
   1623         -1,
   1624         -1,
   1625         NULL,
   1626         STRING_TOKEN (STR_IPSEC_CONFIG_UNWANTED_PARAMETER),
   1627         mHiiHandle,
   1628         mAppName,
   1629         L"--encrypt-algo --encrypt-key"
   1630         );
   1631       return EFI_INVALID_PARAMETER;
   1632     }
   1633   }
   1634 
   1635   if (NewSaId->Proto == EfiIPsecESP && OldSaId->Proto == EfiIPsecAH) {
   1636     //
   1637     // AH -> ESP
   1638     // Should provide encrypt_algo at least.
   1639     //
   1640     if ((Mask & ENCRYPT_ALGO) == 0) {
   1641       ShellPrintHiiEx (
   1642         -1,
   1643         -1,
   1644         NULL,
   1645         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
   1646         mHiiHandle,
   1647         mAppName,
   1648         L"--encrypt-algo"
   1649         );
   1650       return EFI_INVALID_PARAMETER;
   1651     }
   1652 
   1653     //
   1654     // Encrypt_key should be provided if algorithm is not NONE.
   1655     //
   1656     if (NewData->AlgoInfo.EspAlgoInfo.EncAlgoId != IPSEC_EALG_NONE && (Mask & ENCRYPT_KEY) == 0) {
   1657       ShellPrintHiiEx (
   1658         -1,
   1659         -1,
   1660         NULL,
   1661         STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_PARAMETER),
   1662         mHiiHandle,
   1663         mAppName,
   1664         L"--encrypt-algo"
   1665         );
   1666       return EFI_INVALID_PARAMETER;
   1667     }
   1668   }
   1669 
   1670   if ((Mask & LIFEBYTE) != 0) {
   1671     OldData->SaLifetime.ByteCount    = NewData->SaLifetime.ByteCount;
   1672   }
   1673 
   1674   if ((Mask & LIFETIME_SOFT) != 0) {
   1675     OldData->SaLifetime.SoftLifetime = NewData->SaLifetime.SoftLifetime;
   1676   }
   1677 
   1678   if ((Mask & LIFETIME) != 0) {
   1679     OldData->SaLifetime.HardLifetime = NewData->SaLifetime.HardLifetime;
   1680   }
   1681 
   1682   if ((Mask & PATH_MTU) != 0) {
   1683     OldData->PathMTU                 = NewData->PathMTU;
   1684   }
   1685   //
   1686   // Process SpdSelector.
   1687   //
   1688   if (OldData->SpdSelector == NULL) {
   1689     if ((Mask & (LOCAL | REMOTE | PROTO | LOCAL_PORT | REMOTE_PORT | ICMP_TYPE | ICMP_CODE)) != 0) {
   1690       if ((Mask & (LOCAL | REMOTE | PROTO)) != (LOCAL | REMOTE | PROTO)) {
   1691         ShellPrintHiiEx (
   1692           -1,
   1693           -1,
   1694           NULL,
   1695           STRING_TOKEN (STR_IPSEC_CONFIG_MISSING_ONE_OF_PARAMETERS),
   1696           mHiiHandle,
   1697           mAppName,
   1698           L"--local --remote --proto"
   1699           );
   1700         return EFI_INVALID_PARAMETER;
   1701       }
   1702 
   1703       OldData->SpdSelector = NewData->SpdSelector;
   1704     }
   1705   } else {
   1706     if ((Mask & LOCAL) != 0) {
   1707       OldData->SpdSelector->LocalAddressCount  = NewData->SpdSelector->LocalAddressCount;
   1708       OldData->SpdSelector->LocalAddress       = NewData->SpdSelector->LocalAddress;
   1709     }
   1710 
   1711     if ((Mask & REMOTE) != 0) {
   1712       OldData->SpdSelector->RemoteAddressCount = NewData->SpdSelector->RemoteAddressCount;
   1713       OldData->SpdSelector->RemoteAddress      = NewData->SpdSelector->RemoteAddress;
   1714     }
   1715 
   1716     if ((Mask & PROTO) != 0) {
   1717       OldData->SpdSelector->NextLayerProtocol  = NewData->SpdSelector->NextLayerProtocol;
   1718     }
   1719 
   1720     if (OldData->SpdSelector != NULL) {
   1721       switch (OldData->SpdSelector->NextLayerProtocol) {
   1722         case EFI_IP4_PROTO_TCP:
   1723         case EFI_IP4_PROTO_UDP:
   1724           if ((Mask & LOCAL_PORT) != 0) {
   1725             OldData->SpdSelector->LocalPort  = NewData->SpdSelector->LocalPort;
   1726           }
   1727 
   1728           if ((Mask & REMOTE_PORT) != 0) {
   1729             OldData->SpdSelector->RemotePort = NewData->SpdSelector->RemotePort;
   1730           }
   1731           break;
   1732 
   1733         case EFI_IP4_PROTO_ICMP:
   1734           if ((Mask & ICMP_TYPE) != 0) {
   1735             OldData->SpdSelector->LocalPort  = (UINT8) NewData->SpdSelector->LocalPort;
   1736           }
   1737 
   1738           if ((Mask & ICMP_CODE) != 0) {
   1739             OldData->SpdSelector->RemotePort = (UINT8) NewData->SpdSelector->RemotePort;
   1740           }
   1741           break;
   1742       }
   1743     }
   1744   }
   1745 
   1746   return EFI_SUCCESS;
   1747 }
   1748 
   1749 /**
   1750   Combine old PAD entry with new PAD entry.
   1751 
   1752   @param[in, out] OldPadId     The pointer to the EFI_IPSEC_PAD_ID structure.
   1753   @param[in, out] OldData      The pointer to the EFI_IPSEC_PAD_DATA structure.
   1754   @param[in]      NewPadId     The pointer to the EFI_IPSEC_PAD_ID structure.
   1755   @param[in]      NewData      The pointer to the EFI_IPSEC_PAD_DATA structure.
   1756   @param[in]      Mask         The pointer to the Mask.
   1757   @param[out]     CreateNew    The switch to create new.
   1758 
   1759   @retval EFI_SUCCESS              Combined successfully.
   1760   @retval EFI_INVALID_PARAMETER    Invalid user input parameter.
   1761 
   1762 **/
   1763 EFI_STATUS
   1764 CombinePadEntry (
   1765   IN OUT EFI_IPSEC_PAD_ID      *OldPadId,
   1766   IN OUT EFI_IPSEC_PAD_DATA    *OldData,
   1767   IN     EFI_IPSEC_PAD_ID      *NewPadId,
   1768   IN     EFI_IPSEC_PAD_DATA    *NewData,
   1769   IN     UINT32                Mask,
   1770      OUT BOOLEAN               *CreateNew
   1771   )
   1772 {
   1773 
   1774   *CreateNew = FALSE;
   1775 
   1776   if ((Mask & (PEER_ID | PEER_ADDRESS)) == 0) {
   1777     CopyMem (NewPadId, OldPadId, sizeof (EFI_IPSEC_PAD_ID));
   1778   } else {
   1779     if ((Mask & PEER_ID) != 0) {
   1780       if (OldPadId->PeerIdValid) {
   1781         if (StrCmp ((CONST CHAR16 *) OldPadId->Id.PeerId, (CONST CHAR16 *) NewPadId->Id.PeerId) != 0) {
   1782           *CreateNew = TRUE;
   1783         }
   1784       } else {
   1785         *CreateNew = TRUE;
   1786       }
   1787     } else {
   1788       //
   1789       // MASK & PEER_ADDRESS
   1790       //
   1791       if (OldPadId->PeerIdValid) {
   1792         *CreateNew = TRUE;
   1793       } else {
   1794         if ((CompareMem (&OldPadId->Id.IpAddress.Address, &NewPadId->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0) ||
   1795             (OldPadId->Id.IpAddress.PrefixLength != NewPadId->Id.IpAddress.PrefixLength)) {
   1796           *CreateNew = TRUE;
   1797         }
   1798       }
   1799     }
   1800   }
   1801 
   1802   if ((Mask & AUTH_PROTO) != 0) {
   1803     OldData->AuthProtocol = NewData->AuthProtocol;
   1804   }
   1805 
   1806   if ((Mask & AUTH_METHOD) != 0) {
   1807     OldData->AuthMethod = NewData->AuthMethod;
   1808   }
   1809 
   1810   if ((Mask & IKE_ID) != 0) {
   1811     OldData->IkeIdFlag = NewData->IkeIdFlag;
   1812   }
   1813 
   1814   if ((Mask & AUTH_DATA) != 0) {
   1815     OldData->AuthDataSize = NewData->AuthDataSize;
   1816     OldData->AuthData     = NewData->AuthData;
   1817   }
   1818 
   1819   if ((Mask & REVOCATION_DATA) != 0) {
   1820     OldData->RevocationDataSize = NewData->RevocationDataSize;
   1821     OldData->RevocationData     = NewData->RevocationData;
   1822   }
   1823 
   1824   return EFI_SUCCESS;
   1825 }
   1826 
   1827 COMBINE_POLICY_ENTRY mCombinePolicyEntry[] = {
   1828   (COMBINE_POLICY_ENTRY) CombineSpdEntry,
   1829   (COMBINE_POLICY_ENTRY) CombineSadEntry,
   1830   (COMBINE_POLICY_ENTRY) CombinePadEntry
   1831 };
   1832 
   1833 /**
   1834   Edit entry information in the database.
   1835 
   1836   @param[in] Selector    The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure.
   1837   @param[in] Data        The pointer to the data.
   1838   @param[in] Context     The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure.
   1839 
   1840   @retval EFI_SUCCESS    Continue the iteration.
   1841   @retval EFI_ABORTED    Abort the iteration.
   1842 **/
   1843 EFI_STATUS
   1844 EditOperatePolicyEntry (
   1845   IN EFI_IPSEC_CONFIG_SELECTOR    *Selector,
   1846   IN VOID                         *Data,
   1847   IN EDIT_POLICY_ENTRY_CONTEXT    *Context
   1848   )
   1849 {
   1850   EFI_STATUS    Status;
   1851   BOOLEAN       CreateNew;
   1852 
   1853   if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) {
   1854     ASSERT (Context->DataType < 3);
   1855 
   1856     Status = mCombinePolicyEntry[Context->DataType] (
   1857                Selector,
   1858                Data,
   1859                Context->Selector,
   1860                Context->Data,
   1861                Context->Mask,
   1862                &CreateNew
   1863                );
   1864     if (!EFI_ERROR (Status)) {
   1865       if (CreateNew) {
   1866         //
   1867         // Insert new entry before old entry
   1868         //
   1869         Status = mIpSecConfig->SetData (
   1870                                  mIpSecConfig,
   1871                                  Context->DataType,
   1872                                  Context->Selector,
   1873                                  Data,
   1874                                  Selector
   1875                                  );
   1876         ASSERT_EFI_ERROR (Status);
   1877         //
   1878         // Delete old entry
   1879         //
   1880         Status = mIpSecConfig->SetData (
   1881                                  mIpSecConfig,
   1882                                  Context->DataType,
   1883                                  Selector,
   1884                                  NULL,
   1885                                  NULL
   1886                                  );
   1887         ASSERT_EFI_ERROR (Status);
   1888       } else {
   1889         Status = mIpSecConfig->SetData (
   1890                                  mIpSecConfig,
   1891                                  Context->DataType,
   1892                                  Context->Selector,
   1893                                  Data,
   1894                                  NULL
   1895                                  );
   1896       }
   1897     }
   1898 
   1899     Context->Status = Status;
   1900     return EFI_ABORTED;
   1901   }
   1902 
   1903   return EFI_SUCCESS;
   1904 }
   1905 
   1906 /**
   1907   Edit entry information in database according to datatype.
   1908 
   1909   @param[in] DataType        The value of EFI_IPSEC_CONFIG_DATA_TYPE.
   1910   @param[in] ParamPackage    The pointer to the ParamPackage list.
   1911 
   1912   @retval EFI_SUCCESS             Edit entry information successfully.
   1913   @retval EFI_NOT_FOUND           Can't find the specified entry.
   1914   @retval Others                  Some mistaken case.
   1915 **/
   1916 EFI_STATUS
   1917 EditPolicyEntry (
   1918   IN EFI_IPSEC_CONFIG_DATA_TYPE    DataType,
   1919   IN LIST_ENTRY                    *ParamPackage
   1920   )
   1921 {
   1922   EFI_STATUS                   Status;
   1923   EDIT_POLICY_ENTRY_CONTEXT    Context;
   1924   CONST CHAR16                 *ValueStr;
   1925 
   1926   ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
   1927   if (ValueStr == NULL) {
   1928     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr);
   1929     return EFI_NOT_FOUND;
   1930   }
   1931 
   1932   Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage);
   1933   if (!EFI_ERROR (Status)) {
   1934     Context.DataType = DataType;
   1935     Context.Status   = EFI_NOT_FOUND;
   1936     Status = mCreatePolicyEntry[DataType] (&Context.Selector, &Context.Data, ParamPackage, &Context.Mask, FALSE);
   1937     if (!EFI_ERROR (Status)) {
   1938       ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) EditOperatePolicyEntry, &Context);
   1939       Status = Context.Status;
   1940     }
   1941 
   1942     if (Context.Selector != NULL) {
   1943       gBS->FreePool (Context.Selector);
   1944     }
   1945 
   1946     if (Context.Data != NULL) {
   1947       gBS->FreePool (Context.Data);
   1948     }
   1949   }
   1950 
   1951   if (Status == EFI_NOT_FOUND) {
   1952     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr);
   1953   } else if (EFI_ERROR (Status)) {
   1954     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_EDIT_FAILED), mHiiHandle, mAppName);
   1955   }
   1956 
   1957   return Status;
   1958 
   1959 }
   1960 
   1961 /**
   1962   Insert entry information in database.
   1963 
   1964   @param[in] Selector    The pointer to the EFI_IPSEC_CONFIG_SELECTOR structure.
   1965   @param[in] Data        The pointer to the data.
   1966   @param[in] Context     The pointer to the INSERT_POLICY_ENTRY_CONTEXT structure.
   1967 
   1968   @retval EFI_SUCCESS    Continue the iteration.
   1969   @retval EFI_ABORTED    Abort the iteration.
   1970 **/
   1971 EFI_STATUS
   1972 InsertPolicyEntry (
   1973   IN EFI_IPSEC_CONFIG_SELECTOR      *Selector,
   1974   IN VOID                           *Data,
   1975   IN INSERT_POLICY_ENTRY_CONTEXT    *Context
   1976   )
   1977 {
   1978   //
   1979   // Found the entry which we want to insert before.
   1980   //
   1981   if (mMatchPolicyEntry[Context->DataType] (Selector, Data, &Context->Indexer)) {
   1982 
   1983     Context->Status = mIpSecConfig->SetData (
   1984                                       mIpSecConfig,
   1985                                       Context->DataType,
   1986                                       Context->Selector,
   1987                                       Context->Data,
   1988                                       Selector
   1989                                       );
   1990     //
   1991     // Abort the iteration after the insertion.
   1992     //
   1993     return EFI_ABORTED;
   1994   }
   1995 
   1996   return EFI_SUCCESS;
   1997 }
   1998 
   1999 /**
   2000   Insert or add entry information in database according to datatype.
   2001 
   2002   @param[in] DataType        The value of EFI_IPSEC_CONFIG_DATA_TYPE.
   2003   @param[in] ParamPackage    The pointer to the ParamPackage list.
   2004 
   2005   @retval EFI_SUCCESS             Insert or add entry information successfully.
   2006   @retval EFI_NOT_FOUND           Can't find the specified entry.
   2007   @retval EFI_BUFFER_TOO_SMALL    The entry already existed.
   2008   @retval EFI_UNSUPPORTED         The operation is not supported.
   2009   @retval Others                  Some mistaken case.
   2010 **/
   2011 EFI_STATUS
   2012 AddOrInsertPolicyEntry (
   2013   IN EFI_IPSEC_CONFIG_DATA_TYPE    DataType,
   2014   IN LIST_ENTRY                    *ParamPackage
   2015   )
   2016 {
   2017   EFI_STATUS                     Status;
   2018   EFI_IPSEC_CONFIG_SELECTOR      *Selector;
   2019   VOID                           *Data;
   2020   INSERT_POLICY_ENTRY_CONTEXT    Context;
   2021   UINT32                         Mask;
   2022   UINTN                          DataSize;
   2023   CONST CHAR16                   *ValueStr;
   2024 
   2025   Status = mCreatePolicyEntry[DataType] (&Selector, &Data, ParamPackage, &Mask, TRUE);
   2026   if (!EFI_ERROR (Status)) {
   2027     //
   2028     // Find if the Selector to be inserted already exists.
   2029     //
   2030     DataSize = 0;
   2031     Status = mIpSecConfig->GetData (
   2032                              mIpSecConfig,
   2033                              DataType,
   2034                              Selector,
   2035                              &DataSize,
   2036                              NULL
   2037                              );
   2038     if (Status == EFI_BUFFER_TOO_SMALL) {
   2039       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_ALREADY_EXISTS), mHiiHandle, mAppName);
   2040     } else if (ShellCommandLineGetFlag (ParamPackage, L"-a")) {
   2041       Status = mIpSecConfig->SetData (
   2042                                mIpSecConfig,
   2043                                DataType,
   2044                                Selector,
   2045                                Data,
   2046                                NULL
   2047                                );
   2048     } else {
   2049       ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
   2050       if (ValueStr == NULL) {
   2051         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_SPECIFIED), mHiiHandle, mAppName, ValueStr);
   2052         return EFI_NOT_FOUND;
   2053       }
   2054 
   2055       Status = mConstructPolicyEntryIndexer[DataType] (&Context.Indexer, ParamPackage);
   2056       if (!EFI_ERROR (Status)) {
   2057         Context.DataType  = DataType;
   2058         Context.Status    = EFI_NOT_FOUND;
   2059         Context.Selector  = Selector;
   2060         Context.Data      = Data;
   2061 
   2062         ForeachPolicyEntry (DataType, (VISIT_POLICY_ENTRY) InsertPolicyEntry, &Context);
   2063         Status = Context.Status;
   2064         if (Status == EFI_NOT_FOUND) {
   2065           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INDEX_NOT_FOUND), mHiiHandle, mAppName, ValueStr);
   2066         }
   2067       }
   2068     }
   2069 
   2070     gBS->FreePool (Selector);
   2071     gBS->FreePool (Data);
   2072   }
   2073 
   2074   if (Status == EFI_UNSUPPORTED) {
   2075     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_UNSUPPORT), mHiiHandle, mAppName);
   2076   } else if (EFI_ERROR (Status)) {
   2077     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IPSEC_CONFIG_INSERT_FAILED), mHiiHandle, mAppName);
   2078   }
   2079 
   2080   return Status;
   2081 }
   2082