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