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