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