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 
31 typedef struct _IPSEC_PRIVATE_DATA IPSEC_PRIVATE_DATA;
32 typedef struct _IPSEC_SPD_ENTRY IPSEC_SPD_ENTRY;
33 typedef struct _IPSEC_PAD_ENTRY IPSEC_PAD_ENTRY;
34 typedef 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)
57 typedef struct _EFI_AH_HEADER {
58   UINT8   NextHeader;
59   UINT8   PayloadLen;
60   UINT16  Reserved;
61   UINT32  Spi;
62   UINT32  SequenceNumber;
63 } EFI_AH_HEADER;
64 
65 typedef struct _EFI_ESP_HEADER {
66   UINT32  Spi;
67   UINT32  SequenceNumber;
68 } EFI_ESP_HEADER;
69 
70 typedef struct _EFI_ESP_TAIL {
71   UINT8 PaddingLength;
72   UINT8 NextHeader;
73 } EFI_ESP_TAIL;
74 #pragma pack()
75 
76 struct _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 
85 struct _IPSEC_SPD_ENTRY {
86   EFI_IPSEC_SPD_SELECTOR  *Selector;
87   IPSEC_SPD_DATA          *Data;
88   LIST_ENTRY              List;
89 };
90 
91 typedef 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 
107 typedef 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 
114 struct _IPSEC_PAD_ENTRY {
115   EFI_IPSEC_PAD_ID    *Id;
116   EFI_IPSEC_PAD_DATA  *Data;
117   LIST_ENTRY          List;
118 };
119 
120 typedef 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 //
128 typedef struct {
129   UINTN DataSize;
130   UINT8 *Data;
131 } HASH_DATA_FRAGMENT;
132 
133 struct _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 **/
175 EFI_STATUS
176 IpSecProtectInboundPacket (
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 **/
213 EFI_STATUS
214 IpSecProtectOutboundPacket (
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 **/
239 BOOLEAN
240 IpSecMatchIpAddress (
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 **/
256 IPSEC_PAD_ENTRY *
257 IpSecLookupPadEntry (
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 **/
277 EFI_STATUS
278 IpSecLookupSpdEntry (
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 **/
313 EFI_STATUS
314 IpSecLookupSadEntry (
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 **/
335 IPSEC_SAD_ENTRY *
336 IpSecLookupSadBySpi (
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 **/
367 EFI_STATUS
368 EFIAPI
369 IpSecProcess (
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 
383 extern EFI_DPC_PROTOCOL    *mDpc;
384 extern EFI_IPSEC2_PROTOCOL  mIpSecInstance;
385 
386 extern EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2;
387 extern EFI_COMPONENT_NAME_PROTOCOL  gIpSecComponentName;
388 
389 
390 #endif
391