1/** @file
2  The definitions related to IPsec protocol implementation.
3
4  Copyright (c) 2009 - 2011, 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#ifndef _IP_SEC_IMPL_H_
17#define _IP_SEC_IMPL_H_
18
19#include <Uefi.h>
20#include <Library/UefiLib.h>
21#include <Library/NetLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Library/UefiBootServicesTableLib.h>
24#include <Library/MemoryAllocationLib.h>
25#include <Protocol/IpSec.h>
26#include <Protocol/IpSecConfig.h>
27#include <Protocol/Dpc.h>
28#include <Protocol/ComponentName.h>
29#include <Protocol/ComponentName2.h>
30
31typedef struct _IPSEC_PRIVATE_DATA IPSEC_PRIVATE_DATA;
32typedef struct _IPSEC_SPD_ENTRY IPSEC_SPD_ENTRY;
33typedef struct _IPSEC_PAD_ENTRY IPSEC_PAD_ENTRY;
34typedef struct _IPSEC_SPD_DATA IPSEC_SPD_DATA;
35
36#define IPSEC_PRIVATE_DATA_SIGNATURE        SIGNATURE_32 ('I', 'P', 'S', 'E')
37
38#define IPSEC_PRIVATE_DATA_FROM_IPSEC(a)    CR (a, IPSEC_PRIVATE_DATA, IpSec, IPSEC_PRIVATE_DATA_SIGNATURE)
39#define IPSEC_PRIVATE_DATA_FROM_UDP4LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp4List, IPSEC_PRIVATE_DATA_SIGNATURE)
40#define IPSEC_PRIVATE_DATA_FROM_UDP6LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp6List, IPSEC_PRIVATE_DATA_SIGNATURE)
41#define IPSEC_UDP_SERVICE_FROM_LIST(a)      BASE_CR (a, IKE_UDP_SERVICE, List)
42#define IPSEC_SPD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_SPD_ENTRY, List)
43#define IPSEC_SAD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_SAD_ENTRY, List)
44#define IPSEC_PAD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_PAD_ENTRY, List)
45#define IPSEC_SAD_ENTRY_FROM_SPD(a)         BASE_CR (a, IPSEC_SAD_ENTRY, BySpd)
46
47#define IPSEC_STATUS_DISABLED       0
48#define IPSEC_STATUS_ENABLED        1
49#define IPSEC_ESP_PROTOCOL          50
50#define IPSEC_AH_PROTOCOL           51
51#define IPSEC_DEFAULT_VARIABLE_SIZE 0x100
52
53//
54// Internal Structure Definition
55//
56#pragma pack(1)
57typedef struct _EFI_AH_HEADER {
58  UINT8   NextHeader;
59  UINT8   PayloadLen;
60  UINT16  Reserved;
61  UINT32  Spi;
62  UINT32  SequenceNumber;
63} EFI_AH_HEADER;
64
65typedef struct _EFI_ESP_HEADER {
66  UINT32  Spi;
67  UINT32  SequenceNumber;
68} EFI_ESP_HEADER;
69
70typedef struct _EFI_ESP_TAIL {
71  UINT8 PaddingLength;
72  UINT8 NextHeader;
73} EFI_ESP_TAIL;
74#pragma pack()
75
76struct _IPSEC_SPD_DATA {
77  CHAR16                    Name[100];
78  UINT32                    PackageFlag;
79  EFI_IPSEC_TRAFFIC_DIR     TrafficDirection;
80  EFI_IPSEC_ACTION          Action;
81  EFI_IPSEC_PROCESS_POLICY  *ProcessingPolicy;
82  LIST_ENTRY                Sas;
83};
84
85struct _IPSEC_SPD_ENTRY {
86  EFI_IPSEC_SPD_SELECTOR  *Selector;
87  IPSEC_SPD_DATA          *Data;
88  LIST_ENTRY              List;
89};
90
91typedef struct _IPSEC_SAD_DATA {
92  EFI_IPSEC_MODE         Mode;
93  UINT64                 SequenceNumber;
94  UINT8                  AntiReplayWindowSize;
95  UINT64                 AntiReplayBitmap[4];  // bitmap for received packet
96  EFI_IPSEC_ALGO_INFO    AlgoInfo;
97  EFI_IPSEC_SA_LIFETIME  SaLifetime;
98  UINT32                 PathMTU;
99  IPSEC_SPD_ENTRY        *SpdEntry;
100  EFI_IPSEC_SPD_SELECTOR *SpdSelector;
101  BOOLEAN                ESNEnabled;           // Extended (64-bit) SN enabled
102  BOOLEAN                ManualSet;
103  EFI_IP_ADDRESS         TunnelDestAddress;
104  EFI_IP_ADDRESS         TunnelSourceAddress;
105} IPSEC_SAD_DATA;
106
107typedef struct _IPSEC_SAD_ENTRY {
108  EFI_IPSEC_SA_ID  *Id;
109  IPSEC_SAD_DATA  *Data;
110  LIST_ENTRY      List;
111  LIST_ENTRY      BySpd;                      // Linked on IPSEC_SPD_DATA.Sas
112} IPSEC_SAD_ENTRY;
113
114struct _IPSEC_PAD_ENTRY {
115  EFI_IPSEC_PAD_ID    *Id;
116  EFI_IPSEC_PAD_DATA  *Data;
117  LIST_ENTRY          List;
118};
119
120typedef struct _IPSEC_RECYCLE_CONTEXT {
121  EFI_IPSEC_FRAGMENT_DATA *FragmentTable;
122  UINT8                   *PayloadBuffer;
123} IPSEC_RECYCLE_CONTEXT;
124
125//
126// Struct used to store the Hash and its data.
127//
128typedef struct {
129  UINTN DataSize;
130  UINT8 *Data;
131} HASH_DATA_FRAGMENT;
132
133struct _IPSEC_PRIVATE_DATA {
134  UINT32                    Signature;
135  EFI_HANDLE                Handle;           // Virtual handle to install private prtocol
136  EFI_HANDLE                ImageHandle;
137  EFI_IPSEC2_PROTOCOL       IpSec;
138  EFI_IPSEC_CONFIG_PROTOCOL IpSecConfig;
139  BOOLEAN                   SetBySelf;
140  LIST_ENTRY                Udp4List;
141  UINTN                     Udp4Num;
142  LIST_ENTRY                Udp6List;
143  UINTN                     Udp6Num;
144  LIST_ENTRY                Ikev1SessionList;
145  LIST_ENTRY                Ikev1EstablishedList;
146  LIST_ENTRY                Ikev2SessionList;
147  LIST_ENTRY                Ikev2EstablishedList;
148  BOOLEAN                   IsIPsecDisabling;
149};
150
151/**
152  This function processes the inbound traffic with IPsec.
153
154  It checks the received packet security property, trims the ESP/AH header, and then
155  returns without an IPsec protected IP Header and FragmentTable.
156
157  @param[in]      IpVersion          The version of IP.
158  @param[in, out] IpHead             Points to IP header containing the ESP/AH header
159                                     to be trimed on input, and without ESP/AH header
160                                     on return.
161  @param[in, out] LastHead           The Last Header in IP header on return.
162  @param[in, out] OptionsBuffer      Pointer to the options buffer.
163  @param[in, out] OptionsLength      Length of the options buffer.
164  @param[in, out] FragmentTable      Pointer to a list of fragments in form of IPsec
165                                     protected on input, and without IPsec protected
166                                     on return.
167  @param[in, out] FragmentCount      The number of fragments.
168  @param[out]     SpdEntry           Pointer to contain the address of SPD entry on return.
169  @param[out]     RecycleEvent       The event for recycling of resources.
170
171  @retval EFI_SUCCESS              The operation was successful.
172  @retval EFI_UNSUPPORTED          The IPSEC protocol is not supported.
173
174**/
175EFI_STATUS
176IpSecProtectInboundPacket (
177  IN     UINT8                       IpVersion,
178  IN OUT VOID                        *IpHead,
179  IN OUT UINT8                       *LastHead,
180  IN OUT VOID                        **OptionsBuffer,
181  IN OUT UINT32                      *OptionsLength,
182  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,
183  IN OUT UINT32                      *FragmentCount,
184     OUT EFI_IPSEC_SPD_SELECTOR      **SpdEntry,
185     OUT EFI_EVENT                   *RecycleEvent
186  );
187
188
189/**
190  This fucntion processes the output traffic with IPsec.
191
192  It protected the sending packet by encrypting it payload and inserting ESP/AH header
193  in the orginal IP header, then return the IpHeader and IPsec protected Fragmentable.
194
195  @param[in]      IpVersion          The version of IP.
196  @param[in, out] IpHead             Point to IP header containing the orginal IP header
197                                     to be processed on input, and inserted ESP/AH header
198                                     on return.
199  @param[in, out] LastHead           The Last Header in IP header.
200  @param[in, out] OptionsBuffer      Pointer to the options buffer.
201  @param[in, out] OptionsLength      Length of the options buffer.
202  @param[in, out] FragmentTable      Pointer to a list of fragments to be protected by
203                                     IPsec on input, and with IPsec protected
204                                     on return.
205  @param[in, out] FragmentCount      Number of fragments.
206  @param[in]      SadEntry           Related SAD entry.
207  @param[out]     RecycleEvent       Event for recycling of resources.
208
209  @retval EFI_SUCCESS              The operation is successful.
210  @retval EFI_UNSUPPORTED          If the IPSEC protocol is not supported.
211
212**/
213EFI_STATUS
214IpSecProtectOutboundPacket (
215  IN     UINT8                       IpVersion,
216  IN OUT VOID                        *IpHead,
217  IN OUT UINT8                       *LastHead,
218  IN OUT VOID                        **OptionsBuffer,
219  IN OUT UINT32                      *OptionsLength,
220  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,
221  IN OUT UINT32                      *FragmentCount,
222  IN     IPSEC_SAD_ENTRY             *SadEntry,
223     OUT EFI_EVENT                   *RecycleEvent
224  );
225
226/**
227  Check if the IP Address in the address range of AddressInfos specified.
228
229  @param[in]  IpVersion         The IP version.
230  @param[in]  IpAddr            Points to EFI_IP_ADDRESS to be check.
231  @param[in]  AddressInfo       A list of EFI_IP_ADDRESS_INFO that is used to check
232                                the IP Address is matched.
233  @param[in]  AddressCount      The total numbers of the AddressInfo.
234
235  @retval   TRUE    If the Specified IP Address is in the range of the AddressInfos specified.
236  @retval   FALSE   If the Specified IP Address is not in the range of the AddressInfos specified.
237
238**/
239BOOLEAN
240IpSecMatchIpAddress (
241  IN UINT8                                  IpVersion,
242  IN EFI_IP_ADDRESS                         *IpAddr,
243  IN EFI_IP_ADDRESS_INFO                    *AddressInfo,
244  IN UINT32                                 AddressCount
245  );
246
247/**
248  Find a PAD entry according to remote IP address.
249
250  @param[in]  IpVersion         The version of IP.
251  @param[in]  IpAddr            Point to remote IP address.
252
253  @return The pointer of related PAD entry.
254
255**/
256IPSEC_PAD_ENTRY *
257IpSecLookupPadEntry (
258  IN UINT8                                  IpVersion,
259  IN EFI_IP_ADDRESS                         *IpAddr
260  );
261
262/**
263  Check if the specified IP packet can be serviced by this SPD entry.
264
265  @param[in]  SpdEntry          Point to SPD entry.
266  @param[in]  IpVersion         Version of IP.
267  @param[in]  IpHead            Point to IP header.
268  @param[in]  IpPayload         Point to IP payload.
269  @param[in]  Protocol          The Last protocol of IP packet.
270  @param[in]  IsOutbound        Traffic direction.
271  @param[out] Action            The support action of SPD entry.
272
273  @retval EFI_SUCCESS       Find the related SPD.
274  @retval EFI_NOT_FOUND     Not find the related SPD entry;
275
276**/
277EFI_STATUS
278IpSecLookupSpdEntry (
279  IN     IPSEC_SPD_ENTRY         *SpdEntry,
280  IN     UINT8                   IpVersion,
281  IN     VOID                    *IpHead,
282  IN     UINT8                   *IpPayload,
283  IN     UINT8                   Protocol,
284  IN     BOOLEAN                 IsOutbound,
285     OUT EFI_IPSEC_ACTION        *Action
286  );
287
288/**
289  Look up if there is existing SAD entry for specified IP packet sending.
290
291  This function is called by the IPsecProcess when there is some IP packet needed to
292  send out. This function checks if there is an existing SAD entry that can be serviced
293  to this IP packet sending. If no existing SAD entry could be used, this
294  function will invoke an IPsec Key Exchange Negotiation.
295
296  @param[in]  Private           Points to private data.
297  @param[in]  NicHandle         Points to a NIC handle.
298  @param[in]  IpVersion         The version of IP.
299  @param[in]  IpHead            The IP Header of packet to be sent out.
300  @param[in]  IpPayload         The IP Payload to be sent out.
301  @param[in]  OldLastHead       The Last protocol of the IP packet.
302  @param[in]  SpdEntry          Points to a related SPD entry.
303  @param[out] SadEntry          Contains the Point of a related SAD entry.
304
305  @retval EFI_DEVICE_ERROR  One of following conditions is TRUE:
306                            - If don't find related UDP service.
307                            - Sequence Number is used up.
308                            - Extension Sequence Number is used up.
309  @retval EFI_NOT_READY     No existing SAD entry could be used.
310  @retval EFI_SUCCESS       Find the related SAD entry.
311
312**/
313EFI_STATUS
314IpSecLookupSadEntry (
315  IN IPSEC_PRIVATE_DATA      *Private,
316  IN EFI_HANDLE              NicHandle,
317  IN UINT8                   IpVersion,
318  IN VOID                    *IpHead,
319  IN UINT8                   *IpPayload,
320  IN UINT8                   OldLastHead,
321  IN IPSEC_SPD_ENTRY         *SpdEntry,
322  OUT IPSEC_SAD_ENTRY        **SadEntry
323  );
324
325/**
326  Find the SAD through whole SAD list.
327
328  @param[in]  Spi               The SPI used to search the SAD entry.
329  @param[in]  DestAddress       The destination used to search the SAD entry.
330  @param[in]  IpVersion         The IP version. Ip4 or Ip6.
331
332  @return  The pointer to a certain SAD entry.
333
334**/
335IPSEC_SAD_ENTRY *
336IpSecLookupSadBySpi (
337  IN UINT32                                 Spi,
338  IN EFI_IP_ADDRESS                         *DestAddress,
339  IN UINT8                                  IpVersion
340  )
341;
342
343/**
344  Handles IPsec packet processing for inbound and outbound IP packets.
345
346  The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
347  The behavior is that it can perform one of the following actions:
348  bypass the packet, discard the packet, or protect the packet.
349
350  @param[in]      This             Pointer to the EFI_IPSEC2_PROTOCOL instance.
351  @param[in]      NicHandle        Instance of the network interface.
352  @param[in]      IpVersion        IPV4 or IPV6.
353  @param[in, out] IpHead           Pointer to the IP Header.
354  @param[in, out] LastHead         The protocol of the next layer to be processed by IPsec.
355  @param[in, out] OptionsBuffer    Pointer to the options buffer.
356  @param[in, out] OptionsLength    Length of the options buffer.
357  @param[in, out] FragmentTable    Pointer to a list of fragments.
358  @param[in, out] FragmentCount    Number of fragments.
359  @param[in]      TrafficDirection Traffic direction.
360  @param[out]     RecycleSignal    Event for recycling of resources.
361
362  @retval EFI_SUCCESS              The packet was bypassed and all buffers remain the same.
363  @retval EFI_SUCCESS              The packet was protected.
364  @retval EFI_ACCESS_DENIED        The packet was discarded.
365
366**/
367EFI_STATUS
368EFIAPI
369IpSecProcess (
370  IN     EFI_IPSEC2_PROTOCOL              *This,
371  IN     EFI_HANDLE                      NicHandle,
372  IN     UINT8                           IpVersion,
373  IN OUT VOID                            *IpHead,
374  IN OUT UINT8                           *LastHead,
375  IN OUT VOID                            **OptionsBuffer,
376  IN OUT UINT32                          *OptionsLength,
377  IN OUT EFI_IPSEC_FRAGMENT_DATA         **FragmentTable,
378  IN OUT UINT32                          *FragmentCount,
379  IN     EFI_IPSEC_TRAFFIC_DIR           TrafficDirection,
380     OUT EFI_EVENT                       *RecycleSignal
381  );
382
383extern EFI_DPC_PROTOCOL    *mDpc;
384extern EFI_IPSEC2_PROTOCOL  mIpSecInstance;
385
386extern EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2;
387extern EFI_COMPONENT_NAME_PROTOCOL  gIpSecComponentName;
388
389
390#endif
391