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