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