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