• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The operations for IKEv2 SA.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2010 - 2011, 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 "Ikev2.h"
21 
22 /**
23   Generates the DH Key.
24 
25   This generates the DH local public key and store it in the IKEv2 SA Session's GxBuffer.
26 
27   @param[in]  IkeSaSession   Pointer to related IKE SA Session.
28 
29   @retval EFI_SUCCESS        The operation succeeded.
30   @retval Others             The operation failed.
31 
32 **/
33 EFI_STATUS
34 Ikev2GenerateSaDhPublicKey (
35   IN IKEV2_SA_SESSION         *IkeSaSession
36   );
37 
38 /**
39   Generates the IKEv2 SA key for the furthure IKEv2 exchange.
40 
41   @param[in]  IkeSaSession       Pointer to IKEv2 SA Session.
42   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
43 
44   @retval EFI_UNSUPPORTED    If the Algorithm Id is not supported.
45   @retval EFI_SUCCESS        The operation succeeded.
46 
47 **/
48 EFI_STATUS
49 Ikev2GenerateSaKeys (
50   IN IKEV2_SA_SESSION       *IkeSaSession,
51   IN IKE_PAYLOAD            *KePayload
52   );
53 
54 /**
55   Generates the Keys for the furthure IPsec Protocol.
56 
57   @param[in]  ChildSaSession     Pointer to IKE Child SA Session.
58   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
59 
60   @retval EFI_UNSUPPORTED    If one or more Algorithm Id is unsupported.
61   @retval EFI_SUCCESS        The operation succeeded.
62 
63 **/
64 EFI_STATUS
65 Ikev2GenerateChildSaKeys (
66   IN IKEV2_CHILD_SA_SESSION     *ChildSaSession,
67   IN IKE_PAYLOAD                *KePayload
68   );
69 
70 /**
71   Gernerates IKEv2 packet for IKE_SA_INIT exchange.
72 
73   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
74   @param[in] Context    Context Data passed by caller.
75 
76   @retval EFI_SUCCESS   The IKEv2 packet generation succeeded.
77   @retval Others        The IKEv2 packet generation failed.
78 
79 **/
80 IKE_PACKET *
Ikev2InitPskGenerator(IN UINT8 * SaSession,IN VOID * Context)81 Ikev2InitPskGenerator (
82   IN UINT8           *SaSession,
83   IN VOID            *Context
84   )
85 {
86   IKE_PACKET         *IkePacket;
87   IKEV2_SA_SESSION   *IkeSaSession;
88   IKE_PAYLOAD        *SaPayload;
89   IKE_PAYLOAD        *KePayload;
90   IKE_PAYLOAD        *NoncePayload;
91   IKE_PAYLOAD        *NotifyPayload;
92   EFI_STATUS         Status;
93 
94   SaPayload      = NULL;
95   KePayload      = NULL;
96   NoncePayload   = NULL;
97   NotifyPayload  = NULL;
98 
99   IkeSaSession = (IKEV2_SA_SESSION *) SaSession;
100 
101   //
102   // 1. Allocate IKE packet
103   //
104   IkePacket = IkePacketAlloc ();
105   ASSERT (IkePacket != NULL);
106 
107   //
108   // 1.a Fill the IkePacket->Hdr
109   //
110   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_INIT;
111   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
112   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
113   IkePacket->Header->Version         = (UINT8) (2 << 4);
114   IkePacket->Header->MessageId       = 0;
115 
116   if (IkeSaSession->SessionCommon.IsInitiator) {
117     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
118   } else {
119     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
120   }
121 
122   //
123   // If the NCookie is not NULL, this IKE_SA_INIT packet is resent by the NCookie
124   // and the NCookie payload should be the first payload in this packet.
125   //
126   if (IkeSaSession->NCookie != NULL) {
127     IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NOTIFY;
128     NotifyPayload = Ikev2GenerateNotifyPayload (
129                       IPSEC_PROTO_ISAKMP,
130                       IKEV2_PAYLOAD_TYPE_SA,
131                       0,
132                       IKEV2_NOTIFICATION_COOKIE,
133                       NULL,
134                       IkeSaSession->NCookie,
135                       IkeSaSession->NCookieSize
136                       );
137   } else {
138     IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_SA;
139   }
140 
141   //
142   // 2. Generate SA Payload according to the SaData & SaParams
143   //
144   SaPayload = Ikev2GenerateSaPayload (
145                 IkeSaSession->SaData,
146                 IKEV2_PAYLOAD_TYPE_KE,
147                 IkeSessionTypeIkeSa
148                 );
149 
150   //
151   // 3. Generate DH public key.
152   //    The DhPrivate Key has been generated in Ikev2InitPskParser, if the
153   //    IkeSaSession is responder. If resending IKE_SA_INIT with Cookie Notify
154   //    No need to recompute the Public key.
155   //
156   if ((IkeSaSession->SessionCommon.IsInitiator) && (IkeSaSession->NCookie == NULL)) {
157     Status = Ikev2GenerateSaDhPublicKey (IkeSaSession);
158     if (EFI_ERROR (Status)) {
159       goto CheckError;
160     }
161   }
162 
163   //
164   // 4. Generate KE Payload according to SaParams->DhGroup
165   //
166   KePayload = Ikev2GenerateKePayload (
167                 IkeSaSession,
168                 IKEV2_PAYLOAD_TYPE_NONCE
169                 );
170 
171   //
172   // 5. Generate Nonce Payload
173   //    If resending IKE_SA_INIT with Cookie Notify paylaod, no need to regenerate
174   //    the Nonce Payload.
175   //
176   if ((IkeSaSession->SessionCommon.IsInitiator) && (IkeSaSession->NCookie == NULL)) {
177     IkeSaSession->NiBlkSize = IKE_NONCE_SIZE;
178     IkeSaSession->NiBlock   = IkeGenerateNonce (IKE_NONCE_SIZE);
179     ASSERT (IkeSaSession->NiBlock != NULL);
180   }
181 
182   if (IkeSaSession->SessionCommon.IsInitiator) {
183     NoncePayload = Ikev2GenerateNoncePayload (
184                      IkeSaSession->NiBlock,
185                      IkeSaSession->NiBlkSize,
186                      IKEV2_PAYLOAD_TYPE_NONE
187                      );
188   } else {
189     //
190     // The Nonce Payload has been created in Ikev2PskParser if the IkeSaSession is
191     // responder.
192     //
193     NoncePayload = Ikev2GenerateNoncePayload (
194                      IkeSaSession->NrBlock,
195                      IkeSaSession->NrBlkSize,
196                      IKEV2_PAYLOAD_TYPE_NONE
197                      );
198   }
199 
200   if (NotifyPayload != NULL) {
201     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
202   }
203   if (SaPayload != NULL) {
204     IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
205   }
206   if (KePayload != NULL) {
207     IKE_PACKET_APPEND_PAYLOAD (IkePacket, KePayload);
208   }
209   if (NoncePayload != NULL) {
210     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NoncePayload);
211   }
212 
213   return IkePacket;
214 
215 CheckError:
216   if (IkePacket != NULL) {
217     IkePacketFree (IkePacket);
218   }
219   if (SaPayload != NULL) {
220     IkePayloadFree (SaPayload);
221   }
222   return NULL;
223 }
224 
225 /**
226   Parses the IKEv2 packet for IKE_SA_INIT exchange.
227 
228   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
229   @param[in] IkePacket  The received IKE packet to be parsed.
230 
231   @retval EFI_SUCCESS            The IKEv2 packet is acceptable and the relative data is
232                                  saved for furthure communication.
233   @retval EFI_INVALID_PARAMETER  The IKEv2 packet is malformed or the SA proposal is unacceptable.
234 
235 **/
236 EFI_STATUS
Ikev2InitPskParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)237 Ikev2InitPskParser (
238   IN UINT8            *SaSession,
239   IN IKE_PACKET       *IkePacket
240   )
241 {
242   IKEV2_SA_SESSION     *IkeSaSession;
243   IKE_PAYLOAD          *SaPayload;
244   IKE_PAYLOAD          *KeyPayload;
245   IKE_PAYLOAD          *IkePayload;
246   IKE_PAYLOAD          *NoncePayload;
247   IKE_PAYLOAD          *NotifyPayload;
248   UINT8                *NonceBuffer;
249   UINTN                NonceSize;
250   LIST_ENTRY           *Entry;
251   EFI_STATUS           Status;
252 
253   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
254   KeyPayload     = NULL;
255   SaPayload      = NULL;
256   NoncePayload   = NULL;
257   IkePayload     = NULL;
258   NotifyPayload  = NULL;
259 
260   //
261   // Iterate payloads to find the SaPayload and KeyPayload.
262   //
263   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
264     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
265     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
266       SaPayload = IkePayload;
267     }
268     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_KE) {
269       KeyPayload = IkePayload;
270     }
271     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NONCE) {
272       NoncePayload = IkePayload;
273     }
274     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NOTIFY) {
275       NotifyPayload = IkePayload;
276     }
277   }
278 
279   //
280   // According to RFC 4306 - 2.6. If the responder responds with the COOKIE Notify
281   // payload with the cookie data, initiator MUST retry the IKE_SA_INIT with a
282   // Notify payload of type COOKIE containing the responder suppplied cookie data
283   // as first payload and all other payloads unchanged.
284   //
285   if (IkeSaSession->SessionCommon.IsInitiator) {
286     if (NotifyPayload != NULL) {
287       Status = Ikev2ParserNotifyCookiePayload (NotifyPayload, IkeSaSession);
288       return Status;
289     }
290   }
291 
292   if ((KeyPayload == NULL) || (SaPayload == NULL) || (NoncePayload == NULL)) {
293     return EFI_INVALID_PARAMETER;
294   }
295 
296   //
297   // Store NoncePayload for SKEYID computing.
298   //
299   NonceSize   = NoncePayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
300   NonceBuffer = (UINT8 *) AllocatePool (NonceSize);
301   ASSERT (NonceBuffer != NULL);
302   CopyMem (
303     NonceBuffer,
304     NoncePayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
305     NonceSize
306     );
307 
308   //
309   // Check if IkePacket Header matches the state
310   //
311   if (IkeSaSession->SessionCommon.IsInitiator) {
312     //
313     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
314     //
315     if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
316       Status = EFI_INVALID_PARAMETER;
317       goto CheckError;
318     }
319 
320     //
321     // 2. Parse the SA Payload and Key Payload to find out the cryptographic
322     //    suite and fill in the Sa paramse into CommonSession->SaParams
323     //
324     if (!Ikev2SaParseSaPayload (IkeSaSession, SaPayload, IkePacket->Header->Flags)) {
325       Status = EFI_INVALID_PARAMETER;
326       goto CheckError;
327     }
328 
329     //
330     // 3. If Initiator, the NoncePayload is Nr_b.
331     //
332     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateAuth);
333     IkeSaSession->NrBlock             = NonceBuffer;
334     IkeSaSession->NrBlkSize           = NonceSize;
335     IkeSaSession->SessionCommon.State = IkeStateAuth;
336     IkeSaSession->ResponderCookie     = IkePacket->Header->ResponderCookie;
337 
338     //
339     // 4. Change the state of IkeSaSession
340     //
341     IkeSaSession->SessionCommon.State = IkeStateAuth;
342   } else {
343     //
344     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
345     //
346     if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) {
347       Status = EFI_INVALID_PARAMETER;
348       goto CheckError;
349     }
350 
351     //
352     // 2. Parse the SA payload and find out the perfered one
353     //    and fill in the SA parameters into CommonSession->SaParams and SaData into
354     //    IkeSaSession for the responder SA payload generation.
355     //
356     if (!Ikev2SaParseSaPayload (IkeSaSession, SaPayload, IkePacket->Header->Flags)) {
357       Status = EFI_INVALID_PARAMETER;
358       goto CheckError;
359     }
360 
361     //
362     // 3. Generat Dh Y parivate Key
363     //
364     Status = Ikev2GenerateSaDhPublicKey (IkeSaSession);
365     if (EFI_ERROR (Status)) {
366       goto CheckError;
367     }
368 
369     //
370     // 4. If Responder, the NoncePayload is Ni_b and go to generate Nr_b.
371     //
372     IkeSaSession->NiBlock   = NonceBuffer;
373     IkeSaSession->NiBlkSize = NonceSize;
374 
375     //
376     // 5. Generate Nr_b
377     //
378     IkeSaSession->NrBlock   = IkeGenerateNonce (IKE_NONCE_SIZE);
379     ASSERT_EFI_ERROR (IkeSaSession->NrBlock != NULL);
380     IkeSaSession->NrBlkSize = IKE_NONCE_SIZE;
381 
382     //
383     // 6. Save the Cookies
384     //
385     IkeSaSession->InitiatorCookie = IkePacket->Header->InitiatorCookie;
386     IkeSaSession->ResponderCookie = IkeGenerateCookie ();
387   }
388 
389   if (IkeSaSession->SessionCommon.PreferDhGroup != ((IKEV2_KEY_EXCHANGE *)KeyPayload->PayloadBuf)->DhGroup) {
390     Status = EFI_INVALID_PARAMETER;
391     goto CheckError;
392   }
393   //
394   // Call Ikev2GenerateSaKeys to create SKEYID, SKEYID_d, SKEYID_a, SKEYID_e.
395   //
396   Status = Ikev2GenerateSaKeys (IkeSaSession, KeyPayload);
397   if (EFI_ERROR(Status)) {
398     goto CheckError;
399   }
400   return EFI_SUCCESS;
401 
402 CheckError:
403   if (NonceBuffer != NULL) {
404     FreePool (NonceBuffer);
405   }
406 
407   return Status;
408 }
409 
410 /**
411   Generates the IKEv2 packet for IKE_AUTH exchange.
412 
413   @param[in] SaSession  Pointer to IKEV2_SA_SESSION.
414   @param[in] Context    Context data passed by caller.
415 
416   @retval   Pointer to IKE Packet to be sent out.
417 
418 **/
419 IKE_PACKET *
Ikev2AuthPskGenerator(IN UINT8 * SaSession,IN VOID * Context)420 Ikev2AuthPskGenerator (
421   IN UINT8         *SaSession,
422   IN VOID          *Context
423   )
424 {
425   IKE_PACKET             *IkePacket;
426   IKEV2_SA_SESSION       *IkeSaSession;
427   IKE_PAYLOAD            *IdPayload;
428   IKE_PAYLOAD            *AuthPayload;
429   IKE_PAYLOAD            *SaPayload;
430   IKE_PAYLOAD            *TsiPayload;
431   IKE_PAYLOAD            *TsrPayload;
432   IKE_PAYLOAD            *NotifyPayload;
433   IKE_PAYLOAD            *CpPayload;
434   IKEV2_CHILD_SA_SESSION *ChildSaSession;
435 
436 
437   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
438   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
439 
440   CpPayload      = NULL;
441   NotifyPayload  = NULL;
442 
443   //
444   // 1. Allocate IKE Packet
445   //
446   IkePacket= IkePacketAlloc ();
447   ASSERT (IkePacket != NULL);
448 
449   //
450   // 1.a Fill the IkePacket Header.
451   //
452   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_AUTH;
453   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
454   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
455   IkePacket->Header->Version         = (UINT8)(2 << 4);
456   if (ChildSaSession->SessionCommon.IsInitiator) {
457     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_INIT;
458   } else {
459     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_RSP;
460   }
461 
462   //
463   // According to RFC4306_2.2, For the IKE_SA_INIT message the MessageID should
464   // be always number 0 and 1;
465   //
466   IkePacket->Header->MessageId = 1;
467 
468   if (IkeSaSession->SessionCommon.IsInitiator) {
469     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
470   } else {
471     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
472   }
473 
474   //
475   // 2. Generate ID Payload according to IP version and address.
476   //
477   IdPayload = Ikev2GenerateIdPayload (
478                 &IkeSaSession->SessionCommon,
479                 IKEV2_PAYLOAD_TYPE_AUTH
480                 );
481 
482   //
483   // 3. Generate Auth Payload
484   //    If it is tunnel mode, should create the configuration payload after the
485   //    Auth payload.
486   //
487   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
488 
489     AuthPayload = Ikev2PskGenerateAuthPayload (
490                     ChildSaSession->IkeSaSession,
491                     IdPayload,
492                     IKEV2_PAYLOAD_TYPE_SA,
493                     FALSE
494                     );
495   } else {
496     AuthPayload = Ikev2PskGenerateAuthPayload (
497                     ChildSaSession->IkeSaSession,
498                     IdPayload,
499                     IKEV2_PAYLOAD_TYPE_CP,
500                     FALSE
501                     );
502     if (IkeSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) {
503       CpPayload = Ikev2GenerateCpPayload (
504                     ChildSaSession->IkeSaSession,
505                     IKEV2_PAYLOAD_TYPE_SA,
506                     IKEV2_CFG_ATTR_INTERNAL_IP4_ADDRESS
507                     );
508     } else {
509       CpPayload = Ikev2GenerateCpPayload (
510                     ChildSaSession->IkeSaSession,
511                     IKEV2_PAYLOAD_TYPE_SA,
512                     IKEV2_CFG_ATTR_INTERNAL_IP6_ADDRESS
513                     );
514     }
515   }
516 
517   //
518   // 4. Generate SA Payload according to the SA Data in ChildSaSession
519   //
520   SaPayload = Ikev2GenerateSaPayload (
521                 ChildSaSession->SaData,
522                 IKEV2_PAYLOAD_TYPE_TS_INIT,
523                 IkeSessionTypeChildSa
524                 );
525 
526   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
527     //
528     // Generate Tsi and Tsr.
529     //
530     TsiPayload = Ikev2GenerateTsPayload (
531                    ChildSaSession,
532                    IKEV2_PAYLOAD_TYPE_TS_RSP,
533                    FALSE
534                    );
535 
536     TsrPayload = Ikev2GenerateTsPayload (
537                    ChildSaSession,
538                    IKEV2_PAYLOAD_TYPE_NOTIFY,
539                    FALSE
540                    );
541 
542     //
543     // Generate Notify Payload. If transport mode, there should have Notify
544     // payload with TRANSPORT_MODE notification.
545     //
546     NotifyPayload = Ikev2GenerateNotifyPayload (
547                       0,
548                       IKEV2_PAYLOAD_TYPE_NONE,
549                       0,
550                       IKEV2_NOTIFICATION_USE_TRANSPORT_MODE,
551                       NULL,
552                       NULL,
553                       0
554                       );
555   } else {
556     //
557     // Generate Tsr for Tunnel mode.
558     //
559     TsiPayload = Ikev2GenerateTsPayload (
560                    ChildSaSession,
561                    IKEV2_PAYLOAD_TYPE_TS_RSP,
562                    TRUE
563                    );
564     TsrPayload = Ikev2GenerateTsPayload (
565                    ChildSaSession,
566                    IKEV2_PAYLOAD_TYPE_NONE,
567                    FALSE
568                    );
569   }
570 
571   IKE_PACKET_APPEND_PAYLOAD (IkePacket, IdPayload);
572   IKE_PACKET_APPEND_PAYLOAD (IkePacket, AuthPayload);
573   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
574     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CpPayload);
575   }
576   IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
577   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsiPayload);
578   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsrPayload);
579   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
580     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
581   }
582 
583   return IkePacket;
584 }
585 
586 /**
587   Parses IKE_AUTH packet.
588 
589   @param[in]  SaSession   Pointer to the IKE_SA_SESSION related to this packet.
590   @param[in]  IkePacket   Pointer to the IKE_AUTH packet to be parsered.
591 
592   @retval     EFI_INVALID_PARAMETER   The IKE packet is malformed or the SA
593                                       proposal is unacceptable.
594   @retval     EFI_SUCCESS             The IKE packet is acceptable and the
595                                       relative data is saved for furthure communication.
596 
597 **/
598 EFI_STATUS
Ikev2AuthPskParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)599 Ikev2AuthPskParser (
600   IN UINT8             *SaSession,
601   IN IKE_PACKET        *IkePacket
602   )
603 {
604   IKEV2_CHILD_SA_SESSION *ChildSaSession;
605   IKEV2_SA_SESSION       *IkeSaSession;
606   IKE_PAYLOAD            *IkePayload;
607   IKE_PAYLOAD            *SaPayload;
608   IKE_PAYLOAD            *IdiPayload;
609   IKE_PAYLOAD            *IdrPayload;
610   IKE_PAYLOAD            *AuthPayload;
611   IKE_PAYLOAD            *TsiPayload;
612   IKE_PAYLOAD            *TsrPayload;
613   IKE_PAYLOAD            *VerifiedAuthPayload;
614   LIST_ENTRY             *Entry;
615   EFI_STATUS             Status;
616 
617   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
618   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
619 
620   SaPayload   = NULL;
621   IdiPayload  = NULL;
622   IdrPayload  = NULL;
623   AuthPayload = NULL;
624   TsiPayload  = NULL;
625   TsrPayload  = NULL;
626 
627   //
628   // Iterate payloads to find the SaPayload/ID/AUTH/TS Payload.
629   //
630   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
631     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
632 
633     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_INIT) {
634       IdiPayload = IkePayload;
635     }
636     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_RSP) {
637       IdrPayload = IkePayload;
638     }
639     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
640       SaPayload = IkePayload;
641     }
642     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_AUTH) {
643       AuthPayload = IkePayload;
644     }
645     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
646       TsiPayload = IkePayload;
647     }
648     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_RSP) {
649       TsrPayload = IkePayload;
650     }
651   }
652 
653   if ((SaPayload == NULL) || (AuthPayload == NULL) || (TsiPayload == NULL) || (TsrPayload == NULL)) {
654     return EFI_INVALID_PARAMETER;
655   }
656   if ((IdiPayload == NULL) && (IdrPayload == NULL)) {
657     return EFI_INVALID_PARAMETER;
658   }
659 
660   //
661   // Check IkePacket Header is match the state
662   //
663   if (IkeSaSession->SessionCommon.IsInitiator) {
664 
665     //
666     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
667     //
668     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) ||
669         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)
670         ) {
671       return EFI_INVALID_PARAMETER;
672     }
673 
674   } else {
675     //
676     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
677     //
678     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) ||
679         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)
680         ) {
681       return EFI_INVALID_PARAMETER;
682     }
683 
684     //
685     // 2. Parse the SA payload and Key Payload and find out the perferable one
686     //    and fill in the Sa paramse into CommonSession->SaParams and SaData into
687     //    IkeSaSession for the responder SA payload generation.
688     //
689   }
690 
691   //
692   // Verify the Auth Payload.
693   //
694   VerifiedAuthPayload = Ikev2PskGenerateAuthPayload (
695                           IkeSaSession,
696                           IkeSaSession->SessionCommon.IsInitiator ? IdrPayload : IdiPayload,
697                           IKEV2_PAYLOAD_TYPE_SA,
698                           TRUE
699                           );
700   if ((VerifiedAuthPayload != NULL) &&
701       (0 != CompareMem (
702               VerifiedAuthPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
703               AuthPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
704               VerifiedAuthPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER)
705               ))) {
706     return EFI_INVALID_PARAMETER;
707   };
708 
709   //
710   // 3. Parse the SA Payload to find out the cryptographic suite
711   //    and fill in the Sa paramse into CommonSession->SaParams. If no acceptable
712   //    porposal found, return EFI_INVALID_PARAMETER.
713   //
714   if (!Ikev2ChildSaParseSaPayload (ChildSaSession, SaPayload, IkePacket->Header->Flags)) {
715     return EFI_INVALID_PARAMETER;
716   }
717 
718   //
719   // 4. Parse TSi, TSr payloads.
720   //
721   if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId !=
722        ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId) &&
723       (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0) &&
724       (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0)
725       ) {
726     return EFI_INVALID_PARAMETER;
727   }
728 
729   if (!IkeSaSession->SessionCommon.IsInitiator) {
730     //
731     //TODO:check the Port range. Only support any port and one certain port here.
732     //
733     ChildSaSession->ProtoId    = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId;
734     ChildSaSession->LocalPort  = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
735     ChildSaSession->RemotePort = ((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
736     //
737     // Association a SPD with this SA.
738     //
739     Status = Ikev2ChildSaAssociateSpdEntry (ChildSaSession);
740     if (EFI_ERROR (Status)) {
741       return EFI_INVALID_PARAMETER;
742     }
743     //
744     // Associate the IkeSaSession's SPD to the first ChildSaSession's SPD.
745     //
746     if (ChildSaSession->IkeSaSession->Spd == NULL) {
747       ChildSaSession->IkeSaSession->Spd = ChildSaSession->Spd;
748       Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
749     }
750   } else {
751     //
752     //TODO:check the Port range.
753     //
754     if ((((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
755         (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->RemotePort)
756         ) {
757       return EFI_INVALID_PARAMETER;
758     }
759     if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
760         (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->LocalPort)
761         ) {
762       return EFI_INVALID_PARAMETER;
763     }
764     //
765     // For the tunnel mode, it should add the vitual IP address into the SA's SPD Selector.
766     //
767     if (ChildSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
768       if (!ChildSaSession->IkeSaSession->SessionCommon.IsInitiator) {
769         //
770         // If it is tunnel mode, the UEFI part must be the initiator.
771         //
772         return EFI_INVALID_PARAMETER;
773       }
774       //
775       // Get the Virtual IP address from the Tsi traffic selector.
776       // TODO: check the CFG reply payload
777       //
778       CopyMem (
779         &ChildSaSession->SpdSelector->LocalAddress[0].Address,
780         TsiPayload->PayloadBuf + sizeof (IKEV2_TS) + sizeof (TRAFFIC_SELECTOR),
781         (ChildSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) ?
782         sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS)
783         );
784       }
785   }
786 
787   //
788   // 5. Generate keymats for IPsec protocol.
789   //
790   Ikev2GenerateChildSaKeys (ChildSaSession, NULL);
791   if (IkeSaSession->SessionCommon.IsInitiator) {
792     //
793     // 6. Change the state of IkeSaSession
794     //
795     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateIkeSaEstablished);
796     IkeSaSession->SessionCommon.State = IkeStateIkeSaEstablished;
797   }
798 
799   return EFI_SUCCESS;
800 }
801 
802 /**
803   Gernerates IKEv2 packet for IKE_SA_INIT exchange.
804 
805   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
806   @param[in] Context    Context Data passed by caller.
807 
808   @retval EFI_SUCCESS   The IKE packet generation succeeded.
809   @retval Others        The IKE packet generation failed.
810 
811 **/
812 IKE_PACKET*
Ikev2InitCertGenerator(IN UINT8 * SaSession,IN VOID * Context)813 Ikev2InitCertGenerator (
814   IN UINT8           *SaSession,
815   IN VOID            *Context
816   )
817 {
818   IKE_PACKET         *IkePacket;
819   IKE_PAYLOAD        *CertReqPayload;
820   LIST_ENTRY         *Node;
821   IKE_PAYLOAD        *NoncePayload;
822 
823   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
824     return NULL;
825   }
826 
827   //
828   // The first two messages exchange is same between PSK and Cert.
829   //
830   IkePacket = Ikev2InitPskGenerator (SaSession, Context);
831 
832   if ((IkePacket != NULL) && (!((IKEV2_SA_SESSION *)SaSession)->SessionCommon.IsInitiator)) {
833     //
834     // Add the Certification Request Payload
835     //
836     CertReqPayload = Ikev2GenerateCertificatePayload (
837                        (IKEV2_SA_SESSION *)SaSession,
838                        IKEV2_PAYLOAD_TYPE_NONE,
839                        (UINT8*)PcdGetPtr(PcdIpsecUefiCaFile),
840                        PcdGet32(PcdIpsecUefiCaFileSize),
841                        IKEV2_CERT_ENCODEING_HASH_AND_URL_OF_X509_CERT,
842                        TRUE
843                        );
844     //
845     // Change Nonce Payload Next payload type.
846     //
847     IKE_PACKET_END_PAYLOAD (IkePacket, Node);
848     NoncePayload = IKE_PAYLOAD_BY_PACKET (Node);
849     ((IKEV2_NONCE *)NoncePayload->PayloadBuf)->Header.NextPayload = IKEV2_PAYLOAD_TYPE_CERTREQ;
850 
851     //
852     // Add Certification Request Payload
853     //
854     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertReqPayload);
855   }
856 
857   return IkePacket;
858 }
859 
860 /**
861   Parses the IKEv2 packet for IKE_SA_INIT exchange.
862 
863   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
864   @param[in] IkePacket  The received IKEv2 packet to be parsed.
865 
866   @retval EFI_SUCCESS            The IKEv2 packet is acceptable and the relative data is
867                                  saved for furthure communication.
868   @retval EFI_INVALID_PARAMETER  The IKE packet is malformed or the SA proposal is unacceptable.
869   @retval EFI_UNSUPPORTED        The certificate authentication is not supported.
870 
871 **/
872 EFI_STATUS
Ikev2InitCertParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)873 Ikev2InitCertParser (
874   IN UINT8            *SaSession,
875   IN IKE_PACKET       *IkePacket
876   )
877 {
878   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
879     return EFI_UNSUPPORTED;
880   }
881 
882   //
883   // The first two messages exchange is same between PSK and Cert.
884   // Todo: Parse Certificate Request from responder Initial Exchange.
885   //
886   return Ikev2InitPskParser (SaSession, IkePacket);
887 }
888 
889 /**
890   Generates the IKEv2 packet for IKE_AUTH exchange.
891 
892   @param[in] SaSession  Pointer to IKEV2_SA_SESSION.
893   @param[in] Context    Context data passed by caller.
894 
895   @retval Pointer to IKEv2 Packet to be sent out.
896 
897 **/
898 IKE_PACKET *
Ikev2AuthCertGenerator(IN UINT8 * SaSession,IN VOID * Context)899 Ikev2AuthCertGenerator (
900   IN UINT8         *SaSession,
901   IN VOID          *Context
902   )
903 {
904   IKE_PACKET             *IkePacket;
905   IKEV2_SA_SESSION       *IkeSaSession;
906   IKE_PAYLOAD            *IdPayload;
907   IKE_PAYLOAD            *AuthPayload;
908   IKE_PAYLOAD            *SaPayload;
909   IKE_PAYLOAD            *TsiPayload;
910   IKE_PAYLOAD            *TsrPayload;
911   IKE_PAYLOAD            *NotifyPayload;
912   IKE_PAYLOAD            *CpPayload;
913   IKE_PAYLOAD            *CertPayload;
914   IKE_PAYLOAD            *CertReqPayload;
915   IKEV2_CHILD_SA_SESSION *ChildSaSession;
916 
917   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
918     return NULL;
919   }
920 
921   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
922   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
923 
924   CpPayload      = NULL;
925   NotifyPayload  = NULL;
926   CertPayload    = NULL;
927   CertReqPayload = NULL;
928 
929   //
930   // 1. Allocate IKE Packet
931   //
932   IkePacket= IkePacketAlloc ();
933   ASSERT (IkePacket != NULL);
934 
935   //
936   // 1.a Fill the IkePacket Header.
937   //
938   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_AUTH;
939   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
940   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
941   IkePacket->Header->Version         = (UINT8)(2 << 4);
942   if (ChildSaSession->SessionCommon.IsInitiator) {
943     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_INIT;
944   } else {
945     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_RSP;
946   }
947 
948   //
949   // According to RFC4306_2.2, For the IKE_SA_INIT message the MessageID should
950   // be always number 0 and 1;
951   //
952   IkePacket->Header->MessageId = 1;
953 
954   if (IkeSaSession->SessionCommon.IsInitiator) {
955     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
956   } else {
957     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
958   }
959 
960   //
961   // 2. Generate ID Payload according to IP version and address.
962   //
963   IdPayload = Ikev2GenerateCertIdPayload (
964                 &IkeSaSession->SessionCommon,
965                 IKEV2_PAYLOAD_TYPE_CERT,
966                 (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
967                 PcdGet32 (PcdIpsecUefiCertificateSize)
968                 );
969 
970   //
971   // 3. Generate Certificate Payload
972   //
973   CertPayload = Ikev2GenerateCertificatePayload (
974                   IkeSaSession,
975                   (UINT8)(IkeSaSession->SessionCommon.IsInitiator ? IKEV2_PAYLOAD_TYPE_CERTREQ : IKEV2_PAYLOAD_TYPE_AUTH),
976                   (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
977                   PcdGet32 (PcdIpsecUefiCertificateSize),
978                   IKEV2_CERT_ENCODEING_X509_CERT_SIGN,
979                   FALSE
980                   );
981   if (IkeSaSession->SessionCommon.IsInitiator) {
982     CertReqPayload = Ikev2GenerateCertificatePayload (
983                        IkeSaSession,
984                        IKEV2_PAYLOAD_TYPE_AUTH,
985                        (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
986                        PcdGet32 (PcdIpsecUefiCertificateSize),
987                        IKEV2_CERT_ENCODEING_HASH_AND_URL_OF_X509_CERT,
988                        TRUE
989                        );
990   }
991 
992   //
993   // 4. Generate Auth Payload
994   //    If it is tunnel mode, should create the configuration payload after the
995   //    Auth payload.
996   //
997   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
998     AuthPayload = Ikev2CertGenerateAuthPayload (
999                     ChildSaSession->IkeSaSession,
1000                     IdPayload,
1001                     IKEV2_PAYLOAD_TYPE_SA,
1002                     FALSE,
1003                     (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificateKey),
1004                     PcdGet32 (PcdIpsecUefiCertificateKeySize),
1005                     ChildSaSession->IkeSaSession->Pad->Data->AuthData,
1006                     ChildSaSession->IkeSaSession->Pad->Data->AuthDataSize
1007                     );
1008   } else {
1009     AuthPayload = Ikev2CertGenerateAuthPayload (
1010                     ChildSaSession->IkeSaSession,
1011                     IdPayload,
1012                     IKEV2_PAYLOAD_TYPE_CP,
1013                     FALSE,
1014                     (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificateKey),
1015                     PcdGet32 (PcdIpsecUefiCertificateKeySize),
1016                     ChildSaSession->IkeSaSession->Pad->Data->AuthData,
1017                     ChildSaSession->IkeSaSession->Pad->Data->AuthDataSize
1018                     );
1019     if (IkeSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) {
1020       CpPayload = Ikev2GenerateCpPayload (
1021                     ChildSaSession->IkeSaSession,
1022                     IKEV2_PAYLOAD_TYPE_SA,
1023                     IKEV2_CFG_ATTR_INTERNAL_IP4_ADDRESS
1024                     );
1025     } else {
1026       CpPayload = Ikev2GenerateCpPayload (
1027                     ChildSaSession->IkeSaSession,
1028                     IKEV2_PAYLOAD_TYPE_SA,
1029                     IKEV2_CFG_ATTR_INTERNAL_IP6_ADDRESS
1030                     );
1031     }
1032   }
1033 
1034   //
1035   // 5. Generate SA Payload according to the Sa Data in ChildSaSession
1036   //
1037   SaPayload = Ikev2GenerateSaPayload (
1038                 ChildSaSession->SaData,
1039                 IKEV2_PAYLOAD_TYPE_TS_INIT,
1040                 IkeSessionTypeChildSa
1041                 );
1042 
1043   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
1044     //
1045     // Generate Tsi and Tsr.
1046     //
1047     TsiPayload = Ikev2GenerateTsPayload (
1048                    ChildSaSession,
1049                    IKEV2_PAYLOAD_TYPE_TS_RSP,
1050                    FALSE
1051                    );
1052 
1053     TsrPayload = Ikev2GenerateTsPayload (
1054                    ChildSaSession,
1055                    IKEV2_PAYLOAD_TYPE_NOTIFY,
1056                    FALSE
1057                    );
1058 
1059     //
1060     // Generate Notify Payload. If transport mode, there should have Notify
1061     // payload with TRANSPORT_MODE notification.
1062     //
1063     NotifyPayload = Ikev2GenerateNotifyPayload (
1064                       0,
1065                       IKEV2_PAYLOAD_TYPE_NONE,
1066                       0,
1067                       IKEV2_NOTIFICATION_USE_TRANSPORT_MODE,
1068                       NULL,
1069                       NULL,
1070                       0
1071                       );
1072   } else {
1073     //
1074     // Generate Tsr for Tunnel mode.
1075     //
1076     TsiPayload = Ikev2GenerateTsPayload (
1077                    ChildSaSession,
1078                    IKEV2_PAYLOAD_TYPE_TS_RSP,
1079                    TRUE
1080                    );
1081     TsrPayload = Ikev2GenerateTsPayload (
1082                    ChildSaSession,
1083                    IKEV2_PAYLOAD_TYPE_NONE,
1084                    FALSE
1085                    );
1086   }
1087 
1088   IKE_PACKET_APPEND_PAYLOAD (IkePacket, IdPayload);
1089   IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertPayload);
1090   if (IkeSaSession->SessionCommon.IsInitiator) {
1091     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertReqPayload);
1092   }
1093   IKE_PACKET_APPEND_PAYLOAD (IkePacket, AuthPayload);
1094   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
1095     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CpPayload);
1096   }
1097   IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
1098   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsiPayload);
1099   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsrPayload);
1100   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
1101     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
1102   }
1103 
1104   return IkePacket;
1105 }
1106 
1107 /**
1108   Parses IKE_AUTH packet.
1109 
1110   @param[in]  SaSession   Pointer to the IKE_SA_SESSION related to this packet.
1111   @param[in]  IkePacket   Pointer to the IKE_AUTH packet to be parsered.
1112 
1113   @retval     EFI_INVALID_PARAMETER   The IKEv2 packet is malformed or the SA
1114                                       proposal is unacceptable.
1115   @retval     EFI_SUCCESS             The IKE packet is acceptable and the
1116                                       relative data is saved for furthure communication.
1117   @retval     EFI_UNSUPPORTED         The certificate authentication is not supported.
1118 
1119 **/
1120 EFI_STATUS
Ikev2AuthCertParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)1121 Ikev2AuthCertParser (
1122   IN UINT8             *SaSession,
1123   IN IKE_PACKET        *IkePacket
1124   )
1125 {
1126   IKEV2_CHILD_SA_SESSION *ChildSaSession;
1127   IKEV2_SA_SESSION       *IkeSaSession;
1128   IKE_PAYLOAD            *IkePayload;
1129   IKE_PAYLOAD            *SaPayload;
1130   IKE_PAYLOAD            *IdiPayload;
1131   IKE_PAYLOAD            *IdrPayload;
1132   IKE_PAYLOAD            *AuthPayload;
1133   IKE_PAYLOAD            *TsiPayload;
1134   IKE_PAYLOAD            *TsrPayload;
1135   IKE_PAYLOAD            *CertPayload;
1136   IKE_PAYLOAD            *VerifiedAuthPayload;
1137   LIST_ENTRY             *Entry;
1138   EFI_STATUS             Status;
1139 
1140   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
1141     return EFI_UNSUPPORTED;
1142   }
1143 
1144   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
1145   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
1146 
1147   SaPayload           = NULL;
1148   IdiPayload          = NULL;
1149   IdrPayload          = NULL;
1150   AuthPayload         = NULL;
1151   TsiPayload          = NULL;
1152   TsrPayload          = NULL;
1153   CertPayload         = NULL;
1154   VerifiedAuthPayload = NULL;
1155   Status              = EFI_INVALID_PARAMETER;
1156 
1157   //
1158   // Iterate payloads to find the SaPayload/ID/AUTH/TS Payload.
1159   //
1160   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
1161     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
1162 
1163     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_INIT) {
1164       IdiPayload = IkePayload;
1165     }
1166     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_RSP) {
1167       IdrPayload = IkePayload;
1168     }
1169 
1170     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
1171       SaPayload = IkePayload;
1172     }
1173     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_AUTH) {
1174       AuthPayload = IkePayload;
1175     }
1176     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
1177       TsiPayload = IkePayload;
1178     }
1179     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_RSP) {
1180       TsrPayload = IkePayload;
1181     }
1182     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_CERT) {
1183       CertPayload = IkePayload;
1184     }
1185   }
1186 
1187   if ((SaPayload == NULL) || (AuthPayload == NULL) || (TsiPayload == NULL) ||
1188       (TsrPayload == NULL) || (CertPayload == NULL)) {
1189     goto Exit;
1190   }
1191   if ((IdiPayload == NULL) && (IdrPayload == NULL)) {
1192     goto Exit;
1193   }
1194 
1195   //
1196   // Check IkePacket Header is match the state
1197   //
1198   if (IkeSaSession->SessionCommon.IsInitiator) {
1199 
1200     //
1201     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
1202     //
1203     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) ||
1204         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)) {
1205       goto Exit;
1206     }
1207   } else {
1208     //
1209     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
1210     //
1211     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) ||
1212         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)) {
1213       goto Exit;
1214     }
1215   }
1216 
1217   //
1218   // Verify the Auth Payload.
1219   //
1220   VerifiedAuthPayload = Ikev2CertGenerateAuthPayload (
1221                           IkeSaSession,
1222                           IkeSaSession->SessionCommon.IsInitiator ? IdrPayload:IdiPayload,
1223                           IKEV2_PAYLOAD_TYPE_SA,
1224                           TRUE,
1225                           NULL,
1226                           0,
1227                           NULL,
1228                           0
1229                           );
1230 
1231   if ((VerifiedAuthPayload != NULL) &&
1232       (!IpSecCryptoIoVerifySignDataByCertificate (
1233           CertPayload->PayloadBuf + sizeof (IKEV2_CERT),
1234           CertPayload->PayloadSize - sizeof (IKEV2_CERT),
1235           (UINT8 *)PcdGetPtr (PcdIpsecUefiCaFile),
1236           PcdGet32 (PcdIpsecUefiCaFileSize),
1237           VerifiedAuthPayload->PayloadBuf + sizeof (IKEV2_AUTH),
1238           VerifiedAuthPayload->PayloadSize - sizeof (IKEV2_AUTH),
1239           AuthPayload->PayloadBuf + sizeof (IKEV2_AUTH),
1240           AuthPayload->PayloadSize - sizeof (IKEV2_AUTH)
1241           ))) {
1242     goto Exit;
1243   }
1244 
1245   //
1246   // 3. Parse the SA Payload to find out the cryptographic suite
1247   //    and fill in the SA paramse into CommonSession->SaParams. If no acceptable
1248   //    porposal found, return EFI_INVALID_PARAMETER.
1249   //
1250   if (!Ikev2ChildSaParseSaPayload (ChildSaSession, SaPayload, IkePacket->Header->Flags)) {
1251     goto Exit;
1252   }
1253 
1254   //
1255   // 4. Parse TSi, TSr payloads.
1256   //
1257   if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId !=
1258       ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId) &&
1259       (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0) &&
1260       (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0)
1261       ) {
1262     goto Exit;
1263   }
1264 
1265   if (!IkeSaSession->SessionCommon.IsInitiator) {
1266     //
1267     //Todo:check the Port range. Only support any port and one certain port here.
1268     //
1269     ChildSaSession->ProtoId    = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId;
1270     ChildSaSession->LocalPort  = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
1271     ChildSaSession->RemotePort = ((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
1272     //
1273     // Association a SPD with this SA.
1274     //
1275     if (EFI_ERROR (Ikev2ChildSaAssociateSpdEntry (ChildSaSession))) {
1276       goto Exit;
1277     }
1278     //
1279     // Associate the IkeSaSession's SPD to the first ChildSaSession's SPD.
1280     //
1281     if (ChildSaSession->IkeSaSession->Spd == NULL) {
1282       ChildSaSession->IkeSaSession->Spd = ChildSaSession->Spd;
1283       Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
1284     }
1285   } else {
1286     //
1287     // Todo:check the Port range.
1288     //
1289     if ((((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
1290         (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->RemotePort)
1291         ) {
1292       goto Exit;
1293     }
1294     if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
1295         (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->LocalPort)
1296         ) {
1297       goto Exit;
1298     }
1299     //
1300     // For the tunnel mode, it should add the vitual IP address into the SA's SPD Selector.
1301     //
1302     if (ChildSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
1303       if (!ChildSaSession->IkeSaSession->SessionCommon.IsInitiator) {
1304         //
1305         // If it is tunnel mode, the UEFI part must be the initiator.
1306         //
1307         goto Exit;
1308       }
1309       //
1310       // Get the Virtual IP address from the Tsi traffic selector.
1311       // TODO: check the CFG reply payload
1312       //
1313       CopyMem (
1314         &ChildSaSession->SpdSelector->LocalAddress[0].Address,
1315         TsiPayload->PayloadBuf + sizeof (IKEV2_TS) + sizeof (TRAFFIC_SELECTOR),
1316         (ChildSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) ?
1317         sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS)
1318         );
1319     }
1320   }
1321 
1322   //
1323   // 5. Generat keymats for IPsec protocol.
1324   //
1325   Ikev2GenerateChildSaKeys (ChildSaSession, NULL);
1326   if (IkeSaSession->SessionCommon.IsInitiator) {
1327     //
1328     // 6. Change the state of IkeSaSession
1329     //
1330     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateIkeSaEstablished);
1331     IkeSaSession->SessionCommon.State = IkeStateIkeSaEstablished;
1332   }
1333 
1334   Status = EFI_SUCCESS;
1335 
1336 Exit:
1337   if (VerifiedAuthPayload != NULL) {
1338     IkePayloadFree (VerifiedAuthPayload);
1339   }
1340   return Status;
1341 }
1342 
1343 /**
1344   Generates the DH Public Key.
1345 
1346   This generates the DH local public key and store it in the IKE SA Session's GxBuffer.
1347 
1348   @param[in]  IkeSaSession   Pointer to related IKE SA Session.
1349 
1350   @retval EFI_SUCCESS        The operation succeeded.
1351   @retval Others             The operation failed.
1352 
1353 **/
1354 EFI_STATUS
Ikev2GenerateSaDhPublicKey(IN IKEV2_SA_SESSION * IkeSaSession)1355 Ikev2GenerateSaDhPublicKey (
1356   IN IKEV2_SA_SESSION         *IkeSaSession
1357   )
1358 {
1359   EFI_STATUS         Status;
1360   IKEV2_SESSION_KEYS *IkeKeys;
1361 
1362   IkeSaSession->IkeKeys = AllocateZeroPool (sizeof (IKEV2_SESSION_KEYS));
1363   ASSERT (IkeSaSession->IkeKeys != NULL);
1364   IkeKeys = IkeSaSession->IkeKeys;
1365   IkeKeys->DhBuffer = AllocateZeroPool (sizeof (IKEV2_DH_BUFFER));
1366   ASSERT (IkeKeys->DhBuffer != NULL);
1367 
1368   //
1369   // Init DH with the certain DH Group Description.
1370   //
1371   IkeKeys->DhBuffer->GxSize   = OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Size >> 3;
1372   IkeKeys->DhBuffer->GxBuffer = AllocateZeroPool (IkeKeys->DhBuffer->GxSize);
1373   ASSERT (IkeKeys->DhBuffer->GxBuffer != NULL);
1374 
1375   //
1376   // Get X PublicKey
1377   //
1378   Status = IpSecCryptoIoDhGetPublicKey (
1379              &IkeKeys->DhBuffer->DhContext,
1380              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].GroupGenerator,
1381              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Size,
1382              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Modulus,
1383              IkeKeys->DhBuffer->GxBuffer,
1384              &IkeKeys->DhBuffer->GxSize
1385              );
1386   if (EFI_ERROR (Status)) {
1387     DEBUG ((DEBUG_ERROR, "Error CPLKeyManGetKeyParam X public key error Status = %r\n", Status));
1388     return Status;
1389   }
1390 
1391   IPSEC_DUMP_BUF ("DH Public Key (g^x) Dump", IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);
1392 
1393   return EFI_SUCCESS;
1394 }
1395 
1396 /**
1397   Computes the DH Shared/Exchange Key.
1398 
1399   Given peer's public key, this function computes the exchanged common key and
1400   stores it in the IKEv2 SA Session's GxyBuffer.
1401 
1402   @param[in]  DhBuffer       Pointer to buffer of peer's puliic key.
1403   @param[in]  KePayload      Pointer to received key payload.
1404 
1405   @retval EFI_SUCCESS        The operation succeeded.
1406   @retval Otherwise          The operation failed.
1407 
1408 **/
1409 EFI_STATUS
Ikev2GenerateSaDhComputeKey(IN IKEV2_DH_BUFFER * DhBuffer,IN IKE_PAYLOAD * KePayload)1410 Ikev2GenerateSaDhComputeKey (
1411   IN IKEV2_DH_BUFFER       *DhBuffer,
1412   IN IKE_PAYLOAD            *KePayload
1413   )
1414 {
1415   EFI_STATUS          Status;
1416   IKEV2_KEY_EXCHANGE  *Ke;
1417   UINT8               *PubKey;
1418   UINTN               PubKeySize;
1419 
1420   Ke                  = (IKEV2_KEY_EXCHANGE *) KePayload->PayloadBuf;
1421   PubKey              = (UINT8 *) (Ke + 1);
1422   PubKeySize          = KePayload->PayloadSize - sizeof (IKEV2_KEY_EXCHANGE);
1423   DhBuffer->GxySize   = DhBuffer->GxSize;
1424   DhBuffer->GxyBuffer = AllocateZeroPool (DhBuffer->GxySize);
1425   ASSERT (DhBuffer->GxyBuffer != NULL);
1426 
1427   //
1428   // Get GxyBuf
1429   //
1430   Status = IpSecCryptoIoDhComputeKey (
1431              DhBuffer->DhContext,
1432              PubKey,
1433              PubKeySize,
1434              DhBuffer->GxyBuffer,
1435              &DhBuffer->GxySize
1436              );
1437   if (EFI_ERROR (Status)) {
1438     DEBUG ((DEBUG_ERROR, "Error CPLKeyManGetKeyParam Y session key error Status = %r\n", Status));
1439     return Status;
1440   }
1441 
1442   //
1443   // Create GxyBuf.
1444   //
1445   DhBuffer->GySize   = PubKeySize;
1446   DhBuffer->GyBuffer = AllocateZeroPool (DhBuffer->GySize);
1447   ASSERT (DhBuffer->GyBuffer != NULL);
1448   CopyMem (DhBuffer->GyBuffer, PubKey, DhBuffer->GySize);
1449 
1450   IPSEC_DUMP_BUF ("DH Public Key (g^y) Dump", DhBuffer->GyBuffer, DhBuffer->GySize);
1451   IPSEC_DUMP_BUF ("DH Shared Key (g^xy) Dump", DhBuffer->GxyBuffer, DhBuffer->GxySize);
1452 
1453   return EFI_SUCCESS;
1454 }
1455 
1456 /**
1457   Generates the IKE SKEYSEED and seven other secrets. SK_d, SK_ai, SK_ar, SK_ei, SK_er,
1458   SK_pi, SK_pr are keys for the furthure IKE exchange.
1459 
1460   @param[in]  IkeSaSession       Pointer to IKE SA Session.
1461   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
1462 
1463   @retval EFI_UNSUPPORTED        If one or more Algorithm Id is not supported.
1464   @retval EFI_OUT_OF_RESOURCES   If there is no enough resource to be allocated to
1465                                  meet the requirement.
1466   @retval EFI_SUCCESS            The operation succeeded.
1467 
1468 **/
1469 EFI_STATUS
Ikev2GenerateSaKeys(IN IKEV2_SA_SESSION * IkeSaSession,IN IKE_PAYLOAD * KePayload)1470 Ikev2GenerateSaKeys (
1471   IN IKEV2_SA_SESSION       *IkeSaSession,
1472   IN IKE_PAYLOAD            *KePayload
1473   )
1474 {
1475   EFI_STATUS          Status;
1476   IKEV2_SA_PARAMS     *SaParams;
1477   PRF_DATA_FRAGMENT   Fragments[4];
1478   UINT64              InitiatorCookieNet;
1479   UINT64              ResponderCookieNet;
1480   UINT8               *KeyBuffer;
1481   UINTN               KeyBufferSize;
1482   UINTN               AuthAlgKeyLen;
1483   UINTN               EncryptAlgKeyLen;
1484   UINTN               IntegrityAlgKeyLen;
1485   UINTN               PrfAlgKeyLen;
1486   UINT8               *OutputKey;
1487   UINTN               OutputKeyLength;
1488   UINT8               *Digest;
1489   UINTN               DigestSize;
1490 
1491   Digest    = NULL;
1492   OutputKey = NULL;
1493   KeyBuffer = NULL;
1494   Status = EFI_SUCCESS;
1495 
1496   //
1497   // Generate Gxy
1498   //
1499   Ikev2GenerateSaDhComputeKey (IkeSaSession->IkeKeys->DhBuffer, KePayload);
1500 
1501   //
1502   // Get the key length of Authenticaion, Encryption, PRF, and Integrity.
1503   //
1504   SaParams           = IkeSaSession->SessionCommon.SaParams;
1505   AuthAlgKeyLen      = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
1506   EncryptAlgKeyLen   = IpSecGetEncryptKeyLength ((UINT8)SaParams->EncAlgId);
1507   IntegrityAlgKeyLen = IpSecGetHmacDigestLength ((UINT8)SaParams->IntegAlgId);
1508   PrfAlgKeyLen       = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
1509 
1510   //
1511   // If one or more algorithm is not support, return EFI_UNSUPPORTED.
1512   //
1513   if (AuthAlgKeyLen == 0 ||
1514       EncryptAlgKeyLen == 0 ||
1515       IntegrityAlgKeyLen == 0 ||
1516       PrfAlgKeyLen == 0
1517       ) {
1518     Status = EFI_UNSUPPORTED;
1519     goto Exit;
1520   }
1521 
1522   //
1523   // Compute SKEYSEED = prf(Ni | Nr, g^ir)
1524   //
1525   KeyBufferSize = IkeSaSession->NiBlkSize + IkeSaSession->NrBlkSize;
1526   KeyBuffer     = AllocateZeroPool (KeyBufferSize);
1527   ASSERT (KeyBuffer != NULL);
1528 
1529   CopyMem (KeyBuffer, IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
1530   CopyMem (KeyBuffer + IkeSaSession->NiBlkSize, IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
1531 
1532   Fragments[0].Data     = IkeSaSession->IkeKeys->DhBuffer->GxyBuffer;
1533   Fragments[0].DataSize = IkeSaSession->IkeKeys->DhBuffer->GxySize;
1534 
1535   DigestSize = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
1536   Digest     = AllocateZeroPool (DigestSize);
1537 
1538   if (Digest == NULL) {
1539     Status = EFI_OUT_OF_RESOURCES;
1540     goto Exit;
1541   }
1542 
1543   IpSecCryptoIoHmac (
1544     (UINT8)SaParams->Prf,
1545     KeyBuffer,
1546     KeyBufferSize,
1547     (HASH_DATA_FRAGMENT *) Fragments,
1548     1,
1549     Digest,
1550     DigestSize
1551     );
1552 
1553   //
1554   // {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = prf+
1555   //               (SKEYSEED, Ni | Nr | SPIi | SPIr )
1556   //
1557   Fragments[0].Data     = IkeSaSession->NiBlock;
1558   Fragments[0].DataSize = IkeSaSession->NiBlkSize;
1559   Fragments[1].Data     = IkeSaSession->NrBlock;
1560   Fragments[1].DataSize = IkeSaSession->NrBlkSize;
1561   InitiatorCookieNet    = HTONLL (IkeSaSession->InitiatorCookie);
1562   ResponderCookieNet    = HTONLL (IkeSaSession->ResponderCookie);
1563   Fragments[2].Data     = (UINT8 *)(&InitiatorCookieNet);
1564   Fragments[2].DataSize = sizeof (IkeSaSession->InitiatorCookie);
1565   Fragments[3].Data     = (UINT8 *)(&ResponderCookieNet);
1566   Fragments[3].DataSize = sizeof (IkeSaSession->ResponderCookie);
1567 
1568   IPSEC_DUMP_BUF (">>> NiBlock", IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
1569   IPSEC_DUMP_BUF (">>> NrBlock", IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
1570   IPSEC_DUMP_BUF (">>> InitiatorCookie", (UINT8 *)&IkeSaSession->InitiatorCookie, sizeof(UINT64));
1571   IPSEC_DUMP_BUF (">>> ResponderCookie", (UINT8 *)&IkeSaSession->ResponderCookie, sizeof(UINT64));
1572 
1573   OutputKeyLength = PrfAlgKeyLen +
1574                     2 * EncryptAlgKeyLen +
1575                     2 * AuthAlgKeyLen +
1576                     2 * IntegrityAlgKeyLen;
1577   OutputKey       = AllocateZeroPool (OutputKeyLength);
1578   if (OutputKey == NULL) {
1579     Status = EFI_OUT_OF_RESOURCES;
1580     goto Exit;
1581   }
1582 
1583   //
1584   // Generate Seven Keymates.
1585   //
1586   Status = Ikev2SaGenerateKey (
1587              (UINT8)SaParams->Prf,
1588              Digest,
1589              DigestSize,
1590              OutputKey,
1591              OutputKeyLength,
1592              Fragments,
1593              4
1594              );
1595   if (EFI_ERROR(Status)) {
1596     goto Exit;
1597   }
1598 
1599   //
1600   // Save the seven keys into KeySession.
1601   // First, SK_d
1602   //
1603   IkeSaSession->IkeKeys->SkdKey     = AllocateZeroPool (PrfAlgKeyLen);
1604   if (IkeSaSession->IkeKeys->SkdKey == NULL) {
1605     Status = EFI_OUT_OF_RESOURCES;
1606     goto Exit;
1607   }
1608   IkeSaSession->IkeKeys->SkdKeySize = PrfAlgKeyLen;
1609   CopyMem (IkeSaSession->IkeKeys->SkdKey, OutputKey, PrfAlgKeyLen);
1610 
1611   IPSEC_DUMP_BUF (">>> SK_D Key", IkeSaSession->IkeKeys->SkdKey, PrfAlgKeyLen);
1612 
1613   //
1614   // Second, Sk_ai
1615   //
1616   IkeSaSession->IkeKeys->SkAiKey     = AllocateZeroPool (IntegrityAlgKeyLen);
1617   if (IkeSaSession->IkeKeys->SkAiKey == NULL) {
1618     Status = EFI_OUT_OF_RESOURCES;
1619     goto Exit;
1620   }
1621   IkeSaSession->IkeKeys->SkAiKeySize = IntegrityAlgKeyLen;
1622   CopyMem (IkeSaSession->IkeKeys->SkAiKey, OutputKey + PrfAlgKeyLen, IntegrityAlgKeyLen);
1623 
1624   IPSEC_DUMP_BUF (">>> SK_Ai Key", IkeSaSession->IkeKeys->SkAiKey, IkeSaSession->IkeKeys->SkAiKeySize);
1625 
1626   //
1627   // Third, Sk_ar
1628   //
1629   IkeSaSession->IkeKeys->SkArKey     = AllocateZeroPool (IntegrityAlgKeyLen);
1630   if (IkeSaSession->IkeKeys->SkArKey == NULL) {
1631     Status = EFI_OUT_OF_RESOURCES;
1632     goto Exit;
1633   }
1634   IkeSaSession->IkeKeys->SkArKeySize = IntegrityAlgKeyLen;
1635   CopyMem (
1636     IkeSaSession->IkeKeys->SkArKey,
1637     OutputKey + PrfAlgKeyLen + IntegrityAlgKeyLen,
1638     IntegrityAlgKeyLen
1639     );
1640 
1641   IPSEC_DUMP_BUF (">>> SK_Ar Key", IkeSaSession->IkeKeys->SkArKey, IkeSaSession->IkeKeys->SkArKeySize);
1642 
1643   //
1644   // Fourth, Sk_ei
1645   //
1646   IkeSaSession->IkeKeys->SkEiKey     = AllocateZeroPool (EncryptAlgKeyLen);
1647   if (IkeSaSession->IkeKeys->SkEiKey == NULL) {
1648     Status = EFI_OUT_OF_RESOURCES;
1649     goto Exit;
1650   }
1651   IkeSaSession->IkeKeys->SkEiKeySize = EncryptAlgKeyLen;
1652 
1653   CopyMem (
1654     IkeSaSession->IkeKeys->SkEiKey,
1655     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen,
1656     EncryptAlgKeyLen
1657     );
1658   IPSEC_DUMP_BUF (
1659     ">>> SK_Ei Key",
1660     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen,
1661     EncryptAlgKeyLen
1662     );
1663 
1664   //
1665   // Fifth, Sk_er
1666   //
1667   IkeSaSession->IkeKeys->SkErKey     = AllocateZeroPool (EncryptAlgKeyLen);
1668   if (IkeSaSession->IkeKeys->SkErKey == NULL) {
1669     Status = EFI_OUT_OF_RESOURCES;
1670     goto Exit;
1671   }
1672   IkeSaSession->IkeKeys->SkErKeySize = EncryptAlgKeyLen;
1673 
1674   CopyMem (
1675     IkeSaSession->IkeKeys->SkErKey,
1676     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + EncryptAlgKeyLen,
1677     EncryptAlgKeyLen
1678     );
1679   IPSEC_DUMP_BUF (
1680     ">>> SK_Er Key",
1681     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + EncryptAlgKeyLen,
1682     EncryptAlgKeyLen
1683     );
1684 
1685   //
1686   // Sixth, Sk_pi
1687   //
1688   IkeSaSession->IkeKeys->SkPiKey     = AllocateZeroPool (AuthAlgKeyLen);
1689   if (IkeSaSession->IkeKeys->SkPiKey == NULL) {
1690     Status = EFI_OUT_OF_RESOURCES;
1691     goto Exit;
1692   }
1693   IkeSaSession->IkeKeys->SkPiKeySize = AuthAlgKeyLen;
1694 
1695   CopyMem (
1696     IkeSaSession->IkeKeys->SkPiKey,
1697     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen +  2 * EncryptAlgKeyLen,
1698     AuthAlgKeyLen
1699     );
1700   IPSEC_DUMP_BUF (
1701     ">>> SK_Pi Key",
1702     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen +  2 * EncryptAlgKeyLen,
1703     AuthAlgKeyLen
1704     );
1705 
1706   //
1707   // Seventh, Sk_pr
1708   //
1709   IkeSaSession->IkeKeys->SkPrKey     = AllocateZeroPool (AuthAlgKeyLen);
1710   if (IkeSaSession->IkeKeys->SkPrKey == NULL) {
1711     Status = EFI_OUT_OF_RESOURCES;
1712     goto Exit;
1713   }
1714   IkeSaSession->IkeKeys->SkPrKeySize = AuthAlgKeyLen;
1715 
1716   CopyMem (
1717     IkeSaSession->IkeKeys->SkPrKey,
1718     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + 2 * EncryptAlgKeyLen + AuthAlgKeyLen,
1719     AuthAlgKeyLen
1720     );
1721   IPSEC_DUMP_BUF (
1722     ">>> SK_Pr Key",
1723     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + 2 * EncryptAlgKeyLen + AuthAlgKeyLen,
1724     AuthAlgKeyLen
1725     );
1726 
1727 
1728 Exit:
1729   if (Digest != NULL) {
1730     FreePool (Digest);
1731   }
1732   if (KeyBuffer != NULL) {
1733     FreePool (KeyBuffer);
1734   }
1735   if (OutputKey != NULL) {
1736     FreePool (OutputKey);
1737   }
1738 
1739   if (EFI_ERROR(Status)) {
1740     if (IkeSaSession->IkeKeys->SkdKey != NULL) {
1741       FreePool (IkeSaSession->IkeKeys->SkdKey);
1742     }
1743     if (IkeSaSession->IkeKeys->SkAiKey != NULL) {
1744       FreePool (IkeSaSession->IkeKeys->SkAiKey);
1745     }
1746     if (IkeSaSession->IkeKeys->SkArKey != NULL) {
1747       FreePool (IkeSaSession->IkeKeys->SkArKey);
1748     }
1749     if (IkeSaSession->IkeKeys->SkEiKey != NULL) {
1750       FreePool (IkeSaSession->IkeKeys->SkEiKey);
1751     }
1752     if (IkeSaSession->IkeKeys->SkErKey != NULL) {
1753       FreePool (IkeSaSession->IkeKeys->SkErKey);
1754     }
1755     if (IkeSaSession->IkeKeys->SkPiKey != NULL) {
1756       FreePool (IkeSaSession->IkeKeys->SkPiKey);
1757     }
1758     if (IkeSaSession->IkeKeys->SkPrKey != NULL) {
1759       FreePool (IkeSaSession->IkeKeys->SkPrKey);
1760     }
1761   }
1762 
1763 
1764   return Status;
1765 }
1766 
1767 /**
1768   Generates the Keys for the furthure IPsec Protocol.
1769 
1770   @param[in]  ChildSaSession     Pointer to IKE Child SA Session.
1771   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
1772 
1773   @retval EFI_UNSUPPORTED    If one or more Algorithm Id is not supported.
1774   @retval EFI_SUCCESS        The operation succeeded.
1775 
1776 **/
1777 EFI_STATUS
Ikev2GenerateChildSaKeys(IN IKEV2_CHILD_SA_SESSION * ChildSaSession,IN IKE_PAYLOAD * KePayload)1778 Ikev2GenerateChildSaKeys (
1779   IN IKEV2_CHILD_SA_SESSION     *ChildSaSession,
1780   IN IKE_PAYLOAD                *KePayload
1781   )
1782 {
1783   EFI_STATUS          Status;
1784   IKEV2_SA_PARAMS     *SaParams;
1785   PRF_DATA_FRAGMENT   Fragments[3];
1786   UINTN               EncryptAlgKeyLen;
1787   UINTN               IntegrityAlgKeyLen;
1788   UINT8*              OutputKey;
1789   UINTN               OutputKeyLength;
1790 
1791   Status = EFI_SUCCESS;
1792   OutputKey = NULL;
1793 
1794   if (KePayload != NULL) {
1795     //
1796     // Generate Gxy
1797     //
1798     Ikev2GenerateSaDhComputeKey (ChildSaSession->DhBuffer, KePayload);
1799     Fragments[0].Data     = ChildSaSession->DhBuffer->GxyBuffer;
1800     Fragments[0].DataSize = ChildSaSession->DhBuffer->GxySize;
1801   }
1802 
1803   Fragments[1].Data     = ChildSaSession->NiBlock;
1804   Fragments[1].DataSize = ChildSaSession->NiBlkSize;
1805   Fragments[2].Data     = ChildSaSession->NrBlock;
1806   Fragments[2].DataSize = ChildSaSession->NrBlkSize;
1807 
1808   //
1809   // Get the key length of Authenticaion, Encryption, PRF, and Integrity.
1810   //
1811   SaParams           = ChildSaSession->SessionCommon.SaParams;
1812   EncryptAlgKeyLen   = IpSecGetEncryptKeyLength ((UINT8)SaParams->EncAlgId);
1813   IntegrityAlgKeyLen = IpSecGetHmacDigestLength ((UINT8)SaParams->IntegAlgId);
1814   OutputKeyLength    = 2 * EncryptAlgKeyLen + 2 * IntegrityAlgKeyLen;
1815 
1816   if ((EncryptAlgKeyLen == 0) || (IntegrityAlgKeyLen == 0)) {
1817     Status = EFI_UNSUPPORTED;
1818     goto Exit;
1819   }
1820 
1821   //
1822   //
1823   // If KePayload is not NULL, calculate KEYMAT = prf+(SK_d, g^ir (new) | Ni | Nr ),
1824   // otherwise, KEYMAT = prf+(SK_d, Ni | Nr )
1825   //
1826   OutputKey = AllocateZeroPool (OutputKeyLength);
1827   if (OutputKey == NULL) {
1828     Status = EFI_OUT_OF_RESOURCES;
1829     goto Exit;
1830   }
1831 
1832   //
1833   // Derive Key from the SkdKey Buffer.
1834   //
1835   Status = Ikev2SaGenerateKey (
1836              (UINT8)ChildSaSession->IkeSaSession->SessionCommon.SaParams->Prf,
1837              ChildSaSession->IkeSaSession->IkeKeys->SkdKey,
1838              ChildSaSession->IkeSaSession->IkeKeys->SkdKeySize,
1839              OutputKey,
1840              OutputKeyLength,
1841              KePayload == NULL ? &Fragments[1] : Fragments,
1842              KePayload == NULL ? 2 : 3
1843              );
1844 
1845   if (EFI_ERROR (Status)) {
1846     goto Exit;
1847   }
1848 
1849   //
1850   // Copy KEYMATE (SK_ENCRYPT_i | SK_ENCRYPT_r | SK_INTEG_i | SK_INTEG_r) to
1851   // ChildKeyMates.
1852   //
1853   if (!ChildSaSession->SessionCommon.IsInitiator) {
1854 
1855     //
1856     // Initiator Encryption Key
1857     //
1858     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
1859     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
1860     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
1861     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey == NULL) {
1862       Status = EFI_OUT_OF_RESOURCES;
1863       goto Exit;
1864     }
1865 
1866     CopyMem (
1867       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
1868       OutputKey,
1869       EncryptAlgKeyLen
1870       );
1871 
1872     //
1873     // Initiator Authentication Key
1874     //
1875     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
1876     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
1877     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
1878     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey == NULL) {
1879       Status = EFI_OUT_OF_RESOURCES;
1880       goto Exit;
1881     }
1882 
1883     CopyMem (
1884       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
1885       OutputKey + EncryptAlgKeyLen,
1886       IntegrityAlgKeyLen
1887       );
1888 
1889     //
1890     // Responder Encrypt Key
1891     //
1892     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
1893     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
1894     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
1895     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey == NULL) {
1896       Status = EFI_OUT_OF_RESOURCES;
1897       goto Exit;
1898     }
1899 
1900     CopyMem (
1901       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
1902       OutputKey + EncryptAlgKeyLen + IntegrityAlgKeyLen,
1903       EncryptAlgKeyLen
1904       );
1905 
1906     //
1907     // Responder Authentication Key
1908     //
1909     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
1910     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
1911     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
1912     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey == NULL) {
1913       Status = EFI_OUT_OF_RESOURCES;
1914       goto Exit;
1915     }
1916 
1917     CopyMem (
1918       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
1919       OutputKey + 2 * EncryptAlgKeyLen + IntegrityAlgKeyLen,
1920       IntegrityAlgKeyLen
1921       );
1922   } else {
1923     //
1924     // Initiator Encryption Key
1925     //
1926     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
1927     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
1928     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
1929     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey == NULL) {
1930       Status = EFI_OUT_OF_RESOURCES;
1931       goto Exit;
1932     }
1933 
1934     CopyMem (
1935       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
1936       OutputKey,
1937       EncryptAlgKeyLen
1938       );
1939 
1940     //
1941     // Initiator Authentication Key
1942     //
1943     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
1944     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
1945     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
1946     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey == NULL) {
1947       Status = EFI_OUT_OF_RESOURCES;
1948       goto Exit;
1949     }
1950 
1951     CopyMem (
1952       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
1953       OutputKey + EncryptAlgKeyLen,
1954       IntegrityAlgKeyLen
1955       );
1956 
1957     //
1958     // Responder Encryption Key
1959     //
1960     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
1961     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
1962     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
1963     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey == NULL) {
1964       Status = EFI_OUT_OF_RESOURCES;
1965       goto Exit;
1966     }
1967 
1968     CopyMem (
1969       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
1970       OutputKey + EncryptAlgKeyLen + IntegrityAlgKeyLen,
1971       EncryptAlgKeyLen
1972       );
1973 
1974     //
1975     // Responder Authentication Key
1976     //
1977     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
1978     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
1979     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
1980     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey == NULL) {
1981       Status = EFI_OUT_OF_RESOURCES;
1982       goto Exit;
1983     }
1984 
1985     CopyMem (
1986       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
1987       OutputKey + 2 * EncryptAlgKeyLen + IntegrityAlgKeyLen,
1988       IntegrityAlgKeyLen
1989       );
1990   }
1991 
1992   IPSEC_DUMP_BUF (
1993       " >>> Local Encryption Key",
1994       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
1995       EncryptAlgKeyLen
1996       );
1997   IPSEC_DUMP_BUF (
1998       " >>> Remote Encryption Key",
1999       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
2000       EncryptAlgKeyLen
2001       );
2002   IPSEC_DUMP_BUF (
2003       " >>> Local Authentication Key",
2004       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
2005       IntegrityAlgKeyLen
2006       );
2007   IPSEC_DUMP_BUF (
2008     " >>> Remote Authentication Key",
2009     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
2010     IntegrityAlgKeyLen
2011     );
2012 
2013 
2014 
2015 Exit:
2016   if (EFI_ERROR (Status)) {
2017     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey != NULL) {
2018       FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey);
2019     }
2020     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey != NULL) {
2021       FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey);
2022     }
2023     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey != NULL) {
2024       FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey);
2025     }
2026     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey != NULL) {
2027       FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey);
2028     }
2029   }
2030 
2031   if (OutputKey != NULL) {
2032     FreePool (OutputKey);
2033   }
2034 
2035   return EFI_SUCCESS;
2036 }
2037 
2038 GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Initial[][2] = {
2039   { //PSK
2040     { // IKEV2_INIT
2041       Ikev2InitPskParser,
2042       Ikev2InitPskGenerator
2043     },
2044     { //IKEV2_AUTH
2045       Ikev2AuthPskParser,
2046       Ikev2AuthPskGenerator
2047     }
2048   },
2049   { // CERT
2050     { // IKEV2_INIT
2051       Ikev2InitCertParser,
2052       Ikev2InitCertGenerator
2053     },
2054     { // IKEV2_AUTH
2055       Ikev2AuthCertParser,
2056       Ikev2AuthCertGenerator
2057     },
2058   },
2059 };
2060