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