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