]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/Ikev2/Utility.c
Refine code to make it more safely.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Utility.c
1 /** @file
2 The Common operations used by IKE Exchange Process.
3
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Utility.h"
17 #include "IpSecDebug.h"
18 #include "IkeService.h"
19 #include "IpSecConfigImpl.h"
20
21 UINT16 mIkev2EncryptAlgorithmList[IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM] = {
22 IKEV2_TRANSFORM_ID_ENCR_3DES,
23 IKEV2_TRANSFORM_ID_ENCR_AES_CBC,
24 };
25
26 UINT16 mIkev2PrfAlgorithmList[IKEV2_SUPPORT_PRF_ALGORITHM_NUM] = {
27 IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1,
28 };
29
30 UINT16 mIkev2DhGroupAlgorithmList[IKEV2_SUPPORT_DH_ALGORITHM_NUM] = {
31 IKEV2_TRANSFORM_ID_DH_1024MODP,
32 IKEV2_TRANSFORM_ID_DH_2048MODP,
33 };
34
35 UINT16 mIkev2AuthAlgorithmList[IKEV2_SUPPORT_AUTH_ALGORITHM_NUM] = {
36 IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96,
37 };
38
39 /**
40 Allocate buffer for IKEV2_SA_SESSION and initialize it.
41
42 @param[in] Private Pointer to IPSEC_PRIVATE_DATA.
43 @param[in] UdpService Pointer to IKE_UDP_SERVICE related to this IKE SA Session.
44
45 @return Pointer to IKEV2_SA_SESSION or NULL.
46
47 **/
48 IKEV2_SA_SESSION *
49 Ikev2SaSessionAlloc (
50 IN IPSEC_PRIVATE_DATA *Private,
51 IN IKE_UDP_SERVICE *UdpService
52 )
53 {
54 EFI_STATUS Status;
55 IKEV2_SESSION_COMMON *SessionCommon;
56 IKEV2_SA_SESSION *IkeSaSession;
57
58 IkeSaSession = AllocateZeroPool (sizeof (IKEV2_SA_SESSION));
59 ASSERT (IkeSaSession != NULL);
60
61 //
62 // Initialize the fields of IkeSaSession and its SessionCommon.
63 //
64 IkeSaSession->NCookie = NULL;
65 IkeSaSession->Signature = IKEV2_SA_SESSION_SIGNATURE;
66 IkeSaSession->InitiatorCookie = IkeGenerateCookie ();
67 IkeSaSession->ResponderCookie = 0;
68 //
69 // BUGBUG: Message ID starts from 2 is to match the OpenSwan requirement, but it
70 // might not match the IPv6 Logo. In its test specification, it mentions that
71 // the Message ID should start from zero after the IKE_SA_INIT exchange.
72 //
73 IkeSaSession->MessageId = 2;
74 SessionCommon = &IkeSaSession->SessionCommon;
75 SessionCommon->UdpService = UdpService;
76 SessionCommon->Private = Private;
77 SessionCommon->IkeSessionType = IkeSessionTypeIkeSa;
78 SessionCommon->IkeVer = 2;
79 SessionCommon->AfterEncodePayload = NULL;
80 SessionCommon->BeforeDecodePayload = NULL;
81
82 //
83 // Create a resend notfiy event for retry.
84 //
85 Status = gBS->CreateEvent (
86 EVT_TIMER | EVT_NOTIFY_SIGNAL,
87 TPL_CALLBACK,
88 Ikev2ResendNotify,
89 SessionCommon,
90 &SessionCommon->TimeoutEvent
91 );
92
93 if (EFI_ERROR (Status)) {
94 FreePool (IkeSaSession);
95 return NULL;
96 }
97
98 //
99 // Initialize the lists in IkeSaSession.
100 //
101 InitializeListHead (&IkeSaSession->ChildSaSessionList);
102 InitializeListHead (&IkeSaSession->ChildSaEstablishSessionList);
103 InitializeListHead (&IkeSaSession->InfoMIDList);
104 InitializeListHead (&IkeSaSession->DeleteSaList);
105
106 return IkeSaSession;
107 }
108
109 /**
110 Register the established IKEv2 SA into Private->Ikev2EstablishedList. If there is
111 IKEV2_SA_SESSION with same remote peer IP, remove the old one then register the
112 new one.
113
114 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be registered.
115 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
116
117 **/
118 VOID
119 Ikev2SaSessionReg (
120 IN IKEV2_SA_SESSION *IkeSaSession,
121 IN IPSEC_PRIVATE_DATA *Private
122 )
123 {
124 IKEV2_SESSION_COMMON *SessionCommon;
125 IKEV2_SA_SESSION *OldIkeSaSession;
126 EFI_STATUS Status;
127 UINT64 Lifetime;
128
129 //
130 // Keep IKE SA exclusive to remote ip address.
131 //
132 SessionCommon = &IkeSaSession->SessionCommon;
133 OldIkeSaSession = Ikev2SaSessionRemove (&Private->Ikev2EstablishedList, &SessionCommon->RemotePeerIp);
134 if (OldIkeSaSession != NULL) {
135 //
136 // TODO: It should delete all child SAs if rekey the IKE SA.
137 //
138 Ikev2SaSessionFree (OldIkeSaSession);
139 }
140
141 //
142 // Cleanup the fields of SessionCommon for processing.
143 //
144 Ikev2SessionCommonRefresh (SessionCommon);
145
146 //
147 // Insert the ready IKE SA session into established list.
148 //
149 Ikev2SaSessionInsert (&Private->Ikev2EstablishedList, IkeSaSession, &SessionCommon->RemotePeerIp);
150
151 //
152 // Create a notfiy event for the IKE SA life time counting.
153 //
154 Status = gBS->CreateEvent (
155 EVT_TIMER | EVT_NOTIFY_SIGNAL,
156 TPL_CALLBACK,
157 Ikev2LifetimeNotify,
158 SessionCommon,
159 &SessionCommon->TimeoutEvent
160 );
161 if (EFI_ERROR(Status)){
162 //
163 // If TimerEvent creation failed, the SA will be alive untill user disable it or
164 // receiving a Delete Payload from peer.
165 //
166 return;
167 }
168
169 //
170 // Start to count the lifetime of the IKE SA.
171 //
172 if (IkeSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime == 0) {
173 Lifetime = IKE_SA_DEFAULT_LIFETIME;
174 } else {
175 Lifetime = IkeSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime;
176 }
177
178 Status = gBS->SetTimer (
179 SessionCommon->TimeoutEvent,
180 TimerRelative,
181 MultU64x32(Lifetime, 10000000) // ms->100ns
182 );
183 if (EFI_ERROR(Status)){
184 //
185 // If SetTimer failed, the SA will be alive untill user disable it or
186 // receiving a Delete Payload from peer.
187 //
188 return ;
189 }
190
191 DEBUG ((
192 DEBUG_INFO,
193 "\n------IkeSa established and start to count down %d seconds lifetime\n",
194 Lifetime
195 ));
196
197 return ;
198 }
199
200 /**
201 Find a IKEV2_SA_SESSION by the remote peer IP.
202
203 @param[in] SaSessionList SaSession List to be searched.
204 @param[in] RemotePeerIp Pointer to specified IP address.
205
206 @return Pointer to IKEV2_SA_SESSION if find one or NULL.
207
208 **/
209 IKEV2_SA_SESSION *
210 Ikev2SaSessionLookup (
211 IN LIST_ENTRY *SaSessionList,
212 IN EFI_IP_ADDRESS *RemotePeerIp
213 )
214 {
215 LIST_ENTRY *Entry;
216 IKEV2_SA_SESSION *IkeSaSession;
217
218 NET_LIST_FOR_EACH (Entry, SaSessionList) {
219 IkeSaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
220
221 if (CompareMem (
222 &IkeSaSession->SessionCommon.RemotePeerIp,
223 RemotePeerIp,
224 sizeof (EFI_IP_ADDRESS)
225 ) == 0) {
226
227 return IkeSaSession;
228 }
229 }
230
231 return NULL;
232 }
233
234 /**
235 Insert a IKE_SA_SESSION into IkeSaSession list. The IkeSaSession list is either
236 Private->Ikev2SaSession list or Private->Ikev2EstablishedList list.
237
238 @param[in] SaSessionList Pointer to list to be inserted into.
239 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be inserted.
240 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESSS to indicate the
241 unique IKEV2_SA_SESSION.
242
243 **/
244 VOID
245 Ikev2SaSessionInsert (
246 IN LIST_ENTRY *SaSessionList,
247 IN IKEV2_SA_SESSION *IkeSaSession,
248 IN EFI_IP_ADDRESS *RemotePeerIp
249 )
250 {
251 Ikev2SaSessionRemove (SaSessionList, RemotePeerIp);
252 InsertTailList (SaSessionList, &IkeSaSession->BySessionTable);
253 }
254
255 /**
256 Remove the SA Session by Remote Peer IP.
257
258 @param[in] SaSessionList Pointer to list to be searched.
259 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESS to use for SA Session search.
260
261 @retval Pointer to IKEV2_SA_SESSION with the specified remote IP address or NULL.
262
263 **/
264 IKEV2_SA_SESSION *
265 Ikev2SaSessionRemove (
266 IN LIST_ENTRY *SaSessionList,
267 IN EFI_IP_ADDRESS *RemotePeerIp
268 )
269 {
270 LIST_ENTRY *Entry;
271 IKEV2_SA_SESSION *IkeSaSession;
272
273 NET_LIST_FOR_EACH (Entry, SaSessionList) {
274 IkeSaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
275
276 if (CompareMem (
277 &IkeSaSession->SessionCommon.RemotePeerIp,
278 RemotePeerIp,
279 sizeof (EFI_IP_ADDRESS)
280 ) == 0) {
281
282 RemoveEntryList (Entry);
283 return IkeSaSession;
284 }
285 }
286
287 return NULL;
288 }
289
290 /**
291 Marking a SA session as on deleting.
292
293 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION.
294
295 @retval EFI_SUCCESS Find the related SA session and marked it.
296
297 **/
298 EFI_STATUS
299 Ikev2SaSessionOnDeleting (
300 IN IKEV2_SA_SESSION *IkeSaSession
301 )
302 {
303 return EFI_SUCCESS;
304 }
305
306 /**
307 Free specified Seession Common. The session common would belong to a IKE SA or
308 a Child SA.
309
310 @param[in] SessionCommon Pointer to a Session Common.
311
312 **/
313 VOID
314 Ikev2SaSessionCommonFree (
315 IN IKEV2_SESSION_COMMON *SessionCommon
316 )
317 {
318
319 ASSERT (SessionCommon != NULL);
320
321 if (SessionCommon->LastSentPacket != NULL) {
322 IkePacketFree (SessionCommon->LastSentPacket);
323 }
324
325 if (SessionCommon->SaParams != NULL) {
326 FreePool (SessionCommon->SaParams);
327 }
328 if (SessionCommon->TimeoutEvent != NULL) {
329 gBS->CloseEvent (SessionCommon->TimeoutEvent);
330 }
331 }
332
333 /**
334 After IKE/Child SA is estiblished, close the time event and free sent packet.
335
336 @param[in] SessionCommon Pointer to a Session Common.
337
338 **/
339 VOID
340 Ikev2SessionCommonRefresh (
341 IN IKEV2_SESSION_COMMON *SessionCommon
342 )
343 {
344 ASSERT (SessionCommon != NULL);
345
346 gBS->CloseEvent (SessionCommon->TimeoutEvent);
347 SessionCommon->TimeoutEvent = NULL;
348 SessionCommon->TimeoutInterval = 0;
349 SessionCommon->RetryCount = 0;
350 if (SessionCommon->LastSentPacket != NULL) {
351 IkePacketFree (SessionCommon->LastSentPacket);
352 SessionCommon->LastSentPacket = NULL;
353 }
354
355 return ;
356 }
357 /**
358 Free specified IKEV2 SA Session.
359
360 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be freed.
361
362 **/
363 VOID
364 Ikev2SaSessionFree (
365 IN IKEV2_SA_SESSION *IkeSaSession
366 )
367 {
368 IKEV2_SESSION_KEYS *IkeKeys;
369 LIST_ENTRY *Entry;
370 IKEV2_CHILD_SA_SESSION *ChildSa;
371 IKEV2_DH_BUFFER *DhBuffer;
372
373 ASSERT (IkeSaSession != NULL);
374
375 //
376 // Delete Common Session
377 //
378 Ikev2SaSessionCommonFree (&IkeSaSession->SessionCommon);
379
380 //
381 // Delete ChildSaEstablish List and SAD
382 //
383 for (Entry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;
384 Entry != &IkeSaSession->ChildSaEstablishSessionList;
385 ) {
386
387 ChildSa = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
388 Entry = Entry->ForwardLink;
389 Ikev2ChildSaSilentDelete (ChildSa->IkeSaSession, ChildSa->LocalPeerSpi);
390
391 }
392
393 //
394 // Delete ChildSaSessionList
395 //
396 for ( Entry = IkeSaSession->ChildSaSessionList.ForwardLink;
397 Entry != &IkeSaSession->ChildSaSessionList;
398 ){
399 ChildSa = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
400 Entry = Entry->ForwardLink;
401 RemoveEntryList (Entry->BackLink);
402 Ikev2ChildSaSessionFree (ChildSa);
403 }
404
405 //
406 // Delete DhBuffer and Keys
407 //
408 if (IkeSaSession->IkeKeys != NULL) {
409 IkeKeys = IkeSaSession->IkeKeys;
410 DhBuffer = IkeKeys->DhBuffer;
411
412 //
413 // Delete DhBuffer
414 //
415 Ikev2DhBufferFree (DhBuffer);
416
417 //
418 // Delete Keys
419 //
420 if (IkeKeys->SkAiKey != NULL) {
421 FreePool (IkeKeys->SkAiKey);
422 }
423 if (IkeKeys->SkArKey != NULL) {
424 FreePool (IkeKeys->SkArKey);
425 }
426 if (IkeKeys->SkdKey != NULL) {
427 FreePool (IkeKeys->SkdKey);
428 }
429 if (IkeKeys->SkEiKey != NULL) {
430 FreePool (IkeKeys->SkEiKey);
431 }
432 if (IkeKeys->SkErKey != NULL) {
433 FreePool (IkeKeys->SkErKey);
434 }
435 if (IkeKeys->SkPiKey != NULL) {
436 FreePool (IkeKeys->SkPiKey);
437 }
438 if (IkeKeys->SkPrKey != NULL) {
439 FreePool (IkeKeys->SkPrKey);
440 }
441 FreePool (IkeKeys);
442 }
443
444 if (IkeSaSession->SaData != NULL) {
445 FreePool (IkeSaSession->SaData);
446 }
447
448 if (IkeSaSession->NiBlock != NULL) {
449 FreePool (IkeSaSession->NiBlock);
450 }
451
452 if (IkeSaSession->NrBlock != NULL) {
453 FreePool (IkeSaSession->NrBlock);
454 }
455
456 if (IkeSaSession->NCookie != NULL) {
457 FreePool (IkeSaSession->NCookie);
458 }
459
460 if (IkeSaSession->InitPacket != NULL) {
461 FreePool (IkeSaSession->InitPacket);
462 }
463
464 if (IkeSaSession->RespPacket != NULL) {
465 FreePool (IkeSaSession->RespPacket);
466 }
467
468 FreePool (IkeSaSession);
469
470 return ;
471 }
472
473 /**
474 Increase the MessageID in IkeSaSession.
475
476 @param[in] IkeSaSession Pointer to a specified IKEV2_SA_SESSION.
477
478 **/
479 VOID
480 Ikev2SaSessionIncreaseMessageId (
481 IN IKEV2_SA_SESSION *IkeSaSession
482 )
483 {
484 if (IkeSaSession->MessageId < 0xffffffff) {
485 IkeSaSession->MessageId ++;
486 } else {
487 //
488 // TODO: Trigger Rekey process.
489 //
490 }
491 }
492
493 /**
494 Allocate memory for IKEV2 Child SA Session.
495
496 @param[in] UdpService Pointer to IKE_UDP_SERVICE.
497 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA
498 Session.
499
500 @retval Pointer of a new created IKEV2 Child SA Session or NULL.
501
502 **/
503 IKEV2_CHILD_SA_SESSION *
504 Ikev2ChildSaSessionAlloc (
505 IN IKE_UDP_SERVICE *UdpService,
506 IN IKEV2_SA_SESSION *IkeSaSession
507 )
508 {
509 EFI_STATUS Status;
510 IKEV2_CHILD_SA_SESSION *ChildSaSession;
511 IKEV2_SESSION_COMMON *ChildSaCommon;
512 IKEV2_SESSION_COMMON *SaCommon;
513
514 ChildSaSession = AllocateZeroPool (sizeof (IKEV2_CHILD_SA_SESSION));
515 if (ChildSaSession == NULL) {
516 return NULL;
517 }
518
519 //
520 // Initialize the fields of ChildSaSession and its SessionCommon.
521 //
522 ChildSaSession->Signature = IKEV2_CHILD_SA_SESSION_SIGNATURE;
523 ChildSaSession->IkeSaSession = IkeSaSession;
524 ChildSaSession->MessageId = IkeSaSession->MessageId;
525 ChildSaSession->LocalPeerSpi = IkeGenerateSpi ();
526 ChildSaCommon = &ChildSaSession->SessionCommon;
527 ChildSaCommon->UdpService = UdpService;
528 ChildSaCommon->Private = IkeSaSession->SessionCommon.Private;
529 ChildSaCommon->IkeSessionType = IkeSessionTypeChildSa;
530 ChildSaCommon->IkeVer = 2;
531 ChildSaCommon->AfterEncodePayload = Ikev2ChildSaAfterEncodePayload;
532 ChildSaCommon->BeforeDecodePayload = Ikev2ChildSaBeforeDecodePayload;
533 SaCommon = &ChildSaSession->IkeSaSession->SessionCommon;
534
535 //
536 // Create a resend notfiy event for retry.
537 //
538 Status = gBS->CreateEvent (
539 EVT_TIMER | EVT_NOTIFY_SIGNAL,
540 TPL_CALLBACK,
541 Ikev2ResendNotify,
542 ChildSaCommon,
543 &ChildSaCommon->TimeoutEvent
544 );
545 if (EFI_ERROR (Status)) {
546 FreePool (ChildSaSession);
547 return NULL;
548 }
549
550 CopyMem (&ChildSaCommon->LocalPeerIp, &SaCommon->LocalPeerIp, sizeof (EFI_IP_ADDRESS));
551 CopyMem (&ChildSaCommon->RemotePeerIp, &SaCommon->RemotePeerIp, sizeof (EFI_IP_ADDRESS));
552
553 return ChildSaSession;
554 }
555
556 /**
557 Register a established IKEv2 Child SA into IkeSaSession->ChildSaEstablishSessionList.
558 If the there is IKEV2_CHILD_SA_SESSION with same remote peer IP, remove the old one
559 then register the new one.
560
561 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be registered.
562 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
563
564 **/
565 VOID
566 Ikev2ChildSaSessionReg (
567 IN IKEV2_CHILD_SA_SESSION *ChildSaSession,
568 IN IPSEC_PRIVATE_DATA *Private
569 )
570 {
571 IKEV2_SESSION_COMMON *SessionCommon;
572 IKEV2_CHILD_SA_SESSION *OldChildSaSession;
573 IKEV2_SA_SESSION *IkeSaSession;
574 IKEV2_SA_PARAMS *SaParams;
575 EFI_STATUS Status;
576 UINT64 Lifetime;
577
578 //
579 // Keep the IKE SA exclusive.
580 //
581 SessionCommon = &ChildSaSession->SessionCommon;
582 IkeSaSession = ChildSaSession->IkeSaSession;
583 OldChildSaSession = Ikev2ChildSaSessionRemove (
584 &IkeSaSession->ChildSaEstablishSessionList,
585 ChildSaSession->LocalPeerSpi,
586 IKEV2_ESTABLISHED_CHILDSA_LIST
587 );
588 if (OldChildSaSession != NULL) {
589 //
590 // Free the old one.
591 //
592 Ikev2ChildSaSessionFree (OldChildSaSession);
593 }
594
595 //
596 // Store the ready child SA into SAD.
597 //
598 Ikev2StoreSaData (ChildSaSession);
599
600 //
601 // Cleanup the fields of SessionCommon for processing.
602 //
603 Ikev2SessionCommonRefresh (SessionCommon);
604
605 //
606 // Insert the ready child SA session into established list.
607 //
608 Ikev2ChildSaSessionInsert (&IkeSaSession->ChildSaEstablishSessionList, ChildSaSession);
609
610 //
611 // Create a Notify event for the IKE SA life time counting.
612 //
613 Status = gBS->CreateEvent (
614 EVT_TIMER | EVT_NOTIFY_SIGNAL,
615 TPL_CALLBACK,
616 Ikev2LifetimeNotify,
617 SessionCommon,
618 &SessionCommon->TimeoutEvent
619 );
620 if (EFI_ERROR(Status)){
621 return ;
622 }
623
624 //
625 // Start to count the lifetime of the IKE SA.
626 //
627 SaParams = SessionCommon->SaParams;
628 if (ChildSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime != 0){
629 Lifetime = ChildSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime;
630 } else {
631 Lifetime = CHILD_SA_DEFAULT_LIFETIME;
632 }
633
634 Status = gBS->SetTimer (
635 SessionCommon->TimeoutEvent,
636 TimerRelative,
637 MultU64x32(Lifetime, 10000000) // ms->100ns
638 );
639 if (EFI_ERROR(Status)){
640 return ;
641 }
642
643 DEBUG ((
644 DEBUG_INFO,
645 "\n------ChildSa established and start to count down %d seconds lifetime\n",
646 Lifetime
647 ));
648
649 return ;
650 }
651
652 /**
653 Find the ChildSaSession by it's MessagId.
654
655 @param[in] SaSessionList Pointer to a ChildSaSession List.
656 @param[in] Mid The messageId used to search ChildSaSession.
657
658 @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.
659
660 **/
661 IKEV2_CHILD_SA_SESSION *
662 Ikev2ChildSaSessionLookupByMid (
663 IN LIST_ENTRY *SaSessionList,
664 IN UINT32 Mid
665 )
666 {
667 LIST_ENTRY *Entry;
668 IKEV2_CHILD_SA_SESSION *ChildSaSession;
669
670 NET_LIST_FOR_EACH (Entry, SaSessionList) {
671 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
672
673 if (ChildSaSession->MessageId == Mid) {
674 return ChildSaSession;
675 }
676 }
677 return NULL;
678 }
679
680 /**
681 This function find the Child SA by the specified SPI.
682
683 This functin find a ChildSA session by searching the ChildSaSessionlist of
684 the input IKEV2_SA_SESSION by specified MessageID.
685
686 @param[in] SaSessionList Pointer to List to be searched.
687 @param[in] Spi Specified SPI.
688
689 @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.
690
691 **/
692 IKEV2_CHILD_SA_SESSION *
693 Ikev2ChildSaSessionLookupBySpi (
694 IN LIST_ENTRY *SaSessionList,
695 IN UINT32 Spi
696 )
697 {
698 LIST_ENTRY *Entry;
699 IKEV2_CHILD_SA_SESSION *ChildSaSession;
700
701 NET_LIST_FOR_EACH (Entry, SaSessionList) {
702 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
703
704 if (ChildSaSession->RemotePeerSpi == Spi || ChildSaSession->LocalPeerSpi == Spi) {
705 return ChildSaSession;
706 }
707 }
708
709 return NULL;
710 }
711
712 /**
713 Insert a Child SA Session into the specified ChildSa list.
714
715 @param[in] SaSessionList Pointer to list to be inserted in.
716 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be inserted.
717
718 **/
719 VOID
720 Ikev2ChildSaSessionInsert (
721 IN LIST_ENTRY *SaSessionList,
722 IN IKEV2_CHILD_SA_SESSION *ChildSaSession
723 )
724 {
725 InsertTailList (SaSessionList, &ChildSaSession->ByIkeSa);
726 }
727
728 /**
729 Remove the IKEV2_CHILD_SA_SESSION from IkeSaSessionList.
730
731 @param[in] SaSessionList The SA Session List to be iterated.
732 @param[in] Spi Spi used to identified the IKEV2_CHILD_SA_SESSION.
733 @param[in] ListType The type of the List to indicate whether it is a
734 Established.
735
736 @return The point to IKEV2_CHILD_SA_SESSION or NULL.
737
738 **/
739 IKEV2_CHILD_SA_SESSION *
740 Ikev2ChildSaSessionRemove (
741 IN LIST_ENTRY *SaSessionList,
742 IN UINT32 Spi,
743 IN UINT8 ListType
744 )
745 {
746 LIST_ENTRY *Entry;
747 LIST_ENTRY *NextEntry;
748 IKEV2_CHILD_SA_SESSION *ChildSaSession;
749
750 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SaSessionList) {
751
752 if (ListType == IKEV2_ESTABLISHED_CHILDSA_LIST || ListType == IKEV2_ESTABLISHING_CHILDSA_LIST) {
753 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
754 } else if (ListType == IKEV2_DELET_CHILDSA_LIST) {
755 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);
756 } else {
757 return NULL;
758 }
759
760 if (ChildSaSession->RemotePeerSpi == Spi || ChildSaSession->LocalPeerSpi == Spi) {
761 RemoveEntryList (Entry);
762 return ChildSaSession;
763 }
764 }
765
766 return NULL;
767 }
768
769 /**
770 Mark a specified Child SA Session as on deleting.
771
772 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
773
774 @retval EFI_SUCCESS Operation is successful.
775
776 **/
777 EFI_STATUS
778 Ikev2ChildSaSessionOnDeleting (
779 IN IKEV2_CHILD_SA_SESSION *ChildSaSession
780 )
781 {
782 return EFI_SUCCESS;
783 }
784
785 /**
786 Free the memory located for the specified IKEV2_CHILD_SA_SESSION.
787
788 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
789
790 **/
791 VOID
792 Ikev2ChildSaSessionFree (
793 IN IKEV2_CHILD_SA_SESSION *ChildSaSession
794 )
795 {
796 IKEV2_SESSION_COMMON *SessionCommon;
797
798 SessionCommon = &ChildSaSession->SessionCommon;
799 if (ChildSaSession->SaData != NULL) {
800 FreePool (ChildSaSession->SaData);
801 }
802
803 if (ChildSaSession->NiBlock != NULL) {
804 FreePool (ChildSaSession->NiBlock);
805 }
806
807 if (ChildSaSession->NrBlock != NULL) {
808 FreePool (ChildSaSession->NrBlock);
809 }
810
811 if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey != NULL) {
812 FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey);
813 }
814
815 if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey != NULL) {
816 FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey);
817 }
818
819 if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey != NULL) {
820 FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey);
821 }
822
823 if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey != NULL) {
824 FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey);
825 }
826
827 //
828 // Delete DhBuffer
829 //
830 Ikev2DhBufferFree (ChildSaSession->DhBuffer);
831
832 //
833 // Delete SpdSelector
834 //
835 if (ChildSaSession->SpdSelector != NULL) {
836 if (ChildSaSession->SpdSelector->LocalAddress != NULL) {
837 FreePool (ChildSaSession->SpdSelector->LocalAddress);
838 }
839 if (ChildSaSession->SpdSelector->RemoteAddress != NULL) {
840 FreePool (ChildSaSession->SpdSelector->RemoteAddress);
841 }
842 FreePool (ChildSaSession->SpdSelector);
843 }
844 Ikev2SaSessionCommonFree (SessionCommon);
845 FreePool (ChildSaSession);
846
847 return ;
848 }
849
850 /**
851 Delete the specified established Child SA.
852
853 This function delete the Child SA directly and don't send the Information Packet to
854 remote peer.
855
856 @param[in] IkeSaSession Pointer to a IKE SA Session used to be searched for.
857 @param[in] Spi SPI used to find the Child SA.
858
859 @retval EFI_NOT_FOUND Pointer of IKE SA Session is NULL.
860 @retval EFI_NOT_FOUND There is no specified Child SA related with the input
861 SPI under this IKE SA Session.
862 @retval EFI_SUCCESS Delete the Child SA successfully.
863
864 **/
865 EFI_STATUS
866 Ikev2ChildSaSilentDelete (
867 IN IKEV2_SA_SESSION *IkeSaSession,
868 IN UINT32 Spi
869 )
870 {
871 EFI_STATUS Status;
872 EFI_IPSEC_CONFIG_SELECTOR *Selector;
873 UINTN SelectorSize;
874 BOOLEAN IsLocalFound;
875 BOOLEAN IsRemoteFound;
876 UINT32 LocalSpi;
877 UINT32 RemoteSpi;
878 IKEV2_CHILD_SA_SESSION *ChildSession;
879 EFI_IPSEC_CONFIG_SELECTOR *LocalSelector;
880 EFI_IPSEC_CONFIG_SELECTOR *RemoteSelector;
881 IKE_UDP_SERVICE *UdpService;
882 IPSEC_PRIVATE_DATA *Private;
883
884 if (IkeSaSession == NULL) {
885 return EFI_NOT_FOUND;
886 }
887
888 IsLocalFound = FALSE;
889 IsRemoteFound = FALSE;
890 ChildSession = NULL;
891 LocalSelector = NULL;
892 RemoteSelector = NULL;
893 UdpService = IkeSaSession->SessionCommon.UdpService;
894
895 Private = (UdpService->IpVersion == IP_VERSION_4) ?
896 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
897 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
898
899 //
900 // Remove the Established SA from ChildSaEstablishlist.
901 //
902 ChildSession = Ikev2ChildSaSessionRemove(
903 &(IkeSaSession->ChildSaEstablishSessionList),
904 Spi,
905 IKEV2_ESTABLISHED_CHILDSA_LIST
906 );
907 if (ChildSession == NULL) {
908 return EFI_NOT_FOUND;
909 }
910
911 LocalSpi = ChildSession->LocalPeerSpi;
912 RemoteSpi = ChildSession->RemotePeerSpi;
913
914 SelectorSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
915 Selector = AllocateZeroPool (SelectorSize);
916 ASSERT (Selector != NULL);
917
918
919
920 while (1) {
921 Status = EfiIpSecConfigGetNextSelector (
922 &Private->IpSecConfig,
923 IPsecConfigDataTypeSad,
924 &SelectorSize,
925 Selector
926 );
927 if (Status == EFI_BUFFER_TOO_SMALL) {
928 FreePool (Selector);
929
930 Selector = AllocateZeroPool (SelectorSize);
931 ASSERT (Selector != NULL);
932 Status = EfiIpSecConfigGetNextSelector (
933 &Private->IpSecConfig,
934 IPsecConfigDataTypeSad,
935 &SelectorSize,
936 Selector
937 );
938 }
939
940 if (EFI_ERROR (Status)) {
941 break;
942 }
943
944 if (Selector->SaId.Spi == RemoteSpi) {
945 //
946 // SPI is unique. There is only one SAD whose SPI is
947 // same with RemoteSpi.
948 //
949 IsRemoteFound = TRUE;
950 RemoteSelector = AllocateZeroPool (SelectorSize);
951 ASSERT (RemoteSelector != NULL);
952 CopyMem (RemoteSelector, Selector, SelectorSize);
953 }
954
955 if (Selector->SaId.Spi == LocalSpi) {
956 //
957 // SPI is unique. There is only one SAD whose SPI is
958 // same with LocalSpi.
959 //
960 IsLocalFound = TRUE;
961 LocalSelector = AllocateZeroPool (SelectorSize);
962 ASSERT (LocalSelector != NULL);
963 CopyMem (LocalSelector, Selector, SelectorSize);
964 }
965 }
966 //
967 // Delete SA from the Variable.
968 //
969 if (IsLocalFound) {
970 Status = EfiIpSecConfigSetData (
971 &Private->IpSecConfig,
972 IPsecConfigDataTypeSad,
973 LocalSelector,
974 NULL,
975 NULL
976 );
977 }
978
979 if (IsRemoteFound) {
980 Status = EfiIpSecConfigSetData (
981 &Private->IpSecConfig,
982 IPsecConfigDataTypeSad,
983 RemoteSelector,
984 NULL,
985 NULL
986 );
987
988 }
989
990 DEBUG (
991 (DEBUG_INFO,
992 "\n------IKEV2 deleted ChildSa(local spi, remote spi):(0x%x, 0x%x)------\n",
993 LocalSpi,
994 RemoteSpi)
995 );
996 Ikev2ChildSaSessionFree (ChildSession);
997
998 if (RemoteSelector != NULL) {
999 FreePool (RemoteSelector);
1000 }
1001
1002 if (LocalSelector != NULL) {
1003 FreePool (LocalSelector);
1004 }
1005
1006 if (Selector != NULL) {
1007 FreePool (Selector);
1008 }
1009
1010 return Status;
1011 }
1012
1013 /**
1014 Free the specified DhBuffer.
1015
1016 @param[in] DhBuffer Pointer to IKEV2_DH_BUFFER to be freed.
1017
1018 **/
1019 VOID
1020 Ikev2DhBufferFree (
1021 IKEV2_DH_BUFFER *DhBuffer
1022 )
1023 {
1024 if (DhBuffer != NULL) {
1025 if (DhBuffer->GxBuffer != NULL) {
1026 FreePool (DhBuffer->GxBuffer);
1027 }
1028 if (DhBuffer->GyBuffer != NULL) {
1029 FreePool (DhBuffer->GyBuffer);
1030 }
1031 if (DhBuffer->GxyBuffer != NULL) {
1032 FreePool (DhBuffer->GxyBuffer);
1033 }
1034 if (DhBuffer->DhContext != NULL) {
1035 IpSecCryptoIoFreeDh (&DhBuffer->DhContext);
1036 }
1037 FreePool (DhBuffer);
1038 }
1039 }
1040
1041 /**
1042 This function is to parse a request IKE packet and return its request type.
1043 The request type is one of IKE CHILD SA creation, IKE SA rekeying and
1044 IKE CHILD SA rekeying.
1045
1046 @param[in] IkePacket IKE packet to be prased.
1047
1048 return the type of the IKE packet.
1049
1050 **/
1051 IKEV2_CREATE_CHILD_REQUEST_TYPE
1052 Ikev2ChildExchangeRequestType(
1053 IN IKE_PACKET *IkePacket
1054 )
1055 {
1056 BOOLEAN Flag;
1057 LIST_ENTRY *Entry;
1058 IKE_PAYLOAD *IkePayload;
1059
1060 Flag = FALSE;
1061
1062 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
1063 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
1064 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
1065 //
1066 // Packet with Ts Payload means it is for either CHILD_SA_CREATE or CHILD_SA_REKEY.
1067 //
1068 Flag = TRUE;
1069 }
1070 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NOTIFY) {
1071 if (((IKEV2_NOTIFY*)IkePayload)->MessageType == IKEV2_NOTIFICATION_REKEY_SA) {
1072 //
1073 // If notify payload with REKEY_SA message type, the IkePacket is for
1074 // rekeying Child SA.
1075 //
1076 return IkeRequestTypeRekeyChildSa;
1077 }
1078 }
1079 };
1080
1081 if (!Flag){
1082 //
1083 // The Create Child Exchange is for IKE SA rekeying.
1084 //
1085 return IkeRequestTypeRekeyIkeSa;
1086 } else {
1087 //
1088 // If the Notify payloaad with transport mode message type, the IkePacket is
1089 // for create Child SA.
1090 //
1091 return IkeRequestTypeCreateChildSa;
1092 }
1093 }
1094
1095 /**
1096 Associate a SPD selector to the Child SA Session.
1097
1098 This function is called when the Child SA is not the first child SA of its
1099 IKE SA. It associate a SPD to this Child SA.
1100
1101 @param[in, out] ChildSaSession Pointer to the Child SA Session to be associated to
1102 a SPD selector.
1103
1104 @retval EFI_SUCCESS Associate one SPD selector to this Child SA Session successfully.
1105 @retval EFI_NOT_FOUND Can't find the related SPD selector.
1106
1107 **/
1108 EFI_STATUS
1109 Ikev2ChildSaAssociateSpdEntry (
1110 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession
1111 )
1112 {
1113 IpSecVisitConfigData (IPsecConfigDataTypeSpd, Ikev2MatchSpdEntry, ChildSaSession);
1114 if (ChildSaSession->Spd != NULL) {
1115 return EFI_SUCCESS;
1116 } else {
1117 return EFI_NOT_FOUND;
1118 }
1119 }
1120
1121
1122 /**
1123 This function finds the SPI from Create Child SA Exchange Packet.
1124
1125 @param[in] IkePacket Pointer to IKE_PACKET to be searched.
1126
1127 @retval SPI number or 0 if it is not supported.
1128
1129 **/
1130 UINT32
1131 Ikev2ChildExchangeRekeySpi (
1132 IN IKE_PACKET *IkePacket
1133 )
1134 {
1135 //
1136 // Not support yet.
1137 //
1138 return 0;
1139 }
1140
1141 /**
1142 Validate the IKE header of received IKE packet.
1143
1144 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this IKE packet.
1145 @param[in] IkeHdr Pointer to IKE header of received IKE packet.
1146
1147 @retval TRUE If the IKE header is valid.
1148 @retval FALSE If the IKE header is invalid.
1149
1150 **/
1151 BOOLEAN
1152 Ikev2ValidateHeader (
1153 IN IKEV2_SA_SESSION *IkeSaSession,
1154 IN IKE_HEADER *IkeHdr
1155 )
1156 {
1157
1158 IKEV2_SESSION_STATE State;
1159
1160 State = IkeSaSession->SessionCommon.State;
1161 if (State == IkeStateInit) {
1162 //
1163 // For the IKE Initial Exchange, the MessagId should be zero.
1164 //
1165 if (IkeHdr->MessageId != 0) {
1166 return FALSE;
1167 }
1168 } else {
1169 if (State == IkeStateAuth) {
1170 if (IkeHdr->MessageId != 1) {
1171 return FALSE;
1172 }
1173 }
1174 if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie ||
1175 IkeHdr->ResponderCookie != IkeSaSession->ResponderCookie
1176 ) {
1177 //
1178 // TODO: send notification INVALID-COOKIE
1179 //
1180 return FALSE;
1181 }
1182 }
1183
1184 //
1185 // Information Exchagne and Create Child Exchange can be started from each part.
1186 //
1187 if (IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_INFO &&
1188 IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_CREATE_CHILD
1189 ) {
1190 if (IkeSaSession->SessionCommon.IsInitiator) {
1191 if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie) {
1192 //
1193 // TODO: send notification INVALID-COOKIE
1194 //
1195 return FALSE;
1196 }
1197 if (IkeHdr->Flags != IKE_HEADER_FLAGS_RESPOND) {
1198 return FALSE;
1199 }
1200 } else {
1201 if (IkeHdr->Flags != IKE_HEADER_FLAGS_INIT) {
1202 return FALSE;
1203 }
1204 }
1205 }
1206
1207 return TRUE;
1208 }
1209
1210 /**
1211 Create and intialize IKEV2_SA_DATA for speicifed IKEV2_SESSION_COMMON.
1212
1213 This function will be only called by the initiator. The responder's IKEV2_SA_DATA
1214 will be generated during parsed the initiator packet.
1215
1216 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to.
1217
1218 @retval a Pointer to a new IKEV2_SA_DATA or NULL.
1219
1220 **/
1221 IKEV2_SA_DATA *
1222 Ikev2InitializeSaData (
1223 IN IKEV2_SESSION_COMMON *SessionCommon
1224 )
1225 {
1226 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1227 IKEV2_SA_DATA *SaData;
1228 IKEV2_PROPOSAL_DATA *ProposalData;
1229 IKEV2_TRANSFORM_DATA *TransformData;
1230 IKE_SA_ATTRIBUTE *Attribute;
1231
1232 ASSERT (SessionCommon != NULL);
1233 //
1234 // TODO: Remove the hard code of the support Alogrithm. Those data should be
1235 // get from the SPD/PAD data.
1236 //
1237 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1238 SaData = AllocateZeroPool (
1239 sizeof (IKEV2_SA_DATA) +
1240 sizeof (IKEV2_PROPOSAL_DATA) * 2 +
1241 sizeof (IKEV2_TRANSFORM_DATA) * 4 * 2
1242 );
1243 } else {
1244 SaData = AllocateZeroPool (
1245 sizeof (IKEV2_SA_DATA) +
1246 sizeof (IKEV2_PROPOSAL_DATA) * 2 +
1247 sizeof (IKEV2_TRANSFORM_DATA) * 3 * 2
1248 );
1249 }
1250 if (SaData == NULL) {
1251 return NULL;
1252 }
1253
1254 //
1255 // First proposal payload: 3DES + SHA1 + DH
1256 //
1257 SaData->NumProposals = 2;
1258 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
1259 ProposalData->ProposalIndex = 1;
1260
1261 //
1262 // If SA data for IKE_SA_INIT exchage, contains 4 transforms. If SA data for
1263 // IKE_AUTH exchange contains 3 transforms.
1264 //
1265 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1266 ProposalData->NumTransforms = 4;
1267 } else {
1268 ProposalData->NumTransforms = 3;
1269 }
1270
1271
1272 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1273 ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;
1274 } else {
1275 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1276 ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
1277 ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));
1278 ASSERT (ProposalData->Spi != NULL);
1279 CopyMem (
1280 ProposalData->Spi,
1281 &ChildSaSession->LocalPeerSpi,
1282 sizeof(ChildSaSession->LocalPeerSpi)
1283 );
1284 }
1285
1286 //
1287 // Set transform attribute for Encryption Algorithm - 3DES
1288 //
1289 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);
1290 TransformData->TransformIndex = 0;
1291 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;
1292 TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_3DES;
1293
1294 //
1295 // Set transform attribute for Integrity Algorithm - SHA1_96
1296 //
1297 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1298 TransformData->TransformIndex = 1;
1299 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;
1300 TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;
1301
1302 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1303 //
1304 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1305 //
1306 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1307 TransformData->TransformIndex = 2;
1308 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;
1309 TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;
1310 }
1311
1312 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1313 //
1314 // Set transform attribute for DH Group - DH 1024
1315 //
1316 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1317 TransformData->TransformIndex = 3;
1318 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;
1319 TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;
1320 } else {
1321 //
1322 // Transform type for Extended Sequence Numbers. Currently not support Extended
1323 // Sequence Number.
1324 //
1325 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1326 TransformData->TransformIndex = 2;
1327 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;
1328 TransformData->TransformId = 0;
1329 }
1330
1331 //
1332 // Second proposal payload: 3DES + SHA1 + DH
1333 //
1334 ProposalData = (IKEV2_PROPOSAL_DATA *) (TransformData + 1);
1335 ProposalData->ProposalIndex = 2;
1336
1337 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1338 ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;
1339 ProposalData->NumTransforms = 4;
1340 } else {
1341
1342 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1343 ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
1344 ProposalData->NumTransforms = 3;
1345 ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));
1346 ASSERT (ProposalData->Spi != NULL);
1347 CopyMem (
1348 ProposalData->Spi,
1349 &ChildSaSession->LocalPeerSpi,
1350 sizeof(ChildSaSession->LocalPeerSpi)
1351 );
1352 }
1353
1354 //
1355 // Set transform attribute for Encryption Algorithm - AES-CBC
1356 //
1357 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);
1358 TransformData->TransformIndex = 0;
1359 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;
1360 TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_AES_CBC;
1361 Attribute = &TransformData->Attribute;
1362 Attribute->AttrType = IKEV2_ATTRIBUTE_TYPE_KEYLEN;
1363 Attribute->Attr.AttrLength = (UINT16) (8 * IpSecGetEncryptKeyLength (IKEV2_TRANSFORM_ID_ENCR_AES_CBC));
1364
1365 //
1366 // Set transform attribute for Integrity Algorithm - SHA1_96
1367 //
1368 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1369 TransformData->TransformIndex = 1;
1370 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;
1371 TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;
1372
1373 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1374 //
1375 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1376 //
1377 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1378 TransformData->TransformIndex = 2;
1379 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;
1380 TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;
1381 }
1382
1383 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1384 //
1385 // Set transform attrbiute for DH Group - DH-1024
1386 //
1387 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1388 TransformData->TransformIndex = 3;
1389 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;
1390 TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;
1391 } else {
1392 //
1393 // Transform type for Extended Sequence Numbers. Currently not support Extended
1394 // Sequence Number.
1395 //
1396 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1397 TransformData->TransformIndex = 2;
1398 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;
1399 TransformData->TransformId = 0;
1400 }
1401
1402 return SaData;
1403 }
1404
1405 /**
1406 Store the SA into SAD.
1407
1408 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
1409
1410 **/
1411 VOID
1412 Ikev2StoreSaData (
1413 IN IKEV2_CHILD_SA_SESSION *ChildSaSession
1414 )
1415 {
1416 EFI_STATUS Status;
1417 EFI_IPSEC_SA_ID SaId;
1418 EFI_IPSEC_SA_DATA2 SaData;
1419 IKEV2_SESSION_COMMON *SessionCommon;
1420 IPSEC_PRIVATE_DATA *Private;
1421 UINT32 TempAddressCount;
1422 EFI_IP_ADDRESS_INFO *TempAddressInfo;
1423
1424 SessionCommon = &ChildSaSession->SessionCommon;
1425 Private = SessionCommon->Private;
1426
1427 ZeroMem (&SaId, sizeof (EFI_IPSEC_SA_ID));
1428 ZeroMem (&SaData, sizeof (EFI_IPSEC_SA_DATA2));
1429
1430 //
1431 // Create a SpdSelector. In this implementation, one SPD represents
1432 // 2 direction traffic, so in here, there needs to reverse the local address
1433 // and remote address for Remote Peer's SA, then reverse again for the locate
1434 // SA.
1435 //
1436 TempAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;
1437 TempAddressInfo = ChildSaSession->SpdSelector->LocalAddress;
1438
1439 ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->SpdSelector->RemoteAddressCount;
1440 ChildSaSession->SpdSelector->LocalAddress = ChildSaSession->SpdSelector->RemoteAddress;
1441
1442 ChildSaSession->SpdSelector->RemoteAddress = TempAddressInfo;
1443 ChildSaSession->SpdSelector->RemoteAddressCount= TempAddressCount;
1444
1445 //
1446 // Set the SaId and SaData.
1447 //
1448 SaId.Spi = ChildSaSession->LocalPeerSpi;
1449 SaId.Proto = EfiIPsecESP;
1450 SaData.AntiReplayWindows = 16;
1451 SaData.SNCount = 0;
1452 SaData.Mode = ChildSaSession->Spd->Data->ProcessingPolicy->Mode;
1453
1454 //
1455 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1456 //
1457 if (SaData.Mode == EfiIPsecTunnel) {
1458 CopyMem (
1459 &SaData.TunnelSourceAddress,
1460 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1461 sizeof (EFI_IP_ADDRESS)
1462 );
1463 CopyMem (
1464 &SaData.TunnelDestinationAddress,
1465 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1466 sizeof (EFI_IP_ADDRESS)
1467 );
1468 }
1469
1470 CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.LocalPeerIp, sizeof (EFI_IP_ADDRESS));
1471 CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.LocalPeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));
1472 SaData.SpdSelector = ChildSaSession->SpdSelector;
1473
1474 //
1475 // Store the remote SA into SAD.
1476 //
1477 Status = EfiIpSecConfigSetData (
1478 &Private->IpSecConfig,
1479 IPsecConfigDataTypeSad,
1480 (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,
1481 &SaData,
1482 NULL
1483 );
1484 ASSERT_EFI_ERROR (Status);
1485
1486 //
1487 // Store the local SA into SAD.
1488 //
1489 ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;
1490 ChildSaSession->SpdSelector->RemoteAddress = ChildSaSession->SpdSelector->LocalAddress;
1491
1492 ChildSaSession->SpdSelector->LocalAddress = TempAddressInfo;
1493 ChildSaSession->SpdSelector->LocalAddressCount = TempAddressCount;
1494
1495 SaId.Spi = ChildSaSession->RemotePeerSpi;
1496
1497 CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.RemotePeerIp, sizeof (EFI_IP_ADDRESS));
1498 CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.RemotePeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));
1499 SaData.SpdSelector = ChildSaSession->SpdSelector;
1500
1501 //
1502 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1503 //
1504 if (SaData.Mode == EfiIPsecTunnel) {
1505 CopyMem (
1506 &SaData.TunnelSourceAddress,
1507 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1508 sizeof (EFI_IP_ADDRESS)
1509 );
1510 CopyMem (
1511 &SaData.TunnelDestinationAddress,
1512 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1513 sizeof (EFI_IP_ADDRESS)
1514 );
1515 }
1516
1517 Status = EfiIpSecConfigSetData (
1518 &Private->IpSecConfig,
1519 IPsecConfigDataTypeSad,
1520 (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,
1521 &SaData,
1522 NULL
1523 );
1524
1525 ASSERT_EFI_ERROR (Status);
1526 }
1527
1528 /**
1529 Call back function of the IKE life time is over.
1530
1531 This function will mark the related IKE SA Session as deleting and trigger a
1532 Information negotiation.
1533
1534 @param[in] Event The signaled Event.
1535 @param[in] Context Pointer to data passed by caller.
1536
1537 **/
1538 VOID
1539 EFIAPI
1540 Ikev2LifetimeNotify (
1541 IN EFI_EVENT Event,
1542 IN VOID *Context
1543 )
1544 {
1545 IKEV2_SA_SESSION *IkeSaSession;
1546 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1547 IKEV2_SESSION_COMMON *SessionCommon;
1548
1549 ASSERT (Context != NULL);
1550 SessionCommon = (IKEV2_SESSION_COMMON *) Context;
1551
1552 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1553 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
1554 DEBUG ((
1555 DEBUG_INFO,
1556 "\n---IkeSa Lifetime is out(cookie_i, cookie_r):(0x%lx, 0x%lx)---\n",
1557 IkeSaSession->InitiatorCookie,
1558 IkeSaSession->ResponderCookie
1559 ));
1560
1561 //
1562 // Change the IKE SA Session's State to IKE_STATE_SA_DELETING.
1563 //
1564 IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateSaDeleting);
1565 IkeSaSession->SessionCommon.State = IkeStateSaDeleting;
1566
1567 } else {
1568 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1569 IkeSaSession = ChildSaSession->IkeSaSession;
1570
1571 //
1572 // Link the timeout child SA to the DeleteSaList.
1573 //
1574 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);
1575
1576 //
1577 // Change the Child SA Session's State to IKE_STATE_SA_DELETING.
1578 //
1579 DEBUG ((
1580 DEBUG_INFO,
1581 "\n------ChildSa Lifetime is out(SPI):(0x%x)------\n",
1582 ChildSaSession->LocalPeerSpi
1583 ));
1584 }
1585
1586 //
1587 // TODO: Send the delete info packet or delete silently
1588 //
1589 mIkev2Exchange.NegotiateInfo ((UINT8 *) IkeSaSession, NULL);
1590 }
1591
1592 /**
1593 This function will be called if the TimeOut Event is signaled.
1594
1595 @param[in] Event The signaled Event.
1596 @param[in] Context The data passed by caller.
1597
1598 **/
1599 VOID
1600 EFIAPI
1601 Ikev2ResendNotify (
1602 IN EFI_EVENT Event,
1603 IN VOID *Context
1604 )
1605 {
1606 IPSEC_PRIVATE_DATA *Private;
1607 IKEV2_SA_SESSION *IkeSaSession;
1608 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1609 IKEV2_SESSION_COMMON *SessionCommon;
1610 LIST_ENTRY *ChildSaEntry;
1611 UINT8 Value;
1612 EFI_STATUS Status;
1613
1614 ASSERT (Context != NULL);
1615 IkeSaSession = NULL;
1616 ChildSaSession = NULL;
1617 SessionCommon = (IKEV2_SESSION_COMMON *) Context;
1618 Private = SessionCommon->Private;
1619
1620 //
1621 // Remove the SA session from the processing list if exceed the max retry.
1622 //
1623 if (SessionCommon->RetryCount > IKE_MAX_RETRY) {
1624 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1625 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
1626 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {
1627
1628 //
1629 // If the IkeSaSession is initiator, delete all its Child SAs before removing IKE SA.
1630 // If the IkesaSession is responder, all ChildSa has been remove in Ikev2HandleInfo();
1631 //
1632 for (ChildSaEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;
1633 ChildSaEntry != &IkeSaSession->ChildSaEstablishSessionList;
1634 ) {
1635 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ChildSaEntry);
1636 //
1637 // Move to next ChildSa Entry.
1638 //
1639 ChildSaEntry = ChildSaEntry->ForwardLink;
1640 //
1641 // Delete LocalSpi & RemoteSpi and remove the ChildSaSession from the
1642 // EstablishedChildSaList.
1643 //
1644 Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);
1645 }
1646
1647 //
1648 // If the IKE SA Delete Payload wasn't sent out successfully, Delete it from the EstablishedList.
1649 //
1650 Ikev2SaSessionRemove (&Private->Ikev2EstablishedList, &SessionCommon->RemotePeerIp);
1651
1652 if (Private != NULL && Private->IsIPsecDisabling) {
1653 //
1654 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
1655 // IPsec status variable.
1656 //
1657 if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {
1658 Value = IPSEC_STATUS_DISABLED;
1659 Status = gRT->SetVariable (
1660 IPSECCONFIG_STATUS_NAME,
1661 &gEfiIpSecConfigProtocolGuid,
1662 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1663 sizeof (Value),
1664 &Value
1665 );
1666 if (!EFI_ERROR (Status)) {
1667 //
1668 // Set the Disabled Flag in Private data.
1669 //
1670 Private->IpSec.DisabledFlag = TRUE;
1671 Private->IsIPsecDisabling = FALSE;
1672 }
1673 }
1674 }
1675 } else {
1676 Ikev2SaSessionRemove (&Private->Ikev2SessionList, &SessionCommon->RemotePeerIp);
1677 }
1678 Ikev2SaSessionFree (IkeSaSession);
1679
1680 } else {
1681
1682 //
1683 // If the packet sent by Child SA.
1684 //
1685 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1686 IkeSaSession = ChildSaSession->IkeSaSession;
1687 if (ChildSaSession->SessionCommon.State == IkeStateSaDeleting) {
1688
1689 //
1690 // Established Child SA should be remove from the SAD entry and
1691 // DeleteList. The function of Ikev2DeleteChildSaSilent() will remove
1692 // the childSA from the IkeSaSession->ChildSaEstablishedList. So there
1693 // is no need to remove it here.
1694 //
1695 Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);
1696 Ikev2ChildSaSessionRemove (
1697 &IkeSaSession->DeleteSaList,
1698 ChildSaSession->LocalPeerSpi,
1699 IKEV2_DELET_CHILDSA_LIST
1700 );
1701 } else {
1702 Ikev2ChildSaSessionRemove (
1703 &IkeSaSession->ChildSaSessionList,
1704 ChildSaSession->LocalPeerSpi,
1705 IKEV2_ESTABLISHING_CHILDSA_LIST
1706 );
1707 }
1708
1709 Ikev2ChildSaSessionFree (ChildSaSession);
1710 }
1711 return ;
1712 }
1713
1714 //
1715 // Increase the retry count.
1716 //
1717 SessionCommon->RetryCount++;
1718 DEBUG ((DEBUG_INFO, ">>>Resending the last packet ...\n"));
1719
1720 //
1721 // Resend the last packet.
1722 //
1723 Ikev2SendIkePacket (
1724 SessionCommon->UdpService,
1725 (UINT8*)SessionCommon,
1726 SessionCommon->LastSentPacket,
1727 0
1728 );
1729 }
1730
1731 /**
1732 Copy ChildSaSession->Spd->Selector to ChildSaSession->SpdSelector.
1733
1734 ChildSaSession->SpdSelector stores the real Spdselector for its SA. Sometime,
1735 the SpdSelector in ChildSaSession is more accurated or the scope is smaller
1736 than the one in ChildSaSession->Spd, especially for the tunnel mode.
1737
1738 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to.
1739
1740 **/
1741 VOID
1742 Ikev2ChildSaSessionSpdSelectorCreate (
1743 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession
1744 )
1745 {
1746 if (ChildSaSession->Spd != NULL && ChildSaSession->Spd->Selector != NULL) {
1747 if (ChildSaSession->SpdSelector == NULL) {
1748 ChildSaSession->SpdSelector = AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR));
1749 ASSERT (ChildSaSession->SpdSelector != NULL);
1750 }
1751 CopyMem (
1752 ChildSaSession->SpdSelector,
1753 ChildSaSession->Spd->Selector,
1754 sizeof (EFI_IPSEC_SPD_SELECTOR)
1755 );
1756 ChildSaSession->SpdSelector->RemoteAddress = AllocateCopyPool (
1757 ChildSaSession->Spd->Selector->RemoteAddressCount *
1758 sizeof (EFI_IP_ADDRESS_INFO),
1759 ChildSaSession->Spd->Selector->RemoteAddress
1760 );
1761 ChildSaSession->SpdSelector->LocalAddress = AllocateCopyPool (
1762 ChildSaSession->Spd->Selector->LocalAddressCount *
1763 sizeof (EFI_IP_ADDRESS_INFO),
1764 ChildSaSession->Spd->Selector->LocalAddress
1765 );
1766
1767 ASSERT (ChildSaSession->SpdSelector->LocalAddress != NULL);
1768 ASSERT (ChildSaSession->SpdSelector->RemoteAddress != NULL);
1769
1770 ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->Spd->Selector->RemoteAddressCount;
1771 ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->Spd->Selector->LocalAddressCount;
1772 }
1773 }
1774
1775 /**
1776 Generate a ChildSa Session and insert it into related IkeSaSession.
1777
1778 @param[in] IkeSaSession Pointer to related IKEV2_SA_SESSION.
1779 @param[in] UdpService Pointer to related IKE_UDP_SERVICE.
1780
1781 @return pointer of IKEV2_CHILD_SA_SESSION.
1782
1783 **/
1784 IKEV2_CHILD_SA_SESSION *
1785 Ikev2ChildSaSessionCreate (
1786 IN IKEV2_SA_SESSION *IkeSaSession,
1787 IN IKE_UDP_SERVICE *UdpService
1788 )
1789 {
1790 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1791 IKEV2_SESSION_COMMON *ChildSaCommon;
1792
1793 //
1794 // Create a new ChildSaSession.Insert it into processing list and initiate the common parameters.
1795 //
1796 ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, IkeSaSession);
1797 ASSERT (ChildSaSession != NULL);
1798
1799 //
1800 // Set the specific parameters.
1801 //
1802 ChildSaSession->Spd = IkeSaSession->Spd;
1803 ChildSaCommon = &ChildSaSession->SessionCommon;
1804 ChildSaCommon->IsInitiator = IkeSaSession->SessionCommon.IsInitiator;
1805 if (IkeSaSession->SessionCommon.State == IkeStateAuth) {
1806 ChildSaCommon->State = IkeStateAuth;
1807 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateAuth);
1808 } else {
1809 ChildSaCommon->State = IkeStateCreateChild;
1810 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);
1811 }
1812
1813 //
1814 // If SPD->Selector is not NULL, copy it to the ChildSaSession->SpdSelector.
1815 // The ChildSaSession->SpdSelector might be changed after the traffic selector
1816 // negoniation and it will be copied into the SAData after ChildSA established.
1817 //
1818 Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
1819
1820 //
1821 // Copy first NiBlock and NrBlock to ChildSa Session
1822 //
1823 ChildSaSession->NiBlock = AllocateZeroPool (IkeSaSession->NiBlkSize);
1824 ASSERT (ChildSaSession->NiBlock != NULL);
1825 ChildSaSession->NiBlkSize = IkeSaSession->NiBlkSize;
1826 CopyMem (ChildSaSession->NiBlock, IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
1827
1828 ChildSaSession->NrBlock = AllocateZeroPool (IkeSaSession->NrBlkSize);
1829 ASSERT (ChildSaSession->NrBlock != NULL);
1830 ChildSaSession->NrBlkSize = IkeSaSession->NrBlkSize;
1831 CopyMem (ChildSaSession->NrBlock, IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
1832
1833 //
1834 // Only if the Create Child SA is called for the IKE_INIT Exchange and
1835 // IkeSaSession is initiator (Only Initiator's SPD is not NULL), Set the
1836 // Traffic Selectors related information here.
1837 //
1838 if (IkeSaSession->SessionCommon.State == IkeStateAuth && IkeSaSession->Spd != NULL) {
1839 ChildSaSession->ProtoId = IkeSaSession->Spd->Selector->NextLayerProtocol;
1840 ChildSaSession->LocalPort = IkeSaSession->Spd->Selector->LocalPort;
1841 ChildSaSession->RemotePort = IkeSaSession->Spd->Selector->RemotePort;
1842 }
1843
1844 //
1845 // Insert the new ChildSaSession into processing child SA list.
1846 //
1847 Ikev2ChildSaSessionInsert (&IkeSaSession->ChildSaSessionList, ChildSaSession);
1848 return ChildSaSession;
1849 }
1850
1851 /**
1852 Check if the SPD is related to the input Child SA Session.
1853
1854 This function is the subfunction of Ikev1AssociateSpdEntry(). It is the call
1855 back function of IpSecVisitConfigData().
1856
1857
1858 @param[in] Type Type of the input Config Selector.
1859 @param[in] Selector Pointer to the Configure Selector to be checked.
1860 @param[in] Data Pointer to the Configure Selector's Data passed
1861 from the caller.
1862 @param[in] SelectorSize The buffer size of Selector.
1863 @param[in] DataSize The buffer size of the Data.
1864 @param[in] Context The data passed from the caller. It is a Child
1865 SA Session in this context.
1866
1867 @retval EFI_SUCCESS The SPD Selector is not related to the Child SA Session.
1868 @retval EFI_ABORTED The SPD Selector is related to the Child SA session and
1869 set the ChildSaSession->Spd to point to this SPD Selector.
1870
1871 **/
1872 EFI_STATUS
1873 Ikev2MatchSpdEntry (
1874 IN EFI_IPSEC_CONFIG_DATA_TYPE Type,
1875 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1876 IN VOID *Data,
1877 IN UINTN SelectorSize,
1878 IN UINTN DataSize,
1879 IN VOID *Context
1880 )
1881 {
1882 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1883 EFI_IPSEC_SPD_SELECTOR *SpdSelector;
1884 EFI_IPSEC_SPD_DATA *SpdData;
1885 BOOLEAN IsMatch;
1886 UINT8 IpVersion;
1887
1888 ASSERT (Type == IPsecConfigDataTypeSpd);
1889 SpdData = (EFI_IPSEC_SPD_DATA *) Data;
1890 //
1891 // Bypass all non-protect SPD entry first
1892 //
1893 if (SpdData->Action != EfiIPsecActionProtect) {
1894 return EFI_SUCCESS;
1895 }
1896
1897 ChildSaSession = (IKEV2_CHILD_SA_SESSION *) Context;
1898 IpVersion = ChildSaSession->SessionCommon.UdpService->IpVersion;
1899 SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) Selector;
1900 IsMatch = TRUE;
1901
1902 if (SpdSelector->NextLayerProtocol == EFI_IP_PROTO_UDP &&
1903 SpdSelector->LocalPort == IKE_DEFAULT_PORT &&
1904 SpdSelector->LocalPortRange == 0 &&
1905 SpdSelector->RemotePort == IKE_DEFAULT_PORT &&
1906 SpdSelector->RemotePortRange == 0
1907 ) {
1908 //
1909 // TODO: Skip IKE Policy here or set a SPD entry?
1910 //
1911 return EFI_SUCCESS;
1912 }
1913
1914 if (SpdSelector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL &&
1915 SpdSelector->NextLayerProtocol != ChildSaSession->ProtoId
1916 ) {
1917 IsMatch = FALSE;
1918 }
1919
1920 if (SpdSelector->LocalPort != EFI_IPSEC_ANY_PORT && SpdSelector->LocalPort != ChildSaSession->LocalPort) {
1921 IsMatch = FALSE;
1922 }
1923
1924 if (SpdSelector->RemotePort != EFI_IPSEC_ANY_PORT && SpdSelector->RemotePort != ChildSaSession->RemotePort) {
1925 IsMatch = FALSE;
1926 }
1927
1928 IsMatch = (BOOLEAN) (IsMatch &&
1929 IpSecMatchIpAddress (
1930 IpVersion,
1931 &ChildSaSession->SessionCommon.LocalPeerIp,
1932 SpdSelector->LocalAddress,
1933 SpdSelector->LocalAddressCount
1934 ));
1935
1936 IsMatch = (BOOLEAN) (IsMatch &&
1937 IpSecMatchIpAddress (
1938 IpVersion,
1939 &ChildSaSession->SessionCommon.RemotePeerIp,
1940 SpdSelector->RemoteAddress,
1941 SpdSelector->RemoteAddressCount
1942 ));
1943
1944 if (IsMatch) {
1945 ChildSaSession->Spd = IkeSearchSpdEntry (SpdSelector);
1946 return EFI_ABORTED;
1947 } else {
1948 return EFI_SUCCESS;
1949 }
1950 }
1951
1952 /**
1953 Check if the Algorithm ID is supported.
1954
1955 @param[in] AlgorithmId The specified Algorithm ID.
1956 @param[in] Type The type used to indicate the Algorithm is for Encrypt or
1957 Authentication.
1958
1959 @retval TRUE If the Algorithm ID is supported.
1960 @retval FALSE If the Algorithm ID is not supported.
1961
1962 **/
1963 BOOLEAN
1964 Ikev2IsSupportAlg (
1965 IN UINT16 AlgorithmId,
1966 IN UINT8 Type
1967 )
1968 {
1969 UINT8 Index;
1970 switch (Type) {
1971 case IKE_ENCRYPT_TYPE :
1972 for (Index = 0; Index < IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM; Index++) {
1973 if (mIkev2EncryptAlgorithmList[Index] == AlgorithmId) {
1974 return TRUE;
1975 }
1976 }
1977 break;
1978
1979 case IKE_AUTH_TYPE :
1980 for (Index = 0; Index < IKEV2_SUPPORT_AUTH_ALGORITHM_NUM; Index++) {
1981 if (mIkev2AuthAlgorithmList[Index] == AlgorithmId) {
1982 return TRUE;
1983 }
1984 }
1985 break;
1986
1987 case IKE_DH_TYPE :
1988 for (Index = 0; Index < IKEV2_SUPPORT_DH_ALGORITHM_NUM; Index++) {
1989 if (mIkev2DhGroupAlgorithmList[Index] == AlgorithmId) {
1990 return TRUE;
1991 }
1992 }
1993 break;
1994
1995 case IKE_PRF_TYPE :
1996 for (Index = 0; Index < IKEV2_SUPPORT_PRF_ALGORITHM_NUM; Index++) {
1997 if (mIkev2PrfAlgorithmList[Index] == AlgorithmId) {
1998 return TRUE;
1999 }
2000 }
2001 }
2002 return FALSE;
2003 }
2004
2005 /**
2006 Get the preferred algorithm types from ProposalData.
2007
2008 @param[in] ProposalData Pointer to related IKEV2_PROPOSAL_DATA.
2009 @param[out] PreferEncryptAlgorithm Output of preferred encrypt algorithm.
2010 @param[out] PreferIntegrityAlgorithm Output of preferred integrity algorithm.
2011 @param[out] PreferPrfAlgorithm Output of preferred PRF algorithm. Only
2012 for IKE SA.
2013 @param[out] PreferDhGroup Output of preferred DH group. Only for
2014 IKE SA.
2015 @param[out] PreferEncryptKeylength Output of preferred encrypt key length
2016 in bytes.
2017 @param[out] IsSupportEsn Output of value about the Extented Sequence
2018 Number is support or not. Only for Child SA.
2019 @param[in] IsChildSa If it is ture, the ProposalData is for IKE
2020 SA. Otherwise the proposalData is for Child SA.
2021
2022 **/
2023 VOID
2024 Ikev2ParseProposalData (
2025 IN IKEV2_PROPOSAL_DATA *ProposalData,
2026 OUT UINT16 *PreferEncryptAlgorithm,
2027 OUT UINT16 *PreferIntegrityAlgorithm,
2028 OUT UINT16 *PreferPrfAlgorithm,
2029 OUT UINT16 *PreferDhGroup,
2030 OUT UINTN *PreferEncryptKeylength,
2031 OUT BOOLEAN *IsSupportEsn,
2032 IN BOOLEAN IsChildSa
2033 )
2034 {
2035 IKEV2_TRANSFORM_DATA *TransformData;
2036 UINT8 TransformIndex;
2037
2038 //
2039 // Check input parameters.
2040 //
2041 if (ProposalData == NULL ||
2042 PreferEncryptAlgorithm == NULL ||
2043 PreferIntegrityAlgorithm == NULL ||
2044 PreferEncryptKeylength == NULL
2045 ) {
2046 return;
2047 }
2048
2049 if (IsChildSa) {
2050 if (IsSupportEsn == NULL) {
2051 return;
2052 }
2053 } else {
2054 if (PreferPrfAlgorithm == NULL || PreferDhGroup == NULL) {
2055 return;
2056 }
2057 }
2058
2059 TransformData = (IKEV2_TRANSFORM_DATA *)(ProposalData + 1);
2060 for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {
2061 switch (TransformData->TransformType) {
2062 //
2063 // For IKE SA there are four algorithm types. Encryption Algorithm, Pseudo-random Function,
2064 // Integrity Algorithm, Diffie-Hellman Group. For Child SA, there are three algorithm types.
2065 // Encryption Algorithm, Integrity Algorithm, Extended Sequence Number.
2066 //
2067 case IKEV2_TRANSFORM_TYPE_ENCR:
2068 if (*PreferEncryptAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_ENCRYPT_TYPE)) {
2069 //
2070 // Check the attribute value. According to RFC, only Keylength is support.
2071 //
2072 if (TransformData->Attribute.AttrType == IKEV2_ATTRIBUTE_TYPE_KEYLEN) {
2073 //
2074 // If the Keylength is not support, continue to check the next one.
2075 //
2076 if (IpSecGetEncryptKeyLength ((UINT8)TransformData->TransformId) != (UINTN)(TransformData->Attribute.Attr.AttrValue >> 3)){
2077 break;
2078 } else {
2079 *PreferEncryptKeylength = TransformData->Attribute.Attr.AttrValue;
2080 }
2081 }
2082 *PreferEncryptAlgorithm = TransformData->TransformId;
2083 }
2084 break;
2085
2086 case IKEV2_TRANSFORM_TYPE_PRF :
2087 if (!IsChildSa) {
2088 if (*PreferPrfAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_PRF_TYPE)) {
2089 *PreferPrfAlgorithm = TransformData->TransformId;
2090 }
2091 }
2092 break;
2093
2094 case IKEV2_TRANSFORM_TYPE_INTEG :
2095 if (*PreferIntegrityAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_AUTH_TYPE)) {
2096 *PreferIntegrityAlgorithm = TransformData->TransformId;
2097 }
2098 break;
2099
2100 case IKEV2_TRANSFORM_TYPE_DH :
2101 if (!IsChildSa) {
2102 if (*PreferDhGroup == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_DH_TYPE)) {
2103 *PreferDhGroup = TransformData->TransformId;
2104 }
2105 }
2106 break;
2107
2108 case IKEV2_TRANSFORM_TYPE_ESN :
2109 if (IsChildSa) {
2110 if (TransformData->TransformId != 0) {
2111 *IsSupportEsn = TRUE;
2112 }
2113 }
2114 break;
2115
2116 default:
2117 break;
2118 }
2119 TransformData = (IKEV2_TRANSFORM_DATA *)(TransformData + 1);
2120 }
2121 }
2122
2123 /**
2124 Parse the received Initial Exchange Packet.
2125
2126 This function parse the SA Payload and Key Payload to find out the cryptographic
2127 suite for the further IKE negotiation and fill it into the IKE SA Session's
2128 CommonSession->SaParams.
2129
2130 @param[in, out] IkeSaSession Pointer to related IKEV2_SA_SESSION.
2131 @param[in] SaPayload The received packet.
2132 @param[in] Type The received packet IKE header flag.
2133
2134 @retval TRUE If the SA proposal in Packet is acceptable.
2135 @retval FALSE If the SA proposal in Packet is not acceptable.
2136
2137 **/
2138 BOOLEAN
2139 Ikev2SaParseSaPayload (
2140 IN OUT IKEV2_SA_SESSION *IkeSaSession,
2141 IN IKE_PAYLOAD *SaPayload,
2142 IN UINT8 Type
2143 )
2144 {
2145 IKEV2_PROPOSAL_DATA *ProposalData;
2146 UINT8 ProposalIndex;
2147 UINT16 PreferEncryptAlgorithm;
2148 UINT16 PreferIntegrityAlgorithm;
2149 UINT16 PreferPrfAlgorithm;
2150 UINT16 PreferDhGroup;
2151 UINTN PreferEncryptKeylength;
2152 UINT16 EncryptAlgorithm;
2153 UINT16 IntegrityAlgorithm;
2154 UINT16 PrfAlgorithm;
2155 UINT16 DhGroup;
2156 UINTN EncryptKeylength;
2157 BOOLEAN IsMatch;
2158 UINTN SaDataSize;
2159
2160 PreferPrfAlgorithm = 0;
2161 PreferIntegrityAlgorithm = 0;
2162 PreferDhGroup = 0;
2163 PreferEncryptAlgorithm = 0;
2164 PreferEncryptKeylength = 0;
2165 PrfAlgorithm = 0;
2166 IntegrityAlgorithm = 0;
2167 DhGroup = 0;
2168 EncryptAlgorithm = 0;
2169 EncryptKeylength = 0;
2170 IsMatch = FALSE;
2171
2172 if (Type == IKE_HEADER_FLAGS_INIT) {
2173 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2174 for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *)SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {
2175 //
2176 // Iterate each proposal to find the perfered one.
2177 //
2178 if (ProposalData->ProtocolId == IPSEC_PROTO_ISAKMP && ProposalData->NumTransforms >= 4) {
2179 //
2180 // Get the preferred algorithms.
2181 //
2182 Ikev2ParseProposalData (
2183 ProposalData,
2184 &PreferEncryptAlgorithm,
2185 &PreferIntegrityAlgorithm,
2186 &PreferPrfAlgorithm,
2187 &PreferDhGroup,
2188 &PreferEncryptKeylength,
2189 NULL,
2190 FALSE
2191 );
2192
2193 if (PreferEncryptAlgorithm != 0 &&
2194 PreferIntegrityAlgorithm != 0 &&
2195 PreferPrfAlgorithm != 0 &&
2196 PreferDhGroup != 0
2197 ) {
2198 //
2199 // Find the matched one.
2200 //
2201 IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2202 ASSERT (IkeSaSession->SessionCommon.SaParams != NULL);
2203 IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2204 IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2205 IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;
2206 IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;
2207 IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2208 IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;
2209
2210 //
2211 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2212 //
2213 SaDataSize = sizeof (IKEV2_SA_DATA) +
2214 sizeof (IKEV2_PROPOSAL_DATA) +
2215 sizeof (IKEV2_TRANSFORM_DATA) * 4;
2216 IkeSaSession->SaData = AllocateZeroPool (SaDataSize);
2217 ASSERT (IkeSaSession->SaData != NULL);
2218
2219 IkeSaSession->SaData->NumProposals = 1;
2220
2221 //
2222 // BUGBUG: Suppose the matched proposal only has 4 transforms. If
2223 // The matched Proposal has more than 4 transforms means it contains
2224 // one than one transform with same type.
2225 //
2226 CopyMem (
2227 (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1),
2228 ProposalData,
2229 SaDataSize - sizeof (IKEV2_SA_DATA)
2230 );
2231
2232 ((IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1))->ProposalIndex = 1;
2233 return TRUE;
2234 } else {
2235 PreferEncryptAlgorithm = 0;
2236 PreferIntegrityAlgorithm = 0;
2237 PreferPrfAlgorithm = 0;
2238 PreferDhGroup = 0;
2239 PreferEncryptKeylength = 0;
2240 }
2241 }
2242 //
2243 // Point to next Proposal.
2244 //
2245 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2246 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2247 }
2248 } else if (Type == IKE_HEADER_FLAGS_RESPOND) {
2249 //
2250 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2251 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2252 // is 4.
2253 //
2254 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);
2255 if (ProposalData->ProtocolId != IPSEC_PROTO_ISAKMP || ProposalData->NumTransforms != 4) {
2256 return FALSE;
2257 }
2258 //
2259 // Get the preferred algorithms.
2260 //
2261 Ikev2ParseProposalData (
2262 ProposalData,
2263 &PreferEncryptAlgorithm,
2264 &PreferIntegrityAlgorithm,
2265 &PreferPrfAlgorithm,
2266 &PreferDhGroup,
2267 &PreferEncryptKeylength,
2268 NULL,
2269 FALSE
2270 );
2271 //
2272 // Check if the Sa proposal data from received packet is in the IkeSaSession->SaData.
2273 //
2274 ProposalData = (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1);
2275
2276 for (ProposalIndex = 0; ProposalIndex < IkeSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {
2277 Ikev2ParseProposalData (
2278 ProposalData,
2279 &EncryptAlgorithm,
2280 &IntegrityAlgorithm,
2281 &PrfAlgorithm,
2282 &DhGroup,
2283 &EncryptKeylength,
2284 NULL,
2285 FALSE
2286 );
2287 if (EncryptAlgorithm == PreferEncryptAlgorithm &&
2288 EncryptKeylength == PreferEncryptKeylength &&
2289 IntegrityAlgorithm == PreferIntegrityAlgorithm &&
2290 PrfAlgorithm == PreferPrfAlgorithm &&
2291 DhGroup == PreferDhGroup
2292 ) {
2293 IsMatch = TRUE;
2294 } else {
2295 EncryptAlgorithm = 0;
2296 IntegrityAlgorithm = 0;
2297 PrfAlgorithm = 0;
2298 DhGroup = 0;
2299 EncryptKeylength = 0;
2300 }
2301
2302 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2303 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2304 }
2305
2306 if (IsMatch) {
2307 IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2308 ASSERT (IkeSaSession->SessionCommon.SaParams != NULL);
2309 IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2310 IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2311 IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;
2312 IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;
2313 IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2314 IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;
2315
2316 return TRUE;
2317 }
2318 }
2319 return FALSE;
2320 }
2321
2322 /**
2323 Parse the received Authentication Exchange Packet.
2324
2325 This function parse the SA Payload and Key Payload to find out the cryptographic
2326 suite for the ESP and fill it into the Child SA Session's CommonSession->SaParams.
2327
2328 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to
2329 this Authentication Exchange.
2330 @param[in] SaPayload The received packet.
2331 @param[in] Type The IKE header's flag of received packet .
2332
2333 @retval TRUE If the SA proposal in Packet is acceptable.
2334 @retval FALSE If the SA proposal in Packet is not acceptable.
2335
2336 **/
2337 BOOLEAN
2338 Ikev2ChildSaParseSaPayload (
2339 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession,
2340 IN IKE_PAYLOAD *SaPayload,
2341 IN UINT8 Type
2342 )
2343 {
2344 IKEV2_PROPOSAL_DATA *ProposalData;
2345 UINT8 ProposalIndex;
2346 UINT16 PreferEncryptAlgorithm;
2347 UINT16 PreferIntegrityAlgorithm;
2348 UINTN PreferEncryptKeylength;
2349 BOOLEAN PreferIsSupportEsn;
2350 UINT16 EncryptAlgorithm;
2351 UINT16 IntegrityAlgorithm;
2352 UINTN EncryptKeylength;
2353 BOOLEAN IsSupportEsn;
2354 BOOLEAN IsMatch;
2355 UINTN SaDataSize;
2356
2357
2358 PreferIntegrityAlgorithm = 0;
2359 PreferEncryptAlgorithm = 0;
2360 PreferEncryptKeylength = 0;
2361 IntegrityAlgorithm = 0;
2362 EncryptAlgorithm = 0;
2363 EncryptKeylength = 0;
2364 IsMatch = TRUE;
2365 IsSupportEsn = FALSE;
2366 PreferIsSupportEsn = FALSE;
2367
2368 if (Type == IKE_HEADER_FLAGS_INIT) {
2369 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);
2370 for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *) SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {
2371 //
2372 // Iterate each proposal to find the preferred one.
2373 //
2374 if (ProposalData->ProtocolId == IPSEC_PROTO_IPSEC_ESP && ProposalData->NumTransforms >= 3) {
2375 //
2376 // Get the preferred algorithm.
2377 //
2378 Ikev2ParseProposalData (
2379 ProposalData,
2380 &PreferEncryptAlgorithm,
2381 &PreferIntegrityAlgorithm,
2382 NULL,
2383 NULL,
2384 &PreferEncryptKeylength,
2385 &IsSupportEsn,
2386 TRUE
2387 );
2388 //
2389 // Don't support the ESN now.
2390 //
2391 if (PreferEncryptAlgorithm != 0 &&
2392 PreferIntegrityAlgorithm != 0 &&
2393 !IsSupportEsn
2394 ) {
2395 //
2396 // Find the matched one.
2397 //
2398 ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2399 ASSERT (ChildSaSession->SessionCommon.SaParams != NULL);
2400 ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2401 ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2402 ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2403 CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));
2404
2405 //
2406 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2407 //
2408 SaDataSize = sizeof (IKEV2_SA_DATA) +
2409 sizeof (IKEV2_PROPOSAL_DATA) +
2410 sizeof (IKEV2_TRANSFORM_DATA) * 4;
2411
2412 ChildSaSession->SaData = AllocateZeroPool (SaDataSize);
2413 ASSERT (ChildSaSession->SaData != NULL);
2414
2415 ChildSaSession->SaData->NumProposals = 1;
2416
2417 //
2418 // BUGBUG: Suppose there are 4 transforms in the matched proposal. If
2419 // the matched Proposal has more than 4 transforms that means there
2420 // are more than one transform with same type.
2421 //
2422 CopyMem (
2423 (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1),
2424 ProposalData,
2425 SaDataSize - sizeof (IKEV2_SA_DATA)
2426 );
2427
2428 ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->ProposalIndex = 1;
2429
2430 ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi = AllocateCopyPool (
2431 sizeof (ChildSaSession->LocalPeerSpi),
2432 &ChildSaSession->LocalPeerSpi
2433 );
2434 ASSERT (((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi != NULL);
2435 return TRUE;
2436
2437 } else {
2438 PreferEncryptAlgorithm = 0;
2439 PreferIntegrityAlgorithm = 0;
2440 IsSupportEsn = TRUE;
2441 }
2442 }
2443 //
2444 // Point to next Proposal
2445 //
2446 ProposalData = (IKEV2_PROPOSAL_DATA *)((UINT8 *)(ProposalData + 1) +
2447 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2448 }
2449 } else if (Type == IKE_HEADER_FLAGS_RESPOND) {
2450 //
2451 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2452 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2453 // is 3.
2454 //
2455 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2456 if (ProposalData->ProtocolId != IPSEC_PROTO_IPSEC_ESP || ProposalData->NumTransforms != 3) {
2457 return FALSE;
2458 }
2459 //
2460 // Get the preferred algorithms.
2461 //
2462 Ikev2ParseProposalData (
2463 ProposalData,
2464 &PreferEncryptAlgorithm,
2465 &PreferIntegrityAlgorithm,
2466 NULL,
2467 NULL,
2468 &PreferEncryptKeylength,
2469 &PreferIsSupportEsn,
2470 TRUE
2471 );
2472
2473 ProposalData = (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1);
2474
2475 for (ProposalIndex = 0; ProposalIndex < ChildSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {
2476 Ikev2ParseProposalData (
2477 ProposalData,
2478 &EncryptAlgorithm,
2479 &IntegrityAlgorithm,
2480 NULL,
2481 NULL,
2482 &EncryptKeylength,
2483 &IsSupportEsn,
2484 TRUE
2485 );
2486 if (EncryptAlgorithm == PreferEncryptAlgorithm &&
2487 EncryptKeylength == PreferEncryptKeylength &&
2488 IntegrityAlgorithm == PreferIntegrityAlgorithm &&
2489 IsSupportEsn == PreferIsSupportEsn
2490 ) {
2491 IsMatch = TRUE;
2492 } else {
2493 PreferEncryptAlgorithm = 0;
2494 PreferIntegrityAlgorithm = 0;
2495 IsSupportEsn = TRUE;
2496 }
2497 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2498 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2499 }
2500
2501 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2502 if (IsMatch) {
2503 ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2504 ASSERT (ChildSaSession->SessionCommon.SaParams != NULL);
2505 ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2506 ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2507 ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2508 CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));
2509
2510 return TRUE;
2511 }
2512 }
2513 return FALSE;
2514 }
2515
2516 /**
2517 Generate Key buffer from fragments.
2518
2519 If the digest length of specified HashAlgId is larger than or equal with the
2520 required output key length, derive the key directly. Otherwise, Key Material
2521 needs to be PRF-based concatenation according to 2.13 of RFC 4306:
2522 prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2523 T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2524 then derive the key from this key material.
2525
2526 @param[in] HashAlgId The Hash Algorithm ID used to generate key.
2527 @param[in] HashKey Pointer to a key buffer which contains hash key.
2528 @param[in] HashKeyLength The length of HashKey in bytes.
2529 @param[in, out] OutputKey Pointer to buffer which is used to receive the
2530 output key.
2531 @param[in] OutputKeyLength The length of OutPutKey buffer.
2532 @param[in] Fragments Pointer to the data to be used to generate key.
2533 @param[in] NumFragments The numbers of the Fragement.
2534
2535 @retval EFI_SUCCESS The operation complete successfully.
2536 @retval EFI_INVALID_PARAMETER If NumFragments is zero.
2537 @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.
2538 @retval Others The operation is failed.
2539
2540 **/
2541 EFI_STATUS
2542 Ikev2SaGenerateKey (
2543 IN UINT8 HashAlgId,
2544 IN UINT8 *HashKey,
2545 IN UINTN HashKeyLength,
2546 IN OUT UINT8 *OutputKey,
2547 IN UINTN OutputKeyLength,
2548 IN PRF_DATA_FRAGMENT *Fragments,
2549 IN UINTN NumFragments
2550 )
2551 {
2552 EFI_STATUS Status;
2553 PRF_DATA_FRAGMENT LocalFragments[3];
2554 UINT8 *Digest;
2555 UINTN DigestSize;
2556 UINTN Round;
2557 UINTN Index;
2558 UINTN AuthKeyLength;
2559 UINTN FragmentsSize;
2560 UINT8 TailData;
2561
2562 Status = EFI_SUCCESS;
2563
2564 if (NumFragments == 0) {
2565 return EFI_INVALID_PARAMETER;
2566 }
2567
2568 LocalFragments[0].Data = NULL;
2569 LocalFragments[1].Data = NULL;
2570 LocalFragments[2].Data = NULL;
2571
2572 AuthKeyLength = IpSecGetHmacDigestLength (HashAlgId);
2573 DigestSize = AuthKeyLength;
2574 Digest = AllocateZeroPool (AuthKeyLength);
2575
2576 if (Digest == NULL) {
2577 return EFI_OUT_OF_RESOURCES;
2578 }
2579 //
2580 // If the required output key length is less than the digest size,
2581 // copy the digest into OutputKey.
2582 //
2583 if (OutputKeyLength <= DigestSize) {
2584 Status = IpSecCryptoIoHmac (
2585 HashAlgId,
2586 HashKey,
2587 HashKeyLength,
2588 (HASH_DATA_FRAGMENT *) Fragments,
2589 NumFragments,
2590 Digest,
2591 DigestSize
2592 );
2593 if (EFI_ERROR (Status)) {
2594 goto Exit;
2595 }
2596
2597 CopyMem (OutputKey, Digest, OutputKeyLength);
2598 goto Exit;
2599 }
2600
2601 //
2602 //Otherwise, Key Material need to be PRF-based concatenation according to 2.13
2603 //of RFC 4306: prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2604 //T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2605 //then derive the key from this key material.
2606 //
2607 FragmentsSize = 0;
2608 for (Index = 0; Index < NumFragments; Index++) {
2609 FragmentsSize = FragmentsSize + Fragments[Index].DataSize;
2610 }
2611
2612 LocalFragments[1].Data = AllocateZeroPool (FragmentsSize);
2613 ASSERT (LocalFragments[1].Data != NULL);
2614 LocalFragments[1].DataSize = FragmentsSize;
2615
2616 //
2617 // Copy all input fragments into LocalFragments[1];
2618 //
2619 FragmentsSize = 0;
2620 for (Index = 0; Index < NumFragments; Index++) {
2621 CopyMem (
2622 LocalFragments[1].Data + FragmentsSize,
2623 Fragments[Index].Data,
2624 Fragments[Index].DataSize
2625 );
2626 FragmentsSize = FragmentsSize + Fragments[Index].DataSize;
2627 }
2628
2629 //
2630 // Prepare 0x01 as the first tail data.
2631 //
2632 TailData = 0x01;
2633 LocalFragments[2].Data = &TailData;
2634 LocalFragments[2].DataSize = sizeof (TailData);
2635 //
2636 // Allocate buffer for the first fragment
2637 //
2638 LocalFragments[0].Data = AllocateZeroPool (AuthKeyLength);
2639 ASSERT (LocalFragments[0].Data != NULL);
2640 LocalFragments[0].DataSize = AuthKeyLength;
2641
2642 Round = (OutputKeyLength - 1) / AuthKeyLength + 1;
2643 for (Index = 0; Index < Round; Index++) {
2644 Status = IpSecCryptoIoHmac (
2645 HashAlgId,
2646 HashKey,
2647 HashKeyLength,
2648 (HASH_DATA_FRAGMENT *)(Index == 0 ? &LocalFragments[1] : LocalFragments),
2649 Index == 0 ? 2 : 3,
2650 Digest,
2651 DigestSize
2652 );
2653 if (EFI_ERROR(Status)) {
2654 goto Exit;
2655 }
2656 CopyMem (
2657 LocalFragments[0].Data,
2658 Digest,
2659 DigestSize
2660 );
2661 if (OutputKeyLength > DigestSize * (Index + 1)) {
2662 CopyMem (
2663 OutputKey + Index * DigestSize,
2664 Digest,
2665 DigestSize
2666 );
2667 LocalFragments[0].DataSize = DigestSize;
2668 TailData ++;
2669 } else {
2670 //
2671 // The last round
2672 //
2673 CopyMem (
2674 OutputKey + Index * DigestSize,
2675 Digest,
2676 OutputKeyLength - Index * DigestSize
2677 );
2678 }
2679 }
2680
2681 Exit:
2682 //
2683 // Only First and second Framgement Data need to be freed.
2684 //
2685 for (Index = 0 ; Index < 2; Index++) {
2686 if (LocalFragments[Index].Data != NULL) {
2687 FreePool (LocalFragments[Index].Data);
2688 }
2689 }
2690 if (Digest != NULL) {
2691 FreePool (Digest);
2692 }
2693 return Status;
2694 }
2695