]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/Ikev2/Utility.c
8769850d41bb5c723e402281750f42d96abc514a
[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 - 2014, 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 = (UdpService->IpVersion == IP_VERSION_4) ?
895 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
896 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
897
898 //
899 // Remove the Established SA from ChildSaEstablishlist.
900 //
901 ChildSession = Ikev2ChildSaSessionRemove(
902 &(IkeSaSession->ChildSaEstablishSessionList),
903 Spi,
904 IKEV2_ESTABLISHED_CHILDSA_LIST
905 );
906 if (ChildSession == NULL) {
907 return EFI_NOT_FOUND;
908 }
909
910 LocalSpi = ChildSession->LocalPeerSpi;
911 RemoteSpi = ChildSession->RemotePeerSpi;
912
913 SelectorSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
914 Selector = AllocateZeroPool (SelectorSize);
915 ASSERT (Selector != NULL);
916
917
918
919 while (1) {
920 Status = EfiIpSecConfigGetNextSelector (
921 &Private->IpSecConfig,
922 IPsecConfigDataTypeSad,
923 &SelectorSize,
924 Selector
925 );
926 if (Status == EFI_BUFFER_TOO_SMALL) {
927 FreePool (Selector);
928
929 Selector = AllocateZeroPool (SelectorSize);
930 ASSERT (Selector != NULL);
931 Status = EfiIpSecConfigGetNextSelector (
932 &Private->IpSecConfig,
933 IPsecConfigDataTypeSad,
934 &SelectorSize,
935 Selector
936 );
937 }
938
939 if (EFI_ERROR (Status)) {
940 break;
941 }
942
943 if (Selector->SaId.Spi == RemoteSpi) {
944 //
945 // SPI is unique. There is only one SAD whose SPI is
946 // same with RemoteSpi.
947 //
948 IsRemoteFound = TRUE;
949 RemoteSelector = AllocateZeroPool (SelectorSize);
950 ASSERT (RemoteSelector != NULL);
951 CopyMem (RemoteSelector, Selector, SelectorSize);
952 }
953
954 if (Selector->SaId.Spi == LocalSpi) {
955 //
956 // SPI is unique. There is only one SAD whose SPI is
957 // same with LocalSpi.
958 //
959 IsLocalFound = TRUE;
960 LocalSelector = AllocateZeroPool (SelectorSize);
961 ASSERT (LocalSelector != NULL);
962 CopyMem (LocalSelector, Selector, SelectorSize);
963 }
964 }
965 //
966 // Delete SA from the Variable.
967 //
968 if (IsLocalFound) {
969 Status = EfiIpSecConfigSetData (
970 &Private->IpSecConfig,
971 IPsecConfigDataTypeSad,
972 LocalSelector,
973 NULL,
974 NULL
975 );
976 }
977
978 if (IsRemoteFound) {
979 Status = EfiIpSecConfigSetData (
980 &Private->IpSecConfig,
981 IPsecConfigDataTypeSad,
982 RemoteSelector,
983 NULL,
984 NULL
985 );
986
987 }
988
989 DEBUG (
990 (DEBUG_INFO,
991 "\n------IKEV2 deleted ChildSa(local spi, remote spi):(0x%x, 0x%x)------\n",
992 LocalSpi,
993 RemoteSpi)
994 );
995 Ikev2ChildSaSessionFree (ChildSession);
996
997 if (RemoteSelector != NULL) {
998 FreePool (RemoteSelector);
999 }
1000
1001 if (LocalSelector != NULL) {
1002 FreePool (LocalSelector);
1003 }
1004
1005 if (Selector != NULL) {
1006 FreePool (Selector);
1007 }
1008
1009 return Status;
1010 }
1011
1012 /**
1013 Free the specified DhBuffer.
1014
1015 @param[in] DhBuffer Pointer to IKEV2_DH_BUFFER to be freed.
1016
1017 **/
1018 VOID
1019 Ikev2DhBufferFree (
1020 IKEV2_DH_BUFFER *DhBuffer
1021 )
1022 {
1023 if (DhBuffer != NULL) {
1024 if (DhBuffer->GxBuffer != NULL) {
1025 FreePool (DhBuffer->GxBuffer);
1026 }
1027 if (DhBuffer->GyBuffer != NULL) {
1028 FreePool (DhBuffer->GyBuffer);
1029 }
1030 if (DhBuffer->GxyBuffer != NULL) {
1031 FreePool (DhBuffer->GxyBuffer);
1032 }
1033 if (DhBuffer->DhContext != NULL) {
1034 IpSecCryptoIoFreeDh (&DhBuffer->DhContext);
1035 }
1036 FreePool (DhBuffer);
1037 }
1038 }
1039
1040 /**
1041 This function is to parse a request IKE packet and return its request type.
1042 The request type is one of IKE CHILD SA creation, IKE SA rekeying and
1043 IKE CHILD SA rekeying.
1044
1045 @param[in] IkePacket IKE packet to be prased.
1046
1047 return the type of the IKE packet.
1048
1049 **/
1050 IKEV2_CREATE_CHILD_REQUEST_TYPE
1051 Ikev2ChildExchangeRequestType(
1052 IN IKE_PACKET *IkePacket
1053 )
1054 {
1055 BOOLEAN Flag;
1056 LIST_ENTRY *Entry;
1057 IKE_PAYLOAD *IkePayload;
1058
1059 Flag = FALSE;
1060
1061 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
1062 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
1063 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
1064 //
1065 // Packet with Ts Payload means it is for either CHILD_SA_CREATE or CHILD_SA_REKEY.
1066 //
1067 Flag = TRUE;
1068 }
1069 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NOTIFY) {
1070 if (((IKEV2_NOTIFY*)IkePayload)->MessageType == IKEV2_NOTIFICATION_REKEY_SA) {
1071 //
1072 // If notify payload with REKEY_SA message type, the IkePacket is for
1073 // rekeying Child SA.
1074 //
1075 return IkeRequestTypeRekeyChildSa;
1076 }
1077 }
1078 };
1079
1080 if (!Flag){
1081 //
1082 // The Create Child Exchange is for IKE SA rekeying.
1083 //
1084 return IkeRequestTypeRekeyIkeSa;
1085 } else {
1086 //
1087 // If the Notify payloaad with transport mode message type, the IkePacket is
1088 // for create Child SA.
1089 //
1090 return IkeRequestTypeCreateChildSa;
1091 }
1092 }
1093
1094 /**
1095 Associate a SPD selector to the Child SA Session.
1096
1097 This function is called when the Child SA is not the first child SA of its
1098 IKE SA. It associate a SPD to this Child SA.
1099
1100 @param[in, out] ChildSaSession Pointer to the Child SA Session to be associated to
1101 a SPD selector.
1102
1103 @retval EFI_SUCCESS Associate one SPD selector to this Child SA Session successfully.
1104 @retval EFI_NOT_FOUND Can't find the related SPD selector.
1105
1106 **/
1107 EFI_STATUS
1108 Ikev2ChildSaAssociateSpdEntry (
1109 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession
1110 )
1111 {
1112 IpSecVisitConfigData (IPsecConfigDataTypeSpd, Ikev2MatchSpdEntry, ChildSaSession);
1113 if (ChildSaSession->Spd != NULL) {
1114 return EFI_SUCCESS;
1115 } else {
1116 return EFI_NOT_FOUND;
1117 }
1118 }
1119
1120
1121 /**
1122 This function finds the SPI from Create Child SA Exchange Packet.
1123
1124 @param[in] IkePacket Pointer to IKE_PACKET to be searched.
1125
1126 @retval SPI number or 0 if it is not supported.
1127
1128 **/
1129 UINT32
1130 Ikev2ChildExchangeRekeySpi (
1131 IN IKE_PACKET *IkePacket
1132 )
1133 {
1134 //
1135 // Not support yet.
1136 //
1137 return 0;
1138 }
1139
1140 /**
1141 Validate the IKE header of received IKE packet.
1142
1143 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this IKE packet.
1144 @param[in] IkeHdr Pointer to IKE header of received IKE packet.
1145
1146 @retval TRUE If the IKE header is valid.
1147 @retval FALSE If the IKE header is invalid.
1148
1149 **/
1150 BOOLEAN
1151 Ikev2ValidateHeader (
1152 IN IKEV2_SA_SESSION *IkeSaSession,
1153 IN IKE_HEADER *IkeHdr
1154 )
1155 {
1156
1157 IKEV2_SESSION_STATE State;
1158
1159 State = IkeSaSession->SessionCommon.State;
1160 if (State == IkeStateInit) {
1161 //
1162 // For the IKE Initial Exchange, the MessagId should be zero.
1163 //
1164 if (IkeHdr->MessageId != 0) {
1165 return FALSE;
1166 }
1167 } else {
1168 if (State == IkeStateAuth) {
1169 if (IkeHdr->MessageId != 1) {
1170 return FALSE;
1171 }
1172 }
1173 if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie ||
1174 IkeHdr->ResponderCookie != IkeSaSession->ResponderCookie
1175 ) {
1176 //
1177 // TODO: send notification INVALID-COOKIE
1178 //
1179 return FALSE;
1180 }
1181 }
1182
1183 //
1184 // Information Exchagne and Create Child Exchange can be started from each part.
1185 //
1186 if (IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_INFO &&
1187 IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_CREATE_CHILD
1188 ) {
1189 if (IkeSaSession->SessionCommon.IsInitiator) {
1190 if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie) {
1191 //
1192 // TODO: send notification INVALID-COOKIE
1193 //
1194 return FALSE;
1195 }
1196 if (IkeHdr->Flags != IKE_HEADER_FLAGS_RESPOND) {
1197 return FALSE;
1198 }
1199 } else {
1200 if (IkeHdr->Flags != IKE_HEADER_FLAGS_INIT) {
1201 return FALSE;
1202 }
1203 }
1204 }
1205
1206 return TRUE;
1207 }
1208
1209 /**
1210 Create and intialize IKEV2_SA_DATA for speicifed IKEV2_SESSION_COMMON.
1211
1212 This function will be only called by the initiator. The responder's IKEV2_SA_DATA
1213 will be generated during parsed the initiator packet.
1214
1215 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to.
1216
1217 @retval a Pointer to a new IKEV2_SA_DATA or NULL.
1218
1219 **/
1220 IKEV2_SA_DATA *
1221 Ikev2InitializeSaData (
1222 IN IKEV2_SESSION_COMMON *SessionCommon
1223 )
1224 {
1225 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1226 IKEV2_SA_DATA *SaData;
1227 IKEV2_PROPOSAL_DATA *ProposalData;
1228 IKEV2_TRANSFORM_DATA *TransformData;
1229 IKE_SA_ATTRIBUTE *Attribute;
1230
1231 ASSERT (SessionCommon != NULL);
1232 //
1233 // TODO: Remove the hard code of the support Alogrithm. Those data should be
1234 // get from the SPD/PAD data.
1235 //
1236 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1237 SaData = AllocateZeroPool (
1238 sizeof (IKEV2_SA_DATA) +
1239 sizeof (IKEV2_PROPOSAL_DATA) * 2 +
1240 sizeof (IKEV2_TRANSFORM_DATA) * 4 * 2
1241 );
1242 } else {
1243 SaData = AllocateZeroPool (
1244 sizeof (IKEV2_SA_DATA) +
1245 sizeof (IKEV2_PROPOSAL_DATA) * 2 +
1246 sizeof (IKEV2_TRANSFORM_DATA) * 3 * 2
1247 );
1248 }
1249 if (SaData == NULL) {
1250 return NULL;
1251 }
1252
1253 //
1254 // First proposal payload: 3DES + SHA1 + DH
1255 //
1256 SaData->NumProposals = 2;
1257 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
1258 ProposalData->ProposalIndex = 1;
1259
1260 //
1261 // If SA data for IKE_SA_INIT exchage, contains 4 transforms. If SA data for
1262 // IKE_AUTH exchange contains 3 transforms.
1263 //
1264 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1265 ProposalData->NumTransforms = 4;
1266 } else {
1267 ProposalData->NumTransforms = 3;
1268 }
1269
1270
1271 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1272 ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;
1273 } else {
1274 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1275 ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
1276 ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));
1277 ASSERT (ProposalData->Spi != NULL);
1278 CopyMem (
1279 ProposalData->Spi,
1280 &ChildSaSession->LocalPeerSpi,
1281 sizeof(ChildSaSession->LocalPeerSpi)
1282 );
1283 }
1284
1285 //
1286 // Set transform attribute for Encryption Algorithm - 3DES
1287 //
1288 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);
1289 TransformData->TransformIndex = 0;
1290 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;
1291 TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_3DES;
1292
1293 //
1294 // Set transform attribute for Integrity Algorithm - SHA1_96
1295 //
1296 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1297 TransformData->TransformIndex = 1;
1298 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;
1299 TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;
1300
1301 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1302 //
1303 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1304 //
1305 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1306 TransformData->TransformIndex = 2;
1307 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;
1308 TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;
1309 }
1310
1311 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1312 //
1313 // Set transform attribute for DH Group - DH 1024
1314 //
1315 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1316 TransformData->TransformIndex = 3;
1317 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;
1318 TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;
1319 } else {
1320 //
1321 // Transform type for Extended Sequence Numbers. Currently not support Extended
1322 // Sequence Number.
1323 //
1324 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1325 TransformData->TransformIndex = 2;
1326 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;
1327 TransformData->TransformId = 0;
1328 }
1329
1330 //
1331 // Second proposal payload: 3DES + SHA1 + DH
1332 //
1333 ProposalData = (IKEV2_PROPOSAL_DATA *) (TransformData + 1);
1334 ProposalData->ProposalIndex = 2;
1335
1336 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1337 ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;
1338 ProposalData->NumTransforms = 4;
1339 } else {
1340
1341 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1342 ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
1343 ProposalData->NumTransforms = 3;
1344 ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));
1345 ASSERT (ProposalData->Spi != NULL);
1346 CopyMem (
1347 ProposalData->Spi,
1348 &ChildSaSession->LocalPeerSpi,
1349 sizeof(ChildSaSession->LocalPeerSpi)
1350 );
1351 }
1352
1353 //
1354 // Set transform attribute for Encryption Algorithm - AES-CBC
1355 //
1356 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);
1357 TransformData->TransformIndex = 0;
1358 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;
1359 TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_AES_CBC;
1360 Attribute = &TransformData->Attribute;
1361 Attribute->AttrType = IKEV2_ATTRIBUTE_TYPE_KEYLEN;
1362 Attribute->Attr.AttrLength = (UINT16) (8 * IpSecGetEncryptKeyLength (IKEV2_TRANSFORM_ID_ENCR_AES_CBC));
1363
1364 //
1365 // Set transform attribute for Integrity Algorithm - SHA1_96
1366 //
1367 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1368 TransformData->TransformIndex = 1;
1369 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;
1370 TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;
1371
1372 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1373 //
1374 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1375 //
1376 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1377 TransformData->TransformIndex = 2;
1378 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;
1379 TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;
1380 }
1381
1382 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1383 //
1384 // Set transform attrbiute for DH Group - DH-1024
1385 //
1386 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1387 TransformData->TransformIndex = 3;
1388 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;
1389 TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;
1390 } else {
1391 //
1392 // Transform type for Extended Sequence Numbers. Currently not support Extended
1393 // Sequence Number.
1394 //
1395 TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);
1396 TransformData->TransformIndex = 2;
1397 TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;
1398 TransformData->TransformId = 0;
1399 }
1400
1401 return SaData;
1402 }
1403
1404 /**
1405 Store the SA into SAD.
1406
1407 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
1408
1409 **/
1410 VOID
1411 Ikev2StoreSaData (
1412 IN IKEV2_CHILD_SA_SESSION *ChildSaSession
1413 )
1414 {
1415 EFI_STATUS Status;
1416 EFI_IPSEC_SA_ID SaId;
1417 EFI_IPSEC_SA_DATA2 SaData;
1418 IKEV2_SESSION_COMMON *SessionCommon;
1419 IPSEC_PRIVATE_DATA *Private;
1420 UINT32 TempAddressCount;
1421 EFI_IP_ADDRESS_INFO *TempAddressInfo;
1422
1423 SessionCommon = &ChildSaSession->SessionCommon;
1424 Private = SessionCommon->Private;
1425
1426 ZeroMem (&SaId, sizeof (EFI_IPSEC_SA_ID));
1427 ZeroMem (&SaData, sizeof (EFI_IPSEC_SA_DATA2));
1428
1429 //
1430 // Create a SpdSelector. In this implementation, one SPD represents
1431 // 2 direction traffic, so in here, there needs to reverse the local address
1432 // and remote address for Remote Peer's SA, then reverse again for the locate
1433 // SA.
1434 //
1435 TempAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;
1436 TempAddressInfo = ChildSaSession->SpdSelector->LocalAddress;
1437
1438 ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->SpdSelector->RemoteAddressCount;
1439 ChildSaSession->SpdSelector->LocalAddress = ChildSaSession->SpdSelector->RemoteAddress;
1440
1441 ChildSaSession->SpdSelector->RemoteAddress = TempAddressInfo;
1442 ChildSaSession->SpdSelector->RemoteAddressCount= TempAddressCount;
1443
1444 //
1445 // Set the SaId and SaData.
1446 //
1447 SaId.Spi = ChildSaSession->LocalPeerSpi;
1448 SaId.Proto = EfiIPsecESP;
1449 SaData.AntiReplayWindows = 16;
1450 SaData.SNCount = 0;
1451 SaData.Mode = ChildSaSession->Spd->Data->ProcessingPolicy->Mode;
1452
1453 //
1454 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1455 //
1456 if (SaData.Mode == EfiIPsecTunnel) {
1457 CopyMem (
1458 &SaData.TunnelSourceAddress,
1459 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1460 sizeof (EFI_IP_ADDRESS)
1461 );
1462 CopyMem (
1463 &SaData.TunnelDestinationAddress,
1464 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1465 sizeof (EFI_IP_ADDRESS)
1466 );
1467 }
1468
1469 CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.LocalPeerIp, sizeof (EFI_IP_ADDRESS));
1470 CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.LocalPeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));
1471 SaData.SpdSelector = ChildSaSession->SpdSelector;
1472
1473 //
1474 // Store the remote SA into SAD.
1475 //
1476 Status = EfiIpSecConfigSetData (
1477 &Private->IpSecConfig,
1478 IPsecConfigDataTypeSad,
1479 (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,
1480 &SaData,
1481 NULL
1482 );
1483 ASSERT_EFI_ERROR (Status);
1484
1485 //
1486 // Store the local SA into SAD.
1487 //
1488 ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;
1489 ChildSaSession->SpdSelector->RemoteAddress = ChildSaSession->SpdSelector->LocalAddress;
1490
1491 ChildSaSession->SpdSelector->LocalAddress = TempAddressInfo;
1492 ChildSaSession->SpdSelector->LocalAddressCount = TempAddressCount;
1493
1494 SaId.Spi = ChildSaSession->RemotePeerSpi;
1495
1496 CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.RemotePeerIp, sizeof (EFI_IP_ADDRESS));
1497 CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.RemotePeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));
1498 SaData.SpdSelector = ChildSaSession->SpdSelector;
1499
1500 //
1501 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1502 //
1503 if (SaData.Mode == EfiIPsecTunnel) {
1504 CopyMem (
1505 &SaData.TunnelSourceAddress,
1506 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,
1507 sizeof (EFI_IP_ADDRESS)
1508 );
1509 CopyMem (
1510 &SaData.TunnelDestinationAddress,
1511 &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,
1512 sizeof (EFI_IP_ADDRESS)
1513 );
1514 }
1515
1516 Status = EfiIpSecConfigSetData (
1517 &Private->IpSecConfig,
1518 IPsecConfigDataTypeSad,
1519 (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,
1520 &SaData,
1521 NULL
1522 );
1523
1524 ASSERT_EFI_ERROR (Status);
1525 }
1526
1527 /**
1528 Call back function of the IKE life time is over.
1529
1530 This function will mark the related IKE SA Session as deleting and trigger a
1531 Information negotiation.
1532
1533 @param[in] Event The signaled Event.
1534 @param[in] Context Pointer to data passed by caller.
1535
1536 **/
1537 VOID
1538 EFIAPI
1539 Ikev2LifetimeNotify (
1540 IN EFI_EVENT Event,
1541 IN VOID *Context
1542 )
1543 {
1544 IKEV2_SA_SESSION *IkeSaSession;
1545 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1546 IKEV2_SESSION_COMMON *SessionCommon;
1547
1548 ASSERT (Context != NULL);
1549 SessionCommon = (IKEV2_SESSION_COMMON *) Context;
1550
1551 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1552 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
1553 DEBUG ((
1554 DEBUG_INFO,
1555 "\n---IkeSa Lifetime is out(cookie_i, cookie_r):(0x%lx, 0x%lx)---\n",
1556 IkeSaSession->InitiatorCookie,
1557 IkeSaSession->ResponderCookie
1558 ));
1559
1560 //
1561 // Change the IKE SA Session's State to IKE_STATE_SA_DELETING.
1562 //
1563 IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateSaDeleting);
1564 IkeSaSession->SessionCommon.State = IkeStateSaDeleting;
1565
1566 } else {
1567 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1568 IkeSaSession = ChildSaSession->IkeSaSession;
1569
1570 //
1571 // Link the timeout child SA to the DeleteSaList.
1572 //
1573 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);
1574
1575 //
1576 // Change the Child SA Session's State to IKE_STATE_SA_DELETING.
1577 //
1578 DEBUG ((
1579 DEBUG_INFO,
1580 "\n------ChildSa Lifetime is out(SPI):(0x%x)------\n",
1581 ChildSaSession->LocalPeerSpi
1582 ));
1583 }
1584
1585 //
1586 // TODO: Send the delete info packet or delete silently
1587 //
1588 mIkev2Exchange.NegotiateInfo ((UINT8 *) IkeSaSession, NULL);
1589 }
1590
1591 /**
1592 This function will be called if the TimeOut Event is signaled.
1593
1594 @param[in] Event The signaled Event.
1595 @param[in] Context The data passed by caller.
1596
1597 **/
1598 VOID
1599 EFIAPI
1600 Ikev2ResendNotify (
1601 IN EFI_EVENT Event,
1602 IN VOID *Context
1603 )
1604 {
1605 IPSEC_PRIVATE_DATA *Private;
1606 IKEV2_SA_SESSION *IkeSaSession;
1607 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1608 IKEV2_SESSION_COMMON *SessionCommon;
1609 LIST_ENTRY *ChildSaEntry;
1610 UINT8 Value;
1611 EFI_STATUS Status;
1612
1613 ASSERT (Context != NULL);
1614 IkeSaSession = NULL;
1615 ChildSaSession = NULL;
1616 SessionCommon = (IKEV2_SESSION_COMMON *) Context;
1617 Private = SessionCommon->Private;
1618
1619 //
1620 // Remove the SA session from the processing list if exceed the max retry.
1621 //
1622 if (SessionCommon->RetryCount > IKE_MAX_RETRY) {
1623 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
1624 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
1625 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {
1626
1627 //
1628 // If the IkeSaSession is initiator, delete all its Child SAs before removing IKE SA.
1629 // If the IkesaSession is responder, all ChildSa has been remove in Ikev2HandleInfo();
1630 //
1631 for (ChildSaEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;
1632 ChildSaEntry != &IkeSaSession->ChildSaEstablishSessionList;
1633 ) {
1634 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ChildSaEntry);
1635 //
1636 // Move to next ChildSa Entry.
1637 //
1638 ChildSaEntry = ChildSaEntry->ForwardLink;
1639 //
1640 // Delete LocalSpi & RemoteSpi and remove the ChildSaSession from the
1641 // EstablishedChildSaList.
1642 //
1643 Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);
1644 }
1645
1646 //
1647 // If the IKE SA Delete Payload wasn't sent out successfully, Delete it from the EstablishedList.
1648 //
1649 Ikev2SaSessionRemove (&Private->Ikev2EstablishedList, &SessionCommon->RemotePeerIp);
1650
1651 if (Private != NULL && Private->IsIPsecDisabling) {
1652 //
1653 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
1654 // IPsec status variable.
1655 //
1656 if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {
1657 Value = IPSEC_STATUS_DISABLED;
1658 Status = gRT->SetVariable (
1659 IPSECCONFIG_STATUS_NAME,
1660 &gEfiIpSecConfigProtocolGuid,
1661 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1662 sizeof (Value),
1663 &Value
1664 );
1665 if (!EFI_ERROR (Status)) {
1666 //
1667 // Set the Disabled Flag in Private data.
1668 //
1669 Private->IpSec.DisabledFlag = TRUE;
1670 Private->IsIPsecDisabling = FALSE;
1671 }
1672 }
1673 }
1674 } else {
1675 Ikev2SaSessionRemove (&Private->Ikev2SessionList, &SessionCommon->RemotePeerIp);
1676 }
1677 Ikev2SaSessionFree (IkeSaSession);
1678
1679 } else {
1680
1681 //
1682 // If the packet sent by Child SA.
1683 //
1684 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
1685 IkeSaSession = ChildSaSession->IkeSaSession;
1686 if (ChildSaSession->SessionCommon.State == IkeStateSaDeleting) {
1687
1688 //
1689 // Established Child SA should be remove from the SAD entry and
1690 // DeleteList. The function of Ikev2DeleteChildSaSilent() will remove
1691 // the childSA from the IkeSaSession->ChildSaEstablishedList. So there
1692 // is no need to remove it here.
1693 //
1694 Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);
1695 Ikev2ChildSaSessionRemove (
1696 &IkeSaSession->DeleteSaList,
1697 ChildSaSession->LocalPeerSpi,
1698 IKEV2_DELET_CHILDSA_LIST
1699 );
1700 } else {
1701 Ikev2ChildSaSessionRemove (
1702 &IkeSaSession->ChildSaSessionList,
1703 ChildSaSession->LocalPeerSpi,
1704 IKEV2_ESTABLISHING_CHILDSA_LIST
1705 );
1706 }
1707
1708 Ikev2ChildSaSessionFree (ChildSaSession);
1709 }
1710 return ;
1711 }
1712
1713 //
1714 // Increase the retry count.
1715 //
1716 SessionCommon->RetryCount++;
1717 DEBUG ((DEBUG_INFO, ">>>Resending the last packet ...\n"));
1718
1719 //
1720 // Resend the last packet.
1721 //
1722 Ikev2SendIkePacket (
1723 SessionCommon->UdpService,
1724 (UINT8*)SessionCommon,
1725 SessionCommon->LastSentPacket,
1726 0
1727 );
1728 }
1729
1730 /**
1731 Copy ChildSaSession->Spd->Selector to ChildSaSession->SpdSelector.
1732
1733 ChildSaSession->SpdSelector stores the real Spdselector for its SA. Sometime,
1734 the SpdSelector in ChildSaSession is more accurated or the scope is smaller
1735 than the one in ChildSaSession->Spd, especially for the tunnel mode.
1736
1737 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to.
1738
1739 **/
1740 VOID
1741 Ikev2ChildSaSessionSpdSelectorCreate (
1742 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession
1743 )
1744 {
1745 if (ChildSaSession->Spd != NULL && ChildSaSession->Spd->Selector != NULL) {
1746 if (ChildSaSession->SpdSelector == NULL) {
1747 ChildSaSession->SpdSelector = AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR));
1748 ASSERT (ChildSaSession->SpdSelector != NULL);
1749 }
1750 CopyMem (
1751 ChildSaSession->SpdSelector,
1752 ChildSaSession->Spd->Selector,
1753 sizeof (EFI_IPSEC_SPD_SELECTOR)
1754 );
1755 ChildSaSession->SpdSelector->RemoteAddress = AllocateCopyPool (
1756 ChildSaSession->Spd->Selector->RemoteAddressCount *
1757 sizeof (EFI_IP_ADDRESS_INFO),
1758 ChildSaSession->Spd->Selector->RemoteAddress
1759 );
1760 ChildSaSession->SpdSelector->LocalAddress = AllocateCopyPool (
1761 ChildSaSession->Spd->Selector->LocalAddressCount *
1762 sizeof (EFI_IP_ADDRESS_INFO),
1763 ChildSaSession->Spd->Selector->LocalAddress
1764 );
1765
1766 ASSERT (ChildSaSession->SpdSelector->LocalAddress != NULL);
1767 ASSERT (ChildSaSession->SpdSelector->RemoteAddress != NULL);
1768
1769 ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->Spd->Selector->RemoteAddressCount;
1770 ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->Spd->Selector->LocalAddressCount;
1771 }
1772 }
1773
1774 /**
1775 Generate a ChildSa Session and insert it into related IkeSaSession.
1776
1777 @param[in] IkeSaSession Pointer to related IKEV2_SA_SESSION.
1778 @param[in] UdpService Pointer to related IKE_UDP_SERVICE.
1779
1780 @return pointer of IKEV2_CHILD_SA_SESSION.
1781
1782 **/
1783 IKEV2_CHILD_SA_SESSION *
1784 Ikev2ChildSaSessionCreate (
1785 IN IKEV2_SA_SESSION *IkeSaSession,
1786 IN IKE_UDP_SERVICE *UdpService
1787 )
1788 {
1789 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1790 IKEV2_SESSION_COMMON *ChildSaCommon;
1791
1792 //
1793 // Create a new ChildSaSession.Insert it into processing list and initiate the common parameters.
1794 //
1795 ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, IkeSaSession);
1796 ASSERT (ChildSaSession != NULL);
1797
1798 //
1799 // Set the specific parameters.
1800 //
1801 ChildSaSession->Spd = IkeSaSession->Spd;
1802 ChildSaCommon = &ChildSaSession->SessionCommon;
1803 ChildSaCommon->IsInitiator = IkeSaSession->SessionCommon.IsInitiator;
1804 if (IkeSaSession->SessionCommon.State == IkeStateAuth) {
1805 ChildSaCommon->State = IkeStateAuth;
1806 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateAuth);
1807 } else {
1808 ChildSaCommon->State = IkeStateCreateChild;
1809 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);
1810 }
1811
1812 //
1813 // If SPD->Selector is not NULL, copy it to the ChildSaSession->SpdSelector.
1814 // The ChildSaSession->SpdSelector might be changed after the traffic selector
1815 // negoniation and it will be copied into the SAData after ChildSA established.
1816 //
1817 Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
1818
1819 //
1820 // Copy first NiBlock and NrBlock to ChildSa Session
1821 //
1822 ChildSaSession->NiBlock = AllocateZeroPool (IkeSaSession->NiBlkSize);
1823 ASSERT (ChildSaSession->NiBlock != NULL);
1824 ChildSaSession->NiBlkSize = IkeSaSession->NiBlkSize;
1825 CopyMem (ChildSaSession->NiBlock, IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
1826
1827 ChildSaSession->NrBlock = AllocateZeroPool (IkeSaSession->NrBlkSize);
1828 ASSERT (ChildSaSession->NrBlock != NULL);
1829 ChildSaSession->NrBlkSize = IkeSaSession->NrBlkSize;
1830 CopyMem (ChildSaSession->NrBlock, IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
1831
1832 //
1833 // Only if the Create Child SA is called for the IKE_INIT Exchange and
1834 // IkeSaSession is initiator (Only Initiator's SPD is not NULL), Set the
1835 // Traffic Selectors related information here.
1836 //
1837 if (IkeSaSession->SessionCommon.State == IkeStateAuth && IkeSaSession->Spd != NULL) {
1838 ChildSaSession->ProtoId = IkeSaSession->Spd->Selector->NextLayerProtocol;
1839 ChildSaSession->LocalPort = IkeSaSession->Spd->Selector->LocalPort;
1840 ChildSaSession->RemotePort = IkeSaSession->Spd->Selector->RemotePort;
1841 }
1842
1843 //
1844 // Insert the new ChildSaSession into processing child SA list.
1845 //
1846 Ikev2ChildSaSessionInsert (&IkeSaSession->ChildSaSessionList, ChildSaSession);
1847 return ChildSaSession;
1848 }
1849
1850 /**
1851 Check if the SPD is related to the input Child SA Session.
1852
1853 This function is the subfunction of Ikev1AssociateSpdEntry(). It is the call
1854 back function of IpSecVisitConfigData().
1855
1856
1857 @param[in] Type Type of the input Config Selector.
1858 @param[in] Selector Pointer to the Configure Selector to be checked.
1859 @param[in] Data Pointer to the Configure Selector's Data passed
1860 from the caller.
1861 @param[in] SelectorSize The buffer size of Selector.
1862 @param[in] DataSize The buffer size of the Data.
1863 @param[in] Context The data passed from the caller. It is a Child
1864 SA Session in this context.
1865
1866 @retval EFI_SUCCESS The SPD Selector is not related to the Child SA Session.
1867 @retval EFI_ABORTED The SPD Selector is related to the Child SA session and
1868 set the ChildSaSession->Spd to point to this SPD Selector.
1869
1870 **/
1871 EFI_STATUS
1872 Ikev2MatchSpdEntry (
1873 IN EFI_IPSEC_CONFIG_DATA_TYPE Type,
1874 IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
1875 IN VOID *Data,
1876 IN UINTN SelectorSize,
1877 IN UINTN DataSize,
1878 IN VOID *Context
1879 )
1880 {
1881 IKEV2_CHILD_SA_SESSION *ChildSaSession;
1882 EFI_IPSEC_SPD_SELECTOR *SpdSelector;
1883 EFI_IPSEC_SPD_DATA *SpdData;
1884 BOOLEAN IsMatch;
1885 UINT8 IpVersion;
1886
1887 ASSERT (Type == IPsecConfigDataTypeSpd);
1888 SpdData = (EFI_IPSEC_SPD_DATA *) Data;
1889 //
1890 // Bypass all non-protect SPD entry first
1891 //
1892 if (SpdData->Action != EfiIPsecActionProtect) {
1893 return EFI_SUCCESS;
1894 }
1895
1896 ChildSaSession = (IKEV2_CHILD_SA_SESSION *) Context;
1897 IpVersion = ChildSaSession->SessionCommon.UdpService->IpVersion;
1898 SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) Selector;
1899 IsMatch = TRUE;
1900
1901 if (SpdSelector->NextLayerProtocol == EFI_IP_PROTO_UDP &&
1902 SpdSelector->LocalPort == IKE_DEFAULT_PORT &&
1903 SpdSelector->LocalPortRange == 0 &&
1904 SpdSelector->RemotePort == IKE_DEFAULT_PORT &&
1905 SpdSelector->RemotePortRange == 0
1906 ) {
1907 //
1908 // TODO: Skip IKE Policy here or set a SPD entry?
1909 //
1910 return EFI_SUCCESS;
1911 }
1912
1913 if (SpdSelector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL &&
1914 SpdSelector->NextLayerProtocol != ChildSaSession->ProtoId
1915 ) {
1916 IsMatch = FALSE;
1917 }
1918
1919 if (SpdSelector->LocalPort != EFI_IPSEC_ANY_PORT && SpdSelector->LocalPort != ChildSaSession->LocalPort) {
1920 IsMatch = FALSE;
1921 }
1922
1923 if (SpdSelector->RemotePort != EFI_IPSEC_ANY_PORT && SpdSelector->RemotePort != ChildSaSession->RemotePort) {
1924 IsMatch = FALSE;
1925 }
1926
1927 IsMatch = (BOOLEAN) (IsMatch &&
1928 IpSecMatchIpAddress (
1929 IpVersion,
1930 &ChildSaSession->SessionCommon.LocalPeerIp,
1931 SpdSelector->LocalAddress,
1932 SpdSelector->LocalAddressCount
1933 ));
1934
1935 IsMatch = (BOOLEAN) (IsMatch &&
1936 IpSecMatchIpAddress (
1937 IpVersion,
1938 &ChildSaSession->SessionCommon.RemotePeerIp,
1939 SpdSelector->RemoteAddress,
1940 SpdSelector->RemoteAddressCount
1941 ));
1942
1943 if (IsMatch) {
1944 ChildSaSession->Spd = IkeSearchSpdEntry (SpdSelector);
1945 return EFI_ABORTED;
1946 } else {
1947 return EFI_SUCCESS;
1948 }
1949 }
1950
1951 /**
1952 Check if the Algorithm ID is supported.
1953
1954 @param[in] AlgorithmId The specified Algorithm ID.
1955 @param[in] Type The type used to indicate the Algorithm is for Encrypt or
1956 Authentication.
1957
1958 @retval TRUE If the Algorithm ID is supported.
1959 @retval FALSE If the Algorithm ID is not supported.
1960
1961 **/
1962 BOOLEAN
1963 Ikev2IsSupportAlg (
1964 IN UINT16 AlgorithmId,
1965 IN UINT8 Type
1966 )
1967 {
1968 UINT8 Index;
1969 switch (Type) {
1970 case IKE_ENCRYPT_TYPE :
1971 for (Index = 0; Index < IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM; Index++) {
1972 if (mIkev2EncryptAlgorithmList[Index] == AlgorithmId) {
1973 return TRUE;
1974 }
1975 }
1976 break;
1977
1978 case IKE_AUTH_TYPE :
1979 for (Index = 0; Index < IKEV2_SUPPORT_AUTH_ALGORITHM_NUM; Index++) {
1980 if (mIkev2AuthAlgorithmList[Index] == AlgorithmId) {
1981 return TRUE;
1982 }
1983 }
1984 break;
1985
1986 case IKE_DH_TYPE :
1987 for (Index = 0; Index < IKEV2_SUPPORT_DH_ALGORITHM_NUM; Index++) {
1988 if (mIkev2DhGroupAlgorithmList[Index] == AlgorithmId) {
1989 return TRUE;
1990 }
1991 }
1992 break;
1993
1994 case IKE_PRF_TYPE :
1995 for (Index = 0; Index < IKEV2_SUPPORT_PRF_ALGORITHM_NUM; Index++) {
1996 if (mIkev2PrfAlgorithmList[Index] == AlgorithmId) {
1997 return TRUE;
1998 }
1999 }
2000 }
2001 return FALSE;
2002 }
2003
2004 /**
2005 Get the preferred algorithm types from ProposalData.
2006
2007 @param[in] ProposalData Pointer to related IKEV2_PROPOSAL_DATA.
2008 @param[out] PreferEncryptAlgorithm Output of preferred encrypt algorithm.
2009 @param[out] PreferIntegrityAlgorithm Output of preferred integrity algorithm.
2010 @param[out] PreferPrfAlgorithm Output of preferred PRF algorithm. Only
2011 for IKE SA.
2012 @param[out] PreferDhGroup Output of preferred DH group. Only for
2013 IKE SA.
2014 @param[out] PreferEncryptKeylength Output of preferred encrypt key length
2015 in bytes.
2016 @param[out] IsSupportEsn Output of value about the Extented Sequence
2017 Number is support or not. Only for Child SA.
2018 @param[in] IsChildSa If it is ture, the ProposalData is for IKE
2019 SA. Otherwise the proposalData is for Child SA.
2020
2021 **/
2022 VOID
2023 Ikev2ParseProposalData (
2024 IN IKEV2_PROPOSAL_DATA *ProposalData,
2025 OUT UINT16 *PreferEncryptAlgorithm,
2026 OUT UINT16 *PreferIntegrityAlgorithm,
2027 OUT UINT16 *PreferPrfAlgorithm,
2028 OUT UINT16 *PreferDhGroup,
2029 OUT UINTN *PreferEncryptKeylength,
2030 OUT BOOLEAN *IsSupportEsn,
2031 IN BOOLEAN IsChildSa
2032 )
2033 {
2034 IKEV2_TRANSFORM_DATA *TransformData;
2035 UINT8 TransformIndex;
2036
2037 //
2038 // Check input parameters.
2039 //
2040 if (ProposalData == NULL ||
2041 PreferEncryptAlgorithm == NULL ||
2042 PreferIntegrityAlgorithm == NULL ||
2043 PreferEncryptKeylength == NULL
2044 ) {
2045 return;
2046 }
2047
2048 if (IsChildSa) {
2049 if (IsSupportEsn == NULL) {
2050 return;
2051 }
2052 } else {
2053 if (PreferPrfAlgorithm == NULL || PreferDhGroup == NULL) {
2054 return;
2055 }
2056 }
2057
2058 TransformData = (IKEV2_TRANSFORM_DATA *)(ProposalData + 1);
2059 for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {
2060 switch (TransformData->TransformType) {
2061 //
2062 // For IKE SA there are four algorithm types. Encryption Algorithm, Pseudo-random Function,
2063 // Integrity Algorithm, Diffie-Hellman Group. For Child SA, there are three algorithm types.
2064 // Encryption Algorithm, Integrity Algorithm, Extended Sequence Number.
2065 //
2066 case IKEV2_TRANSFORM_TYPE_ENCR:
2067 if (*PreferEncryptAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_ENCRYPT_TYPE)) {
2068 //
2069 // Check the attribute value. According to RFC, only Keylength is support.
2070 //
2071 if (TransformData->Attribute.AttrType == IKEV2_ATTRIBUTE_TYPE_KEYLEN) {
2072 //
2073 // If the Keylength is not support, continue to check the next one.
2074 //
2075 if (IpSecGetEncryptKeyLength ((UINT8)TransformData->TransformId) != (UINTN)(TransformData->Attribute.Attr.AttrValue >> 3)){
2076 break;
2077 } else {
2078 *PreferEncryptKeylength = TransformData->Attribute.Attr.AttrValue;
2079 }
2080 }
2081 *PreferEncryptAlgorithm = TransformData->TransformId;
2082 }
2083 break;
2084
2085 case IKEV2_TRANSFORM_TYPE_PRF :
2086 if (!IsChildSa) {
2087 if (*PreferPrfAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_PRF_TYPE)) {
2088 *PreferPrfAlgorithm = TransformData->TransformId;
2089 }
2090 }
2091 break;
2092
2093 case IKEV2_TRANSFORM_TYPE_INTEG :
2094 if (*PreferIntegrityAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_AUTH_TYPE)) {
2095 *PreferIntegrityAlgorithm = TransformData->TransformId;
2096 }
2097 break;
2098
2099 case IKEV2_TRANSFORM_TYPE_DH :
2100 if (!IsChildSa) {
2101 if (*PreferDhGroup == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_DH_TYPE)) {
2102 *PreferDhGroup = TransformData->TransformId;
2103 }
2104 }
2105 break;
2106
2107 case IKEV2_TRANSFORM_TYPE_ESN :
2108 if (IsChildSa) {
2109 if (TransformData->TransformId != 0) {
2110 *IsSupportEsn = TRUE;
2111 }
2112 }
2113 break;
2114
2115 default:
2116 break;
2117 }
2118 TransformData = (IKEV2_TRANSFORM_DATA *)(TransformData + 1);
2119 }
2120 }
2121
2122 /**
2123 Parse the received Initial Exchange Packet.
2124
2125 This function parse the SA Payload and Key Payload to find out the cryptographic
2126 suite for the further IKE negotiation and fill it into the IKE SA Session's
2127 CommonSession->SaParams.
2128
2129 @param[in, out] IkeSaSession Pointer to related IKEV2_SA_SESSION.
2130 @param[in] SaPayload The received packet.
2131 @param[in] Type The received packet IKE header flag.
2132
2133 @retval TRUE If the SA proposal in Packet is acceptable.
2134 @retval FALSE If the SA proposal in Packet is not acceptable.
2135
2136 **/
2137 BOOLEAN
2138 Ikev2SaParseSaPayload (
2139 IN OUT IKEV2_SA_SESSION *IkeSaSession,
2140 IN IKE_PAYLOAD *SaPayload,
2141 IN UINT8 Type
2142 )
2143 {
2144 IKEV2_PROPOSAL_DATA *ProposalData;
2145 UINT8 ProposalIndex;
2146 UINT16 PreferEncryptAlgorithm;
2147 UINT16 PreferIntegrityAlgorithm;
2148 UINT16 PreferPrfAlgorithm;
2149 UINT16 PreferDhGroup;
2150 UINTN PreferEncryptKeylength;
2151 UINT16 EncryptAlgorithm;
2152 UINT16 IntegrityAlgorithm;
2153 UINT16 PrfAlgorithm;
2154 UINT16 DhGroup;
2155 UINTN EncryptKeylength;
2156 BOOLEAN IsMatch;
2157 UINTN SaDataSize;
2158
2159 PreferPrfAlgorithm = 0;
2160 PreferIntegrityAlgorithm = 0;
2161 PreferDhGroup = 0;
2162 PreferEncryptAlgorithm = 0;
2163 PreferEncryptKeylength = 0;
2164 PrfAlgorithm = 0;
2165 IntegrityAlgorithm = 0;
2166 DhGroup = 0;
2167 EncryptAlgorithm = 0;
2168 EncryptKeylength = 0;
2169 IsMatch = FALSE;
2170
2171 if (Type == IKE_HEADER_FLAGS_INIT) {
2172 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2173 for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *)SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {
2174 //
2175 // Iterate each proposal to find the perfered one.
2176 //
2177 if (ProposalData->ProtocolId == IPSEC_PROTO_ISAKMP && ProposalData->NumTransforms >= 4) {
2178 //
2179 // Get the preferred algorithms.
2180 //
2181 Ikev2ParseProposalData (
2182 ProposalData,
2183 &PreferEncryptAlgorithm,
2184 &PreferIntegrityAlgorithm,
2185 &PreferPrfAlgorithm,
2186 &PreferDhGroup,
2187 &PreferEncryptKeylength,
2188 NULL,
2189 FALSE
2190 );
2191
2192 if (PreferEncryptAlgorithm != 0 &&
2193 PreferIntegrityAlgorithm != 0 &&
2194 PreferPrfAlgorithm != 0 &&
2195 PreferDhGroup != 0
2196 ) {
2197 //
2198 // Find the matched one.
2199 //
2200 IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2201 ASSERT (IkeSaSession->SessionCommon.SaParams != NULL);
2202 IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2203 IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2204 IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;
2205 IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;
2206 IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2207 IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;
2208
2209 //
2210 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2211 //
2212 SaDataSize = sizeof (IKEV2_SA_DATA) +
2213 sizeof (IKEV2_PROPOSAL_DATA) +
2214 sizeof (IKEV2_TRANSFORM_DATA) * 4;
2215 IkeSaSession->SaData = AllocateZeroPool (SaDataSize);
2216 ASSERT (IkeSaSession->SaData != NULL);
2217
2218 IkeSaSession->SaData->NumProposals = 1;
2219
2220 //
2221 // BUGBUG: Suppose the matched proposal only has 4 transforms. If
2222 // The matched Proposal has more than 4 transforms means it contains
2223 // one than one transform with same type.
2224 //
2225 CopyMem (
2226 (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1),
2227 ProposalData,
2228 SaDataSize - sizeof (IKEV2_SA_DATA)
2229 );
2230
2231 ((IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1))->ProposalIndex = 1;
2232 return TRUE;
2233 } else {
2234 PreferEncryptAlgorithm = 0;
2235 PreferIntegrityAlgorithm = 0;
2236 PreferPrfAlgorithm = 0;
2237 PreferDhGroup = 0;
2238 PreferEncryptKeylength = 0;
2239 }
2240 }
2241 //
2242 // Point to next Proposal.
2243 //
2244 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2245 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2246 }
2247 } else if (Type == IKE_HEADER_FLAGS_RESPOND) {
2248 //
2249 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2250 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2251 // is 4.
2252 //
2253 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);
2254 if (ProposalData->ProtocolId != IPSEC_PROTO_ISAKMP || ProposalData->NumTransforms != 4) {
2255 return FALSE;
2256 }
2257 //
2258 // Get the preferred algorithms.
2259 //
2260 Ikev2ParseProposalData (
2261 ProposalData,
2262 &PreferEncryptAlgorithm,
2263 &PreferIntegrityAlgorithm,
2264 &PreferPrfAlgorithm,
2265 &PreferDhGroup,
2266 &PreferEncryptKeylength,
2267 NULL,
2268 FALSE
2269 );
2270 //
2271 // Check if the Sa proposal data from received packet is in the IkeSaSession->SaData.
2272 //
2273 ProposalData = (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1);
2274
2275 for (ProposalIndex = 0; ProposalIndex < IkeSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {
2276 Ikev2ParseProposalData (
2277 ProposalData,
2278 &EncryptAlgorithm,
2279 &IntegrityAlgorithm,
2280 &PrfAlgorithm,
2281 &DhGroup,
2282 &EncryptKeylength,
2283 NULL,
2284 FALSE
2285 );
2286 if (EncryptAlgorithm == PreferEncryptAlgorithm &&
2287 EncryptKeylength == PreferEncryptKeylength &&
2288 IntegrityAlgorithm == PreferIntegrityAlgorithm &&
2289 PrfAlgorithm == PreferPrfAlgorithm &&
2290 DhGroup == PreferDhGroup
2291 ) {
2292 IsMatch = TRUE;
2293 } else {
2294 EncryptAlgorithm = 0;
2295 IntegrityAlgorithm = 0;
2296 PrfAlgorithm = 0;
2297 DhGroup = 0;
2298 EncryptKeylength = 0;
2299 }
2300
2301 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2302 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2303 }
2304
2305 if (IsMatch) {
2306 IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2307 ASSERT (IkeSaSession->SessionCommon.SaParams != NULL);
2308 IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2309 IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2310 IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;
2311 IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;
2312 IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2313 IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;
2314
2315 return TRUE;
2316 }
2317 }
2318 return FALSE;
2319 }
2320
2321 /**
2322 Parse the received Authentication Exchange Packet.
2323
2324 This function parse the SA Payload and Key Payload to find out the cryptographic
2325 suite for the ESP and fill it into the Child SA Session's CommonSession->SaParams.
2326
2327 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to
2328 this Authentication Exchange.
2329 @param[in] SaPayload The received packet.
2330 @param[in] Type The IKE header's flag of received packet .
2331
2332 @retval TRUE If the SA proposal in Packet is acceptable.
2333 @retval FALSE If the SA proposal in Packet is not acceptable.
2334
2335 **/
2336 BOOLEAN
2337 Ikev2ChildSaParseSaPayload (
2338 IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession,
2339 IN IKE_PAYLOAD *SaPayload,
2340 IN UINT8 Type
2341 )
2342 {
2343 IKEV2_PROPOSAL_DATA *ProposalData;
2344 UINT8 ProposalIndex;
2345 UINT16 PreferEncryptAlgorithm;
2346 UINT16 PreferIntegrityAlgorithm;
2347 UINTN PreferEncryptKeylength;
2348 BOOLEAN PreferIsSupportEsn;
2349 UINT16 EncryptAlgorithm;
2350 UINT16 IntegrityAlgorithm;
2351 UINTN EncryptKeylength;
2352 BOOLEAN IsSupportEsn;
2353 BOOLEAN IsMatch;
2354 UINTN SaDataSize;
2355
2356
2357 PreferIntegrityAlgorithm = 0;
2358 PreferEncryptAlgorithm = 0;
2359 PreferEncryptKeylength = 0;
2360 IntegrityAlgorithm = 0;
2361 EncryptAlgorithm = 0;
2362 EncryptKeylength = 0;
2363 IsMatch = TRUE;
2364 IsSupportEsn = FALSE;
2365 PreferIsSupportEsn = FALSE;
2366
2367 if (Type == IKE_HEADER_FLAGS_INIT) {
2368 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);
2369 for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *) SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {
2370 //
2371 // Iterate each proposal to find the preferred one.
2372 //
2373 if (ProposalData->ProtocolId == IPSEC_PROTO_IPSEC_ESP && ProposalData->NumTransforms >= 3) {
2374 //
2375 // Get the preferred algorithm.
2376 //
2377 Ikev2ParseProposalData (
2378 ProposalData,
2379 &PreferEncryptAlgorithm,
2380 &PreferIntegrityAlgorithm,
2381 NULL,
2382 NULL,
2383 &PreferEncryptKeylength,
2384 &IsSupportEsn,
2385 TRUE
2386 );
2387 //
2388 // Don't support the ESN now.
2389 //
2390 if (PreferEncryptAlgorithm != 0 &&
2391 PreferIntegrityAlgorithm != 0 &&
2392 !IsSupportEsn
2393 ) {
2394 //
2395 // Find the matched one.
2396 //
2397 ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2398 ASSERT (ChildSaSession->SessionCommon.SaParams != NULL);
2399 ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2400 ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2401 ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2402 CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));
2403
2404 //
2405 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2406 //
2407 SaDataSize = sizeof (IKEV2_SA_DATA) +
2408 sizeof (IKEV2_PROPOSAL_DATA) +
2409 sizeof (IKEV2_TRANSFORM_DATA) * 4;
2410
2411 ChildSaSession->SaData = AllocateZeroPool (SaDataSize);
2412 ASSERT (ChildSaSession->SaData != NULL);
2413
2414 ChildSaSession->SaData->NumProposals = 1;
2415
2416 //
2417 // BUGBUG: Suppose there are 4 transforms in the matched proposal. If
2418 // the matched Proposal has more than 4 transforms that means there
2419 // are more than one transform with same type.
2420 //
2421 CopyMem (
2422 (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1),
2423 ProposalData,
2424 SaDataSize - sizeof (IKEV2_SA_DATA)
2425 );
2426
2427 ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->ProposalIndex = 1;
2428
2429 ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi = AllocateCopyPool (
2430 sizeof (ChildSaSession->LocalPeerSpi),
2431 &ChildSaSession->LocalPeerSpi
2432 );
2433 ASSERT (((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi != NULL);
2434 return TRUE;
2435
2436 } else {
2437 PreferEncryptAlgorithm = 0;
2438 PreferIntegrityAlgorithm = 0;
2439 IsSupportEsn = TRUE;
2440 }
2441 }
2442 //
2443 // Point to next Proposal
2444 //
2445 ProposalData = (IKEV2_PROPOSAL_DATA *)((UINT8 *)(ProposalData + 1) +
2446 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2447 }
2448 } else if (Type == IKE_HEADER_FLAGS_RESPOND) {
2449 //
2450 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2451 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2452 // is 3.
2453 //
2454 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2455 if (ProposalData->ProtocolId != IPSEC_PROTO_IPSEC_ESP || ProposalData->NumTransforms != 3) {
2456 return FALSE;
2457 }
2458 //
2459 // Get the preferred algorithms.
2460 //
2461 Ikev2ParseProposalData (
2462 ProposalData,
2463 &PreferEncryptAlgorithm,
2464 &PreferIntegrityAlgorithm,
2465 NULL,
2466 NULL,
2467 &PreferEncryptKeylength,
2468 &PreferIsSupportEsn,
2469 TRUE
2470 );
2471
2472 ProposalData = (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1);
2473
2474 for (ProposalIndex = 0; ProposalIndex < ChildSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {
2475 Ikev2ParseProposalData (
2476 ProposalData,
2477 &EncryptAlgorithm,
2478 &IntegrityAlgorithm,
2479 NULL,
2480 NULL,
2481 &EncryptKeylength,
2482 &IsSupportEsn,
2483 TRUE
2484 );
2485 if (EncryptAlgorithm == PreferEncryptAlgorithm &&
2486 EncryptKeylength == PreferEncryptKeylength &&
2487 IntegrityAlgorithm == PreferIntegrityAlgorithm &&
2488 IsSupportEsn == PreferIsSupportEsn
2489 ) {
2490 IsMatch = TRUE;
2491 } else {
2492 PreferEncryptAlgorithm = 0;
2493 PreferIntegrityAlgorithm = 0;
2494 IsSupportEsn = TRUE;
2495 }
2496 ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +
2497 ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));
2498 }
2499
2500 ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);
2501 if (IsMatch) {
2502 ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));
2503 ASSERT (ChildSaSession->SessionCommon.SaParams != NULL);
2504 ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;
2505 ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;
2506 ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;
2507 CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));
2508
2509 return TRUE;
2510 }
2511 }
2512 return FALSE;
2513 }
2514
2515 /**
2516 Generate Key buffer from fragments.
2517
2518 If the digest length of specified HashAlgId is larger than or equal with the
2519 required output key length, derive the key directly. Otherwise, Key Material
2520 needs to be PRF-based concatenation according to 2.13 of RFC 4306:
2521 prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2522 T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2523 then derive the key from this key material.
2524
2525 @param[in] HashAlgId The Hash Algorithm ID used to generate key.
2526 @param[in] HashKey Pointer to a key buffer which contains hash key.
2527 @param[in] HashKeyLength The length of HashKey in bytes.
2528 @param[in, out] OutputKey Pointer to buffer which is used to receive the
2529 output key.
2530 @param[in] OutputKeyLength The length of OutPutKey buffer.
2531 @param[in] Fragments Pointer to the data to be used to generate key.
2532 @param[in] NumFragments The numbers of the Fragement.
2533
2534 @retval EFI_SUCCESS The operation complete successfully.
2535 @retval EFI_INVALID_PARAMETER If NumFragments is zero.
2536 @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.
2537 @retval Others The operation is failed.
2538
2539 **/
2540 EFI_STATUS
2541 Ikev2SaGenerateKey (
2542 IN UINT8 HashAlgId,
2543 IN UINT8 *HashKey,
2544 IN UINTN HashKeyLength,
2545 IN OUT UINT8 *OutputKey,
2546 IN UINTN OutputKeyLength,
2547 IN PRF_DATA_FRAGMENT *Fragments,
2548 IN UINTN NumFragments
2549 )
2550 {
2551 EFI_STATUS Status;
2552 PRF_DATA_FRAGMENT LocalFragments[3];
2553 UINT8 *Digest;
2554 UINTN DigestSize;
2555 UINTN Round;
2556 UINTN Index;
2557 UINTN AuthKeyLength;
2558 UINTN FragmentsSize;
2559 UINT8 TailData;
2560
2561 Status = EFI_SUCCESS;
2562
2563 if (NumFragments == 0) {
2564 return EFI_INVALID_PARAMETER;
2565 }
2566
2567 LocalFragments[0].Data = NULL;
2568 LocalFragments[1].Data = NULL;
2569 LocalFragments[2].Data = NULL;
2570
2571 AuthKeyLength = IpSecGetHmacDigestLength (HashAlgId);
2572 DigestSize = AuthKeyLength;
2573 Digest = AllocateZeroPool (AuthKeyLength);
2574
2575 if (Digest == NULL) {
2576 return EFI_OUT_OF_RESOURCES;
2577 }
2578 //
2579 // If the required output key length is less than the digest size,
2580 // copy the digest into OutputKey.
2581 //
2582 if (OutputKeyLength <= DigestSize) {
2583 Status = IpSecCryptoIoHmac (
2584 HashAlgId,
2585 HashKey,
2586 HashKeyLength,
2587 (HASH_DATA_FRAGMENT *) Fragments,
2588 NumFragments,
2589 Digest,
2590 DigestSize
2591 );
2592 if (EFI_ERROR (Status)) {
2593 goto Exit;
2594 }
2595
2596 CopyMem (OutputKey, Digest, OutputKeyLength);
2597 goto Exit;
2598 }
2599
2600 //
2601 //Otherwise, Key Material need to be PRF-based concatenation according to 2.13
2602 //of RFC 4306: prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2603 //T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2604 //then derive the key from this key material.
2605 //
2606 FragmentsSize = 0;
2607 for (Index = 0; Index < NumFragments; Index++) {
2608 FragmentsSize = FragmentsSize + Fragments[Index].DataSize;
2609 }
2610
2611 LocalFragments[1].Data = AllocateZeroPool (FragmentsSize);
2612 ASSERT (LocalFragments[1].Data != NULL);
2613 LocalFragments[1].DataSize = FragmentsSize;
2614
2615 //
2616 // Copy all input fragments into LocalFragments[1];
2617 //
2618 FragmentsSize = 0;
2619 for (Index = 0; Index < NumFragments; Index++) {
2620 CopyMem (
2621 LocalFragments[1].Data + FragmentsSize,
2622 Fragments[Index].Data,
2623 Fragments[Index].DataSize
2624 );
2625 FragmentsSize = FragmentsSize + Fragments[Index].DataSize;
2626 }
2627
2628 //
2629 // Prepare 0x01 as the first tail data.
2630 //
2631 TailData = 0x01;
2632 LocalFragments[2].Data = &TailData;
2633 LocalFragments[2].DataSize = sizeof (TailData);
2634 //
2635 // Allocate buffer for the first fragment
2636 //
2637 LocalFragments[0].Data = AllocateZeroPool (AuthKeyLength);
2638 ASSERT (LocalFragments[0].Data != NULL);
2639 LocalFragments[0].DataSize = AuthKeyLength;
2640
2641 Round = (OutputKeyLength - 1) / AuthKeyLength + 1;
2642 for (Index = 0; Index < Round; Index++) {
2643 Status = IpSecCryptoIoHmac (
2644 HashAlgId,
2645 HashKey,
2646 HashKeyLength,
2647 (HASH_DATA_FRAGMENT *)(Index == 0 ? &LocalFragments[1] : LocalFragments),
2648 Index == 0 ? 2 : 3,
2649 Digest,
2650 DigestSize
2651 );
2652 if (EFI_ERROR(Status)) {
2653 goto Exit;
2654 }
2655 CopyMem (
2656 LocalFragments[0].Data,
2657 Digest,
2658 DigestSize
2659 );
2660 if (OutputKeyLength > DigestSize * (Index + 1)) {
2661 CopyMem (
2662 OutputKey + Index * DigestSize,
2663 Digest,
2664 DigestSize
2665 );
2666 LocalFragments[0].DataSize = DigestSize;
2667 TailData ++;
2668 } else {
2669 //
2670 // The last round
2671 //
2672 CopyMem (
2673 OutputKey + Index * DigestSize,
2674 Digest,
2675 OutputKeyLength - Index * DigestSize
2676 );
2677 }
2678 }
2679
2680 Exit:
2681 //
2682 // Only First and second Framgement Data need to be freed.
2683 //
2684 for (Index = 0 ; Index < 2; Index++) {
2685 if (LocalFragments[Index].Data != NULL) {
2686 FreePool (LocalFragments[Index].Data);
2687 }
2688 }
2689 if (Digest != NULL) {
2690 FreePool (Digest);
2691 }
2692 return Status;
2693 }
2694