]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/Ikev2/Sa.c
NetworkPkg: Remove unused variables from IpSecDxe to fix GCC build.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Sa.c
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 *
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
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 *
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
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*
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
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 *
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
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
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
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
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
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 };