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