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