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