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