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