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