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