]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/Ikev2/Payload.c
MdeModulePkg/StatusCodeHandlerRuntimeDxe: make global variable static
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Payload.c
CommitLineData
9166f840 1/** @file\r
2 The implementation of Payloads Creation.\r
3\r
e8837edd 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
f75a7f56 5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
9166f840 6\r
ecf98fbc 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9166f840 8\r
9**/\r
10\r
11#include "Utility.h"\r
12#include "IpSecDebug.h"\r
13#include "IpSecConfigImpl.h"\r
14#include "IpSecCryptIo.h"\r
15\r
16//\r
6cf9230f 17// The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.\r
9166f840 18//\r
19#define CONSTANT_KEY_SIZE 17\r
6cf9230f 20GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey[CONSTANT_KEY_SIZE] =\r
9166f840 21{\r
22 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'\r
23};\r
24\r
25/**\r
26 Generate Ikev2 SA payload according to SessionSaData\r
27\r
28 @param[in] SessionSaData The data used in SA payload.\r
6cf9230f 29 @param[in] NextPayload The payload type presented in NextPayload field of\r
9166f840 30 SA Payload header.\r
31 @param[in] Type The SA type. It MUST be neither (1) for IKE_SA or\r
32 (2) for CHILD_SA or (3) for INFO.\r
33\r
34 @retval a Pointer to SA IKE payload.\r
6cf9230f 35\r
9166f840 36**/\r
37IKE_PAYLOAD *\r
38Ikev2GenerateSaPayload (\r
39 IN IKEV2_SA_DATA *SessionSaData,\r
40 IN UINT8 NextPayload,\r
41 IN IKE_SESSION_TYPE Type\r
42 )\r
43{\r
44 IKE_PAYLOAD *SaPayload;\r
45 IKEV2_SA_DATA *SaData;\r
46 UINTN SaDataSize;\r
47\r
48 SaPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
49 if (SaPayload == NULL) {\r
50 return NULL;\r
51 }\r
f75a7f56 52\r
9166f840 53 //\r
54 // TODO: Get the Proposal Number and Transform Number from IPsec Config,\r
55 // after the Ipsecconfig Application is support it.\r
56 //\r
6cf9230f 57\r
9166f840 58 if (Type == IkeSessionTypeIkeSa) {\r
6cf9230f 59 SaDataSize = sizeof (IKEV2_SA_DATA) +\r
9166f840 60 SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
61 sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 4;\r
62 } else {\r
6cf9230f 63 SaDataSize = sizeof (IKEV2_SA_DATA) +\r
9166f840 64 SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
65 sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 3;\r
6cf9230f 66\r
9166f840 67 }\r
68\r
69 SaData = AllocateZeroPool (SaDataSize);\r
6b16c9e7
JW
70 if (SaData == NULL) {\r
71 IkePayloadFree (SaPayload);\r
72 return NULL;\r
73 }\r
9166f840 74\r
75 CopyMem (SaData, SessionSaData, SaDataSize);\r
76 SaData->SaHeader.Header.NextPayload = NextPayload;\r
77 SaPayload->PayloadType = IKEV2_PAYLOAD_TYPE_SA;\r
78 SaPayload->PayloadBuf = (UINT8 *) SaData;\r
79\r
80 return SaPayload;\r
81}\r
82\r
83/**\r
84 Generate a Nonce payload containing the input parameter NonceBuf.\r
85\r
6cf9230f 86 @param[in] NonceBuf The nonce buffer contains the whole Nonce payload block\r
9166f840 87 except the payload header.\r
88 @param[in] NonceSize The buffer size of the NonceBuf\r
6cf9230f 89 @param[in] NextPayload The payload type presented in the NextPayload field\r
9166f840 90 of Nonce Payload header.\r
91\r
92 @retval Pointer to Nonce IKE paload.\r
93\r
94**/\r
95IKE_PAYLOAD *\r
96Ikev2GenerateNoncePayload (\r
97 IN UINT8 *NonceBuf,\r
98 IN UINTN NonceSize,\r
99 IN UINT8 NextPayload\r
100 )\r
101{\r
102 IKE_PAYLOAD *NoncePayload;\r
103 IKEV2_NONCE *Nonce;\r
104 UINTN Size;\r
105 UINT8 *NonceBlock;\r
106\r
107 // 1 2 3\r
108 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
109 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
110 // ! Next Payload !C! RESERVED ! Payload Length !\r
111 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
112 // ! !\r
113 // ~ Nonce Data ~\r
114 // ! !\r
115 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
116 //\r
117 Size = sizeof (IKEV2_NONCE) + NonceSize;\r
118 NonceBlock = NonceBuf;\r
119\r
120 Nonce = AllocateZeroPool (Size);\r
6b16c9e7
JW
121 if (Nonce == NULL) {\r
122 return NULL;\r
123 }\r
f75a7f56 124\r
9166f840 125 CopyMem (Nonce + 1, NonceBlock, Size - sizeof (IKEV2_NONCE));\r
126\r
127 Nonce->Header.NextPayload = NextPayload;\r
128 Nonce->Header.PayloadLength = (UINT16) Size;\r
129 NoncePayload = IkePayloadAlloc ();\r
6b16c9e7
JW
130 if (NoncePayload == NULL) {\r
131 FreePool (Nonce);\r
132 return NULL;\r
133 }\r
f75a7f56 134\r
9166f840 135 NoncePayload->PayloadType = IKEV2_PAYLOAD_TYPE_NONCE;\r
136 NoncePayload->PayloadBuf = (UINT8 *) Nonce;\r
137 NoncePayload->PayloadSize = Size;\r
138\r
139 return NoncePayload;\r
140}\r
141\r
142/**\r
6cf9230f 143 Generate a Key Exchange payload according to the DH group type and save the\r
9166f840 144 public Key into IkeSaSession IkeKey field.\r
145\r
146 @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.\r
6cf9230f 147 @param[in] NextPayload The payload type presented in the NextPayload field of Key\r
9166f840 148 Exchange Payload header.\r
149\r
150 @retval Pointer to Key IKE payload.\r
151\r
152**/\r
153IKE_PAYLOAD*\r
154Ikev2GenerateKePayload (\r
155 IN OUT IKEV2_SA_SESSION *IkeSaSession,\r
156 IN UINT8 NextPayload\r
157 )\r
158{\r
159 IKE_PAYLOAD *KePayload;\r
160 IKEV2_KEY_EXCHANGE *Ke;\r
161 UINTN KeSize;\r
162 IKEV2_SESSION_KEYS *IkeKeys;\r
163\r
164 //\r
165 // 1 2 3\r
166 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
167 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
168 // ! Next Payload !C! RESERVED ! Payload Length !\r
169 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
170 // ! DH Group # ! RESERVED !\r
171 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
172 // ! !\r
173 // ~ Key Exchange Data ~\r
174 // ! !\r
175 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
176 //\r
177 IkeKeys = IkeSaSession->IkeKeys;\r
178\r
179 if (IkeSaSession->SessionCommon.IsInitiator) {\r
180 KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;\r
181 } else {\r
182 KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;\r
183 }\r
6cf9230f 184\r
9166f840 185 //\r
186 // Allocate buffer for Key Exchange\r
187 //\r
188 Ke = AllocateZeroPool (KeSize);\r
6b16c9e7
JW
189 if (Ke == NULL) {\r
190 return NULL;\r
191 }\r
9166f840 192\r
193 Ke->Header.NextPayload = NextPayload;\r
194 Ke->Header.PayloadLength = (UINT16) KeSize;\r
195 Ke->DhGroup = IkeSaSession->SessionCommon.PreferDhGroup;\r
196\r
197 CopyMem (Ke + 1, IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);\r
6cf9230f 198\r
199 //\r
200 // Create IKE_PAYLOAD to point to Key Exchange payload\r
9166f840 201 //\r
9166f840 202 KePayload = IkePayloadAlloc ();\r
6b16c9e7
JW
203 if (KePayload == NULL) {\r
204 FreePool (Ke);\r
205 return NULL;\r
206 }\r
6cf9230f 207\r
9166f840 208 KePayload->PayloadType = IKEV2_PAYLOAD_TYPE_KE;\r
209 KePayload->PayloadBuf = (UINT8 *) Ke;\r
210 KePayload->PayloadSize = KeSize;\r
211 return KePayload;\r
212}\r
213\r
214/**\r
215 Generate a ID payload.\r
216\r
217 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.\r
6cf9230f 218 @param[in] NextPayload The payload type presented in the NextPayload field\r
9166f840 219 of ID Payload header.\r
220\r
221 @retval Pointer to ID IKE payload.\r
222\r
223**/\r
224IKE_PAYLOAD *\r
225Ikev2GenerateIdPayload (\r
226 IN IKEV2_SESSION_COMMON *CommonSession,\r
227 IN UINT8 NextPayload\r
228 )\r
229{\r
230 IKE_PAYLOAD *IdPayload;\r
231 IKEV2_ID *Id;\r
232 UINTN IdSize;\r
233 UINT8 IpVersion;\r
234 UINT8 AddrSize;\r
235\r
236 //\r
237 // ID payload\r
238 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
239 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
240 // ! Next Payload ! RESERVED ! Payload Length !\r
241 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
242 // ! ID Type ! RESERVED !\r
243 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
244 // ! !\r
245 // ~ Identification Data ~\r
246 // ! !\r
247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
248 //\r
6cf9230f 249\r
9166f840 250 IpVersion = CommonSession->UdpService->IpVersion;\r
251 AddrSize = (UINT8) ((IpVersion == IP_VERSION_4) ? sizeof(EFI_IPv4_ADDRESS) : sizeof(EFI_IPv6_ADDRESS));\r
252 IdSize = sizeof (IKEV2_ID) + AddrSize;\r
253\r
254 Id = (IKEV2_ID *) AllocateZeroPool (IdSize);\r
6b16c9e7
JW
255 if (Id == NULL) {\r
256 return NULL;\r
257 }\r
9166f840 258\r
259 IdPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
260 if (IdPayload == NULL) {\r
261 FreePool (Id);\r
262 return NULL;\r
263 }\r
9166f840 264\r
265 IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);\r
266 IdPayload->PayloadBuf = (UINT8 *) Id;\r
267 IdPayload->PayloadSize = IdSize;\r
268\r
269 //\r
6cf9230f 270 // Set generic header of identification payload\r
9166f840 271 //\r
272 Id->Header.NextPayload = NextPayload;\r
273 Id->Header.PayloadLength = (UINT16) IdSize;\r
274 Id->IdType = (UINT8) ((IpVersion == IP_VERSION_4) ? IKEV2_ID_TYPE_IPV4_ADDR : IKEV2_ID_TYPE_IPV6_ADDR);\r
275 CopyMem (Id + 1, &CommonSession->LocalPeerIp, AddrSize);\r
276\r
277 return IdPayload;\r
278}\r
279\r
280/**\r
281 Generate a ID payload.\r
282\r
283 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.\r
6cf9230f 284 @param[in] NextPayload The payload type presented in the NextPayload field\r
9166f840 285 of ID Payload header.\r
286 @param[in] InCert Pointer to the Certificate which distinguished name\r
287 will be added into the Id payload.\r
288 @param[in] CertSize Size of the Certificate.\r
289\r
290 @retval Pointer to ID IKE payload.\r
291\r
292**/\r
293IKE_PAYLOAD *\r
294Ikev2GenerateCertIdPayload (\r
295 IN IKEV2_SESSION_COMMON *CommonSession,\r
296 IN UINT8 NextPayload,\r
297 IN UINT8 *InCert,\r
298 IN UINTN CertSize\r
299 )\r
300{\r
301 IKE_PAYLOAD *IdPayload;\r
302 IKEV2_ID *Id;\r
303 UINTN IdSize;\r
9166f840 304 UINTN SubjectSize;\r
305 UINT8 *CertSubject;\r
6cf9230f 306\r
9166f840 307 //\r
308 // ID payload\r
309 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
310 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
311 // ! Next Payload ! RESERVED ! Payload Length !\r
312 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
313 // ! ID Type ! RESERVED !\r
314 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
315 // ! !\r
316 // ~ Identification Data ~\r
317 // ! !\r
318 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
319 //\r
320\r
321 SubjectSize = 0;\r
322 CertSubject = NULL;\r
9166f840 323 IpSecCryptoIoGetSubjectFromCert (\r
324 InCert,\r
325 CertSize,\r
326 &CertSubject,\r
327 &SubjectSize\r
328 );\r
02a758cb 329 if (SubjectSize != 0) {\r
330 ASSERT (CertSubject != NULL);\r
331 }\r
9166f840 332\r
333 IdSize = sizeof (IKEV2_ID) + SubjectSize;\r
334\r
335 Id = (IKEV2_ID *) AllocateZeroPool (IdSize);\r
6b16c9e7
JW
336 if (Id == NULL) {\r
337 return NULL;\r
338 }\r
9166f840 339\r
340 IdPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
341 if (IdPayload == NULL) {\r
342 FreePool (Id);\r
343 return NULL;\r
344 }\r
9166f840 345\r
346 IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);\r
347 IdPayload->PayloadBuf = (UINT8 *) Id;\r
348 IdPayload->PayloadSize = IdSize;\r
349\r
350 //\r
6cf9230f 351 // Set generic header of identification payload\r
9166f840 352 //\r
353 Id->Header.NextPayload = NextPayload;\r
354 Id->Header.PayloadLength = (UINT16) IdSize;\r
355 Id->IdType = 9;\r
356 CopyMem (Id + 1, CertSubject, SubjectSize);\r
357\r
358 if (CertSubject != NULL) {\r
359 FreePool (CertSubject);\r
360 }\r
361 return IdPayload;\r
362}\r
363\r
364/**\r
365 Generate a Authentication Payload.\r
366\r
6cf9230f 367 This function is used for both Authentication generation and verification. When the\r
368 IsVerify is TRUE, it create a Auth Data for verification. This function choose the\r
9166f840 369 related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type\r
370 and the value of IsVerify parameter.\r
371\r
372 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.\r
6cf9230f 373 @param[in] IdPayload Pointer to the ID payload to be used for Authentication\r
9166f840 374 payload generation.\r
6cf9230f 375 @param[in] NextPayload The type filled into the Authentication Payload next\r
9166f840 376 payload field.\r
377 @param[in] IsVerify If it is TURE, the Authentication payload is used for\r
378 verification.\r
379\r
380 @return pointer to IKE Authentication payload for Pre-shared key method.\r
381\r
382**/\r
383IKE_PAYLOAD *\r
384Ikev2PskGenerateAuthPayload (\r
385 IN IKEV2_SA_SESSION *IkeSaSession,\r
386 IN IKE_PAYLOAD *IdPayload,\r
387 IN UINT8 NextPayload,\r
388 IN BOOLEAN IsVerify\r
389 )\r
390{\r
391 UINT8 *Digest;\r
392 UINTN DigestSize;\r
393 PRF_DATA_FRAGMENT Fragments[3];\r
394 UINT8 *KeyBuf;\r
395 UINTN KeySize;\r
396 IKE_PAYLOAD *AuthPayload;\r
397 IKEV2_AUTH *PayloadBuf;\r
398 EFI_STATUS Status;\r
399\r
400 //\r
401 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
402 //\r
403 // 1 2 3\r
404 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
406 // ! Next Payload !C! RESERVED ! Payload Length !\r
407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
408 // ! Auth Method ! RESERVED !\r
409 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
410 // ! !\r
411 // ~ Authentication Data ~\r
412 // ! !\r
413 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
414 //\r
6cf9230f 415\r
9166f840 416 KeyBuf = NULL;\r
417 AuthPayload = NULL;\r
418 Digest = NULL;\r
6cf9230f 419\r
9166f840 420 DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);\r
421 Digest = AllocateZeroPool (DigestSize);\r
9166f840 422 if (Digest == NULL) {\r
423 return NULL;\r
424 }\r
f75a7f56 425\r
9166f840 426 if (IdPayload == NULL) {\r
427 return NULL;\r
428 }\r
f75a7f56 429\r
9166f840 430 //\r
431 // Calcualte Prf(Seceret, "Key Pad for IKEv2");\r
432 //\r
433 Fragments[0].Data = (UINT8 *) mConstantKey;\r
434 Fragments[0].DataSize = CONSTANT_KEY_SIZE;\r
435\r
436 Status = IpSecCryptoIoHmac (\r
437 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
438 IkeSaSession->Pad->Data->AuthData,\r
6cf9230f 439 IkeSaSession->Pad->Data->AuthDataSize,\r
9166f840 440 (HASH_DATA_FRAGMENT *)Fragments,\r
441 1,\r
442 Digest,\r
443 DigestSize\r
444 );\r
445 if (EFI_ERROR (Status)) {\r
446 goto EXIT;\r
447 }\r
448\r
449 //\r
450 // Store the AuthKey into KeyBuf\r
451 //\r
452 KeyBuf = AllocateZeroPool (DigestSize);\r
6b16c9e7
JW
453 if (KeyBuf == NULL) {\r
454 Status = EFI_OUT_OF_RESOURCES;\r
455 goto EXIT;\r
456 }\r
f75a7f56 457\r
9166f840 458 CopyMem (KeyBuf, Digest, DigestSize);\r
459 KeySize = DigestSize;\r
460\r
461 //\r
462 // Calculate Prf(SK_Pi/r, IDi/r)\r
463 //\r
464 Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
465 Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
466\r
467 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
468 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
469 ) {\r
470 Status = IpSecCryptoIoHmac (\r
471 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
472 IkeSaSession->IkeKeys->SkPrKey,\r
473 IkeSaSession->IkeKeys->SkPrKeySize,\r
474 (HASH_DATA_FRAGMENT *) Fragments,\r
475 1,\r
476 Digest,\r
477 DigestSize\r
478 );\r
479 } else {\r
480 Status = IpSecCryptoIoHmac (\r
481 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
482 IkeSaSession->IkeKeys->SkPiKey,\r
483 IkeSaSession->IkeKeys->SkPiKeySize,\r
484 (HASH_DATA_FRAGMENT *) Fragments,\r
485 1,\r
486 Digest,\r
487 DigestSize\r
488 );\r
489 }\r
490 if (EFI_ERROR (Status)) {\r
491 goto EXIT;\r
492 }\r
493\r
494 //\r
495 // Copy data to Fragments.\r
496 //\r
497 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
498 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
499 ) {\r
500 Fragments[0].Data = IkeSaSession->RespPacket;\r
501 Fragments[0].DataSize = IkeSaSession->RespPacketSize;\r
502 Fragments[1].Data = IkeSaSession->NiBlock;\r
503 Fragments[1].DataSize = IkeSaSession->NiBlkSize;\r
504 } else {\r
505 Fragments[0].Data = IkeSaSession->InitPacket;\r
506 Fragments[0].DataSize = IkeSaSession->InitPacketSize;\r
507 Fragments[1].Data = IkeSaSession->NrBlock;\r
508 Fragments[1].DataSize = IkeSaSession->NrBlkSize;\r
509 }\r
510\r
511 //\r
512 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].\r
6cf9230f 513 //\r
9166f840 514 Fragments[2].Data = AllocateZeroPool (DigestSize);\r
6b16c9e7
JW
515 if (Fragments[2].Data == NULL) {\r
516 Status = EFI_OUT_OF_RESOURCES;\r
517 goto EXIT;\r
518 }\r
f75a7f56 519\r
9166f840 520 Fragments[2].DataSize = DigestSize;\r
521 CopyMem (Fragments[2].Data, Digest, DigestSize);\r
522\r
523 //\r
524 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
525 //\r
526 Status = IpSecCryptoIoHmac (\r
527 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
528 KeyBuf,\r
529 KeySize,\r
530 (HASH_DATA_FRAGMENT *) Fragments,\r
531 3,\r
532 Digest,\r
533 DigestSize\r
534 );\r
535 if (EFI_ERROR (Status)) {\r
536 goto EXIT;\r
537 }\r
538\r
539 //\r
540 // Allocate buffer for Auth Payload\r
541 //\r
542 AuthPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
543 if (AuthPayload == NULL) {\r
544 Status = EFI_OUT_OF_RESOURCES;\r
545 goto EXIT;\r
546 }\r
9166f840 547\r
548 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;\r
549 PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);\r
6b16c9e7
JW
550 if (PayloadBuf == NULL) {\r
551 Status = EFI_OUT_OF_RESOURCES;\r
552 goto EXIT;\r
553 }\r
f75a7f56 554\r
9166f840 555 //\r
556 // Fill in Auth payload.\r
557 //\r
558 PayloadBuf->Header.NextPayload = NextPayload;\r
559 PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);\r
560 if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodPreSharedSecret) {\r
561 //\r
562 // Only support Shared Key Message Integrity\r
563 //\r
564 PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_SKMI;\r
565 } else {\r
566 //\r
567 // Not support other Auth method.\r
568 //\r
569 Status = EFI_UNSUPPORTED;\r
570 goto EXIT;\r
571 }\r
572\r
573 //\r
574 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth\r
575 // payload block.\r
576 //\r
577 CopyMem (\r
578 PayloadBuf + 1,\r
579 Digest,\r
580 DigestSize\r
581 );\r
6cf9230f 582\r
9166f840 583 //\r
584 // Fill in IKE_PACKET\r
585 //\r
586 AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;\r
587 AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;\r
588\r
589EXIT:\r
590 if (KeyBuf != NULL) {\r
591 FreePool (KeyBuf);\r
592 }\r
593 if (Digest != NULL) {\r
594 FreePool (Digest);\r
595 }\r
596 if (Fragments[2].Data != NULL) {\r
597 //\r
598 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)\r
6cf9230f 599 //\r
9166f840 600 FreePool (Fragments[2].Data);\r
601 }\r
602\r
603 if (EFI_ERROR (Status)) {\r
604 if (AuthPayload != NULL) {\r
605 IkePayloadFree (AuthPayload);\r
606 }\r
607 return NULL;\r
608 } else {\r
609 return AuthPayload;\r
610 }\r
611}\r
612\r
613/**\r
6cf9230f 614 Generate a Authentication Payload for Certificate Auth method.\r
9166f840 615\r
6cf9230f 616 This function has two functions. One is creating a local Authentication\r
617 Payload for sending and other is creating the remote Authentication data\r
9166f840 618 for verification when the IsVerify is TURE.\r
619\r
620 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.\r
6cf9230f 621 @param[in] IdPayload Pointer to the ID payload to be used for Authentication\r
9166f840 622 payload generation.\r
6cf9230f 623 @param[in] NextPayload The type filled into the Authentication Payload\r
9166f840 624 next payload field.\r
6cf9230f 625 @param[in] IsVerify If it is TURE, the Authentication payload is used\r
9166f840 626 for verification.\r
6cf9230f 627 @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when\r
9166f840 628 verify the authenticate payload.\r
6cf9230f 629 @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it\r
9166f840 630 when verify the authenticate payload.\r
6cf9230f 631 @param[in] UefiKeyPwd Pointer to the password of UEFI private key.\r
9166f840 632 Ignore it when verify the authenticate payload.\r
6cf9230f 633 @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when\r
9166f840 634 verify the authenticate payload.\r
635\r
636 @return pointer to IKE Authentication payload for Cerifitcation method.\r
637\r
638**/\r
639IKE_PAYLOAD *\r
640Ikev2CertGenerateAuthPayload (\r
641 IN IKEV2_SA_SESSION *IkeSaSession,\r
642 IN IKE_PAYLOAD *IdPayload,\r
643 IN UINT8 NextPayload,\r
644 IN BOOLEAN IsVerify,\r
645 IN UINT8 *UefiPrivateKey,\r
646 IN UINTN UefiPrivateKeyLen,\r
647 IN UINT8 *UefiKeyPwd,\r
648 IN UINTN UefiKeyPwdLen\r
649 )\r
650{\r
651 UINT8 *Digest;\r
652 UINTN DigestSize;\r
653 PRF_DATA_FRAGMENT Fragments[3];\r
9166f840 654 IKE_PAYLOAD *AuthPayload;\r
655 IKEV2_AUTH *PayloadBuf;\r
656 EFI_STATUS Status;\r
657 UINT8 *Signature;\r
658 UINTN SigSize;\r
659\r
660 //\r
661 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
662 //\r
663 // 1 2 3\r
664 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
665 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
666 // ! Next Payload !C! RESERVED ! Payload Length !\r
667 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
668 // ! Auth Method ! RESERVED !\r
669 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
670 // ! !\r
671 // ~ Authentication Data ~\r
672 // ! !\r
673 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
674 //\r
675 //\r
676 // Initial point\r
677 //\r
9166f840 678 AuthPayload = NULL;\r
679 Digest = NULL;\r
680 Signature = NULL;\r
681 SigSize = 0;\r
682\r
683 if (IdPayload == NULL) {\r
684 return NULL;\r
685 }\r
686 DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);\r
687 Digest = AllocateZeroPool (DigestSize);\r
9166f840 688 if (Digest == NULL) {\r
689 return NULL;\r
690 }\r
691\r
9166f840 692 //\r
693 // Calculate Prf(SK_Pi/r, IDi/r)\r
694 //\r
695 Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
696 Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);\r
697\r
698 IpSecDumpBuf ("RestofIDPayload", Fragments[0].Data, Fragments[0].DataSize);\r
699\r
700 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
701 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
702 ) {\r
703 Status = IpSecCryptoIoHmac(\r
704 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
705 IkeSaSession->IkeKeys->SkPrKey,\r
706 IkeSaSession->IkeKeys->SkPrKeySize,\r
707 (HASH_DATA_FRAGMENT *) Fragments,\r
708 1,\r
709 Digest,\r
710 DigestSize\r
711 );\r
712 IpSecDumpBuf ("MACedIDForR", Digest, DigestSize);\r
713 } else {\r
714 Status = IpSecCryptoIoHmac (\r
715 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
716 IkeSaSession->IkeKeys->SkPiKey,\r
717 IkeSaSession->IkeKeys->SkPiKeySize,\r
718 (HASH_DATA_FRAGMENT *) Fragments,\r
719 1,\r
720 Digest,\r
721 DigestSize\r
722 );\r
723 IpSecDumpBuf ("MACedIDForI", Digest, DigestSize);\r
724 }\r
725 if (EFI_ERROR (Status)) {\r
726 goto EXIT;\r
727 }\r
728\r
729 //\r
730 // Copy data to Fragments.\r
731 //\r
732 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||\r
733 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)\r
734 ) {\r
735 Fragments[0].Data = IkeSaSession->RespPacket;\r
736 Fragments[0].DataSize = IkeSaSession->RespPacketSize;\r
737 Fragments[1].Data = IkeSaSession->NiBlock;\r
738 Fragments[1].DataSize = IkeSaSession->NiBlkSize;\r
739 IpSecDumpBuf ("RealMessage2", Fragments[0].Data, Fragments[0].DataSize);\r
740 IpSecDumpBuf ("NonceIDdata", Fragments[1].Data, Fragments[1].DataSize);\r
741 } else {\r
742 Fragments[0].Data = IkeSaSession->InitPacket;\r
743 Fragments[0].DataSize = IkeSaSession->InitPacketSize;\r
744 Fragments[1].Data = IkeSaSession->NrBlock;\r
745 Fragments[1].DataSize = IkeSaSession->NrBlkSize;\r
746 IpSecDumpBuf ("RealMessage1", Fragments[0].Data, Fragments[0].DataSize);\r
747 IpSecDumpBuf ("NonceRDdata", Fragments[1].Data, Fragments[1].DataSize);\r
748 }\r
6cf9230f 749\r
9166f840 750 //\r
751 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].\r
6cf9230f 752 //\r
9166f840 753 Fragments[2].Data = AllocateZeroPool (DigestSize);\r
6b16c9e7
JW
754 if (Fragments[2].Data == NULL) {\r
755 Status = EFI_OUT_OF_RESOURCES;\r
756 goto EXIT;\r
757 }\r
f75a7f56 758\r
9166f840 759 Fragments[2].DataSize = DigestSize;\r
760 CopyMem (Fragments[2].Data, Digest, DigestSize);\r
761\r
762 //\r
763 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))\r
764 //\r
765 Status = IpSecCryptoIoHash (\r
766 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,\r
767 (HASH_DATA_FRAGMENT *) Fragments,\r
768 3,\r
769 Digest,\r
770 DigestSize\r
771 );\r
772 if (EFI_ERROR (Status)) {\r
773 goto EXIT;\r
774 }\r
775\r
776 IpSecDumpBuf ("HashSignedOctects", Digest, DigestSize);\r
777 //\r
6cf9230f 778 // Sign the data by the private Key\r
9166f840 779 //\r
780 if (!IsVerify) {\r
781 IpSecCryptoIoAuthDataWithCertificate (\r
782 Digest,\r
783 DigestSize,\r
784 UefiPrivateKey,\r
785 UefiPrivateKeyLen,\r
786 UefiKeyPwd,\r
787 UefiKeyPwdLen,\r
788 &Signature,\r
789 &SigSize\r
790 );\r
791\r
02a758cb 792 if (SigSize == 0 || Signature == NULL) {\r
9166f840 793 goto EXIT;\r
794 }\r
795 }\r
796\r
797 //\r
798 // Allocate buffer for Auth Payload\r
799 //\r
800 AuthPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
801 if (AuthPayload == NULL) {\r
802 Status = EFI_OUT_OF_RESOURCES;\r
803 goto EXIT;\r
804 }\r
9166f840 805\r
806 if (!IsVerify) {\r
807 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + SigSize;\r
808 } else {\r
809 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;\r
810 }\r
811\r
812 PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);\r
6b16c9e7
JW
813 if (PayloadBuf == NULL) {\r
814 Status = EFI_OUT_OF_RESOURCES;\r
815 goto EXIT;\r
816 }\r
f75a7f56 817\r
9166f840 818 //\r
819 // Fill in Auth payload.\r
820 //\r
821 PayloadBuf->Header.NextPayload = NextPayload;\r
822 PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);\r
823 if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodCertificates) {\r
824 PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_RSA;\r
825 } else {\r
826 Status = EFI_INVALID_PARAMETER;\r
827 goto EXIT;\r
828 }\r
829\r
830 //\r
831 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth\r
832 // payload block.\r
833 //\r
834 if (!IsVerify) {\r
835 CopyMem (PayloadBuf + 1, Signature, SigSize);\r
836 } else {\r
837 CopyMem (PayloadBuf + 1, Digest, DigestSize);\r
838 }\r
839\r
840 //\r
841 // Fill in IKE_PACKET\r
842 //\r
843 AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;\r
844 AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;\r
845\r
846EXIT:\r
9166f840 847 if (Digest != NULL) {\r
848 FreePool (Digest);\r
849 }\r
850 if (Signature != NULL) {\r
851 FreePool (Signature);\r
852 }\r
853 if (Fragments[2].Data != NULL) {\r
854 //\r
855 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)\r
6cf9230f 856 //\r
9166f840 857 FreePool (Fragments[2].Data);\r
858 }\r
859\r
860 if (EFI_ERROR (Status)) {\r
861 if (AuthPayload != NULL) {\r
862 IkePayloadFree (AuthPayload);\r
863 }\r
864 return NULL;\r
865 } else {\r
866 return AuthPayload;\r
867 }\r
868}\r
869\r
870/**\r
871 Generate TS payload.\r
872\r
873 This function generates TSi or TSr payload according to type of next payload.\r
874 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate\r
875 TSr payload.\r
6cf9230f 876\r
9166f840 877 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.\r
6cf9230f 878 @param[in] NextPayload The payload type presented in the NextPayload field\r
9166f840 879 of ID Payload header.\r
880 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.\r
881 If yes, it means the Tsi and Tsr payload should be with\r
882 Max port range and address range and protocol is marked\r
883 as zero.\r
884\r
885 @retval Pointer to Ts IKE payload.\r
886\r
887**/\r
888IKE_PAYLOAD *\r
889Ikev2GenerateTsPayload (\r
890 IN IKEV2_CHILD_SA_SESSION *ChildSa,\r
891 IN UINT8 NextPayload,\r
892 IN BOOLEAN IsTunnel\r
893 )\r
894{\r
895 IKE_PAYLOAD *TsPayload;\r
896 IKEV2_TS *TsPayloadBuf;\r
897 TRAFFIC_SELECTOR *TsSelector;\r
898 UINTN SelectorSize;\r
899 UINTN TsPayloadSize;\r
900 UINT8 IpVersion;\r
901 UINT8 AddrSize;\r
902\r
903 //\r
904 // 1 2 3\r
905 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
906 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
907 // ! Next Payload !C! RESERVED ! Payload Length !\r
908 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
909 // ! Number of TSs ! RESERVED !\r
910 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
911 // ! !\r
912 // ~ <Traffic Selectors> ~\r
913 // ! !\r
914 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
915 //\r
916\r
917 TsPayload = IkePayloadAlloc();\r
6b16c9e7
JW
918 if (TsPayload == NULL) {\r
919 return NULL;\r
920 }\r
9166f840 921\r
922 IpVersion = ChildSa->SessionCommon.UdpService->IpVersion;\r
923 //\r
6cf9230f 924 // The Starting Address and Ending Address is variable length depends on\r
9166f840 925 // is IPv4 or IPv6\r
926 //\r
927 AddrSize = (UINT8)((IpVersion == IP_VERSION_4) ? sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS));\r
928 SelectorSize = sizeof (TRAFFIC_SELECTOR) + 2 * AddrSize;\r
929 TsPayloadSize = sizeof (IKEV2_TS) + SelectorSize;\r
930 TsPayloadBuf = AllocateZeroPool (TsPayloadSize);\r
6b16c9e7
JW
931 if (TsPayloadBuf == NULL) {\r
932 goto ON_ERROR;\r
933 }\r
9166f840 934\r
935 TsPayload->PayloadBuf = (UINT8 *) TsPayloadBuf;\r
936 TsSelector = (TRAFFIC_SELECTOR*)(TsPayloadBuf + 1);\r
937\r
938 TsSelector->TSType = (UINT8)((IpVersion == IP_VERSION_4) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE : IKEV2_TS_TYPS_IPV6_ADDR_RANGE);\r
939\r
940 //\r
6cf9230f 941 // For tunnel mode\r
9166f840 942 //\r
943 if (IsTunnel) {\r
944 TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;\r
945 TsSelector->SelecorLen = (UINT16) SelectorSize;\r
946 TsSelector->StartPort = 0;\r
947 TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
948 ZeroMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR), AddrSize);\r
949 SetMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize, AddrSize, 0xff);\r
950\r
951 } else {\r
952 //\r
953 // TODO: Support port range and address range\r
954 //\r
955 if (NextPayload == IKEV2_PAYLOAD_TYPE_TS_RSP){\r
956 //\r
6cf9230f 957 // Create initiator Traffic Selector\r
958 //\r
9166f840 959 TsSelector->SelecorLen = (UINT16)SelectorSize;\r
960\r
961 //\r
962 // Currently only support the port range from 0~0xffff. Don't support other\r
963 // port range.\r
964 // TODO: support Port range\r
965 //\r
966 if (ChildSa->SessionCommon.IsInitiator) {\r
967 if (ChildSa->Spd->Selector->LocalPort != 0 &&\r
968 ChildSa->Spd->Selector->LocalPortRange == 0) {\r
6cf9230f 969 //\r
9166f840 970 // For not port range.\r
971 //\r
972 TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;\r
973 TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;\r
974 } else if (ChildSa->Spd->Selector->LocalPort == 0){\r
975 //\r
976 // For port from 0~0xffff\r
977 //\r
978 TsSelector->StartPort = 0;\r
979 TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
980 } else {\r
981 //\r
982 // Not support now.\r
983 //\r
984 goto ON_ERROR;\r
985 }\r
986 } else {\r
6cf9230f 987 if (ChildSa->Spd->Selector->RemotePort != 0 &&\r
9166f840 988 ChildSa->Spd->Selector->RemotePortRange == 0) {\r
989 //\r
990 // For not port range.\r
991 //\r
992 TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;\r
993 TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;\r
994 } else if (ChildSa->Spd->Selector->RemotePort == 0) {\r
995 //\r
996 // For port from 0~0xffff\r
997 //\r
998 TsSelector->StartPort = 0;\r
999 TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
1000 } else {\r
1001 //\r
1002 // Not support now.\r
1003 //\r
1004 goto ON_ERROR;\r
1005 }\r
1006 }\r
1007 //\r
1008 // Copy Address.Currently the address range is not supported.\r
1009 // The Starting address is same as Ending address\r
6cf9230f 1010 // TODO: Support Address Range.\r
9166f840 1011 //\r
1012 CopyMem (\r
1013 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),\r
1014 ChildSa->SessionCommon.IsInitiator ?\r
1015 ChildSa->Spd->Selector->LocalAddress :\r
1016 ChildSa->Spd->Selector->RemoteAddress,\r
1017 AddrSize\r
1018 );\r
1019 CopyMem (\r
1020 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,\r
1021 ChildSa->SessionCommon.IsInitiator ?\r
1022 ChildSa->Spd->Selector->LocalAddress :\r
1023 ChildSa->Spd->Selector->RemoteAddress,\r
1024 AddrSize\r
1025 );\r
1026 //\r
1027 // If the Next Payload is not TS responder, this TS payload type is the TS responder.\r
1028 //\r
1029 TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_INIT;\r
1030 }else{\r
1031 //\r
1032 // Create responder Traffic Selector\r
6cf9230f 1033 //\r
9166f840 1034 TsSelector->SelecorLen = (UINT16)SelectorSize;\r
6cf9230f 1035\r
9166f840 1036 //\r
1037 // Currently only support the port range from 0~0xffff. Don't support other\r
1038 // port range.\r
1039 // TODO: support Port range\r
1040 //\r
1041 if (!ChildSa->SessionCommon.IsInitiator) {\r
1042 if (ChildSa->Spd->Selector->LocalPort != 0 &&\r
1043 ChildSa->Spd->Selector->LocalPortRange == 0) {\r
1044 //\r
1045 // For not port range.\r
1046 //\r
1047 TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;\r
1048 TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;\r
1049 } else if (ChildSa->Spd->Selector->LocalPort == 0){\r
1050 //\r
1051 // For port from 0~0xffff\r
1052 //\r
1053 TsSelector->StartPort = 0;\r
1054 TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
1055 } else {\r
1056 //\r
1057 // Not support now.\r
1058 //\r
1059 goto ON_ERROR;\r
1060 }\r
1061 } else {\r
1062 if (ChildSa->Spd->Selector->RemotePort != 0 &&\r
1063 ChildSa->Spd->Selector->RemotePortRange == 0) {\r
1064 //\r
1065 // For not port range.\r
1066 //\r
1067 TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;\r
1068 TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;\r
1069 } else if (ChildSa->Spd->Selector->RemotePort == 0){\r
1070 //\r
1071 // For port from 0~0xffff\r
1072 //\r
1073 TsSelector->StartPort = 0;\r
1074 TsSelector->EndPort = IKEV2_TS_ANY_PORT;\r
1075 } else {\r
1076 //\r
1077 // Not support now.\r
1078 //\r
1079 goto ON_ERROR;\r
1080 }\r
1081 }\r
1082 //\r
1083 // Copy Address.Currently the address range is not supported.\r
1084 // The Starting address is same as Ending address\r
6cf9230f 1085 // TODO: Support Address Range.\r
9166f840 1086 //\r
1087 CopyMem (\r
1088 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),\r
1089 ChildSa->SessionCommon.IsInitiator ?\r
1090 ChildSa->Spd->Selector->RemoteAddress :\r
1091 ChildSa->Spd->Selector->LocalAddress,\r
1092 AddrSize\r
1093 );\r
1094 CopyMem (\r
1095 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,\r
1096 ChildSa->SessionCommon.IsInitiator ?\r
1097 ChildSa->Spd->Selector->RemoteAddress :\r
1098 ChildSa->Spd->Selector->LocalAddress,\r
1099 AddrSize\r
1100 );\r
1101 //\r
1102 // If the Next Payload is not TS responder, this TS payload type is the TS responder.\r
1103 //\r
1104 TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_RSP;\r
1105 }\r
1106 }\r
1107\r
1108 if (ChildSa->Spd->Selector->NextLayerProtocol != 0xffff) {\r
1109 TsSelector->IpProtocolId = (UINT8)ChildSa->Spd->Selector->NextLayerProtocol;\r
1110 } else {\r
1111 TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;\r
6cf9230f 1112 }\r
1113\r
9166f840 1114 TsPayloadBuf->Header.NextPayload = NextPayload;\r
1115 TsPayloadBuf->Header.PayloadLength = (UINT16)TsPayloadSize;\r
1116 TsPayloadBuf->TSNumbers = 1;\r
1117 TsPayload->PayloadSize = TsPayloadSize;\r
1118 goto ON_EXIT;\r
1119\r
1120ON_ERROR:\r
1121 if (TsPayload != NULL) {\r
6cf9230f 1122 IkePayloadFree (TsPayload);\r
9166f840 1123 TsPayload = NULL;\r
1124 }\r
6cf9230f 1125ON_EXIT:\r
9166f840 1126 return TsPayload;\r
1127}\r
1128\r
1129/**\r
1130 Generate the Notify payload.\r
1131\r
1132 Since the structure of Notify payload which defined in RFC 4306 is simple, so\r
6cf9230f 1133 there is no internal data structure for Notify payload. This function generate\r
1134 Notify payload defined in RFC 4306, but all the fields in this payload are still\r
1135 in host order and need call Ikev2EncodePayload() to convert those fields from\r
9166f840 1136 the host order to network order beforing sending it.\r
1137\r
1138 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).\r
1139 For IPsec SAs it MUST be neither (2) for AH or (3)\r
1140 for ESP.\r
6cf9230f 1141 @param[in] NextPayload The next paylaod type in NextPayload field of\r
9166f840 1142 the Notify payload.\r
6cf9230f 1143 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.\r
1144 @param[in] MessageType The message type in NotifyMessageType field of the\r
9166f840 1145 Notify Payload.\r
1146 @param[in] SpiBuf Pointer to buffer contains the SPI value.\r
1147 @param[in] NotifyData Pointer to buffer contains the notification data.\r
1148 @param[in] NotifyDataSize The size of NotifyData in bytes.\r
6cf9230f 1149\r
9166f840 1150\r
1151 @retval Pointer to IKE Notify Payload.\r
1152\r
1153**/\r
1154IKE_PAYLOAD *\r
1155Ikev2GenerateNotifyPayload (\r
1156 IN UINT8 ProtocolId,\r
1157 IN UINT8 NextPayload,\r
1158 IN UINT8 SpiSize,\r
1159 IN UINT16 MessageType,\r
1160 IN UINT8 *SpiBuf,\r
1161 IN UINT8 *NotifyData,\r
1162 IN UINTN NotifyDataSize\r
1163 )\r
1164{\r
1165 IKE_PAYLOAD *NotifyPayload;\r
1166 IKEV2_NOTIFY *Notify;\r
1167 UINT16 NotifyPayloadLen;\r
1168 UINT8 *MessageData;\r
1169\r
1170 // 1 2 3\r
1171 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1172 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1173 // ! Next Payload !C! RESERVED ! Payload Length !\r
1174 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1175 // ! Protocol ID ! SPI Size ! Notify Message Type !\r
1176 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1177 // ! !\r
1178 // ~ Security Parameter Index (SPI) ~\r
1179 // ! !\r
1180 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1181 // ! !\r
1182 // ~ Notification Data ~\r
1183 // ! !\r
1184 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1185 //\r
1186 //\r
1187 NotifyPayloadLen = (UINT16) (sizeof (IKEV2_NOTIFY) + NotifyDataSize + SpiSize);\r
1188 Notify = (IKEV2_NOTIFY *) AllocateZeroPool (NotifyPayloadLen);\r
6b16c9e7
JW
1189 if (Notify == NULL) {\r
1190 return NULL;\r
1191 }\r
9166f840 1192\r
1193 //\r
1194 // Set Delete Payload's Generic Header\r
1195 //\r
1196 Notify->Header.NextPayload = NextPayload;\r
1197 Notify->Header.PayloadLength = NotifyPayloadLen;\r
1198 Notify->SpiSize = SpiSize;\r
1199 Notify->ProtocolId = ProtocolId;\r
1200 Notify->MessageType = MessageType;\r
1201\r
1202 //\r
1203 // Copy Spi , for Cookie Notify, there is no SPI.\r
1204 //\r
1205 if (SpiBuf != NULL && SpiSize != 0 ) {\r
1206 CopyMem (Notify + 1, SpiBuf, SpiSize);\r
1207 }\r
1208\r
1209 MessageData = ((UINT8 *) (Notify + 1)) + SpiSize;\r
1210\r
1211 //\r
1212 // Copy Notification Data\r
1213 //\r
1214 if (NotifyDataSize != 0) {\r
1215 CopyMem (MessageData, NotifyData, NotifyDataSize);\r
1216 }\r
1217\r
1218 //\r
1219 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY\r
1220 //\r
1221 NotifyPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
1222 if (NotifyPayload == NULL) {\r
1223 FreePool (Notify);\r
1224 return NULL;\r
1225 }\r
f75a7f56 1226\r
9166f840 1227 NotifyPayload->PayloadType = IKEV2_PAYLOAD_TYPE_NOTIFY;\r
1228 NotifyPayload->PayloadBuf = (UINT8 *) Notify;\r
1229 NotifyPayload->PayloadSize = NotifyPayloadLen;\r
1230 return NotifyPayload;\r
1231}\r
1232\r
1233/**\r
1234 Generate the Delete payload.\r
1235\r
6cf9230f 1236 Since the structure of Delete payload which defined in RFC 4306 is simple,\r
1237 there is no internal data structure for Delete payload. This function generate\r
1238 Delete payload defined in RFC 4306, but all the fields in this payload are still\r
1239 in host order and need call Ikev2EncodePayload() to convert those fields from\r
9166f840 1240 the host order to network order beforing sending it.\r
1241\r
1242 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.\r
6cf9230f 1243 @param[in] NextPayload The next paylaod type in NextPayload field of\r
9166f840 1244 the Delete payload.\r
1245 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.\r
1246 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.\r
1247 @param[in] SpiBuf Pointer to buffer contains the SPI value.\r
1248\r
1249 @retval a Pointer of IKE Delete Payload.\r
1250\r
1251**/\r
1252IKE_PAYLOAD *\r
1253Ikev2GenerateDeletePayload (\r
1254 IN IKEV2_SA_SESSION *IkeSaSession,\r
1255 IN UINT8 NextPayload,\r
1256 IN UINT8 SpiSize,\r
1257 IN UINT16 SpiNum,\r
1258 IN UINT8 *SpiBuf\r
6cf9230f 1259\r
9166f840 1260 )\r
1261{\r
1262 IKE_PAYLOAD *DelPayload;\r
1263 IKEV2_DELETE *Del;\r
1264 UINT16 SpiBufSize;\r
1265 UINT16 DelPayloadLen;\r
1266\r
1267 // 1 2 3\r
1268 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1269 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1270 // ! Next Payload !C! RESERVED ! Payload Length !\r
1271 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1272 // ! Protocol ID ! SPI Size ! # of SPIs !\r
1273 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1274 // ! !\r
1275 // ~ Security Parameter Index(es) (SPI) ~\r
1276 // ! !\r
1277 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1278 //\r
1279 SpiBufSize = (UINT16) (SpiSize * SpiNum);\r
02a758cb 1280 if (SpiBufSize != 0 && SpiBuf == NULL) {\r
1281 return NULL;\r
1282 }\r
6cf9230f 1283\r
9166f840 1284 DelPayloadLen = (UINT16) (sizeof (IKEV2_DELETE) + SpiBufSize);\r
1285\r
1286 Del = AllocateZeroPool (DelPayloadLen);\r
6b16c9e7
JW
1287 if (Del == NULL) {\r
1288 return NULL;\r
1289 }\r
6cf9230f 1290\r
9166f840 1291 //\r
1292 // Set Delete Payload's Generic Header\r
1293 //\r
1294 Del->Header.NextPayload = NextPayload;\r
1295 Del->Header.PayloadLength = DelPayloadLen;\r
1296 Del->NumSpis = SpiNum;\r
1297 Del->SpiSize = SpiSize;\r
1298\r
1299 if (SpiSize == 4) {\r
1300 //\r
1301 // TODO: should consider the AH if needs to support.\r
1302 //\r
1303 Del->ProtocolId = IPSEC_PROTO_IPSEC_ESP;\r
1304 } else {\r
1305 Del->ProtocolId = IPSEC_PROTO_ISAKMP;\r
1306 }\r
1307\r
1308 //\r
1309 // Set Del Payload's Idntification Data\r
1310 //\r
1311 CopyMem (Del + 1, SpiBuf, SpiBufSize);\r
1312 DelPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
1313 if (DelPayload == NULL) {\r
1314 FreePool (Del);\r
1315 return NULL;\r
1316 }\r
f75a7f56 1317\r
9166f840 1318 DelPayload->PayloadType = IKEV2_PAYLOAD_TYPE_DELETE;\r
1319 DelPayload->PayloadBuf = (UINT8 *) Del;\r
1320 DelPayload->PayloadSize = DelPayloadLen;\r
1321 return DelPayload;\r
1322}\r
1323\r
1324/**\r
1325 Generate the Configuration payload.\r
1326\r
6cf9230f 1327 This function generate configuration payload defined in RFC 4306, but all the\r
1328 fields in this payload are still in host order and need call Ikev2EncodePayload()\r
9166f840 1329 to convert those fields from the host order to network order beforing sending it.\r
1330\r
6cf9230f 1331 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload\r
9166f840 1332 generation.\r
6cf9230f 1333 @param[in] NextPayload The next paylaod type in NextPayload field of\r
9166f840 1334 the Delete payload.\r
1335 @param[in] CfgType The attribute type in the Configuration attribute.\r
1336\r
1337 @retval Pointer to IKE CP Payload.\r
1338\r
1339**/\r
1340IKE_PAYLOAD *\r
1341Ikev2GenerateCpPayload (\r
1342 IN IKEV2_SA_SESSION *IkeSaSession,\r
1343 IN UINT8 NextPayload,\r
1344 IN UINT8 CfgType\r
1345 )\r
1346{\r
1347 IKE_PAYLOAD *CpPayload;\r
1348 IKEV2_CFG *Cfg;\r
1349 UINT16 PayloadLen;\r
1350 IKEV2_CFG_ATTRIBUTES *CfgAttributes;\r
1351\r
1352 //\r
1353 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1354 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1355 // ! Next Payload !C! RESERVED ! Payload Length !\r
1356 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1357 // ! CFG Type ! RESERVED !\r
1358 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1359 // ! !\r
1360 // ~ Configuration Attributes ~\r
1361 // ! !\r
1362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1363 //\r
1364\r
1365 PayloadLen = (UINT16) (sizeof (IKEV2_CFG) + sizeof (IKEV2_CFG_ATTRIBUTES));\r
1366 Cfg = (IKEV2_CFG *) AllocateZeroPool (PayloadLen);\r
1367\r
1368 if (Cfg == NULL) {\r
1369 return NULL;\r
1370 }\r
1371\r
1372 CfgAttributes = (IKEV2_CFG_ATTRIBUTES *)((UINT8 *)Cfg + sizeof (IKEV2_CFG));\r
1373\r
1374 //\r
6cf9230f 1375 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS\r
1376 // or INTERNAL_IP6_ADDRESS.\r
9166f840 1377 //\r
1378\r
1379 Cfg->Header.NextPayload = NextPayload;\r
1380 Cfg->Header.PayloadLength = PayloadLen;\r
1381 Cfg->CfgType = IKEV2_CFG_TYPE_REQUEST;\r
1382\r
1383 CfgAttributes->AttritType = CfgType;\r
1384 CfgAttributes->ValueLength = 0;\r
1385\r
1386 CpPayload = IkePayloadAlloc ();\r
1387 if (CpPayload == NULL) {\r
1388 if (Cfg != NULL) {\r
1389 FreePool (Cfg);\r
1390 }\r
1391 return NULL;\r
1392 }\r
1393\r
1394 CpPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CP;\r
1395 CpPayload->PayloadBuf = (UINT8 *) Cfg;\r
1396 CpPayload->PayloadSize = PayloadLen;\r
1397 return CpPayload;\r
1398}\r
1399\r
1400/**\r
1401 Parser the Notify Cookie payload.\r
1402\r
1403 This function parses the Notify Cookie payload.If the Notify ProtocolId is not\r
1404 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not\r
1405 the COOKIE, return EFI_INVALID_PARAMETER.\r
1406\r
6cf9230f 1407 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the\r
9166f840 1408 Notify Cookie payload.\r
1409 the Notify payload.\r
1410 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.\r
1411\r
1412 @retval EFI_SUCCESS The Notify Cookie Payload is valid.\r
1413 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.\r
1414 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.\r
1415\r
1416**/\r
1417EFI_STATUS\r
1418Ikev2ParserNotifyCookiePayload (\r
1419 IN IKE_PAYLOAD *IkeNCookie,\r
1420 IN OUT IKEV2_SA_SESSION *IkeSaSession\r
6cf9230f 1421 )\r
9166f840 1422{\r
1423 IKEV2_NOTIFY *NotifyPayload;\r
1424 UINTN NotifyDataSize;\r
1425\r
1426 NotifyPayload = (IKEV2_NOTIFY *)IkeNCookie->PayloadBuf;\r
1427\r
6cf9230f 1428 if ((NotifyPayload->ProtocolId != IPSEC_PROTO_ISAKMP) ||\r
9166f840 1429 (NotifyPayload->SpiSize != 0) ||\r
1430 (NotifyPayload->MessageType != IKEV2_NOTIFICATION_COOKIE)\r
1431 ) {\r
1432 return EFI_INVALID_PARAMETER;\r
1433 }\r
1434\r
1435 NotifyDataSize = NotifyPayload->Header.PayloadLength - sizeof (IKEV2_NOTIFY);\r
1436 IkeSaSession->NCookie = AllocateZeroPool (NotifyDataSize);\r
1437 if (IkeSaSession->NCookie == NULL) {\r
1438 return EFI_OUT_OF_RESOURCES;\r
1439 }\r
1440\r
1441 IkeSaSession->NCookieSize = NotifyDataSize;\r
1442\r
1443 CopyMem (\r
6cf9230f 1444 IkeSaSession->NCookie,\r
2922e29a 1445 (UINT8 *)NotifyPayload + sizeof (IKEV2_NOTIFY),\r
9166f840 1446 NotifyDataSize\r
1447 );\r
1448\r
1449 return EFI_SUCCESS;\r
1450}\r
1451\r
1452\r
1453/**\r
1454 Generate the Certificate payload or Certificate Request Payload.\r
1455\r
6cf9230f 1456 Since the Certificate Payload structure is same with Certificate Request Payload,\r
9166f840 1457 the only difference is that one contains the Certificate Data, other contains\r
6cf9230f 1458 the acceptable certificateion CA. This function generate Certificate payload\r
1459 or Certificate Request Payload defined in RFC 4306, but all the fields\r
1460 in the payload are still in host order and need call Ikev2EncodePayload()\r
9166f840 1461 to convert those fields from the host order to network order beforing sending it.\r
1462\r
6cf9230f 1463 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload\r
9166f840 1464 generation.\r
6cf9230f 1465 @param[in] NextPayload The next paylaod type in NextPayload field of\r
9166f840 1466 the Delete payload.\r
1467 @param[in] Certificate Pointer of buffer contains the certification data.\r
1468 @param[in] CertificateLen The length of Certificate in byte.\r
1469 @param[in] EncodeType Specified the Certificate Encodeing which is defined\r
1470 in RFC 4306.\r
1471 @param[in] IsRequest To indicate create Certificate Payload or Certificate\r
1472 Request Payload. If it is TURE, create Certificate\r
aa63a866 1473 Request Payload. Otherwise, create Certificate Payload.\r
9166f840 1474\r
1475 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate\r
1476 payload or Certificated Request payload.\r
1477\r
1478**/\r
1479IKE_PAYLOAD *\r
1480Ikev2GenerateCertificatePayload (\r
1481 IN IKEV2_SA_SESSION *IkeSaSession,\r
1482 IN UINT8 NextPayload,\r
1483 IN UINT8 *Certificate,\r
1484 IN UINTN CertificateLen,\r
1485 IN UINT8 EncodeType,\r
1486 IN BOOLEAN IsRequest\r
1487 )\r
1488{\r
1489 IKE_PAYLOAD *CertPayload;\r
1490 IKEV2_CERT *Cert;\r
1491 UINT16 PayloadLen;\r
1492 UINT8 *PublicKey;\r
1493 UINTN PublicKeyLen;\r
1494 HASH_DATA_FRAGMENT Fragment[1];\r
1495 UINT8 *HashData;\r
1496 UINTN HashDataSize;\r
1497 EFI_STATUS Status;\r
1498\r
1499 //\r
1500 // 1 2 3\r
1501 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1502 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1503 // ! Next Payload !C! RESERVED ! Payload Length !\r
1504 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1505 // ! Cert Encoding ! !\r
1506 // +-+-+-+-+-+-+-+-+ !\r
1507 // ~ Certificate Data/Authority ~\r
1508 // ! !\r
1509 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1510 //\r
1511\r
1512 Status = EFI_SUCCESS;\r
1513 PublicKey = NULL;\r
6cf9230f 1514 PublicKeyLen = 0;\r
9166f840 1515\r
1516 if (!IsRequest) {\r
1517 PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + CertificateLen);\r
1518 } else {\r
1519 //\r
1520 // SHA1 Hash length is 20.\r
1521 //\r
1522 PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + 20);\r
1523 }\r
1524\r
1525 Cert = AllocateZeroPool (PayloadLen);\r
1526 if (Cert == NULL) {\r
1527 return NULL;\r
1528 }\r
6cf9230f 1529\r
9166f840 1530 //\r
1531 // Generate Certificate Payload or Certificate Request Payload.\r
1532 //\r
1533 Cert->Header.NextPayload = NextPayload;\r
1534 Cert->Header.PayloadLength = PayloadLen;\r
1535 Cert->CertEncoding = EncodeType;\r
1536 if (!IsRequest) {\r
1537 CopyMem (\r
1538 ((UINT8 *)Cert) + sizeof (IKEV2_CERT),\r
1539 Certificate,\r
1540 CertificateLen\r
1541 );\r
1542 } else {\r
1543 Status = IpSecCryptoIoGetPublicKeyFromCert (\r
1544 Certificate,\r
1545 CertificateLen,\r
1546 &PublicKey,\r
1547 &PublicKeyLen\r
1548 );\r
1549 if (EFI_ERROR (Status)) {\r
6cf9230f 1550 goto ON_EXIT;\r
9166f840 1551 }\r
1552\r
1553 Fragment[0].Data = PublicKey;\r
1554 Fragment[0].DataSize = PublicKeyLen;\r
1555 HashDataSize = IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC);\r
1556 HashData = AllocateZeroPool (HashDataSize);\r
02a758cb 1557 if (HashData == NULL) {\r
1558 goto ON_EXIT;\r
1559 }\r
6cf9230f 1560\r
9166f840 1561 Status = IpSecCryptoIoHash (\r
1562 IKE_AALG_SHA1HMAC,\r
1563 Fragment,\r
1564 1,\r
1565 HashData,\r
1566 HashDataSize\r
1567 );\r
1568 if (EFI_ERROR (Status)) {\r
1569 goto ON_EXIT;\r
1570 }\r
6cf9230f 1571\r
9166f840 1572 CopyMem (\r
1573 ((UINT8 *)Cert) + sizeof (IKEV2_CERT),\r
1574 HashData,\r
1575 HashDataSize\r
1576 );\r
1577 }\r
1578\r
1579 CertPayload = IkePayloadAlloc ();\r
1580 if (CertPayload == NULL) {\r
1581 goto ON_EXIT;\r
1582 }\r
6cf9230f 1583\r
9166f840 1584 if (!IsRequest) {\r
1585 CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERT;\r
1586 } else {\r
1587 CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERTREQ;\r
1588 }\r
1589\r
1590 CertPayload->PayloadBuf = (UINT8 *) Cert;\r
1591 CertPayload->PayloadSize = PayloadLen;\r
1592 return CertPayload;\r
1593\r
1594ON_EXIT:\r
1595 if (Cert != NULL) {\r
1596 FreePool (Cert);\r
1597 }\r
1598 if (PublicKey != NULL) {\r
1599 FreePool (PublicKey);\r
1600 }\r
1601 return NULL;\r
1602}\r
1603\r
1604/**\r
1605 Remove and free all IkePayloads in the specified IkePacket.\r
1606\r
1607 @param[in] IkePacket The pointer of IKE_PACKET.\r
1608\r
1609**/\r
1610VOID\r
1611ClearAllPayloads (\r
1612 IN IKE_PACKET *IkePacket\r
1613 )\r
1614{\r
1615 LIST_ENTRY *PayloadEntry;\r
1616 IKE_PAYLOAD *IkePayload;\r
1617 //\r
1618 // remove all payloads from list and free each payload.\r
1619 //\r
1620 while (!IsListEmpty (&IkePacket->PayloadList)) {\r
1621 PayloadEntry = IkePacket->PayloadList.ForwardLink;\r
1622 IkePayload = IKE_PAYLOAD_BY_PACKET (PayloadEntry);\r
1623 IKE_PACKET_REMOVE_PAYLOAD (IkePacket, IkePayload);\r
1624 IkePayloadFree (IkePayload);\r
1625 }\r
1626}\r
1627\r
1628/**\r
1629 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.\r
1630\r
1631 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.\r
1632 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.\r
1633\r
1634 @retval return the pointer of IKEV2_SA.\r
6cf9230f 1635\r
9166f840 1636**/\r
1637IKEV2_SA*\r
1638Ikev2EncodeSa (\r
686d4d4a 1639 IN IKEV2_SESSION_COMMON *SessionCommon,\r
1640 IN IKEV2_SA_DATA *SaData\r
9166f840 1641 )\r
1642{\r
1643 IKEV2_SA *Sa;\r
1644 UINTN SaSize;\r
1645 IKEV2_PROPOSAL_DATA *ProposalData;\r
1646 IKEV2_TRANSFORM_DATA *TransformData;\r
1647 UINTN TotalTransforms;\r
1648 UINTN SaAttrsSize;\r
1649 UINTN TransformsSize;\r
1650 UINTN TransformSize;\r
1651 UINTN ProposalsSize;\r
1652 UINTN ProposalSize;\r
1653 UINTN ProposalIndex;\r
1654 UINTN TransformIndex;\r
1655 IKE_SA_ATTRIBUTE *SaAttribute;\r
1656 IKEV2_PROPOSAL *Proposal;\r
9166f840 1657 IKEV2_TRANSFORM *Transform;\r
6cf9230f 1658\r
9166f840 1659 //\r
1660 // Transform IKE_SA_DATA structure to IKE_SA Payload.\r
1661 // Header length is host order.\r
1662 // The returned IKE_SA struct should be freed by caller.\r
1663 //\r
1664 TotalTransforms = 0;\r
1665 //\r
5edac28e 1666 // Calculate the Proposal numbers and Transform numbers.\r
9166f840 1667 //\r
1668 for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {\r
1669\r
1670 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1) + ProposalIndex;\r
1671 TotalTransforms += ProposalData->NumTransforms;\r
1672\r
1673 }\r
1674 SaSize = sizeof (IKEV2_SA) +\r
1675 SaData->NumProposals * sizeof (IKEV2_PROPOSAL) +\r
1676 TotalTransforms * (sizeof (IKEV2_TRANSFORM) + MAX_SA_ATTRS_SIZE);\r
1677 //\r
1678 // Allocate buffer for IKE_SA.\r
1679 //\r
1680 Sa = AllocateZeroPool (SaSize);\r
6b16c9e7
JW
1681 if (Sa == NULL) {\r
1682 return NULL;\r
1683 }\r
f75a7f56 1684\r
9166f840 1685 CopyMem (Sa, SaData, sizeof (IKEV2_SA));\r
1686 Sa->Header.PayloadLength = (UINT16) sizeof (IKEV2_SA);\r
1687 ProposalsSize = 0;\r
9166f840 1688 Proposal = (IKEV2_PROPOSAL *) (Sa + 1);\r
1689\r
1690 //\r
1691 // Set IKE_PROPOSAL\r
1692 //\r
1693 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);\r
1694 for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {\r
1695 Proposal->ProposalIndex = ProposalData->ProposalIndex;\r
1696 Proposal->ProtocolId = ProposalData->ProtocolId;\r
1697 Proposal->NumTransforms = ProposalData->NumTransforms;\r
1698\r
1699 if (ProposalData->Spi == 0) {\r
1700 Proposal->SpiSize = 0;\r
1701 } else {\r
1702 Proposal->SpiSize = 4;\r
1703 *(UINT32 *) (Proposal + 1) = HTONL (*((UINT32*)ProposalData->Spi));\r
1704 }\r
1705\r
1706 TransformsSize = 0;\r
9166f840 1707 Transform = (IKEV2_TRANSFORM *) ((UINT8 *) (Proposal + 1) + Proposal->SpiSize);\r
1708\r
1709 //\r
1710 // Set IKE_TRANSFORM\r
1711 //\r
1712 for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {\r
1713 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;\r
1714 Transform->TransformType = TransformData->TransformType;\r
1715 Transform->TransformId = HTONS (TransformData->TransformId);\r
1716 SaAttrsSize = 0;\r
1717\r
1718 //\r
1719 // If the Encryption Algorithm is variable key length set the key length in attribute.\r
1720 // Note that only a single attribute type (Key Length) is defined and it is fixed length.\r
1721 //\r
1722 if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_ENCR && TransformData->Attribute.Attr.AttrValue != 0) {\r
1723 SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);\r
1724 SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);\r
1725 SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);\r
1726 SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);\r
1727 }\r
1728\r
1729 //\r
1730 // If the Integrity Algorithm is variable key length set the key length in attribute.\r
1731 //\r
1732 if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_INTEG && TransformData->Attribute.Attr.AttrValue != 0) {\r
1733 SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);\r
1734 SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);\r
1735 SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);\r
1736 SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);\r
1737 }\r
1738\r
1739 TransformSize = sizeof (IKEV2_TRANSFORM) + SaAttrsSize;\r
1740 TransformsSize += TransformSize;\r
6cf9230f 1741\r
9166f840 1742 Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_MORE;\r
1743 Transform->Header.PayloadLength = HTONS ((UINT16)TransformSize);\r
6cf9230f 1744\r
ce5c3273 1745 if (TransformIndex == ((UINT32)ProposalData->NumTransforms - 1)) {\r
6cf9230f 1746 Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_NONE;\r
9166f840 1747 }\r
1748\r
1749 Transform = (IKEV2_TRANSFORM *)((UINT8 *) Transform + TransformSize);\r
1750 }\r
6cf9230f 1751\r
9166f840 1752 //\r
1753 // Set Proposal's Generic Header.\r
1754 //\r
1755 ProposalSize = sizeof (IKEV2_PROPOSAL) + Proposal->SpiSize + TransformsSize;\r
1756 ProposalsSize += ProposalSize;\r
1757 Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_MORE;\r
1758 Proposal->Header.PayloadLength = HTONS ((UINT16)ProposalSize);\r
6cf9230f 1759\r
1760 if (ProposalIndex == (UINTN)(SaData->NumProposals - 1)) {\r
1761 Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_NONE;\r
9166f840 1762 }\r
1763\r
1764 //\r
1765 // Point to next Proposal Payload\r
1766 //\r
1767 Proposal = (IKEV2_PROPOSAL *) ((UINT8 *) Proposal + ProposalSize);\r
1768 ProposalData = (IKEV2_PROPOSAL_DATA *)(((UINT8 *)ProposalData) + sizeof (IKEV2_PROPOSAL_DATA) + (TransformIndex * sizeof (IKEV2_TRANSFORM_DATA)));\r
1769 }\r
1770 //\r
1771 // Set SA's Generic Header.\r
1772 //\r
1773 Sa->Header.PayloadLength = (UINT16) (Sa->Header.PayloadLength + ProposalsSize);\r
1774 return Sa;\r
1775}\r
1776\r
1777/**\r
1778 Decode SA payload.\r
1779\r
1780 This function converts the received SA payload to internal data structure.\r
1781\r
6cf9230f 1782 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA\r
9166f840 1783 Payload.\r
1784 @param[in] Sa Pointer to SA Payload\r
1785\r
1786 @return a Pointer to internal data structure for SA payload.\r
1787\r
1788**/\r
1789IKEV2_SA_DATA *\r
1790Ikev2DecodeSa (\r
686d4d4a 1791 IN IKEV2_SESSION_COMMON *SessionCommon,\r
1792 IN IKEV2_SA *Sa\r
9166f840 1793 )\r
1794{\r
1795 IKEV2_SA_DATA *SaData;\r
1796 EFI_STATUS Status;\r
1797 IKEV2_PROPOSAL *Proposal;\r
1798 IKEV2_TRANSFORM *Transform;\r
1799 UINTN TotalProposals;\r
1800 UINTN TotalTransforms;\r
1801 UINTN ProposalNextPayloadSum;\r
1802 UINTN ProposalIndex;\r
1803 UINTN TransformIndex;\r
1804 UINTN SaRemaining;\r
1805 UINT16 ProposalSize;\r
1806 UINTN ProposalRemaining;\r
1807 UINT16 TransformSize;\r
1808 UINTN SaAttrRemaining;\r
1809 IKE_SA_ATTRIBUTE *SaAttribute;\r
1810 IKEV2_PROPOSAL_DATA *ProposalData;\r
1811 IKEV2_TRANSFORM_DATA *TransformData;\r
1812 UINT8 *Spi;\r
1813\r
1814 //\r
1815 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.\r
1816 // Header length NTOH is already done\r
1817 // The returned IKE_SA_DATA should be freed by caller\r
1818 //\r
1819 SaData = NULL;\r
1820 Status = EFI_SUCCESS;\r
1821\r
1822 //\r
1823 // First round sanity check and size calculae\r
1824 //\r
1825 TotalProposals = 0;\r
1826 TotalTransforms = 0;\r
1827 ProposalNextPayloadSum = 0;\r
1828 SaRemaining = Sa->Header.PayloadLength - sizeof (IKEV2_SA);// Point to current position in SA\r
1829 Proposal = (IKEV2_PROPOSAL *)((IKEV2_SA *)(Sa)+1);\r
1830\r
1831 //\r
5edac28e 1832 // Calculate the number of Proposal payload and the total numbers of\r
9166f840 1833 // Transforms payload (the transforms in all proposal payload).\r
1834 //\r
1835 while (SaRemaining > sizeof (IKEV2_PROPOSAL)) {\r
1836 ProposalSize = NTOHS (Proposal->Header.PayloadLength);\r
1837 if (SaRemaining < ProposalSize) {\r
1838 Status = EFI_INVALID_PARAMETER;\r
1839 goto Exit;\r
1840 }\r
1841\r
1842 if (Proposal->SpiSize != 0 && Proposal->SpiSize != 4) {\r
1843 Status = EFI_INVALID_PARAMETER;\r
1844 goto Exit;\r
1845 }\r
1846\r
1847 TotalProposals++;\r
1848 TotalTransforms += Proposal->NumTransforms;\r
1849 SaRemaining -= ProposalSize;\r
1850 ProposalNextPayloadSum += Proposal->Header.NextPayload;\r
1851 Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);\r
1852 }\r
1853\r
1854 //\r
6cf9230f 1855 // Check the proposal number.\r
1856 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)\r
1857 // which Specifies whether this is the last Proposal Substructure in the SA.\r
1858 // Here suming all Proposal NextPayLoad field to check the proposal number is correct\r
1859 // or not.\r
9166f840 1860 //\r
1861 if (TotalProposals == 0 ||\r
6cf9230f 1862 (TotalProposals - 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE != ProposalNextPayloadSum\r
9166f840 1863 ) {\r
1864 Status = EFI_INVALID_PARAMETER;\r
1865 goto Exit;\r
1866 }\r
1867\r
1868 //\r
1869 // Second round sanity check and decode. Transform the SA payload into\r
1870 // a IKE_SA_DATA structure.\r
1871 //\r
1872 SaData = (IKEV2_SA_DATA *) AllocateZeroPool (\r
1873 sizeof (IKEV2_SA_DATA) +\r
1874 TotalProposals * sizeof (IKEV2_PROPOSAL_DATA) +\r
1875 TotalTransforms * sizeof (IKEV2_TRANSFORM_DATA)\r
1876 );\r
6b16c9e7
JW
1877 if (SaData == NULL) {\r
1878 Status = EFI_OUT_OF_RESOURCES;\r
1879 goto Exit;\r
1880 }\r
f75a7f56 1881\r
9166f840 1882 CopyMem (SaData, Sa, sizeof (IKEV2_SA));\r
1883 SaData->NumProposals = TotalProposals;\r
1884 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);\r
1885\r
1886 //\r
1887 // Proposal Payload\r
1888 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1889 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1890 // ! Next Payload ! RESERVED ! Payload Length !\r
1891 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1892 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!\r
1893 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1894 // ! SPI (variable) !\r
1895 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1896 //\r
1897 for (ProposalIndex = 0, Proposal = IKEV2_SA_FIRST_PROPOSAL (Sa);\r
1898 ProposalIndex < TotalProposals;\r
1899 ProposalIndex++\r
1900 ) {\r
6cf9230f 1901\r
9166f840 1902 //\r
1903 // TODO: check ProposalId\r
1904 //\r
1905 ProposalData->ProposalIndex = Proposal->ProposalIndex;\r
1906 ProposalData->ProtocolId = Proposal->ProtocolId;\r
1907 if (Proposal->SpiSize == 0) {\r
1908 ProposalData->Spi = 0;\r
1909 } else {\r
1910 //\r
1911 // SpiSize == 4\r
1912 //\r
1913 Spi = AllocateZeroPool (Proposal->SpiSize);\r
6b16c9e7
JW
1914 if (Spi == NULL) {\r
1915 Status = EFI_OUT_OF_RESOURCES;\r
1916 goto Exit;\r
1917 }\r
f75a7f56 1918\r
9166f840 1919 CopyMem (Spi, (UINT32 *) (Proposal + 1), Proposal->SpiSize);\r
1920 *((UINT32*) Spi) = NTOHL (*((UINT32*) Spi));\r
1921 ProposalData->Spi = Spi;\r
1922 }\r
1923\r
1924 ProposalData->NumTransforms = Proposal->NumTransforms;\r
1925 ProposalSize = NTOHS (Proposal->Header.PayloadLength);\r
1926 ProposalRemaining = ProposalSize;\r
1927 //\r
1928 // Transform Payload\r
1929 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\r
1930 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1931 // ! Next Payload ! RESERVED ! Payload Length !\r
1932 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1933 // !Transform Type ! RESERVED ! Transform ID !\r
1934 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1935 // ! !\r
1936 // ~ SA Attributes ~\r
1937 // ! !\r
1938 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\r
1939 //\r
1940 Transform = IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal);\r
1941 for (TransformIndex = 0; TransformIndex < Proposal->NumTransforms; TransformIndex++) {\r
1942\r
1943 //\r
1944 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.\r
1945 //\r
1946 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;\r
1947 TransformData->TransformId = NTOHS (Transform->TransformId);\r
1948 TransformData->TransformType = Transform->TransformType;\r
1949 TransformSize = NTOHS (Transform->Header.PayloadLength);\r
1950 //\r
1951 // Check the Proposal Data is correct.\r
1952 //\r
1953 if (ProposalRemaining < TransformSize) {\r
1954 Status = EFI_INVALID_PARAMETER;\r
1955 goto Exit;\r
1956 }\r
1957\r
1958 //\r
1959 // Check if the Transform payload includes Attribution.\r
1960 //\r
1961 SaAttrRemaining = TransformSize - sizeof (IKEV2_TRANSFORM);\r
1962\r
1963 //\r
6cf9230f 1964 // According to RFC 4603, currently only the Key length attribute type is\r
9166f840 1965 // supported. For each Transform, there is only one attributeion.\r
1966 //\r
1967 if (SaAttrRemaining > 0) {\r
1968 if (SaAttrRemaining != sizeof (IKE_SA_ATTRIBUTE)) {\r
1969 Status = EFI_INVALID_PARAMETER;\r
1970 goto Exit;\r
1971 }\r
1972 SaAttribute = (IKE_SA_ATTRIBUTE *) ((IKEV2_TRANSFORM *)(Transform) + 1);\r
1973 TransformData->Attribute.AttrType = (UINT16)((NTOHS (SaAttribute->AttrType)) & ~SA_ATTR_FORMAT_BIT);\r
1974 TransformData->Attribute.Attr.AttrValue = NTOHS (SaAttribute->Attr.AttrValue);\r
1975\r
1976 //\r
1977 // Currently, only supports the Key Length Attribution.\r
1978 //\r
1979 if (TransformData->Attribute.AttrType != IKEV2_ATTRIBUTE_TYPE_KEYLEN) {\r
1980 Status = EFI_INVALID_PARAMETER;\r
1981 goto Exit;\r
6cf9230f 1982 }\r
9166f840 1983 }\r
1984\r
1985 //\r
1986 // Move to next Transform\r
6cf9230f 1987 //\r
9166f840 1988 Transform = IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform, TransformSize);\r
1989 }\r
1990 Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);\r
1991 ProposalData = (IKEV2_PROPOSAL_DATA *) ((UINT8 *)(ProposalData + 1) +\r
1992 ProposalData->NumTransforms *\r
1993 sizeof (IKEV2_TRANSFORM_DATA));\r
1994 }\r
1995\r
1996Exit:\r
1997 if (EFI_ERROR (Status) && SaData != NULL) {\r
1998 FreePool (SaData);\r
1999 SaData = NULL;\r
2000 }\r
2001 return SaData;\r
2002}\r
2003\r
2004/**\r
2005 General interface of payload encoding.\r
2006\r
6cf9230f 2007 This function encodes the internal data structure into payload which\r
9166f840 2008 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input\r
2009 payload and converted payload. Only the SA payload use the interal structure\r
2010 to store the attribute. Other payload use structure which is same with the RFC\r
2011 defined, for this kind payloads just do host order to network order change of\r
2012 some fields.\r
2013\r
2014 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.\r
2015 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and\r
2016 store the encoded result as output.\r
2017\r
2018 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.\r
2019 @retval EFI_SUCCESS Encoded successfully.\r
2020\r
2021**/\r
2022EFI_STATUS\r
2023Ikev2EncodePayload (\r
2024 IN UINT8 *SessionCommon,\r
2025 IN OUT IKE_PAYLOAD *IkePayload\r
2026 )\r
2027{\r
2028 IKEV2_SA_DATA *SaData;\r
2029 IKEV2_SA *SaPayload;\r
2030 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
2031 IKEV2_NOTIFY *NotifyPayload;\r
2032 IKEV2_DELETE *DeletePayload;\r
2033 IKEV2_KEY_EXCHANGE *KeyPayload;\r
2034 IKEV2_TS *TsPayload;\r
2035 IKEV2_CFG_ATTRIBUTES *CfgAttribute;\r
2036 UINT8 *TsBuffer;\r
2037 UINT8 Index;\r
2038 TRAFFIC_SELECTOR *TrafficSelector;\r
2039\r
2040 //\r
2041 // Transform the Internal IKE structure to IKE payload.\r
2042 // Only the SA payload use the interal structure to store the attribute.\r
2043 // Other payload use structure which same with the RFC defined, so there is\r
2044 // no need to tranform them to IKE payload.\r
2045 //\r
2046 switch (IkePayload->PayloadType) {\r
2047 case IKEV2_PAYLOAD_TYPE_SA:\r
2048 //\r
2049 // Transform IKE_SA_DATA to IK_SA payload\r
2050 //\r
2051 SaData = (IKEV2_SA_DATA *) IkePayload->PayloadBuf;\r
2052 SaPayload = Ikev2EncodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, SaData);\r
2053\r
2054 if (SaPayload == NULL) {\r
2055 return EFI_INVALID_PARAMETER;\r
2056 }\r
2057 if (!IkePayload->IsPayloadBufExt) {\r
2058 FreePool (IkePayload->PayloadBuf);\r
2059 }\r
2060 IkePayload->PayloadBuf = (UINT8 *) SaPayload;\r
2061 IkePayload->IsPayloadBufExt = FALSE;\r
2062 break;\r
2063\r
2064 case IKEV2_PAYLOAD_TYPE_NOTIFY:\r
2065 NotifyPayload = (IKEV2_NOTIFY *) IkePayload->PayloadBuf;\r
2066 NotifyPayload->MessageType = HTONS (NotifyPayload->MessageType);\r
2067 break;\r
6cf9230f 2068\r
9166f840 2069 case IKEV2_PAYLOAD_TYPE_DELETE:\r
2070 DeletePayload = (IKEV2_DELETE *) IkePayload->PayloadBuf;\r
2071 DeletePayload->NumSpis = HTONS (DeletePayload->NumSpis);\r
2072 break;\r
6cf9230f 2073\r
9166f840 2074 case IKEV2_PAYLOAD_TYPE_KE:\r
2075 KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;\r
2076 KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);\r
2077 break;\r
6cf9230f 2078\r
9166f840 2079 case IKEV2_PAYLOAD_TYPE_TS_INIT:\r
2080 case IKEV2_PAYLOAD_TYPE_TS_RSP:\r
2081 TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;\r
2082 TsBuffer = IkePayload->PayloadBuf + sizeof (IKEV2_TS);\r
2083\r
2084 for (Index = 0; Index < TsPayload->TSNumbers; Index++) {\r
2085 TrafficSelector = (TRAFFIC_SELECTOR *) TsBuffer;\r
2086 TsBuffer = TsBuffer + TrafficSelector->SelecorLen;\r
2087 //\r
2088 // Host order to network order\r
2089 //\r
2090 TrafficSelector->SelecorLen = HTONS (TrafficSelector->SelecorLen);\r
2091 TrafficSelector->StartPort = HTONS (TrafficSelector->StartPort);\r
2092 TrafficSelector->EndPort = HTONS (TrafficSelector->EndPort);\r
6cf9230f 2093\r
9166f840 2094 }\r
2095\r
2096 break;\r
2097\r
2098 case IKEV2_PAYLOAD_TYPE_CP:\r
2099 CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);\r
2100 CfgAttribute->AttritType = HTONS (CfgAttribute->AttritType);\r
2101 CfgAttribute->ValueLength = HTONS (CfgAttribute->ValueLength);\r
6cf9230f 2102\r
9166f840 2103 case IKEV2_PAYLOAD_TYPE_ID_INIT:\r
2104 case IKEV2_PAYLOAD_TYPE_ID_RSP:\r
2105 case IKEV2_PAYLOAD_TYPE_AUTH:\r
2106 default:\r
2107 break;\r
2108 }\r
6cf9230f 2109\r
9166f840 2110 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;\r
2111 IkePayload->PayloadSize = PayloadHdr->PayloadLength;\r
2112 PayloadHdr->PayloadLength = HTONS (PayloadHdr->PayloadLength);\r
2113 IKEV2_DUMP_PAYLOAD (IkePayload);\r
2114 return EFI_SUCCESS;\r
2115}\r
2116\r
2117/**\r
2118 The general interface for decoding Payload.\r
2119\r
2120 This function converts the received Payload into internal structure.\r
2121\r
2122 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.\r
2123 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and\r
6cf9230f 2124 store the decoded result as output.\r
9166f840 2125\r
2126 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.\r
2127 @retval EFI_SUCCESS Decoded successfully.\r
2128\r
2129**/\r
2130EFI_STATUS\r
2131Ikev2DecodePayload (\r
2132 IN UINT8 *SessionCommon,\r
2133 IN OUT IKE_PAYLOAD *IkePayload\r
2134 )\r
2135{\r
2136 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
2137 UINT16 PayloadSize;\r
2138 UINT8 PayloadType;\r
2139 IKEV2_SA_DATA *SaData;\r
2140 EFI_STATUS Status;\r
2141 IKEV2_NOTIFY *NotifyPayload;\r
2142 IKEV2_DELETE *DeletePayload;\r
2143 UINT16 TsTotalSize;\r
2144 TRAFFIC_SELECTOR *TsSelector;\r
2145 IKEV2_TS *TsPayload;\r
2146 IKEV2_KEY_EXCHANGE *KeyPayload;\r
2147 IKEV2_CFG_ATTRIBUTES *CfgAttribute;\r
2148 UINT8 Index;\r
2149\r
2150 //\r
2151 // Transform the IKE payload to Internal IKE structure.\r
2152 // Only the SA payload and Hash Payload use the interal\r
2153 // structure to store the attribute. Other payloads use\r
6cf9230f 2154 // structure which is same with the definitions in RFC,\r
2155 // so there is no need to tranform them to internal IKE\r
9166f840 2156 // structure.\r
2157 //\r
2158 Status = EFI_SUCCESS;\r
2159 PayloadSize = (UINT16) IkePayload->PayloadSize;\r
2160 PayloadType = IkePayload->PayloadType;\r
2161 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;\r
2162 //\r
2163 // The PayloadSize is the size of whole payload.\r
2164 // Replace HTONS operation to assignment statements, since the result is same.\r
2165 //\r
2166 PayloadHdr->PayloadLength = PayloadSize;\r
2167\r
2168 IKEV2_DUMP_PAYLOAD (IkePayload);\r
2169 switch (PayloadType) {\r
2170 case IKEV2_PAYLOAD_TYPE_SA:\r
2171 if (PayloadSize < sizeof (IKEV2_SA)) {\r
2172 Status = EFI_INVALID_PARAMETER;\r
2173 goto Exit;\r
2174 }\r
2175\r
2176 SaData = Ikev2DecodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, (IKEV2_SA *) PayloadHdr);\r
2177 if (SaData == NULL) {\r
2178 Status = EFI_INVALID_PARAMETER;\r
2179 goto Exit;\r
2180 }\r
2181\r
2182 if (!IkePayload->IsPayloadBufExt) {\r
2183 FreePool (IkePayload->PayloadBuf);\r
2184 }\r
6cf9230f 2185\r
9166f840 2186 IkePayload->PayloadBuf = (UINT8 *) SaData;\r
6cf9230f 2187 IkePayload->IsPayloadBufExt = FALSE;\r
9166f840 2188 break;\r
2189\r
2190 case IKEV2_PAYLOAD_TYPE_ID_INIT:\r
2191 case IKEV2_PAYLOAD_TYPE_ID_RSP :\r
2192 if (PayloadSize < sizeof (IKEV2_ID)) {\r
2193 Status = EFI_INVALID_PARAMETER;\r
2194 goto Exit;\r
2195 }\r
2196 break;\r
2197\r
2198 case IKEV2_PAYLOAD_TYPE_NOTIFY:\r
2199 if (PayloadSize < sizeof (IKEV2_NOTIFY)) {\r
2200 Status = EFI_INVALID_PARAMETER;\r
2201 goto Exit;\r
2202 }\r
2203\r
2204 NotifyPayload = (IKEV2_NOTIFY *) PayloadHdr;\r
2205 NotifyPayload->MessageType = NTOHS (NotifyPayload->MessageType);\r
2206 break;\r
6cf9230f 2207\r
9166f840 2208 case IKEV2_PAYLOAD_TYPE_DELETE:\r
2209 if (PayloadSize < sizeof (IKEV2_DELETE)) {\r
2210 Status = EFI_INVALID_PARAMETER;\r
2211 goto Exit;\r
2212 }\r
2213\r
2214 DeletePayload = (IKEV2_DELETE *) PayloadHdr;\r
2215 DeletePayload->NumSpis = NTOHS (DeletePayload->NumSpis);\r
2216 break;\r
6cf9230f 2217\r
9166f840 2218 case IKEV2_PAYLOAD_TYPE_AUTH:\r
2219 if (PayloadSize < sizeof (IKEV2_AUTH)) {\r
2220 Status = EFI_INVALID_PARAMETER;\r
2221 goto Exit;\r
2222 }\r
2223 break;\r
2224\r
2225 case IKEV2_PAYLOAD_TYPE_KE:\r
2226 KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;\r
2227 KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);\r
6cf9230f 2228 break;\r
9166f840 2229\r
2230 case IKEV2_PAYLOAD_TYPE_TS_INIT:\r
2231 case IKEV2_PAYLOAD_TYPE_TS_RSP :\r
2232 TsTotalSize = 0;\r
2233 if (PayloadSize < sizeof (IKEV2_TS)) {\r
2234 Status = EFI_INVALID_PARAMETER;\r
2235 goto Exit;\r
2236 }\r
2237 //\r
2238 // Parse each traffic selector and transfer network-order to host-order\r
2239 //\r
2240 TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;\r
2241 TsSelector = (TRAFFIC_SELECTOR *) (IkePayload->PayloadBuf + sizeof (IKEV2_TS));\r
2242\r
2243 for (Index = 0; Index < TsPayload->TSNumbers; Index++) {\r
2244 TsSelector->SelecorLen = NTOHS (TsSelector->SelecorLen);\r
2245 TsSelector->StartPort = NTOHS (TsSelector->StartPort);\r
2246 TsSelector->EndPort = NTOHS (TsSelector->EndPort);\r
2247\r
2248 TsTotalSize = (UINT16) (TsTotalSize + TsSelector->SelecorLen);\r
2249 TsSelector = (TRAFFIC_SELECTOR *) ((UINT8 *) TsSelector + TsSelector->SelecorLen);\r
2250 }\r
2251 //\r
2252 // Check if the total size of Traffic Selectors is correct.\r
2253 //\r
2254 if (TsTotalSize != PayloadSize - sizeof(IKEV2_TS)) {\r
2255 Status = EFI_INVALID_PARAMETER;\r
2256 }\r
2257\r
2258 case IKEV2_PAYLOAD_TYPE_CP:\r
2259 CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);\r
2260 CfgAttribute->AttritType = NTOHS (CfgAttribute->AttritType);\r
2261 CfgAttribute->ValueLength = NTOHS (CfgAttribute->ValueLength);\r
2262\r
2263 default:\r
2264 break;\r
2265 }\r
2266\r
2267 Exit:\r
2268 return Status;\r
2269}\r
2270\r
2271/**\r
2272 Decode the IKE packet.\r
2273\r
6cf9230f 2274 This function first decrypts the IKE packet if needed , then separates the whole\r
9166f840 2275 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.\r
6cf9230f 2276\r
2277 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing\r
9166f840 2278 some parameter used by IKE packet decoding.\r
6cf9230f 2279 @param[in, out] IkePacket The IKE Packet to be decoded on input, and\r
9166f840 2280 the decoded result on return.\r
2281 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
2282 IKE_CHILD_TYPE are supported.\r
2283\r
2284 @retval EFI_SUCCESS The IKE packet is decoded successfully.\r
2285 @retval Otherwise The IKE packet decoding is failed.\r
2286\r
2287**/\r
2288EFI_STATUS\r
2289Ikev2DecodePacket (\r
2290 IN IKEV2_SESSION_COMMON *SessionCommon,\r
2291 IN OUT IKE_PACKET *IkePacket,\r
2292 IN UINTN IkeType\r
2293 )\r
2294{\r
2295 EFI_STATUS Status;\r
2296 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;\r
2297 UINT8 PayloadType;\r
2298 UINTN RemainBytes;\r
2299 UINT16 PayloadSize;\r
2300 IKE_PAYLOAD *IkePayload;\r
2301 IKE_HEADER *IkeHeader;\r
2302 IKEV2_SA_SESSION *IkeSaSession;\r
2303\r
2304 IkeHeader = NULL;\r
6cf9230f 2305\r
9166f840 2306 //\r
2307 // Check if the IkePacket need decrypt.\r
2308 //\r
2309 if (SessionCommon->State >= IkeStateAuth) {\r
2310 Status = Ikev2DecryptPacket (SessionCommon, IkePacket, IkeType);\r
2311 if (EFI_ERROR (Status)) {\r
2312 return Status;\r
2313 }\r
2314 }\r
2315\r
2316 Status = EFI_SUCCESS;\r
2317\r
2318 //\r
2319 // If the IkePacket doesn't contain any payload return invalid parameter.\r
2320 //\r
2321 if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE) {\r
6cf9230f 2322 if ((SessionCommon->State >= IkeStateAuth) &&\r
9166f840 2323 (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INFO)\r
2324 ) {\r
2325 //\r
2326 // If it is Liveness check, there will be no payload load in the encrypt payload.\r
2327 //\r
2328 Status = EFI_SUCCESS;\r
2329 } else {\r
2330 Status = EFI_INVALID_PARAMETER;\r
2331 }\r
2332 }\r
2333\r
2334 //\r
2335 // If the PayloadTotalSize < Header length, return invalid parameter.\r
2336 //\r
2337 RemainBytes = IkePacket->PayloadTotalSize;\r
2338 if (RemainBytes < sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {\r
2339 Status = EFI_INVALID_PARAMETER;\r
2340 goto Exit;\r
2341 }\r
2342\r
2343 //\r
2344 // If the packet is first or second message, store whole message in\r
2345 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload\r
2346 // calculate.\r
2347 //\r
2348 if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {\r
2349 IkeHeader = AllocateZeroPool (sizeof (IKE_HEADER));\r
6b16c9e7
JW
2350 if (IkeHeader == NULL) {\r
2351 Status = EFI_OUT_OF_RESOURCES;\r
2352 goto Exit;\r
2353 }\r
f75a7f56 2354\r
9166f840 2355 CopyMem (IkeHeader, IkePacket->Header, sizeof (IKE_HEADER));\r
2356\r
2357 //\r
2358 // Before store the whole packet, roll back the host order to network order,\r
2359 // since the header order was changed in the IkePacketFromNetbuf.\r
2360 //\r
2361 IkeHdrNetToHost (IkeHeader);\r
2362 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
2363 if (SessionCommon->IsInitiator) {\r
2364 IkeSaSession->RespPacket = AllocateZeroPool (IkePacket->Header->Length);\r
02a758cb 2365 if (IkeSaSession->RespPacket == NULL) {\r
2366 Status = EFI_OUT_OF_RESOURCES;\r
6cf9230f 2367 goto Exit;\r
02a758cb 2368 }\r
9166f840 2369 IkeSaSession->RespPacketSize = IkePacket->Header->Length;\r
2370 CopyMem (IkeSaSession->RespPacket, IkeHeader, sizeof (IKE_HEADER));\r
2371 CopyMem (\r
2372 IkeSaSession->RespPacket + sizeof (IKE_HEADER),\r
2373 IkePacket->PayloadsBuf,\r
2374 IkePacket->Header->Length - sizeof (IKE_HEADER)\r
6cf9230f 2375 );\r
9166f840 2376 } else {\r
2377 IkeSaSession->InitPacket = AllocateZeroPool (IkePacket->Header->Length);\r
02a758cb 2378 if (IkeSaSession->InitPacket == NULL) {\r
2379 Status = EFI_OUT_OF_RESOURCES;\r
6cf9230f 2380 goto Exit;\r
02a758cb 2381 }\r
9166f840 2382 IkeSaSession->InitPacketSize = IkePacket->Header->Length;\r
2383 CopyMem (IkeSaSession->InitPacket, IkeHeader, sizeof (IKE_HEADER));\r
2384 CopyMem (\r
2385 IkeSaSession->InitPacket + sizeof (IKE_HEADER),\r
2386 IkePacket->PayloadsBuf,\r
2387 IkePacket->Header->Length - sizeof (IKE_HEADER)\r
2388 );\r
2389 }\r
2390 }\r
2391\r
2392 //\r
6cf9230f 2393 // Point to the first Payload\r
9166f840 2394 //\r
2395 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePacket->PayloadsBuf;\r
2396 PayloadType = IkePacket->Header->NextPayload;\r
2397\r
2398 //\r
2399 // Parse each payload\r
2400 //\r
2401 while (RemainBytes >= sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {\r
2402 PayloadSize = NTOHS (PayloadHdr->PayloadLength);\r
2403\r
2404 //\r
2405 //Check the size of the payload is correct.\r
2406 //\r
2407 if (RemainBytes < PayloadSize) {\r
2408 Status = EFI_INVALID_PARAMETER;\r
2409 goto Exit;\r
2410 }\r
2411\r
2412 //\r
2413 // At certain states, it should save some datas before decoding.\r
2414 //\r
2415 if (SessionCommon->BeforeDecodePayload != NULL) {\r
2416 SessionCommon->BeforeDecodePayload (\r
2417 (UINT8 *) SessionCommon,\r
2418 (UINT8 *) PayloadHdr,\r
2419 PayloadSize,\r
2420 PayloadType\r
2421 );\r
2422 }\r
2423\r
2424 //\r
2425 // Initial IkePayload\r
2426 //\r
2427 IkePayload = IkePayloadAlloc ();\r
6b16c9e7
JW
2428 if (IkePayload == NULL) {\r
2429 Status = EFI_OUT_OF_RESOURCES;\r
2430 goto Exit;\r
2431 }\r
9166f840 2432\r
2433 IkePayload->PayloadType = PayloadType;\r
2434 IkePayload->PayloadBuf = (UINT8 *) PayloadHdr;\r
2435 IkePayload->PayloadSize = PayloadSize;\r
2436 IkePayload->IsPayloadBufExt = TRUE;\r
2437\r
2438 Status = Ikev2DecodePayload ((UINT8 *) SessionCommon, IkePayload);\r
2439 if (EFI_ERROR (Status)) {\r
2440 goto Exit;\r
2441 }\r
2442\r
2443 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload->PayloadBuf, IkePayload->PayloadSize);\r
2444 //\r
2445 // Add each payload into packet\r
2446 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length\r
2447 // which is before the decoding.\r
2448 //\r
2449 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);\r
2450\r
2451 RemainBytes -= PayloadSize;\r
2452 PayloadType = PayloadHdr->NextPayload;\r
2453 if (PayloadType == IKEV2_PAYLOAD_TYPE_NONE) {\r
2454 break;\r
2455 }\r
2456\r
2457 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) ((UINT8 *) PayloadHdr + PayloadSize);\r
2458 }\r
2459\r
2460 if (PayloadType != IKEV2_PAYLOAD_TYPE_NONE) {\r
2461 Status = EFI_INVALID_PARAMETER;\r
2462 goto Exit;\r
2463 }\r
2464\r
2465Exit:\r
2466 if (EFI_ERROR (Status)) {\r
2467 ClearAllPayloads (IkePacket);\r
2468 }\r
2469\r
2470 if (IkeHeader != NULL) {\r
2471 FreePool (IkeHeader);\r
2472 }\r
2473 return Status;\r
2474}\r
2475\r
2476/**\r
2477 Encode the IKE packet.\r
2478\r
2479 This function puts all Payloads into one payload then encrypt it if needed.\r
2480\r
6cf9230f 2481 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing\r
9166f840 2482 some parameter used during IKE packet encoding.\r
6cf9230f 2483 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,\r
9166f840 2484 and the encoded result as output.\r
2485 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
2486 IKE_CHILD_TYPE are supportted.\r
2487\r
2488 @retval EFI_SUCCESS Encode IKE packet successfully.\r
2489 @retval Otherwise Encode IKE packet failed.\r
2490\r
2491**/\r
2492EFI_STATUS\r
2493Ikev2EncodePacket (\r
2494 IN IKEV2_SESSION_COMMON *SessionCommon,\r
2495 IN OUT IKE_PACKET *IkePacket,\r
2496 IN UINTN IkeType\r
2497 )\r
2498{\r
2499 IKE_PAYLOAD *IkePayload;\r
2500 UINTN PayloadTotalSize;\r
2501 LIST_ENTRY *Entry;\r
2502 EFI_STATUS Status;\r
2503 IKEV2_SA_SESSION *IkeSaSession;\r
2504\r
2505 PayloadTotalSize = 0;\r
2506 //\r
2507 // Encode each payload\r
2508 //\r
2509 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
2510 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
2511 Entry = Entry->ForwardLink;\r
2512 Status = Ikev2EncodePayload ((UINT8 *) SessionCommon, IkePayload);\r
2513 if (EFI_ERROR (Status)) {\r
2514 return Status;\r
2515 }\r
2516\r
2517 if (SessionCommon->AfterEncodePayload != NULL) {\r
2518 //\r
2519 // For certain states, save some payload for further calculation\r
2520 //\r
2521 SessionCommon->AfterEncodePayload (\r
2522 (UINT8 *) SessionCommon,\r
2523 IkePayload->PayloadBuf,\r
2524 IkePayload->PayloadSize,\r
2525 IkePayload->PayloadType\r
2526 );\r
2527 }\r
2528\r
2529 PayloadTotalSize += IkePayload->PayloadSize;\r
2530 }\r
2531 IkePacket->PayloadTotalSize = PayloadTotalSize;\r
2532\r
2533 Status = EFI_SUCCESS;\r
2534 if (SessionCommon->State >= IkeStateAuth) {\r
2535 //\r
2536 // Encrypt all payload and transfer IKE packet header from Host order to Network order.\r
2537 //\r
2538 Status = Ikev2EncryptPacket (SessionCommon, IkePacket);\r
6771c1d6
JW
2539 if (EFI_ERROR (Status)) {\r
2540 return Status;\r
2541 }\r
9166f840 2542 } else {\r
2543 //\r
2544 // Fill in the lenght into IkePacket header and transfer Host order to Network order.\r
2545 //\r
2546 IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);\r
2547 IkeHdrHostToNet (IkePacket->Header);\r
2548 }\r
2549\r
2550 //\r
6cf9230f 2551 // If the packet is first message, store whole message in IkeSa->InitiPacket\r
9166f840 2552 // for following Auth Payload calculation.\r
2553 //\r
2554 if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {\r
2555 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
6cf9230f 2556 if (SessionCommon->IsInitiator) {\r
9166f840 2557 IkeSaSession->InitPacketSize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);\r
2558 IkeSaSession->InitPacket = AllocateZeroPool (IkeSaSession->InitPacketSize);\r
6b16c9e7
JW
2559 if (IkeSaSession->InitPacket == NULL) {\r
2560 return EFI_OUT_OF_RESOURCES;\r
2561 }\r
f75a7f56 2562\r
9166f840 2563 CopyMem (IkeSaSession->InitPacket, IkePacket->Header, sizeof (IKE_HEADER));\r
2564 PayloadTotalSize = 0;\r
2565 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
2566 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
2567 Entry = Entry->ForwardLink;\r
2568 CopyMem (\r
2569 IkeSaSession->InitPacket + sizeof (IKE_HEADER) + PayloadTotalSize,\r
2570 IkePayload->PayloadBuf,\r
2571 IkePayload->PayloadSize\r
2572 );\r
2573 PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;\r
2574 }\r
6cf9230f 2575 } else {\r
9166f840 2576 IkeSaSession->RespPacketSize = IkePacket->PayloadTotalSize + sizeof(IKE_HEADER);\r
2577 IkeSaSession->RespPacket = AllocateZeroPool (IkeSaSession->RespPacketSize);\r
6b16c9e7
JW
2578 if (IkeSaSession->RespPacket == NULL) {\r
2579 return EFI_OUT_OF_RESOURCES;\r
2580 }\r
f75a7f56 2581\r
9166f840 2582 CopyMem (IkeSaSession->RespPacket, IkePacket->Header, sizeof (IKE_HEADER));\r
2583 PayloadTotalSize = 0;\r
2584 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {\r
2585 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
2586 Entry = Entry->ForwardLink;\r
2587\r
2588 CopyMem (\r
2589 IkeSaSession->RespPacket + sizeof (IKE_HEADER) + PayloadTotalSize,\r
2590 IkePayload->PayloadBuf,\r
2591 IkePayload->PayloadSize\r
2592 );\r
2593 PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;\r
2594 }\r
2595 }\r
2596 }\r
2597\r
2598 return Status;\r
2599}\r
2600\r
2601/**\r
2602 Decrypt IKE packet.\r
2603\r
2604 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.\r
2605\r
6cf9230f 2606 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing\r
9166f840 2607 some parameter used during decrypting.\r
6cf9230f 2608 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,\r
9166f840 2609 and the decrypted result as output.\r
2610 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and\r
2611 IKE_CHILD_TYPE are supportted.\r
2612\r
2613 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the\r
2614 IKE packet length is not aligned with Algorithm Block Size\r
2615 @retval EFI_SUCCESS Decrypt IKE packet successfully.\r
6cf9230f 2616\r
9166f840 2617**/\r
2618EFI_STATUS\r
2619Ikev2DecryptPacket (\r
2620 IN IKEV2_SESSION_COMMON *SessionCommon,\r
2621 IN OUT IKE_PACKET *IkePacket,\r
2622 IN OUT UINTN IkeType\r
2623 )\r
2624{\r
2625 UINT8 CryptBlockSize; // Encrypt Block Size\r
6cf9230f 2626 UINTN DecryptedSize; // Encrypted IKE Payload Size\r
9166f840 2627 UINT8 *DecryptedBuf; // Encrypted IKE Payload buffer\r
2628 UINTN IntegritySize;\r
2629 UINT8 *IntegrityBuffer;\r
6cf9230f 2630 UINTN IvSize; // Iv Size\r
2631 UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth\r
9166f840 2632 UINT8 *CheckSumData; // Check Sum data\r
2633 IKEV2_SA_SESSION *IkeSaSession;\r
2634 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
2635 EFI_STATUS Status;\r
2636 UINT8 PadLen;\r
9166f840 2637 HASH_DATA_FRAGMENT Fragments[1];\r
2638\r
2639 IvSize = 0;\r
2640 IkeSaSession = NULL;\r
2641 CryptBlockSize = 0;\r
2642 CheckSumSize = 0;\r
9166f840 2643\r
2644 //\r
2645 // Check if the first payload is the Encrypted payload\r
2646 //\r
2647 if (IkePacket->Header->NextPayload != IKEV2_PAYLOAD_TYPE_ENCRYPT) {\r
2648 return EFI_ACCESS_DENIED;\r
2649 }\r
2650 CheckSumData = NULL;\r
2651 DecryptedBuf = NULL;\r
2652 IntegrityBuffer = NULL;\r
2653\r
2654 //\r
2655 // Get the Block Size\r
2656 //\r
2657 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
6cf9230f 2658\r
9166f840 2659 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);\r
e8837edd 2660\r
9166f840 2661 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);\r
2662 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
2663\r
2664 } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {\r
2665\r
2666 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
2667 IkeSaSession = ChildSaSession->IkeSaSession;\r
2668 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);\r
9166f840 2669 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);\r
2670 } else {\r
2671 //\r
2672 // The type of SA Session would either be IkeSa or ChildSa.\r
2673 //\r
2674 return EFI_INVALID_PARAMETER;\r
2675 }\r
2676\r
2677 CheckSumData = AllocateZeroPool (CheckSumSize);\r
6b16c9e7
JW
2678 if (CheckSumData == NULL) {\r
2679 Status = EFI_OUT_OF_RESOURCES;\r
2680 goto ON_EXIT;\r
2681 }\r
9166f840 2682\r
2683 //\r
2684 // Fill in the Integrity buffer\r
2685 //\r
2686 IntegritySize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);\r
2687 IntegrityBuffer = AllocateZeroPool (IntegritySize);\r
6b16c9e7
JW
2688 if (IntegrityBuffer == NULL) {\r
2689 Status = EFI_OUT_OF_RESOURCES;\r
2690 goto ON_EXIT;\r
2691 }\r
f75a7f56 2692\r
9166f840 2693 CopyMem (IntegrityBuffer, IkePacket->Header, sizeof(IKE_HEADER));\r
2694 CopyMem (IntegrityBuffer + sizeof (IKE_HEADER), IkePacket->PayloadsBuf, IkePacket->PayloadTotalSize);\r
2695\r
2696 //\r
6cf9230f 2697 // Change Host order to Network order, since the header order was changed\r
9166f840 2698 // in the IkePacketFromNetbuf.\r
2699 //\r
2700 IkeHdrHostToNet ((IKE_HEADER *)IntegrityBuffer);\r
2701\r
2702 //\r
2703 // Calculate the Integrity CheckSum Data\r
2704 //\r
2705 Fragments[0].Data = IntegrityBuffer;\r
2706 Fragments[0].DataSize = IntegritySize - CheckSumSize;\r
2707\r
2708 if (SessionCommon->IsInitiator) {\r
2709 Status = IpSecCryptoIoHmac (\r
2710 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
2711 IkeSaSession->IkeKeys->SkArKey,\r
2712 IkeSaSession->IkeKeys->SkArKeySize,\r
2713 (HASH_DATA_FRAGMENT *) Fragments,\r
2714 1,\r
2715 CheckSumData,\r
2716 CheckSumSize\r
2717 );\r
2718 } else {\r
2719 Status = IpSecCryptoIoHmac (\r
2720 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
2721 IkeSaSession->IkeKeys->SkAiKey,\r
2722 IkeSaSession->IkeKeys->SkAiKeySize,\r
2723 (HASH_DATA_FRAGMENT *) Fragments,\r
2724 1,\r
2725 CheckSumData,\r
2726 CheckSumSize\r
2727 );\r
2728 }\r
2729\r
2730 if (EFI_ERROR (Status)) {\r
2731 goto ON_EXIT;\r
2732 }\r
2733 //\r
2734 // Compare the Integrity CheckSum Data with the one in IkePacket\r
2735 //\r
2736 if (CompareMem (\r
2737 IkePacket->PayloadsBuf + IkePacket->PayloadTotalSize - CheckSumSize,\r
2738 CheckSumData,\r
2739 CheckSumSize\r
2740 ) != 0) {\r
2741 DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));\r
2742 Status = EFI_ACCESS_DENIED;\r
2743 goto ON_EXIT;\r
2744 }\r
6cf9230f 2745\r
9166f840 2746 IvSize = CryptBlockSize;\r
6cf9230f 2747\r
9166f840 2748 //\r
2749 // Decrypt the payload with the key.\r
2750 //\r
2751 DecryptedSize = IkePacket->PayloadTotalSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER) - IvSize - CheckSumSize;\r
2752 DecryptedBuf = AllocateZeroPool (DecryptedSize);\r
6b16c9e7
JW
2753 if (DecryptedBuf == NULL) {\r
2754 Status = EFI_OUT_OF_RESOURCES;\r
2755 goto ON_EXIT;\r
2756 }\r
9166f840 2757\r
2758 CopyMem (\r
2759 DecryptedBuf,\r
2760 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER) + IvSize,\r
2761 DecryptedSize\r
2762 );\r
2763\r
2764 if (SessionCommon->IsInitiator) {\r
2765 Status = IpSecCryptoIoDecrypt (\r
2766 (UINT8) SessionCommon->SaParams->EncAlgId,\r
2767 IkeSaSession->IkeKeys->SkErKey,\r
2768 IkeSaSession->IkeKeys->SkErKeySize << 3,\r
2769 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),\r
2770 DecryptedBuf,\r
2771 DecryptedSize,\r
2772 DecryptedBuf\r
2773 );\r
2774 } else {\r
2775 Status = IpSecCryptoIoDecrypt (\r
2776 (UINT8) SessionCommon->SaParams->EncAlgId,\r
2777 IkeSaSession->IkeKeys->SkEiKey,\r
2778 IkeSaSession->IkeKeys->SkEiKeySize << 3,\r
2779 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),\r
2780 DecryptedBuf,\r
2781 DecryptedSize,\r
2782 DecryptedBuf\r
2783 );\r
2784 }\r
2785\r
2786 if (EFI_ERROR (Status)) {\r
2787 DEBUG ((DEBUG_ERROR, "Error decrypt buffer with %r\n", Status));\r
2788 goto ON_EXIT;\r
2789 }\r
2790\r
2791 //\r
2792 // Get the Padding length\r
2793 //\r
2794 //\r
2795 PadLen = (UINT8) (*(DecryptedBuf + DecryptedSize - sizeof (IKEV2_PAD_LEN)));\r
2796\r
2797 //\r
2798 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload\r
2799 //\r
2800 IkePacket->Header->NextPayload = ((IKEV2_ENCRYPTED *) IkePacket->PayloadsBuf)->Header.NextPayload;\r
6cf9230f 2801\r
9166f840 2802 //\r
2803 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.\r
2804 //\r
2805 FreePool (IkePacket->PayloadsBuf);\r
2806 IkePacket->PayloadsBuf = DecryptedBuf;\r
2807 IkePacket->PayloadTotalSize = DecryptedSize - PadLen;\r
2808\r
2809 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf, DecryptedSize);\r
6cf9230f 2810\r
9166f840 2811\r
2812ON_EXIT:\r
2813 if (CheckSumData != NULL) {\r
2814 FreePool (CheckSumData);\r
2815 }\r
2816\r
2817 if (EFI_ERROR (Status) && DecryptedBuf != NULL) {\r
2818 FreePool (DecryptedBuf);\r
2819 }\r
2820\r
2821 if (IntegrityBuffer != NULL) {\r
2822 FreePool (IntegrityBuffer);\r
2823 }\r
6cf9230f 2824\r
9166f840 2825 return Status;\r
2826}\r
2827\r
2828/**\r
2829 Encrypt IKE packet.\r
2830\r
2831 This function encrypt IKE packet before sending it. The Encrypted IKE packet\r
2832 is put in to IKEV2 Encrypted Payload.\r
6cf9230f 2833\r
9166f840 2834 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.\r
2835 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.\r
2836\r
2837 @retval EFI_SUCCESS Operation is successful.\r
2838 @retval Others Operation is failed.\r
2839\r
2840**/\r
2841EFI_STATUS\r
2842Ikev2EncryptPacket (\r
2843 IN IKEV2_SESSION_COMMON *SessionCommon,\r
2844 IN OUT IKE_PACKET *IkePacket\r
2845 )\r
2846{\r
2847 UINT8 CryptBlockSize; // Encrypt Block Size\r
2848 UINT8 CryptBlockSizeMask; // Block Mask\r
6cf9230f 2849 UINTN EncryptedSize; // Encrypted IKE Payload Size\r
9166f840 2850 UINT8 *EncryptedBuf; // Encrypted IKE Payload buffer\r
2851 UINT8 *EncryptPayloadBuf; // Contain whole Encrypted Payload\r
2852 UINTN EncryptPayloadSize; // Total size of the Encrypted payload\r
6cf9230f 2853 UINT8 *IntegrityBuf; // Buffer to be intergity\r
9166f840 2854 UINT8 *IvBuffer; // Initialization Vector\r
6cf9230f 2855 UINT8 IvSize; // Iv Size\r
2856 UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth\r
9166f840 2857 UINT8 *CheckSumData; // Check Sum data\r
2858 UINTN Index;\r
2859 IKE_PAYLOAD *EncryptPayload;\r
2860 IKEV2_SA_SESSION *IkeSaSession;\r
2861 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
2862 EFI_STATUS Status;\r
2863 LIST_ENTRY *Entry;\r
2864 IKE_PAYLOAD *IkePayload;\r
9166f840 2865 HASH_DATA_FRAGMENT Fragments[1];\r
2866\r
02a758cb 2867 Status = EFI_SUCCESS;\r
2868\r
9166f840 2869 //\r
2870 // Initial all buffers to NULL.\r
2871 //\r
2872 EncryptedBuf = NULL;\r
2873 EncryptPayloadBuf = NULL;\r
2874 IvBuffer = NULL;\r
2875 CheckSumData = NULL;\r
2876 IkeSaSession = NULL;\r
2877 CryptBlockSize = 0;\r
2878 CheckSumSize = 0;\r
9166f840 2879 IntegrityBuf = NULL;\r
2880 //\r
2881 // Get the Block Size\r
2882 //\r
2883 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
2884\r
2885 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);\r
9166f840 2886 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);\r
2887 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
2888\r
2889 } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {\r
2890\r
2891 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
2892 IkeSaSession = ChildSaSession->IkeSaSession;\r
2893 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);\r
9166f840 2894 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);\r
2895 }\r
6cf9230f 2896\r
9166f840 2897 //\r
2898 // Calcualte the EncryptPayloadSize and the PAD length\r
2899 //\r
2900 CryptBlockSizeMask = (UINT8) (CryptBlockSize - 1);\r
2901 EncryptedSize = (IkePacket->PayloadTotalSize + sizeof (IKEV2_PAD_LEN) + CryptBlockSizeMask) & ~CryptBlockSizeMask;\r
2902 EncryptedBuf = (UINT8 *) AllocateZeroPool (EncryptedSize);\r
6b16c9e7
JW
2903 if (EncryptedBuf == NULL) {\r
2904 Status = EFI_OUT_OF_RESOURCES;\r
2905 goto ON_EXIT;\r
2906 }\r
f75a7f56 2907\r
9166f840 2908 //\r
2909 // Copy all payload into EncryptedIkePayload\r
2910 //\r
2911 Index = 0;\r
2912 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {\r
2913 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
2914\r
2915 CopyMem (EncryptedBuf + Index, IkePayload->PayloadBuf, IkePayload->PayloadSize);\r
2916 Index += IkePayload->PayloadSize;\r
2917\r
2918 };\r
2919\r
2920 //\r
2921 // Fill in the Pading Length\r
2922 //\r
2923 *(EncryptedBuf + EncryptedSize - 1) = (UINT8)(EncryptedSize - IkePacket->PayloadTotalSize - 1);\r
2924\r
2925 //\r
2926 // The IV size is equal with block size\r
2927 //\r
2928 IvSize = CryptBlockSize;\r
2929 IvBuffer = (UINT8 *) AllocateZeroPool (IvSize);\r
02a758cb 2930 if (IvBuffer == NULL) {\r
2931 Status = EFI_OUT_OF_RESOURCES;\r
2932 goto ON_EXIT;\r
2933 }\r
9166f840 2934\r
2935 //\r
2936 // Generate IV\r
2937 //\r
2938 IkeGenerateIv (IvBuffer, IvSize);\r
2939\r
2940 //\r
2941 // Encrypt payload buf\r
2942 //\r
2943 if (SessionCommon->IsInitiator) {\r
2944 Status = IpSecCryptoIoEncrypt (\r
2945 (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,\r
2946 IkeSaSession->IkeKeys->SkEiKey,\r
2947 IkeSaSession->IkeKeys->SkEiKeySize << 3,\r
2948 IvBuffer,\r
2949 EncryptedBuf,\r
2950 EncryptedSize,\r
2951 EncryptedBuf\r
2952 );\r
2953 } else {\r
2954 Status = IpSecCryptoIoEncrypt (\r
2955 (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,\r
2956 IkeSaSession->IkeKeys->SkErKey,\r
2957 IkeSaSession->IkeKeys->SkErKeySize << 3,\r
2958 IvBuffer,\r
2959 EncryptedBuf,\r
2960 EncryptedSize,\r
2961 EncryptedBuf\r
2962 );\r
2963 }\r
2964 if (EFI_ERROR (Status)) {\r
2965 goto ON_EXIT;\r
2966 }\r
2967\r
2968 //\r
2969 // Allocate the buffer for the whole IKE payload (Encrypted Payload).\r
2970 //\r
2971 EncryptPayloadSize = sizeof(IKEV2_ENCRYPTED) + IvSize + EncryptedSize + CheckSumSize;\r
2972 EncryptPayloadBuf = AllocateZeroPool (EncryptPayloadSize);\r
6b16c9e7
JW
2973 if (EncryptPayloadBuf == NULL) {\r
2974 Status = EFI_OUT_OF_RESOURCES;\r
2975 goto ON_EXIT;\r
2976 }\r
9166f840 2977\r
2978 //\r
2979 // Fill in Header of Encrypted Payload\r
2980 //\r
2981 ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.NextPayload = IkePacket->Header->NextPayload;\r
2982 ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.PayloadLength = HTONS ((UINT16)EncryptPayloadSize);\r
2983\r
2984 //\r
2985 // Fill in Iv\r
2986 //\r
2987 CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED), IvBuffer, IvSize);\r
2988\r
2989 //\r
2990 // Fill in encrypted data\r
2991 //\r
2992 CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED) + IvSize, EncryptedBuf, EncryptedSize);\r
2993\r
2994 //\r
2995 // Fill in the IKE Packet header\r
6cf9230f 2996 //\r
9166f840 2997 IkePacket->PayloadTotalSize = EncryptPayloadSize;\r
2998 IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);\r
2999 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_ENCRYPT;\r
6cf9230f 3000\r
9166f840 3001 IntegrityBuf = AllocateZeroPool (IkePacket->Header->Length);\r
02a758cb 3002 if (IntegrityBuf == NULL) {\r
3003 Status = EFI_OUT_OF_RESOURCES;\r
3004 goto ON_EXIT;\r
3005 }\r
9166f840 3006 IkeHdrHostToNet (IkePacket->Header);\r
3007\r
3008 CopyMem (IntegrityBuf, IkePacket->Header, sizeof (IKE_HEADER));\r
3009 CopyMem (IntegrityBuf + sizeof (IKE_HEADER), EncryptPayloadBuf, EncryptPayloadSize);\r
3010\r
3011 //\r
3012 // Calcualte Integrity CheckSum\r
3013 //\r
3014 Fragments[0].Data = IntegrityBuf;\r
3015 Fragments[0].DataSize = EncryptPayloadSize + sizeof (IKE_HEADER) - CheckSumSize;\r
3016\r
3017 CheckSumData = AllocateZeroPool (CheckSumSize);\r
02a758cb 3018 if (CheckSumData == NULL) {\r
3019 Status = EFI_OUT_OF_RESOURCES;\r
3020 goto ON_EXIT;\r
3021 }\r
9166f840 3022 if (SessionCommon->IsInitiator) {\r
3023\r
3024 IpSecCryptoIoHmac (\r
3025 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
3026 IkeSaSession->IkeKeys->SkAiKey,\r
3027 IkeSaSession->IkeKeys->SkAiKeySize,\r
3028 (HASH_DATA_FRAGMENT *) Fragments,\r
3029 1,\r
3030 CheckSumData,\r
3031 CheckSumSize\r
3032 );\r
3033 } else {\r
3034\r
3035 IpSecCryptoIoHmac (\r
3036 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,\r
3037 IkeSaSession->IkeKeys->SkArKey,\r
3038 IkeSaSession->IkeKeys->SkArKeySize,\r
6cf9230f 3039 (HASH_DATA_FRAGMENT *) Fragments,\r
9166f840 3040 1,\r
3041 CheckSumData,\r
3042 CheckSumSize\r
3043 );\r
3044 }\r
3045\r
3046 //\r
3047 // Copy CheckSum into Encrypted Payload\r
3048 //\r
3049 CopyMem (EncryptPayloadBuf + EncryptPayloadSize - CheckSumSize, CheckSumData, CheckSumSize);\r
3050\r
3051 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf, EncryptPayloadSize);\r
3052 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData, CheckSumSize);\r
3053\r
3054 //\r
3055 // Clean all payload under IkePacket->PayloadList.\r
3056 //\r
3057 ClearAllPayloads (IkePacket);\r
3058\r
3059 //\r
3060 // Create Encrypted Payload and add into IkePacket->PayloadList\r
3061 //\r
3062 EncryptPayload = IkePayloadAlloc ();\r
6b16c9e7
JW
3063 if (EncryptPayload == NULL) {\r
3064 Status = EFI_OUT_OF_RESOURCES;\r
3065 goto ON_EXIT;\r
3066 }\r
9166f840 3067\r
3068 //\r
3069 // Fill the encrypted payload into the IKE_PAYLOAD structure.\r
3070 //\r
3071 EncryptPayload->PayloadBuf = EncryptPayloadBuf;\r
3072 EncryptPayload->PayloadSize = EncryptPayloadSize;\r
3073 EncryptPayload->PayloadType = IKEV2_PAYLOAD_TYPE_ENCRYPT;\r
6cf9230f 3074\r
9166f840 3075 IKE_PACKET_APPEND_PAYLOAD (IkePacket, EncryptPayload);\r
3076\r
3077ON_EXIT:\r
3078 if (EncryptedBuf != NULL) {\r
3079 FreePool (EncryptedBuf);\r
3080 }\r
3081\r
3082 if (EFI_ERROR (Status) && EncryptPayloadBuf != NULL) {\r
3083 FreePool (EncryptPayloadBuf);\r
3084 }\r
3085\r
3086 if (IvBuffer != NULL) {\r
3087 FreePool (IvBuffer);\r
3088 }\r
3089\r
3090 if (CheckSumData != NULL) {\r
3091 FreePool (CheckSumData);\r
3092 }\r
3093\r
3094 if (IntegrityBuf != NULL) {\r
3095 FreePool (IntegrityBuf);\r
3096 }\r
3097\r
3098 return Status;\r
3099}\r
3100\r
9166f840 3101\r
3102/**\r
3103\r
3104 The notification function. It will be called when the related UDP_TX_TOKEN's event\r
3105 is signaled.\r
3106\r
6cf9230f 3107 This function frees the Net Buffer pointed to the input Packet.\r
3108\r
9166f840 3109 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.\r
3110 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local\r
3111 address information.\r
3112 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.\r
3113 @param[in] Context Pointer to data passed from the caller.\r
3114\r
3115**/\r
3116VOID\r
1d8fa5e9 3117EFIAPI\r
9166f840 3118Ikev2OnPacketSent (\r
3119 IN NET_BUF *Packet,\r
3120 IN UDP_END_POINT *EndPoint,\r
3121 IN EFI_STATUS IoStatus,\r
3122 IN VOID *Context\r
3123 )\r
3124{\r
3125 IKE_PACKET *IkePacket;\r
3126 IKEV2_SA_SESSION *IkeSaSession;\r
3127 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
3128 UINT8 Value;\r
3129 IPSEC_PRIVATE_DATA *Private;\r
3130 EFI_STATUS Status;\r
3131\r
3132 IkePacket = (IKE_PACKET *) Context;\r
3133 Private = NULL;\r
6cf9230f 3134\r
9166f840 3135 if (EFI_ERROR (IoStatus)) {\r
3136 DEBUG ((DEBUG_ERROR, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus));\r
3137 }\r
6cf9230f 3138\r
9166f840 3139 NetbufFree (Packet);\r
3140\r
3141 if (IkePacket->IsDeleteInfo) {\r
3142 //\r
3143 // For each RemotePeerIP, there are only one IKESA.\r
3144 //\r
3145 IkeSaSession = Ikev2SaSessionLookup (\r
3146 &IkePacket->Private->Ikev2EstablishedList,\r
3147 &IkePacket->RemotePeerIp\r
3148 );\r
3149 if (IkeSaSession == NULL) {\r
3150 IkePacketFree (IkePacket);\r
3151 return;\r
3152 }\r
1d8fa5e9 3153\r
9166f840 3154 Private = IkePacket->Private;\r
3155 if (IkePacket->Spi != 0 ) {\r
3156 //\r
3157 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.\r
6cf9230f 3158 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,\r
9166f840 3159 // remove it from delete list and delete it direclty.\r
3160 //\r
3161 ChildSaSession = Ikev2ChildSaSessionLookupBySpi (\r
3162 &IkeSaSession->ChildSaEstablishSessionList,\r
3163 IkePacket->Spi\r
3164 );\r
3165 if (ChildSaSession != NULL) {\r
3166 Ikev2ChildSaSessionRemove (\r
3167 &IkeSaSession->DeleteSaList,\r
3168 ChildSaSession->LocalPeerSpi,\r
3169 IKEV2_DELET_CHILDSA_LIST\r
3170 );\r
3171\r
3172 //\r
3173 // Delete the Child SA.\r
3174 //\r
3175 Ikev2ChildSaSilentDelete (\r
3176 IkeSaSession,\r
3177 IkePacket->Spi\r
3178 );\r
3179 }\r
3180\r
3181 } else {\r
3182 //\r
3183 // Delete the IKE SA\r
3184 //\r
3185 DEBUG (\r
3186 (DEBUG_INFO,\r
3187 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",\r
3188 IkeSaSession->InitiatorCookie,\r
3189 IkeSaSession->ResponderCookie)\r
3190 );\r
1d8fa5e9 3191\r
9166f840 3192 RemoveEntryList (&IkeSaSession->BySessionTable);\r
3193 Ikev2SaSessionFree (IkeSaSession);\r
3194 }\r
3195 }\r
3196 IkePacketFree (IkePacket);\r
3197\r
3198 //\r
6cf9230f 3199 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status\r
9166f840 3200 // should be changed.\r
3201 //\r
3202 if (Private != NULL && Private->IsIPsecDisabling) {\r
1d8fa5e9 3203 //\r
3204 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in\r
3205 // IPsec status variable.\r
3206 //\r
9166f840 3207 if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {\r
1d8fa5e9 3208 Value = IPSEC_STATUS_DISABLED;\r
3209 Status = gRT->SetVariable (\r
3210 IPSECCONFIG_STATUS_NAME,\r
3211 &gEfiIpSecConfigProtocolGuid,\r
3212 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
3213 sizeof (Value),\r
3214 &Value\r
3215 );\r
3216 if (!EFI_ERROR (Status)) {\r
3217 //\r
3218 // Set the DisabledFlag in Private data.\r
3219 //\r
3220 Private->IpSec.DisabledFlag = TRUE;\r
3221 Private->IsIPsecDisabling = FALSE;\r
3222 }\r
3223 }\r
9166f840 3224 }\r
3225}\r
3226\r
3227/**\r
3228 Send out IKEV2 packet.\r
3229\r
3230 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.\r
3231 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.\r
3232 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.\r
6cf9230f 3233 @param[in] IkeType The type of IKE to point what's kind of the IKE\r
3234 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE\r
9166f840 3235 and IKE_CHILD_TYPE are supportted.\r
3236\r
3237 @retval EFI_SUCCESS The operation complete successfully.\r
3238 @retval Otherwise The operation is failed.\r
3239\r
3240**/\r
3241EFI_STATUS\r
3242Ikev2SendIkePacket (\r
3243 IN IKE_UDP_SERVICE *IkeUdpService,\r
3244 IN UINT8 *SessionCommon,\r
3245 IN IKE_PACKET *IkePacket,\r
3246 IN UINTN IkeType\r
3247 )\r
3248{\r
3249 EFI_STATUS Status;\r
3250 NET_BUF *IkePacketNetbuf;\r
3251 UDP_END_POINT EndPoint;\r
3252 IKEV2_SESSION_COMMON *Common;\r
3253\r
3254 Common = (IKEV2_SESSION_COMMON *) SessionCommon;\r
6cf9230f 3255\r
9166f840 3256 //\r
3257 // Set the resend interval\r
3258 //\r
3259 if (Common->TimeoutInterval == 0) {\r
3260 Common->TimeoutInterval = IKE_DEFAULT_TIMEOUT_INTERVAL;\r
3261 }\r
3262\r
3263 //\r
3264 // Retransfer the packet if it is initial packet.\r
3265 //\r
3266 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {\r
3267 //\r
3268 // Set timer for next retry, this will cancel previous timer\r
3269 //\r
3270 Status = gBS->SetTimer (\r
3271 Common->TimeoutEvent,\r
3272 TimerRelative,\r
3273 MultU64x32 (Common->TimeoutInterval, 10000) // ms->100ns\r
3274 );\r
3275 if (EFI_ERROR (Status)) {\r
3276 return Status;\r
3277 }\r
3278 }\r
3279\r
3280 IKE_PACKET_REF (IkePacket);\r
3281 //\r
6cf9230f 3282 // If the last sent packet is same with this round packet, the packet is resent packet.\r
9166f840 3283 //\r
3284 if (IkePacket != Common->LastSentPacket && Common->LastSentPacket != NULL) {\r
3285 IkePacketFree (Common->LastSentPacket);\r
3286 }\r
3287\r
3288 Common->LastSentPacket = IkePacket;\r
3289\r
3290 //\r
3291 // Transform IkePacke to NetBuf\r
3292 //\r
3293 IkePacketNetbuf = IkeNetbufFromPacket ((UINT8 *) SessionCommon, IkePacket, IkeType);\r
6b16c9e7
JW
3294 if (IkePacketNetbuf == NULL) {\r
3295 return EFI_OUT_OF_RESOURCES;\r
3296 }\r
9166f840 3297\r
3298 ZeroMem (&EndPoint, sizeof (UDP_END_POINT));\r
3299 EndPoint.RemotePort = IKE_DEFAULT_PORT;\r
3300 CopyMem (&IkePacket->RemotePeerIp, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
3301 CopyMem (&EndPoint.RemoteAddr, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
3302 CopyMem (&EndPoint.LocalAddr, &Common->LocalPeerIp, sizeof (EFI_IP_ADDRESS));\r
3303\r
3304 IPSEC_DUMP_PACKET (IkePacket, EfiIPsecOutBound, IkeUdpService->IpVersion);\r
3305\r
3306 if (IkeUdpService->IpVersion == IP_VERSION_4) {\r
3307 EndPoint.RemoteAddr.Addr[0] = HTONL (EndPoint.RemoteAddr.Addr[0]);\r
3308 EndPoint.LocalAddr.Addr[0] = HTONL (EndPoint.LocalAddr.Addr[0]);\r
3309 }\r
3310\r
3311 //\r
3312 // Call UDPIO to send out the IKE packet.\r
3313 //\r
3314 Status = UdpIoSendDatagram (\r
3315 IkeUdpService->Output,\r
3316 IkePacketNetbuf,\r
3317 &EndPoint,\r
3318 NULL,\r
3319 Ikev2OnPacketSent,\r
3320 (VOID*)IkePacket\r
3321 );\r
3322\r
3323 if (EFI_ERROR (Status)) {\r
3324 DEBUG ((DEBUG_ERROR, "Error send packet with %r\n", Status));\r
3325 }\r
3326\r
3327 return Status;\r
3328}\r
3329\r