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