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