1 /** @file
2   Common operation of the IKE
3 
4   Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "Ike.h"
17 #include "IkeCommon.h"
18 #include "IpSecConfigImpl.h"
19 #include "IpSecDebug.h"
20 
21 /**
22   Check whether the new generated Spi has existed.
23 
24   @param[in]   IkeSaSession   Pointer to the Child SA Session.
25   @param[in]   SpiValue       SPI Value.
26 
27   @retval  TRUE    This SpiValue has existed in the Child SA Session
28   @retval  FALSE   This SpiValue doesn't exist in the Child SA Session.
29 
30 **/
31 BOOLEAN
IkeSpiValueExisted(IN IKEV2_SA_SESSION * IkeSaSession,IN UINT32 SpiValue)32 IkeSpiValueExisted (
33   IN IKEV2_SA_SESSION      *IkeSaSession,
34   IN UINT32                SpiValue
35   )
36 {
37   LIST_ENTRY              *Entry;
38   LIST_ENTRY              *Next;
39   IKEV2_CHILD_SA_SESSION  *SaSession;
40 
41   Entry     = NULL;
42   Next      = NULL;
43   SaSession = NULL;
44 
45   //
46   // Check whether the SPI value has existed in ChildSaEstablishSessionList.
47   //
48   NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaEstablishSessionList) {
49     SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
50     if (SaSession->LocalPeerSpi == SpiValue) {
51       return TRUE;
52     }
53   }
54 
55   //
56   // Check whether the SPI value has existed in ChildSaSessionList.
57   //
58   NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaSessionList) {
59     SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
60     if (SaSession->LocalPeerSpi == SpiValue) {
61       return TRUE;
62     }
63   }
64 
65   return FALSE;
66 }
67 
68 /**
69   Call Crypto Lib to generate a random value with eight-octet length.
70 
71   @return the 64 byte vaule.
72 
73 **/
74 UINT64
IkeGenerateCookie(VOID)75 IkeGenerateCookie (
76   VOID
77   )
78 {
79   UINT64     Cookie;
80   EFI_STATUS Status;
81 
82   Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)&Cookie, sizeof (UINT64));
83   if (EFI_ERROR (Status)) {
84     return 0;
85   } else {
86     return Cookie;
87   }
88 }
89 
90 /**
91   Generate the random data for Nonce payload.
92 
93   @param[in]  NonceSize      Size of the data in bytes.
94 
95   @return Buffer which contains the random data of the spcified size.
96 
97 **/
98 UINT8 *
IkeGenerateNonce(IN UINTN NonceSize)99 IkeGenerateNonce (
100   IN UINTN              NonceSize
101   )
102 {
103   UINT8                  *Nonce;
104   EFI_STATUS             Status;
105 
106   Nonce = AllocateZeroPool (NonceSize);
107   if (Nonce == NULL) {
108     return NULL;
109   }
110 
111   Status = IpSecCryptoIoGenerateRandomBytes (Nonce, NonceSize);
112   if (EFI_ERROR (Status)) {
113     FreePool (Nonce);
114     return NULL;
115   } else {
116     return Nonce;
117   }
118 }
119 
120 /**
121   Convert the IKE Header from Network order to Host order.
122 
123   @param[in, out]  Header    The pointer of the IKE_HEADER.
124 
125 **/
126 VOID
IkeHdrNetToHost(IN OUT IKE_HEADER * Header)127 IkeHdrNetToHost (
128   IN OUT IKE_HEADER *Header
129   )
130 {
131   Header->InitiatorCookie = NTOHLL (Header->InitiatorCookie);
132   Header->ResponderCookie = NTOHLL (Header->ResponderCookie);
133   Header->MessageId       = NTOHL (Header->MessageId);
134   Header->Length          = NTOHL (Header->Length);
135 }
136 
137 /**
138   Convert the IKE Header from Host order to Network order.
139 
140   @param[in, out] Header     The pointer of the IKE_HEADER.
141 
142 **/
143 VOID
IkeHdrHostToNet(IN OUT IKE_HEADER * Header)144 IkeHdrHostToNet (
145   IN OUT IKE_HEADER *Header
146   )
147 {
148   Header->InitiatorCookie = HTONLL (Header->InitiatorCookie);
149   Header->ResponderCookie = HTONLL (Header->ResponderCookie);
150   Header->MessageId       = HTONL (Header->MessageId);
151   Header->Length          = HTONL (Header->Length);
152 }
153 
154 /**
155   Allocate a buffer of IKE_PAYLOAD and set its Signature.
156 
157   @return A buffer of IKE_PAYLOAD.
158 
159 **/
160 IKE_PAYLOAD *
IkePayloadAlloc(VOID)161 IkePayloadAlloc (
162   VOID
163   )
164 {
165   IKE_PAYLOAD *IkePayload;
166 
167   IkePayload            = (IKE_PAYLOAD *) AllocateZeroPool (sizeof (IKE_PAYLOAD));
168   if (IkePayload == NULL) {
169     return NULL;
170   }
171 
172   IkePayload->Signature = IKE_PAYLOAD_SIGNATURE;
173 
174   return IkePayload;
175 }
176 
177 /**
178   Free a specified IKE_PAYLOAD buffer.
179 
180   @param[in]  IkePayload   Pointer of IKE_PAYLOAD to be freed.
181 
182 **/
183 VOID
IkePayloadFree(IN IKE_PAYLOAD * IkePayload)184 IkePayloadFree (
185   IN IKE_PAYLOAD *IkePayload
186   )
187 {
188   if (IkePayload == NULL) {
189     return;
190   }
191   //
192   // If this IkePayload is not referred by others, free it.
193   //
194   if (!IkePayload->IsPayloadBufExt && (IkePayload->PayloadBuf != NULL)) {
195     FreePool (IkePayload->PayloadBuf);
196   }
197 
198   FreePool (IkePayload);
199 }
200 
201 /**
202   Generate an new SPI.
203 
204   @param[in]       IkeSaSession   Pointer to IKEV2_SA_SESSION related to this Child SA
205                                   Session.
206   @param[in, out]  SpiValue       Pointer to the new generated SPI value.
207 
208   @retval EFI_SUCCESS         The operation performs successfully.
209   @retval Otherwise           The operation is failed.
210 
211 **/
212 EFI_STATUS
IkeGenerateSpi(IN IKEV2_SA_SESSION * IkeSaSession,IN OUT UINT32 * SpiValue)213 IkeGenerateSpi (
214   IN     IKEV2_SA_SESSION         *IkeSaSession,
215   IN OUT UINT32                   *SpiValue
216   )
217 {
218   EFI_STATUS   Status;
219 
220   Status = EFI_SUCCESS;
221 
222   while (TRUE) {
223     //
224     // Generate SPI randomly
225     //
226     Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)SpiValue, sizeof (UINT32));
227     if (EFI_ERROR (Status)) {
228       break;
229     }
230 
231     //
232     // The set of SPI values in the range 1 through 255 are reserved by the
233     // Internet Assigned Numbers Authority (IANA) for future use; a reserved
234     // SPI value will not normally be assigned by IANA unless the use of the
235     // assigned SPI value is specified in an RFC.
236     //
237     if (*SpiValue < IKE_SPI_BASE) {
238       *SpiValue += IKE_SPI_BASE;
239     }
240 
241     //
242     // Check whether the new generated SPI has existed.
243     //
244     if (!IkeSpiValueExisted (IkeSaSession, *SpiValue)) {
245       break;
246     }
247   }
248 
249   return Status;
250 }
251 
252 /**
253   Generate a random data for IV
254 
255   @param[in]  IvBuffer  The pointer of the IV buffer.
256   @param[in]  IvSize    The IV size.
257 
258   @retval     EFI_SUCCESS  Create a random data for IV.
259   @retval     otherwise    Failed.
260 
261 **/
262 EFI_STATUS
IkeGenerateIv(IN UINT8 * IvBuffer,IN UINTN IvSize)263 IkeGenerateIv (
264   IN UINT8                           *IvBuffer,
265   IN UINTN                           IvSize
266   )
267 {
268   return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize);
269 }
270 
271 
272 /**
273   Find SPD entry by a specified SPD selector.
274 
275   @param[in] SpdSel       Point to SPD Selector to be searched for.
276 
277   @retval Point to SPD Entry if the SPD entry found.
278   @retval NULL if not found.
279 
280 **/
281 IPSEC_SPD_ENTRY *
IkeSearchSpdEntry(IN EFI_IPSEC_SPD_SELECTOR * SpdSel)282 IkeSearchSpdEntry (
283   IN EFI_IPSEC_SPD_SELECTOR             *SpdSel
284   )
285 {
286   IPSEC_SPD_ENTRY *SpdEntry;
287   LIST_ENTRY      *SpdList;
288   LIST_ENTRY      *Entry;
289 
290   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
291 
292   NET_LIST_FOR_EACH (Entry, SpdList) {
293     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
294 
295     //
296     // Find the required SPD entry
297     //
298     if (CompareSpdSelector (
299           (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
300           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
301           )) {
302       return SpdEntry;
303     }
304 
305   }
306 
307   return NULL;
308 }
309 
310 /**
311   Get the IKE Version from the IKE_SA_SESSION.
312 
313   @param[in]  Session  Pointer of the IKE_SA_SESSION.
314 
315 **/
316 UINT8
IkeGetVersionFromSession(IN UINT8 * Session)317 IkeGetVersionFromSession (
318   IN UINT8    *Session
319   )
320 {
321   if (*(UINT32 *) Session == IKEV2_SA_SESSION_SIGNATURE) {
322     return ((IKEV2_SA_SESSION *) Session)->SessionCommon.IkeVer;
323   } else {
324     //
325     // Add IKEv1 support here.
326     //
327     return 0;
328   }
329 }
330 
331