]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/Ikev2/Payload.c
1bb5e2e5e53d216dd6cc7d1a86853911ed244903
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Payload.c
1 /** @file
2 The implementation of Payloads Creation.
3
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
6
7 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 "IpSecConfigImpl.h"
20 #include "IpSecCryptIo.h"
21
22 //
23 // The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.
24 //
25 #define CONSTANT_KEY_SIZE 17
26 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey[CONSTANT_KEY_SIZE] =
27 {
28 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'
29 };
30
31 /**
32 Generate Ikev2 SA payload according to SessionSaData
33
34 @param[in] SessionSaData The data used in SA payload.
35 @param[in] NextPayload The payload type presented in NextPayload field of
36 SA Payload header.
37 @param[in] Type The SA type. It MUST be neither (1) for IKE_SA or
38 (2) for CHILD_SA or (3) for INFO.
39
40 @retval a Pointer to SA IKE payload.
41
42 **/
43 IKE_PAYLOAD *
44 Ikev2GenerateSaPayload (
45 IN IKEV2_SA_DATA *SessionSaData,
46 IN UINT8 NextPayload,
47 IN IKE_SESSION_TYPE Type
48 )
49 {
50 IKE_PAYLOAD *SaPayload;
51 IKEV2_SA_DATA *SaData;
52 UINTN SaDataSize;
53
54 SaPayload = IkePayloadAlloc ();
55 if (SaPayload == NULL) {
56 return NULL;
57 }
58
59 //
60 // TODO: Get the Proposal Number and Transform Number from IPsec Config,
61 // after the Ipsecconfig Application is support it.
62 //
63
64 if (Type == IkeSessionTypeIkeSa) {
65 SaDataSize = sizeof (IKEV2_SA_DATA) +
66 SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +
67 sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 4;
68 } else {
69 SaDataSize = sizeof (IKEV2_SA_DATA) +
70 SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +
71 sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 3;
72
73 }
74
75 SaData = AllocateZeroPool (SaDataSize);
76 if (SaData == NULL) {
77 IkePayloadFree (SaPayload);
78 return NULL;
79 }
80
81 CopyMem (SaData, SessionSaData, SaDataSize);
82 SaData->SaHeader.Header.NextPayload = NextPayload;
83 SaPayload->PayloadType = IKEV2_PAYLOAD_TYPE_SA;
84 SaPayload->PayloadBuf = (UINT8 *) SaData;
85
86 return SaPayload;
87 }
88
89 /**
90 Generate a Nonce payload containing the input parameter NonceBuf.
91
92 @param[in] NonceBuf The nonce buffer contains the whole Nonce payload block
93 except the payload header.
94 @param[in] NonceSize The buffer size of the NonceBuf
95 @param[in] NextPayload The payload type presented in the NextPayload field
96 of Nonce Payload header.
97
98 @retval Pointer to Nonce IKE paload.
99
100 **/
101 IKE_PAYLOAD *
102 Ikev2GenerateNoncePayload (
103 IN UINT8 *NonceBuf,
104 IN UINTN NonceSize,
105 IN UINT8 NextPayload
106 )
107 {
108 IKE_PAYLOAD *NoncePayload;
109 IKEV2_NONCE *Nonce;
110 UINTN Size;
111 UINT8 *NonceBlock;
112
113 // 1 2 3
114 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
115 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 // ! Next Payload !C! RESERVED ! Payload Length !
117 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 // ! !
119 // ~ Nonce Data ~
120 // ! !
121 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 //
123 Size = sizeof (IKEV2_NONCE) + NonceSize;
124 NonceBlock = NonceBuf;
125
126 Nonce = AllocateZeroPool (Size);
127 if (Nonce == NULL) {
128 return NULL;
129 }
130
131 CopyMem (Nonce + 1, NonceBlock, Size - sizeof (IKEV2_NONCE));
132
133 Nonce->Header.NextPayload = NextPayload;
134 Nonce->Header.PayloadLength = (UINT16) Size;
135 NoncePayload = IkePayloadAlloc ();
136 if (NoncePayload == NULL) {
137 FreePool (Nonce);
138 return NULL;
139 }
140
141 NoncePayload->PayloadType = IKEV2_PAYLOAD_TYPE_NONCE;
142 NoncePayload->PayloadBuf = (UINT8 *) Nonce;
143 NoncePayload->PayloadSize = Size;
144
145 return NoncePayload;
146 }
147
148 /**
149 Generate a Key Exchange payload according to the DH group type and save the
150 public Key into IkeSaSession IkeKey field.
151
152 @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.
153 @param[in] NextPayload The payload type presented in the NextPayload field of Key
154 Exchange Payload header.
155
156 @retval Pointer to Key IKE payload.
157
158 **/
159 IKE_PAYLOAD*
160 Ikev2GenerateKePayload (
161 IN OUT IKEV2_SA_SESSION *IkeSaSession,
162 IN UINT8 NextPayload
163 )
164 {
165 IKE_PAYLOAD *KePayload;
166 IKEV2_KEY_EXCHANGE *Ke;
167 UINTN KeSize;
168 IKEV2_SESSION_KEYS *IkeKeys;
169
170 //
171 // 1 2 3
172 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
173 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174 // ! Next Payload !C! RESERVED ! Payload Length !
175 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176 // ! DH Group # ! RESERVED !
177 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178 // ! !
179 // ~ Key Exchange Data ~
180 // ! !
181 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
182 //
183 IkeKeys = IkeSaSession->IkeKeys;
184
185 if (IkeSaSession->SessionCommon.IsInitiator) {
186 KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;
187 } else {
188 KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;
189 }
190
191 //
192 // Allocate buffer for Key Exchange
193 //
194 Ke = AllocateZeroPool (KeSize);
195 if (Ke == NULL) {
196 return NULL;
197 }
198
199 Ke->Header.NextPayload = NextPayload;
200 Ke->Header.PayloadLength = (UINT16) KeSize;
201 Ke->DhGroup = IkeSaSession->SessionCommon.PreferDhGroup;
202
203 CopyMem (Ke + 1, IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);
204
205 //
206 // Create IKE_PAYLOAD to point to Key Exchange payload
207 //
208 KePayload = IkePayloadAlloc ();
209 if (KePayload == NULL) {
210 FreePool (Ke);
211 return NULL;
212 }
213
214 KePayload->PayloadType = IKEV2_PAYLOAD_TYPE_KE;
215 KePayload->PayloadBuf = (UINT8 *) Ke;
216 KePayload->PayloadSize = KeSize;
217 return KePayload;
218 }
219
220 /**
221 Generate a ID payload.
222
223 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
224 @param[in] NextPayload The payload type presented in the NextPayload field
225 of ID Payload header.
226
227 @retval Pointer to ID IKE payload.
228
229 **/
230 IKE_PAYLOAD *
231 Ikev2GenerateIdPayload (
232 IN IKEV2_SESSION_COMMON *CommonSession,
233 IN UINT8 NextPayload
234 )
235 {
236 IKE_PAYLOAD *IdPayload;
237 IKEV2_ID *Id;
238 UINTN IdSize;
239 UINT8 IpVersion;
240 UINT8 AddrSize;
241
242 //
243 // ID payload
244 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
245 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
246 // ! Next Payload ! RESERVED ! Payload Length !
247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248 // ! ID Type ! RESERVED !
249 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250 // ! !
251 // ~ Identification Data ~
252 // ! !
253 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254 //
255
256 IpVersion = CommonSession->UdpService->IpVersion;
257 AddrSize = (UINT8) ((IpVersion == IP_VERSION_4) ? sizeof(EFI_IPv4_ADDRESS) : sizeof(EFI_IPv6_ADDRESS));
258 IdSize = sizeof (IKEV2_ID) + AddrSize;
259
260 Id = (IKEV2_ID *) AllocateZeroPool (IdSize);
261 if (Id == NULL) {
262 return NULL;
263 }
264
265 IdPayload = IkePayloadAlloc ();
266 if (IdPayload == NULL) {
267 FreePool (Id);
268 return NULL;
269 }
270
271 IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);
272 IdPayload->PayloadBuf = (UINT8 *) Id;
273 IdPayload->PayloadSize = IdSize;
274
275 //
276 // Set generic header of identification payload
277 //
278 Id->Header.NextPayload = NextPayload;
279 Id->Header.PayloadLength = (UINT16) IdSize;
280 Id->IdType = (UINT8) ((IpVersion == IP_VERSION_4) ? IKEV2_ID_TYPE_IPV4_ADDR : IKEV2_ID_TYPE_IPV6_ADDR);
281 CopyMem (Id + 1, &CommonSession->LocalPeerIp, AddrSize);
282
283 return IdPayload;
284 }
285
286 /**
287 Generate a ID payload.
288
289 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
290 @param[in] NextPayload The payload type presented in the NextPayload field
291 of ID Payload header.
292 @param[in] InCert Pointer to the Certificate which distinguished name
293 will be added into the Id payload.
294 @param[in] CertSize Size of the Certificate.
295
296 @retval Pointer to ID IKE payload.
297
298 **/
299 IKE_PAYLOAD *
300 Ikev2GenerateCertIdPayload (
301 IN IKEV2_SESSION_COMMON *CommonSession,
302 IN UINT8 NextPayload,
303 IN UINT8 *InCert,
304 IN UINTN CertSize
305 )
306 {
307 IKE_PAYLOAD *IdPayload;
308 IKEV2_ID *Id;
309 UINTN IdSize;
310 UINTN SubjectSize;
311 UINT8 *CertSubject;
312
313 //
314 // ID payload
315 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
316 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
317 // ! Next Payload ! RESERVED ! Payload Length !
318 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319 // ! ID Type ! RESERVED !
320 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
321 // ! !
322 // ~ Identification Data ~
323 // ! !
324 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325 //
326
327 SubjectSize = 0;
328 CertSubject = NULL;
329 IpSecCryptoIoGetSubjectFromCert (
330 InCert,
331 CertSize,
332 &CertSubject,
333 &SubjectSize
334 );
335 if (SubjectSize != 0) {
336 ASSERT (CertSubject != NULL);
337 }
338
339 IdSize = sizeof (IKEV2_ID) + SubjectSize;
340
341 Id = (IKEV2_ID *) AllocateZeroPool (IdSize);
342 if (Id == NULL) {
343 return NULL;
344 }
345
346 IdPayload = IkePayloadAlloc ();
347 if (IdPayload == NULL) {
348 FreePool (Id);
349 return NULL;
350 }
351
352 IdPayload->PayloadType = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);
353 IdPayload->PayloadBuf = (UINT8 *) Id;
354 IdPayload->PayloadSize = IdSize;
355
356 //
357 // Set generic header of identification payload
358 //
359 Id->Header.NextPayload = NextPayload;
360 Id->Header.PayloadLength = (UINT16) IdSize;
361 Id->IdType = 9;
362 CopyMem (Id + 1, CertSubject, SubjectSize);
363
364 if (CertSubject != NULL) {
365 FreePool (CertSubject);
366 }
367 return IdPayload;
368 }
369
370 /**
371 Generate a Authentication Payload.
372
373 This function is used for both Authentication generation and verification. When the
374 IsVerify is TRUE, it create a Auth Data for verification. This function choose the
375 related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type
376 and the value of IsVerify parameter.
377
378 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
379 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
380 payload generation.
381 @param[in] NextPayload The type filled into the Authentication Payload next
382 payload field.
383 @param[in] IsVerify If it is TURE, the Authentication payload is used for
384 verification.
385
386 @return pointer to IKE Authentication payload for Pre-shared key method.
387
388 **/
389 IKE_PAYLOAD *
390 Ikev2PskGenerateAuthPayload (
391 IN IKEV2_SA_SESSION *IkeSaSession,
392 IN IKE_PAYLOAD *IdPayload,
393 IN UINT8 NextPayload,
394 IN BOOLEAN IsVerify
395 )
396 {
397 UINT8 *Digest;
398 UINTN DigestSize;
399 PRF_DATA_FRAGMENT Fragments[3];
400 UINT8 *KeyBuf;
401 UINTN KeySize;
402 IKE_PAYLOAD *AuthPayload;
403 IKEV2_AUTH *PayloadBuf;
404 EFI_STATUS Status;
405
406 //
407 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
408 //
409 // 1 2 3
410 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
411 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412 // ! Next Payload !C! RESERVED ! Payload Length !
413 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414 // ! Auth Method ! RESERVED !
415 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416 // ! !
417 // ~ Authentication Data ~
418 // ! !
419 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420 //
421
422 KeyBuf = NULL;
423 AuthPayload = NULL;
424 Digest = NULL;
425
426 DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);
427 Digest = AllocateZeroPool (DigestSize);
428 if (Digest == NULL) {
429 return NULL;
430 }
431
432 if (IdPayload == NULL) {
433 return NULL;
434 }
435
436 //
437 // Calcualte Prf(Seceret, "Key Pad for IKEv2");
438 //
439 Fragments[0].Data = (UINT8 *) mConstantKey;
440 Fragments[0].DataSize = CONSTANT_KEY_SIZE;
441
442 Status = IpSecCryptoIoHmac (
443 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
444 IkeSaSession->Pad->Data->AuthData,
445 IkeSaSession->Pad->Data->AuthDataSize,
446 (HASH_DATA_FRAGMENT *)Fragments,
447 1,
448 Digest,
449 DigestSize
450 );
451 if (EFI_ERROR (Status)) {
452 goto EXIT;
453 }
454
455 //
456 // Store the AuthKey into KeyBuf
457 //
458 KeyBuf = AllocateZeroPool (DigestSize);
459 if (KeyBuf == NULL) {
460 Status = EFI_OUT_OF_RESOURCES;
461 goto EXIT;
462 }
463
464 CopyMem (KeyBuf, Digest, DigestSize);
465 KeySize = DigestSize;
466
467 //
468 // Calculate Prf(SK_Pi/r, IDi/r)
469 //
470 Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
471 Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
472
473 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
474 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
475 ) {
476 Status = IpSecCryptoIoHmac (
477 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
478 IkeSaSession->IkeKeys->SkPrKey,
479 IkeSaSession->IkeKeys->SkPrKeySize,
480 (HASH_DATA_FRAGMENT *) Fragments,
481 1,
482 Digest,
483 DigestSize
484 );
485 } else {
486 Status = IpSecCryptoIoHmac (
487 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
488 IkeSaSession->IkeKeys->SkPiKey,
489 IkeSaSession->IkeKeys->SkPiKeySize,
490 (HASH_DATA_FRAGMENT *) Fragments,
491 1,
492 Digest,
493 DigestSize
494 );
495 }
496 if (EFI_ERROR (Status)) {
497 goto EXIT;
498 }
499
500 //
501 // Copy data to Fragments.
502 //
503 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
504 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
505 ) {
506 Fragments[0].Data = IkeSaSession->RespPacket;
507 Fragments[0].DataSize = IkeSaSession->RespPacketSize;
508 Fragments[1].Data = IkeSaSession->NiBlock;
509 Fragments[1].DataSize = IkeSaSession->NiBlkSize;
510 } else {
511 Fragments[0].Data = IkeSaSession->InitPacket;
512 Fragments[0].DataSize = IkeSaSession->InitPacketSize;
513 Fragments[1].Data = IkeSaSession->NrBlock;
514 Fragments[1].DataSize = IkeSaSession->NrBlkSize;
515 }
516
517 //
518 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
519 //
520 Fragments[2].Data = AllocateZeroPool (DigestSize);
521 if (Fragments[2].Data == NULL) {
522 Status = EFI_OUT_OF_RESOURCES;
523 goto EXIT;
524 }
525
526 Fragments[2].DataSize = DigestSize;
527 CopyMem (Fragments[2].Data, Digest, DigestSize);
528
529 //
530 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
531 //
532 Status = IpSecCryptoIoHmac (
533 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
534 KeyBuf,
535 KeySize,
536 (HASH_DATA_FRAGMENT *) Fragments,
537 3,
538 Digest,
539 DigestSize
540 );
541 if (EFI_ERROR (Status)) {
542 goto EXIT;
543 }
544
545 //
546 // Allocate buffer for Auth Payload
547 //
548 AuthPayload = IkePayloadAlloc ();
549 if (AuthPayload == NULL) {
550 Status = EFI_OUT_OF_RESOURCES;
551 goto EXIT;
552 }
553
554 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;
555 PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);
556 if (PayloadBuf == NULL) {
557 Status = EFI_OUT_OF_RESOURCES;
558 goto EXIT;
559 }
560
561 //
562 // Fill in Auth payload.
563 //
564 PayloadBuf->Header.NextPayload = NextPayload;
565 PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);
566 if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodPreSharedSecret) {
567 //
568 // Only support Shared Key Message Integrity
569 //
570 PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_SKMI;
571 } else {
572 //
573 // Not support other Auth method.
574 //
575 Status = EFI_UNSUPPORTED;
576 goto EXIT;
577 }
578
579 //
580 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
581 // payload block.
582 //
583 CopyMem (
584 PayloadBuf + 1,
585 Digest,
586 DigestSize
587 );
588
589 //
590 // Fill in IKE_PACKET
591 //
592 AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;
593 AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;
594
595 EXIT:
596 if (KeyBuf != NULL) {
597 FreePool (KeyBuf);
598 }
599 if (Digest != NULL) {
600 FreePool (Digest);
601 }
602 if (Fragments[2].Data != NULL) {
603 //
604 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
605 //
606 FreePool (Fragments[2].Data);
607 }
608
609 if (EFI_ERROR (Status)) {
610 if (AuthPayload != NULL) {
611 IkePayloadFree (AuthPayload);
612 }
613 return NULL;
614 } else {
615 return AuthPayload;
616 }
617 }
618
619 /**
620 Generate a Authentication Payload for Certificate Auth method.
621
622 This function has two functions. One is creating a local Authentication
623 Payload for sending and other is creating the remote Authentication data
624 for verification when the IsVerify is TURE.
625
626 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
627 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
628 payload generation.
629 @param[in] NextPayload The type filled into the Authentication Payload
630 next payload field.
631 @param[in] IsVerify If it is TURE, the Authentication payload is used
632 for verification.
633 @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when
634 verify the authenticate payload.
635 @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it
636 when verify the authenticate payload.
637 @param[in] UefiKeyPwd Pointer to the password of UEFI private key.
638 Ignore it when verify the authenticate payload.
639 @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when
640 verify the authenticate payload.
641
642 @return pointer to IKE Authentication payload for Cerifitcation method.
643
644 **/
645 IKE_PAYLOAD *
646 Ikev2CertGenerateAuthPayload (
647 IN IKEV2_SA_SESSION *IkeSaSession,
648 IN IKE_PAYLOAD *IdPayload,
649 IN UINT8 NextPayload,
650 IN BOOLEAN IsVerify,
651 IN UINT8 *UefiPrivateKey,
652 IN UINTN UefiPrivateKeyLen,
653 IN UINT8 *UefiKeyPwd,
654 IN UINTN UefiKeyPwdLen
655 )
656 {
657 UINT8 *Digest;
658 UINTN DigestSize;
659 PRF_DATA_FRAGMENT Fragments[3];
660 IKE_PAYLOAD *AuthPayload;
661 IKEV2_AUTH *PayloadBuf;
662 EFI_STATUS Status;
663 UINT8 *Signature;
664 UINTN SigSize;
665
666 //
667 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
668 //
669 // 1 2 3
670 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
671 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
672 // ! Next Payload !C! RESERVED ! Payload Length !
673 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
674 // ! Auth Method ! RESERVED !
675 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 // ! !
677 // ~ Authentication Data ~
678 // ! !
679 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680 //
681 //
682 // Initial point
683 //
684 AuthPayload = NULL;
685 Digest = NULL;
686 Signature = NULL;
687 SigSize = 0;
688
689 if (IdPayload == NULL) {
690 return NULL;
691 }
692 DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);
693 Digest = AllocateZeroPool (DigestSize);
694 if (Digest == NULL) {
695 return NULL;
696 }
697
698 //
699 // Calculate Prf(SK_Pi/r, IDi/r)
700 //
701 Fragments[0].Data = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
702 Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
703
704 IpSecDumpBuf ("RestofIDPayload", Fragments[0].Data, Fragments[0].DataSize);
705
706 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
707 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
708 ) {
709 Status = IpSecCryptoIoHmac(
710 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
711 IkeSaSession->IkeKeys->SkPrKey,
712 IkeSaSession->IkeKeys->SkPrKeySize,
713 (HASH_DATA_FRAGMENT *) Fragments,
714 1,
715 Digest,
716 DigestSize
717 );
718 IpSecDumpBuf ("MACedIDForR", Digest, DigestSize);
719 } else {
720 Status = IpSecCryptoIoHmac (
721 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
722 IkeSaSession->IkeKeys->SkPiKey,
723 IkeSaSession->IkeKeys->SkPiKeySize,
724 (HASH_DATA_FRAGMENT *) Fragments,
725 1,
726 Digest,
727 DigestSize
728 );
729 IpSecDumpBuf ("MACedIDForI", Digest, DigestSize);
730 }
731 if (EFI_ERROR (Status)) {
732 goto EXIT;
733 }
734
735 //
736 // Copy data to Fragments.
737 //
738 if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
739 (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
740 ) {
741 Fragments[0].Data = IkeSaSession->RespPacket;
742 Fragments[0].DataSize = IkeSaSession->RespPacketSize;
743 Fragments[1].Data = IkeSaSession->NiBlock;
744 Fragments[1].DataSize = IkeSaSession->NiBlkSize;
745 IpSecDumpBuf ("RealMessage2", Fragments[0].Data, Fragments[0].DataSize);
746 IpSecDumpBuf ("NonceIDdata", Fragments[1].Data, Fragments[1].DataSize);
747 } else {
748 Fragments[0].Data = IkeSaSession->InitPacket;
749 Fragments[0].DataSize = IkeSaSession->InitPacketSize;
750 Fragments[1].Data = IkeSaSession->NrBlock;
751 Fragments[1].DataSize = IkeSaSession->NrBlkSize;
752 IpSecDumpBuf ("RealMessage1", Fragments[0].Data, Fragments[0].DataSize);
753 IpSecDumpBuf ("NonceRDdata", Fragments[1].Data, Fragments[1].DataSize);
754 }
755
756 //
757 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
758 //
759 Fragments[2].Data = AllocateZeroPool (DigestSize);
760 if (Fragments[2].Data == NULL) {
761 Status = EFI_OUT_OF_RESOURCES;
762 goto EXIT;
763 }
764
765 Fragments[2].DataSize = DigestSize;
766 CopyMem (Fragments[2].Data, Digest, DigestSize);
767
768 //
769 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
770 //
771 Status = IpSecCryptoIoHash (
772 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
773 (HASH_DATA_FRAGMENT *) Fragments,
774 3,
775 Digest,
776 DigestSize
777 );
778 if (EFI_ERROR (Status)) {
779 goto EXIT;
780 }
781
782 IpSecDumpBuf ("HashSignedOctects", Digest, DigestSize);
783 //
784 // Sign the data by the private Key
785 //
786 if (!IsVerify) {
787 IpSecCryptoIoAuthDataWithCertificate (
788 Digest,
789 DigestSize,
790 UefiPrivateKey,
791 UefiPrivateKeyLen,
792 UefiKeyPwd,
793 UefiKeyPwdLen,
794 &Signature,
795 &SigSize
796 );
797
798 if (SigSize == 0 || Signature == NULL) {
799 goto EXIT;
800 }
801 }
802
803 //
804 // Allocate buffer for Auth Payload
805 //
806 AuthPayload = IkePayloadAlloc ();
807 if (AuthPayload == NULL) {
808 Status = EFI_OUT_OF_RESOURCES;
809 goto EXIT;
810 }
811
812 if (!IsVerify) {
813 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + SigSize;
814 } else {
815 AuthPayload->PayloadSize = sizeof (IKEV2_AUTH) + DigestSize;
816 }
817
818 PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);
819 if (PayloadBuf == NULL) {
820 Status = EFI_OUT_OF_RESOURCES;
821 goto EXIT;
822 }
823
824 //
825 // Fill in Auth payload.
826 //
827 PayloadBuf->Header.NextPayload = NextPayload;
828 PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);
829 if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodCertificates) {
830 PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_RSA;
831 } else {
832 Status = EFI_INVALID_PARAMETER;
833 goto EXIT;
834 }
835
836 //
837 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
838 // payload block.
839 //
840 if (!IsVerify) {
841 CopyMem (PayloadBuf + 1, Signature, SigSize);
842 } else {
843 CopyMem (PayloadBuf + 1, Digest, DigestSize);
844 }
845
846 //
847 // Fill in IKE_PACKET
848 //
849 AuthPayload->PayloadBuf = (UINT8 *) PayloadBuf;
850 AuthPayload->PayloadType = IKEV2_PAYLOAD_TYPE_AUTH;
851
852 EXIT:
853 if (Digest != NULL) {
854 FreePool (Digest);
855 }
856 if (Signature != NULL) {
857 FreePool (Signature);
858 }
859 if (Fragments[2].Data != NULL) {
860 //
861 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
862 //
863 FreePool (Fragments[2].Data);
864 }
865
866 if (EFI_ERROR (Status)) {
867 if (AuthPayload != NULL) {
868 IkePayloadFree (AuthPayload);
869 }
870 return NULL;
871 } else {
872 return AuthPayload;
873 }
874 }
875
876 /**
877 Generate TS payload.
878
879 This function generates TSi or TSr payload according to type of next payload.
880 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
881 TSr payload.
882
883 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
884 @param[in] NextPayload The payload type presented in the NextPayload field
885 of ID Payload header.
886 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
887 If yes, it means the Tsi and Tsr payload should be with
888 Max port range and address range and protocol is marked
889 as zero.
890
891 @retval Pointer to Ts IKE payload.
892
893 **/
894 IKE_PAYLOAD *
895 Ikev2GenerateTsPayload (
896 IN IKEV2_CHILD_SA_SESSION *ChildSa,
897 IN UINT8 NextPayload,
898 IN BOOLEAN IsTunnel
899 )
900 {
901 IKE_PAYLOAD *TsPayload;
902 IKEV2_TS *TsPayloadBuf;
903 TRAFFIC_SELECTOR *TsSelector;
904 UINTN SelectorSize;
905 UINTN TsPayloadSize;
906 UINT8 IpVersion;
907 UINT8 AddrSize;
908
909 //
910 // 1 2 3
911 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
912 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913 // ! Next Payload !C! RESERVED ! Payload Length !
914 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
915 // ! Number of TSs ! RESERVED !
916 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
917 // ! !
918 // ~ <Traffic Selectors> ~
919 // ! !
920 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
921 //
922
923 TsPayload = IkePayloadAlloc();
924 if (TsPayload == NULL) {
925 return NULL;
926 }
927
928 IpVersion = ChildSa->SessionCommon.UdpService->IpVersion;
929 //
930 // The Starting Address and Ending Address is variable length depends on
931 // is IPv4 or IPv6
932 //
933 AddrSize = (UINT8)((IpVersion == IP_VERSION_4) ? sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS));
934 SelectorSize = sizeof (TRAFFIC_SELECTOR) + 2 * AddrSize;
935 TsPayloadSize = sizeof (IKEV2_TS) + SelectorSize;
936 TsPayloadBuf = AllocateZeroPool (TsPayloadSize);
937 if (TsPayloadBuf == NULL) {
938 goto ON_ERROR;
939 }
940
941 TsPayload->PayloadBuf = (UINT8 *) TsPayloadBuf;
942 TsSelector = (TRAFFIC_SELECTOR*)(TsPayloadBuf + 1);
943
944 TsSelector->TSType = (UINT8)((IpVersion == IP_VERSION_4) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE : IKEV2_TS_TYPS_IPV6_ADDR_RANGE);
945
946 //
947 // For tunnel mode
948 //
949 if (IsTunnel) {
950 TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;
951 TsSelector->SelecorLen = (UINT16) SelectorSize;
952 TsSelector->StartPort = 0;
953 TsSelector->EndPort = IKEV2_TS_ANY_PORT;
954 ZeroMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR), AddrSize);
955 SetMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize, AddrSize, 0xff);
956
957 } else {
958 //
959 // TODO: Support port range and address range
960 //
961 if (NextPayload == IKEV2_PAYLOAD_TYPE_TS_RSP){
962 //
963 // Create initiator Traffic Selector
964 //
965 TsSelector->SelecorLen = (UINT16)SelectorSize;
966
967 //
968 // Currently only support the port range from 0~0xffff. Don't support other
969 // port range.
970 // TODO: support Port range
971 //
972 if (ChildSa->SessionCommon.IsInitiator) {
973 if (ChildSa->Spd->Selector->LocalPort != 0 &&
974 ChildSa->Spd->Selector->LocalPortRange == 0) {
975 //
976 // For not port range.
977 //
978 TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;
979 TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;
980 } else if (ChildSa->Spd->Selector->LocalPort == 0){
981 //
982 // For port from 0~0xffff
983 //
984 TsSelector->StartPort = 0;
985 TsSelector->EndPort = IKEV2_TS_ANY_PORT;
986 } else {
987 //
988 // Not support now.
989 //
990 goto ON_ERROR;
991 }
992 } else {
993 if (ChildSa->Spd->Selector->RemotePort != 0 &&
994 ChildSa->Spd->Selector->RemotePortRange == 0) {
995 //
996 // For not port range.
997 //
998 TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;
999 TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;
1000 } else if (ChildSa->Spd->Selector->RemotePort == 0) {
1001 //
1002 // For port from 0~0xffff
1003 //
1004 TsSelector->StartPort = 0;
1005 TsSelector->EndPort = IKEV2_TS_ANY_PORT;
1006 } else {
1007 //
1008 // Not support now.
1009 //
1010 goto ON_ERROR;
1011 }
1012 }
1013 //
1014 // Copy Address.Currently the address range is not supported.
1015 // The Starting address is same as Ending address
1016 // TODO: Support Address Range.
1017 //
1018 CopyMem (
1019 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),
1020 ChildSa->SessionCommon.IsInitiator ?
1021 ChildSa->Spd->Selector->LocalAddress :
1022 ChildSa->Spd->Selector->RemoteAddress,
1023 AddrSize
1024 );
1025 CopyMem (
1026 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,
1027 ChildSa->SessionCommon.IsInitiator ?
1028 ChildSa->Spd->Selector->LocalAddress :
1029 ChildSa->Spd->Selector->RemoteAddress,
1030 AddrSize
1031 );
1032 //
1033 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1034 //
1035 TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_INIT;
1036 }else{
1037 //
1038 // Create responder Traffic Selector
1039 //
1040 TsSelector->SelecorLen = (UINT16)SelectorSize;
1041
1042 //
1043 // Currently only support the port range from 0~0xffff. Don't support other
1044 // port range.
1045 // TODO: support Port range
1046 //
1047 if (!ChildSa->SessionCommon.IsInitiator) {
1048 if (ChildSa->Spd->Selector->LocalPort != 0 &&
1049 ChildSa->Spd->Selector->LocalPortRange == 0) {
1050 //
1051 // For not port range.
1052 //
1053 TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;
1054 TsSelector->EndPort = ChildSa->Spd->Selector->LocalPort;
1055 } else if (ChildSa->Spd->Selector->LocalPort == 0){
1056 //
1057 // For port from 0~0xffff
1058 //
1059 TsSelector->StartPort = 0;
1060 TsSelector->EndPort = IKEV2_TS_ANY_PORT;
1061 } else {
1062 //
1063 // Not support now.
1064 //
1065 goto ON_ERROR;
1066 }
1067 } else {
1068 if (ChildSa->Spd->Selector->RemotePort != 0 &&
1069 ChildSa->Spd->Selector->RemotePortRange == 0) {
1070 //
1071 // For not port range.
1072 //
1073 TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;
1074 TsSelector->EndPort = ChildSa->Spd->Selector->RemotePort;
1075 } else if (ChildSa->Spd->Selector->RemotePort == 0){
1076 //
1077 // For port from 0~0xffff
1078 //
1079 TsSelector->StartPort = 0;
1080 TsSelector->EndPort = IKEV2_TS_ANY_PORT;
1081 } else {
1082 //
1083 // Not support now.
1084 //
1085 goto ON_ERROR;
1086 }
1087 }
1088 //
1089 // Copy Address.Currently the address range is not supported.
1090 // The Starting address is same as Ending address
1091 // TODO: Support Address Range.
1092 //
1093 CopyMem (
1094 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),
1095 ChildSa->SessionCommon.IsInitiator ?
1096 ChildSa->Spd->Selector->RemoteAddress :
1097 ChildSa->Spd->Selector->LocalAddress,
1098 AddrSize
1099 );
1100 CopyMem (
1101 (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,
1102 ChildSa->SessionCommon.IsInitiator ?
1103 ChildSa->Spd->Selector->RemoteAddress :
1104 ChildSa->Spd->Selector->LocalAddress,
1105 AddrSize
1106 );
1107 //
1108 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1109 //
1110 TsPayload->PayloadType = IKEV2_PAYLOAD_TYPE_TS_RSP;
1111 }
1112 }
1113
1114 if (ChildSa->Spd->Selector->NextLayerProtocol != 0xffff) {
1115 TsSelector->IpProtocolId = (UINT8)ChildSa->Spd->Selector->NextLayerProtocol;
1116 } else {
1117 TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;
1118 }
1119
1120 TsPayloadBuf->Header.NextPayload = NextPayload;
1121 TsPayloadBuf->Header.PayloadLength = (UINT16)TsPayloadSize;
1122 TsPayloadBuf->TSNumbers = 1;
1123 TsPayload->PayloadSize = TsPayloadSize;
1124 goto ON_EXIT;
1125
1126 ON_ERROR:
1127 if (TsPayload != NULL) {
1128 IkePayloadFree (TsPayload);
1129 TsPayload = NULL;
1130 }
1131 ON_EXIT:
1132 return TsPayload;
1133 }
1134
1135 /**
1136 Generate the Notify payload.
1137
1138 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1139 there is no internal data structure for Notify payload. This function generate
1140 Notify payload defined in RFC 4306, but all the fields in this payload are still
1141 in host order and need call Ikev2EncodePayload() to convert those fields from
1142 the host order to network order beforing sending it.
1143
1144 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1145 For IPsec SAs it MUST be neither (2) for AH or (3)
1146 for ESP.
1147 @param[in] NextPayload The next paylaod type in NextPayload field of
1148 the Notify payload.
1149 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1150 @param[in] MessageType The message type in NotifyMessageType field of the
1151 Notify Payload.
1152 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1153 @param[in] NotifyData Pointer to buffer contains the notification data.
1154 @param[in] NotifyDataSize The size of NotifyData in bytes.
1155
1156
1157 @retval Pointer to IKE Notify Payload.
1158
1159 **/
1160 IKE_PAYLOAD *
1161 Ikev2GenerateNotifyPayload (
1162 IN UINT8 ProtocolId,
1163 IN UINT8 NextPayload,
1164 IN UINT8 SpiSize,
1165 IN UINT16 MessageType,
1166 IN UINT8 *SpiBuf,
1167 IN UINT8 *NotifyData,
1168 IN UINTN NotifyDataSize
1169 )
1170 {
1171 IKE_PAYLOAD *NotifyPayload;
1172 IKEV2_NOTIFY *Notify;
1173 UINT16 NotifyPayloadLen;
1174 UINT8 *MessageData;
1175
1176 // 1 2 3
1177 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1178 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1179 // ! Next Payload !C! RESERVED ! Payload Length !
1180 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1181 // ! Protocol ID ! SPI Size ! Notify Message Type !
1182 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1183 // ! !
1184 // ~ Security Parameter Index (SPI) ~
1185 // ! !
1186 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1187 // ! !
1188 // ~ Notification Data ~
1189 // ! !
1190 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1191 //
1192 //
1193 NotifyPayloadLen = (UINT16) (sizeof (IKEV2_NOTIFY) + NotifyDataSize + SpiSize);
1194 Notify = (IKEV2_NOTIFY *) AllocateZeroPool (NotifyPayloadLen);
1195 if (Notify == NULL) {
1196 return NULL;
1197 }
1198
1199 //
1200 // Set Delete Payload's Generic Header
1201 //
1202 Notify->Header.NextPayload = NextPayload;
1203 Notify->Header.PayloadLength = NotifyPayloadLen;
1204 Notify->SpiSize = SpiSize;
1205 Notify->ProtocolId = ProtocolId;
1206 Notify->MessageType = MessageType;
1207
1208 //
1209 // Copy Spi , for Cookie Notify, there is no SPI.
1210 //
1211 if (SpiBuf != NULL && SpiSize != 0 ) {
1212 CopyMem (Notify + 1, SpiBuf, SpiSize);
1213 }
1214
1215 MessageData = ((UINT8 *) (Notify + 1)) + SpiSize;
1216
1217 //
1218 // Copy Notification Data
1219 //
1220 if (NotifyDataSize != 0) {
1221 CopyMem (MessageData, NotifyData, NotifyDataSize);
1222 }
1223
1224 //
1225 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1226 //
1227 NotifyPayload = IkePayloadAlloc ();
1228 if (NotifyPayload == NULL) {
1229 FreePool (Notify);
1230 return NULL;
1231 }
1232
1233 NotifyPayload->PayloadType = IKEV2_PAYLOAD_TYPE_NOTIFY;
1234 NotifyPayload->PayloadBuf = (UINT8 *) Notify;
1235 NotifyPayload->PayloadSize = NotifyPayloadLen;
1236 return NotifyPayload;
1237 }
1238
1239 /**
1240 Generate the Delete payload.
1241
1242 Since the structure of Delete payload which defined in RFC 4306 is simple,
1243 there is no internal data structure for Delete payload. This function generate
1244 Delete payload defined in RFC 4306, but all the fields in this payload are still
1245 in host order and need call Ikev2EncodePayload() to convert those fields from
1246 the host order to network order beforing sending it.
1247
1248 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1249 @param[in] NextPayload The next paylaod type in NextPayload field of
1250 the Delete payload.
1251 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1252 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1253 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1254
1255 @retval a Pointer of IKE Delete Payload.
1256
1257 **/
1258 IKE_PAYLOAD *
1259 Ikev2GenerateDeletePayload (
1260 IN IKEV2_SA_SESSION *IkeSaSession,
1261 IN UINT8 NextPayload,
1262 IN UINT8 SpiSize,
1263 IN UINT16 SpiNum,
1264 IN UINT8 *SpiBuf
1265
1266 )
1267 {
1268 IKE_PAYLOAD *DelPayload;
1269 IKEV2_DELETE *Del;
1270 UINT16 SpiBufSize;
1271 UINT16 DelPayloadLen;
1272
1273 // 1 2 3
1274 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1275 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1276 // ! Next Payload !C! RESERVED ! Payload Length !
1277 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1278 // ! Protocol ID ! SPI Size ! # of SPIs !
1279 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1280 // ! !
1281 // ~ Security Parameter Index(es) (SPI) ~
1282 // ! !
1283 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1284 //
1285 SpiBufSize = (UINT16) (SpiSize * SpiNum);
1286 if (SpiBufSize != 0 && SpiBuf == NULL) {
1287 return NULL;
1288 }
1289
1290 DelPayloadLen = (UINT16) (sizeof (IKEV2_DELETE) + SpiBufSize);
1291
1292 Del = AllocateZeroPool (DelPayloadLen);
1293 if (Del == NULL) {
1294 return NULL;
1295 }
1296
1297 //
1298 // Set Delete Payload's Generic Header
1299 //
1300 Del->Header.NextPayload = NextPayload;
1301 Del->Header.PayloadLength = DelPayloadLen;
1302 Del->NumSpis = SpiNum;
1303 Del->SpiSize = SpiSize;
1304
1305 if (SpiSize == 4) {
1306 //
1307 // TODO: should consider the AH if needs to support.
1308 //
1309 Del->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
1310 } else {
1311 Del->ProtocolId = IPSEC_PROTO_ISAKMP;
1312 }
1313
1314 //
1315 // Set Del Payload's Idntification Data
1316 //
1317 CopyMem (Del + 1, SpiBuf, SpiBufSize);
1318 DelPayload = IkePayloadAlloc ();
1319 if (DelPayload == NULL) {
1320 FreePool (Del);
1321 return NULL;
1322 }
1323
1324 DelPayload->PayloadType = IKEV2_PAYLOAD_TYPE_DELETE;
1325 DelPayload->PayloadBuf = (UINT8 *) Del;
1326 DelPayload->PayloadSize = DelPayloadLen;
1327 return DelPayload;
1328 }
1329
1330 /**
1331 Generate the Configuration payload.
1332
1333 This function generate configuration payload defined in RFC 4306, but all the
1334 fields in this payload are still in host order and need call Ikev2EncodePayload()
1335 to convert those fields from the host order to network order beforing sending it.
1336
1337 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1338 generation.
1339 @param[in] NextPayload The next paylaod type in NextPayload field of
1340 the Delete payload.
1341 @param[in] CfgType The attribute type in the Configuration attribute.
1342
1343 @retval Pointer to IKE CP Payload.
1344
1345 **/
1346 IKE_PAYLOAD *
1347 Ikev2GenerateCpPayload (
1348 IN IKEV2_SA_SESSION *IkeSaSession,
1349 IN UINT8 NextPayload,
1350 IN UINT8 CfgType
1351 )
1352 {
1353 IKE_PAYLOAD *CpPayload;
1354 IKEV2_CFG *Cfg;
1355 UINT16 PayloadLen;
1356 IKEV2_CFG_ATTRIBUTES *CfgAttributes;
1357
1358 //
1359 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1360 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1361 // ! Next Payload !C! RESERVED ! Payload Length !
1362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1363 // ! CFG Type ! RESERVED !
1364 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1365 // ! !
1366 // ~ Configuration Attributes ~
1367 // ! !
1368 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1369 //
1370
1371 PayloadLen = (UINT16) (sizeof (IKEV2_CFG) + sizeof (IKEV2_CFG_ATTRIBUTES));
1372 Cfg = (IKEV2_CFG *) AllocateZeroPool (PayloadLen);
1373
1374 if (Cfg == NULL) {
1375 return NULL;
1376 }
1377
1378 CfgAttributes = (IKEV2_CFG_ATTRIBUTES *)((UINT8 *)Cfg + sizeof (IKEV2_CFG));
1379
1380 //
1381 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1382 // or INTERNAL_IP6_ADDRESS.
1383 //
1384
1385 Cfg->Header.NextPayload = NextPayload;
1386 Cfg->Header.PayloadLength = PayloadLen;
1387 Cfg->CfgType = IKEV2_CFG_TYPE_REQUEST;
1388
1389 CfgAttributes->AttritType = CfgType;
1390 CfgAttributes->ValueLength = 0;
1391
1392 CpPayload = IkePayloadAlloc ();
1393 if (CpPayload == NULL) {
1394 if (Cfg != NULL) {
1395 FreePool (Cfg);
1396 }
1397 return NULL;
1398 }
1399
1400 CpPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CP;
1401 CpPayload->PayloadBuf = (UINT8 *) Cfg;
1402 CpPayload->PayloadSize = PayloadLen;
1403 return CpPayload;
1404 }
1405
1406 /**
1407 Parser the Notify Cookie payload.
1408
1409 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1410 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1411 the COOKIE, return EFI_INVALID_PARAMETER.
1412
1413 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1414 Notify Cookie payload.
1415 the Notify payload.
1416 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1417
1418 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1419 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1420 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1421
1422 **/
1423 EFI_STATUS
1424 Ikev2ParserNotifyCookiePayload (
1425 IN IKE_PAYLOAD *IkeNCookie,
1426 IN OUT IKEV2_SA_SESSION *IkeSaSession
1427 )
1428 {
1429 IKEV2_NOTIFY *NotifyPayload;
1430 UINTN NotifyDataSize;
1431
1432 NotifyPayload = (IKEV2_NOTIFY *)IkeNCookie->PayloadBuf;
1433
1434 if ((NotifyPayload->ProtocolId != IPSEC_PROTO_ISAKMP) ||
1435 (NotifyPayload->SpiSize != 0) ||
1436 (NotifyPayload->MessageType != IKEV2_NOTIFICATION_COOKIE)
1437 ) {
1438 return EFI_INVALID_PARAMETER;
1439 }
1440
1441 NotifyDataSize = NotifyPayload->Header.PayloadLength - sizeof (IKEV2_NOTIFY);
1442 IkeSaSession->NCookie = AllocateZeroPool (NotifyDataSize);
1443 if (IkeSaSession->NCookie == NULL) {
1444 return EFI_OUT_OF_RESOURCES;
1445 }
1446
1447 IkeSaSession->NCookieSize = NotifyDataSize;
1448
1449 CopyMem (
1450 IkeSaSession->NCookie,
1451 (UINT8 *)NotifyPayload + sizeof (IKEV2_NOTIFY),
1452 NotifyDataSize
1453 );
1454
1455 return EFI_SUCCESS;
1456 }
1457
1458
1459 /**
1460 Generate the Certificate payload or Certificate Request Payload.
1461
1462 Since the Certificate Payload structure is same with Certificate Request Payload,
1463 the only difference is that one contains the Certificate Data, other contains
1464 the acceptable certificateion CA. This function generate Certificate payload
1465 or Certificate Request Payload defined in RFC 4306, but all the fields
1466 in the payload are still in host order and need call Ikev2EncodePayload()
1467 to convert those fields from the host order to network order beforing sending it.
1468
1469 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1470 generation.
1471 @param[in] NextPayload The next paylaod type in NextPayload field of
1472 the Delete payload.
1473 @param[in] Certificate Pointer of buffer contains the certification data.
1474 @param[in] CertificateLen The length of Certificate in byte.
1475 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1476 in RFC 4306.
1477 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1478 Request Payload. If it is TURE, create Certificate
1479 Request Payload. Otherwise, create Certificate Payload.
1480
1481 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1482 payload or Certificated Request payload.
1483
1484 **/
1485 IKE_PAYLOAD *
1486 Ikev2GenerateCertificatePayload (
1487 IN IKEV2_SA_SESSION *IkeSaSession,
1488 IN UINT8 NextPayload,
1489 IN UINT8 *Certificate,
1490 IN UINTN CertificateLen,
1491 IN UINT8 EncodeType,
1492 IN BOOLEAN IsRequest
1493 )
1494 {
1495 IKE_PAYLOAD *CertPayload;
1496 IKEV2_CERT *Cert;
1497 UINT16 PayloadLen;
1498 UINT8 *PublicKey;
1499 UINTN PublicKeyLen;
1500 HASH_DATA_FRAGMENT Fragment[1];
1501 UINT8 *HashData;
1502 UINTN HashDataSize;
1503 EFI_STATUS Status;
1504
1505 //
1506 // 1 2 3
1507 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1508 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1509 // ! Next Payload !C! RESERVED ! Payload Length !
1510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1511 // ! Cert Encoding ! !
1512 // +-+-+-+-+-+-+-+-+ !
1513 // ~ Certificate Data/Authority ~
1514 // ! !
1515 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1516 //
1517
1518 Status = EFI_SUCCESS;
1519 PublicKey = NULL;
1520 PublicKeyLen = 0;
1521
1522 if (!IsRequest) {
1523 PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + CertificateLen);
1524 } else {
1525 //
1526 // SHA1 Hash length is 20.
1527 //
1528 PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + 20);
1529 }
1530
1531 Cert = AllocateZeroPool (PayloadLen);
1532 if (Cert == NULL) {
1533 return NULL;
1534 }
1535
1536 //
1537 // Generate Certificate Payload or Certificate Request Payload.
1538 //
1539 Cert->Header.NextPayload = NextPayload;
1540 Cert->Header.PayloadLength = PayloadLen;
1541 Cert->CertEncoding = EncodeType;
1542 if (!IsRequest) {
1543 CopyMem (
1544 ((UINT8 *)Cert) + sizeof (IKEV2_CERT),
1545 Certificate,
1546 CertificateLen
1547 );
1548 } else {
1549 Status = IpSecCryptoIoGetPublicKeyFromCert (
1550 Certificate,
1551 CertificateLen,
1552 &PublicKey,
1553 &PublicKeyLen
1554 );
1555 if (EFI_ERROR (Status)) {
1556 goto ON_EXIT;
1557 }
1558
1559 Fragment[0].Data = PublicKey;
1560 Fragment[0].DataSize = PublicKeyLen;
1561 HashDataSize = IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC);
1562 HashData = AllocateZeroPool (HashDataSize);
1563 if (HashData == NULL) {
1564 goto ON_EXIT;
1565 }
1566
1567 Status = IpSecCryptoIoHash (
1568 IKE_AALG_SHA1HMAC,
1569 Fragment,
1570 1,
1571 HashData,
1572 HashDataSize
1573 );
1574 if (EFI_ERROR (Status)) {
1575 goto ON_EXIT;
1576 }
1577
1578 CopyMem (
1579 ((UINT8 *)Cert) + sizeof (IKEV2_CERT),
1580 HashData,
1581 HashDataSize
1582 );
1583 }
1584
1585 CertPayload = IkePayloadAlloc ();
1586 if (CertPayload == NULL) {
1587 goto ON_EXIT;
1588 }
1589
1590 if (!IsRequest) {
1591 CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERT;
1592 } else {
1593 CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERTREQ;
1594 }
1595
1596 CertPayload->PayloadBuf = (UINT8 *) Cert;
1597 CertPayload->PayloadSize = PayloadLen;
1598 return CertPayload;
1599
1600 ON_EXIT:
1601 if (Cert != NULL) {
1602 FreePool (Cert);
1603 }
1604 if (PublicKey != NULL) {
1605 FreePool (PublicKey);
1606 }
1607 return NULL;
1608 }
1609
1610 /**
1611 Remove and free all IkePayloads in the specified IkePacket.
1612
1613 @param[in] IkePacket The pointer of IKE_PACKET.
1614
1615 **/
1616 VOID
1617 ClearAllPayloads (
1618 IN IKE_PACKET *IkePacket
1619 )
1620 {
1621 LIST_ENTRY *PayloadEntry;
1622 IKE_PAYLOAD *IkePayload;
1623 //
1624 // remove all payloads from list and free each payload.
1625 //
1626 while (!IsListEmpty (&IkePacket->PayloadList)) {
1627 PayloadEntry = IkePacket->PayloadList.ForwardLink;
1628 IkePayload = IKE_PAYLOAD_BY_PACKET (PayloadEntry);
1629 IKE_PACKET_REMOVE_PAYLOAD (IkePacket, IkePayload);
1630 IkePayloadFree (IkePayload);
1631 }
1632 }
1633
1634 /**
1635 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1636
1637 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1638 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1639
1640 @retval return the pointer of IKEV2_SA.
1641
1642 **/
1643 IKEV2_SA*
1644 Ikev2EncodeSa (
1645 IN IKEV2_SESSION_COMMON *SessionCommon,
1646 IN IKEV2_SA_DATA *SaData
1647 )
1648 {
1649 IKEV2_SA *Sa;
1650 UINTN SaSize;
1651 IKEV2_PROPOSAL_DATA *ProposalData;
1652 IKEV2_TRANSFORM_DATA *TransformData;
1653 UINTN TotalTransforms;
1654 UINTN SaAttrsSize;
1655 UINTN TransformsSize;
1656 UINTN TransformSize;
1657 UINTN ProposalsSize;
1658 UINTN ProposalSize;
1659 UINTN ProposalIndex;
1660 UINTN TransformIndex;
1661 IKE_SA_ATTRIBUTE *SaAttribute;
1662 IKEV2_PROPOSAL *Proposal;
1663 IKEV2_TRANSFORM *Transform;
1664
1665 //
1666 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1667 // Header length is host order.
1668 // The returned IKE_SA struct should be freed by caller.
1669 //
1670 TotalTransforms = 0;
1671 //
1672 // Calculate the Proposal numbers and Transform numbers.
1673 //
1674 for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {
1675
1676 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1) + ProposalIndex;
1677 TotalTransforms += ProposalData->NumTransforms;
1678
1679 }
1680 SaSize = sizeof (IKEV2_SA) +
1681 SaData->NumProposals * sizeof (IKEV2_PROPOSAL) +
1682 TotalTransforms * (sizeof (IKEV2_TRANSFORM) + MAX_SA_ATTRS_SIZE);
1683 //
1684 // Allocate buffer for IKE_SA.
1685 //
1686 Sa = AllocateZeroPool (SaSize);
1687 if (Sa == NULL) {
1688 return NULL;
1689 }
1690
1691 CopyMem (Sa, SaData, sizeof (IKEV2_SA));
1692 Sa->Header.PayloadLength = (UINT16) sizeof (IKEV2_SA);
1693 ProposalsSize = 0;
1694 Proposal = (IKEV2_PROPOSAL *) (Sa + 1);
1695
1696 //
1697 // Set IKE_PROPOSAL
1698 //
1699 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
1700 for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {
1701 Proposal->ProposalIndex = ProposalData->ProposalIndex;
1702 Proposal->ProtocolId = ProposalData->ProtocolId;
1703 Proposal->NumTransforms = ProposalData->NumTransforms;
1704
1705 if (ProposalData->Spi == 0) {
1706 Proposal->SpiSize = 0;
1707 } else {
1708 Proposal->SpiSize = 4;
1709 *(UINT32 *) (Proposal + 1) = HTONL (*((UINT32*)ProposalData->Spi));
1710 }
1711
1712 TransformsSize = 0;
1713 Transform = (IKEV2_TRANSFORM *) ((UINT8 *) (Proposal + 1) + Proposal->SpiSize);
1714
1715 //
1716 // Set IKE_TRANSFORM
1717 //
1718 for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {
1719 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;
1720 Transform->TransformType = TransformData->TransformType;
1721 Transform->TransformId = HTONS (TransformData->TransformId);
1722 SaAttrsSize = 0;
1723
1724 //
1725 // If the Encryption Algorithm is variable key length set the key length in attribute.
1726 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1727 //
1728 if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_ENCR && TransformData->Attribute.Attr.AttrValue != 0) {
1729 SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);
1730 SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);
1731 SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);
1732 SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);
1733 }
1734
1735 //
1736 // If the Integrity Algorithm is variable key length set the key length in attribute.
1737 //
1738 if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_INTEG && TransformData->Attribute.Attr.AttrValue != 0) {
1739 SaAttribute = (IKE_SA_ATTRIBUTE *) (Transform + 1);
1740 SaAttribute->AttrType = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);
1741 SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);
1742 SaAttrsSize = sizeof (IKE_SA_ATTRIBUTE);
1743 }
1744
1745 TransformSize = sizeof (IKEV2_TRANSFORM) + SaAttrsSize;
1746 TransformsSize += TransformSize;
1747
1748 Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_MORE;
1749 Transform->Header.PayloadLength = HTONS ((UINT16)TransformSize);
1750
1751 if (TransformIndex == ((UINT32)ProposalData->NumTransforms - 1)) {
1752 Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_NONE;
1753 }
1754
1755 Transform = (IKEV2_TRANSFORM *)((UINT8 *) Transform + TransformSize);
1756 }
1757
1758 //
1759 // Set Proposal's Generic Header.
1760 //
1761 ProposalSize = sizeof (IKEV2_PROPOSAL) + Proposal->SpiSize + TransformsSize;
1762 ProposalsSize += ProposalSize;
1763 Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_MORE;
1764 Proposal->Header.PayloadLength = HTONS ((UINT16)ProposalSize);
1765
1766 if (ProposalIndex == (UINTN)(SaData->NumProposals - 1)) {
1767 Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_NONE;
1768 }
1769
1770 //
1771 // Point to next Proposal Payload
1772 //
1773 Proposal = (IKEV2_PROPOSAL *) ((UINT8 *) Proposal + ProposalSize);
1774 ProposalData = (IKEV2_PROPOSAL_DATA *)(((UINT8 *)ProposalData) + sizeof (IKEV2_PROPOSAL_DATA) + (TransformIndex * sizeof (IKEV2_TRANSFORM_DATA)));
1775 }
1776 //
1777 // Set SA's Generic Header.
1778 //
1779 Sa->Header.PayloadLength = (UINT16) (Sa->Header.PayloadLength + ProposalsSize);
1780 return Sa;
1781 }
1782
1783 /**
1784 Decode SA payload.
1785
1786 This function converts the received SA payload to internal data structure.
1787
1788 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1789 Payload.
1790 @param[in] Sa Pointer to SA Payload
1791
1792 @return a Pointer to internal data structure for SA payload.
1793
1794 **/
1795 IKEV2_SA_DATA *
1796 Ikev2DecodeSa (
1797 IN IKEV2_SESSION_COMMON *SessionCommon,
1798 IN IKEV2_SA *Sa
1799 )
1800 {
1801 IKEV2_SA_DATA *SaData;
1802 EFI_STATUS Status;
1803 IKEV2_PROPOSAL *Proposal;
1804 IKEV2_TRANSFORM *Transform;
1805 UINTN TotalProposals;
1806 UINTN TotalTransforms;
1807 UINTN ProposalNextPayloadSum;
1808 UINTN ProposalIndex;
1809 UINTN TransformIndex;
1810 UINTN SaRemaining;
1811 UINT16 ProposalSize;
1812 UINTN ProposalRemaining;
1813 UINT16 TransformSize;
1814 UINTN SaAttrRemaining;
1815 IKE_SA_ATTRIBUTE *SaAttribute;
1816 IKEV2_PROPOSAL_DATA *ProposalData;
1817 IKEV2_TRANSFORM_DATA *TransformData;
1818 UINT8 *Spi;
1819
1820 //
1821 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1822 // Header length NTOH is already done
1823 // The returned IKE_SA_DATA should be freed by caller
1824 //
1825 SaData = NULL;
1826 Status = EFI_SUCCESS;
1827
1828 //
1829 // First round sanity check and size calculae
1830 //
1831 TotalProposals = 0;
1832 TotalTransforms = 0;
1833 ProposalNextPayloadSum = 0;
1834 SaRemaining = Sa->Header.PayloadLength - sizeof (IKEV2_SA);// Point to current position in SA
1835 Proposal = (IKEV2_PROPOSAL *)((IKEV2_SA *)(Sa)+1);
1836
1837 //
1838 // Calculate the number of Proposal payload and the total numbers of
1839 // Transforms payload (the transforms in all proposal payload).
1840 //
1841 while (SaRemaining > sizeof (IKEV2_PROPOSAL)) {
1842 ProposalSize = NTOHS (Proposal->Header.PayloadLength);
1843 if (SaRemaining < ProposalSize) {
1844 Status = EFI_INVALID_PARAMETER;
1845 goto Exit;
1846 }
1847
1848 if (Proposal->SpiSize != 0 && Proposal->SpiSize != 4) {
1849 Status = EFI_INVALID_PARAMETER;
1850 goto Exit;
1851 }
1852
1853 TotalProposals++;
1854 TotalTransforms += Proposal->NumTransforms;
1855 SaRemaining -= ProposalSize;
1856 ProposalNextPayloadSum += Proposal->Header.NextPayload;
1857 Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);
1858 }
1859
1860 //
1861 // Check the proposal number.
1862 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1863 // which Specifies whether this is the last Proposal Substructure in the SA.
1864 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1865 // or not.
1866 //
1867 if (TotalProposals == 0 ||
1868 (TotalProposals - 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE != ProposalNextPayloadSum
1869 ) {
1870 Status = EFI_INVALID_PARAMETER;
1871 goto Exit;
1872 }
1873
1874 //
1875 // Second round sanity check and decode. Transform the SA payload into
1876 // a IKE_SA_DATA structure.
1877 //
1878 SaData = (IKEV2_SA_DATA *) AllocateZeroPool (
1879 sizeof (IKEV2_SA_DATA) +
1880 TotalProposals * sizeof (IKEV2_PROPOSAL_DATA) +
1881 TotalTransforms * sizeof (IKEV2_TRANSFORM_DATA)
1882 );
1883 if (SaData == NULL) {
1884 Status = EFI_OUT_OF_RESOURCES;
1885 goto Exit;
1886 }
1887
1888 CopyMem (SaData, Sa, sizeof (IKEV2_SA));
1889 SaData->NumProposals = TotalProposals;
1890 ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
1891
1892 //
1893 // Proposal Payload
1894 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1895 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1896 // ! Next Payload ! RESERVED ! Payload Length !
1897 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1898 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1899 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1900 // ! SPI (variable) !
1901 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1902 //
1903 for (ProposalIndex = 0, Proposal = IKEV2_SA_FIRST_PROPOSAL (Sa);
1904 ProposalIndex < TotalProposals;
1905 ProposalIndex++
1906 ) {
1907
1908 //
1909 // TODO: check ProposalId
1910 //
1911 ProposalData->ProposalIndex = Proposal->ProposalIndex;
1912 ProposalData->ProtocolId = Proposal->ProtocolId;
1913 if (Proposal->SpiSize == 0) {
1914 ProposalData->Spi = 0;
1915 } else {
1916 //
1917 // SpiSize == 4
1918 //
1919 Spi = AllocateZeroPool (Proposal->SpiSize);
1920 if (Spi == NULL) {
1921 Status = EFI_OUT_OF_RESOURCES;
1922 goto Exit;
1923 }
1924
1925 CopyMem (Spi, (UINT32 *) (Proposal + 1), Proposal->SpiSize);
1926 *((UINT32*) Spi) = NTOHL (*((UINT32*) Spi));
1927 ProposalData->Spi = Spi;
1928 }
1929
1930 ProposalData->NumTransforms = Proposal->NumTransforms;
1931 ProposalSize = NTOHS (Proposal->Header.PayloadLength);
1932 ProposalRemaining = ProposalSize;
1933 //
1934 // Transform Payload
1935 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1936 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1937 // ! Next Payload ! RESERVED ! Payload Length !
1938 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1939 // !Transform Type ! RESERVED ! Transform ID !
1940 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1941 // ! !
1942 // ~ SA Attributes ~
1943 // ! !
1944 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1945 //
1946 Transform = IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal);
1947 for (TransformIndex = 0; TransformIndex < Proposal->NumTransforms; TransformIndex++) {
1948
1949 //
1950 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1951 //
1952 TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;
1953 TransformData->TransformId = NTOHS (Transform->TransformId);
1954 TransformData->TransformType = Transform->TransformType;
1955 TransformSize = NTOHS (Transform->Header.PayloadLength);
1956 //
1957 // Check the Proposal Data is correct.
1958 //
1959 if (ProposalRemaining < TransformSize) {
1960 Status = EFI_INVALID_PARAMETER;
1961 goto Exit;
1962 }
1963
1964 //
1965 // Check if the Transform payload includes Attribution.
1966 //
1967 SaAttrRemaining = TransformSize - sizeof (IKEV2_TRANSFORM);
1968
1969 //
1970 // According to RFC 4603, currently only the Key length attribute type is
1971 // supported. For each Transform, there is only one attributeion.
1972 //
1973 if (SaAttrRemaining > 0) {
1974 if (SaAttrRemaining != sizeof (IKE_SA_ATTRIBUTE)) {
1975 Status = EFI_INVALID_PARAMETER;
1976 goto Exit;
1977 }
1978 SaAttribute = (IKE_SA_ATTRIBUTE *) ((IKEV2_TRANSFORM *)(Transform) + 1);
1979 TransformData->Attribute.AttrType = (UINT16)((NTOHS (SaAttribute->AttrType)) & ~SA_ATTR_FORMAT_BIT);
1980 TransformData->Attribute.Attr.AttrValue = NTOHS (SaAttribute->Attr.AttrValue);
1981
1982 //
1983 // Currently, only supports the Key Length Attribution.
1984 //
1985 if (TransformData->Attribute.AttrType != IKEV2_ATTRIBUTE_TYPE_KEYLEN) {
1986 Status = EFI_INVALID_PARAMETER;
1987 goto Exit;
1988 }
1989 }
1990
1991 //
1992 // Move to next Transform
1993 //
1994 Transform = IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform, TransformSize);
1995 }
1996 Proposal = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);
1997 ProposalData = (IKEV2_PROPOSAL_DATA *) ((UINT8 *)(ProposalData + 1) +
1998 ProposalData->NumTransforms *
1999 sizeof (IKEV2_TRANSFORM_DATA));
2000 }
2001
2002 Exit:
2003 if (EFI_ERROR (Status) && SaData != NULL) {
2004 FreePool (SaData);
2005 SaData = NULL;
2006 }
2007 return SaData;
2008 }
2009
2010 /**
2011 General interface of payload encoding.
2012
2013 This function encodes the internal data structure into payload which
2014 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
2015 payload and converted payload. Only the SA payload use the interal structure
2016 to store the attribute. Other payload use structure which is same with the RFC
2017 defined, for this kind payloads just do host order to network order change of
2018 some fields.
2019
2020 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
2021 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
2022 store the encoded result as output.
2023
2024 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
2025 @retval EFI_SUCCESS Encoded successfully.
2026
2027 **/
2028 EFI_STATUS
2029 Ikev2EncodePayload (
2030 IN UINT8 *SessionCommon,
2031 IN OUT IKE_PAYLOAD *IkePayload
2032 )
2033 {
2034 IKEV2_SA_DATA *SaData;
2035 IKEV2_SA *SaPayload;
2036 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
2037 IKEV2_NOTIFY *NotifyPayload;
2038 IKEV2_DELETE *DeletePayload;
2039 IKEV2_KEY_EXCHANGE *KeyPayload;
2040 IKEV2_TS *TsPayload;
2041 IKEV2_CFG_ATTRIBUTES *CfgAttribute;
2042 UINT8 *TsBuffer;
2043 UINT8 Index;
2044 TRAFFIC_SELECTOR *TrafficSelector;
2045
2046 //
2047 // Transform the Internal IKE structure to IKE payload.
2048 // Only the SA payload use the interal structure to store the attribute.
2049 // Other payload use structure which same with the RFC defined, so there is
2050 // no need to tranform them to IKE payload.
2051 //
2052 switch (IkePayload->PayloadType) {
2053 case IKEV2_PAYLOAD_TYPE_SA:
2054 //
2055 // Transform IKE_SA_DATA to IK_SA payload
2056 //
2057 SaData = (IKEV2_SA_DATA *) IkePayload->PayloadBuf;
2058 SaPayload = Ikev2EncodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, SaData);
2059
2060 if (SaPayload == NULL) {
2061 return EFI_INVALID_PARAMETER;
2062 }
2063 if (!IkePayload->IsPayloadBufExt) {
2064 FreePool (IkePayload->PayloadBuf);
2065 }
2066 IkePayload->PayloadBuf = (UINT8 *) SaPayload;
2067 IkePayload->IsPayloadBufExt = FALSE;
2068 break;
2069
2070 case IKEV2_PAYLOAD_TYPE_NOTIFY:
2071 NotifyPayload = (IKEV2_NOTIFY *) IkePayload->PayloadBuf;
2072 NotifyPayload->MessageType = HTONS (NotifyPayload->MessageType);
2073 break;
2074
2075 case IKEV2_PAYLOAD_TYPE_DELETE:
2076 DeletePayload = (IKEV2_DELETE *) IkePayload->PayloadBuf;
2077 DeletePayload->NumSpis = HTONS (DeletePayload->NumSpis);
2078 break;
2079
2080 case IKEV2_PAYLOAD_TYPE_KE:
2081 KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;
2082 KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);
2083 break;
2084
2085 case IKEV2_PAYLOAD_TYPE_TS_INIT:
2086 case IKEV2_PAYLOAD_TYPE_TS_RSP:
2087 TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;
2088 TsBuffer = IkePayload->PayloadBuf + sizeof (IKEV2_TS);
2089
2090 for (Index = 0; Index < TsPayload->TSNumbers; Index++) {
2091 TrafficSelector = (TRAFFIC_SELECTOR *) TsBuffer;
2092 TsBuffer = TsBuffer + TrafficSelector->SelecorLen;
2093 //
2094 // Host order to network order
2095 //
2096 TrafficSelector->SelecorLen = HTONS (TrafficSelector->SelecorLen);
2097 TrafficSelector->StartPort = HTONS (TrafficSelector->StartPort);
2098 TrafficSelector->EndPort = HTONS (TrafficSelector->EndPort);
2099
2100 }
2101
2102 break;
2103
2104 case IKEV2_PAYLOAD_TYPE_CP:
2105 CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);
2106 CfgAttribute->AttritType = HTONS (CfgAttribute->AttritType);
2107 CfgAttribute->ValueLength = HTONS (CfgAttribute->ValueLength);
2108
2109 case IKEV2_PAYLOAD_TYPE_ID_INIT:
2110 case IKEV2_PAYLOAD_TYPE_ID_RSP:
2111 case IKEV2_PAYLOAD_TYPE_AUTH:
2112 default:
2113 break;
2114 }
2115
2116 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;
2117 IkePayload->PayloadSize = PayloadHdr->PayloadLength;
2118 PayloadHdr->PayloadLength = HTONS (PayloadHdr->PayloadLength);
2119 IKEV2_DUMP_PAYLOAD (IkePayload);
2120 return EFI_SUCCESS;
2121 }
2122
2123 /**
2124 The general interface for decoding Payload.
2125
2126 This function converts the received Payload into internal structure.
2127
2128 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2129 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2130 store the decoded result as output.
2131
2132 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2133 @retval EFI_SUCCESS Decoded successfully.
2134
2135 **/
2136 EFI_STATUS
2137 Ikev2DecodePayload (
2138 IN UINT8 *SessionCommon,
2139 IN OUT IKE_PAYLOAD *IkePayload
2140 )
2141 {
2142 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
2143 UINT16 PayloadSize;
2144 UINT8 PayloadType;
2145 IKEV2_SA_DATA *SaData;
2146 EFI_STATUS Status;
2147 IKEV2_NOTIFY *NotifyPayload;
2148 IKEV2_DELETE *DeletePayload;
2149 UINT16 TsTotalSize;
2150 TRAFFIC_SELECTOR *TsSelector;
2151 IKEV2_TS *TsPayload;
2152 IKEV2_KEY_EXCHANGE *KeyPayload;
2153 IKEV2_CFG_ATTRIBUTES *CfgAttribute;
2154 UINT8 Index;
2155
2156 //
2157 // Transform the IKE payload to Internal IKE structure.
2158 // Only the SA payload and Hash Payload use the interal
2159 // structure to store the attribute. Other payloads use
2160 // structure which is same with the definitions in RFC,
2161 // so there is no need to tranform them to internal IKE
2162 // structure.
2163 //
2164 Status = EFI_SUCCESS;
2165 PayloadSize = (UINT16) IkePayload->PayloadSize;
2166 PayloadType = IkePayload->PayloadType;
2167 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;
2168 //
2169 // The PayloadSize is the size of whole payload.
2170 // Replace HTONS operation to assignment statements, since the result is same.
2171 //
2172 PayloadHdr->PayloadLength = PayloadSize;
2173
2174 IKEV2_DUMP_PAYLOAD (IkePayload);
2175 switch (PayloadType) {
2176 case IKEV2_PAYLOAD_TYPE_SA:
2177 if (PayloadSize < sizeof (IKEV2_SA)) {
2178 Status = EFI_INVALID_PARAMETER;
2179 goto Exit;
2180 }
2181
2182 SaData = Ikev2DecodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, (IKEV2_SA *) PayloadHdr);
2183 if (SaData == NULL) {
2184 Status = EFI_INVALID_PARAMETER;
2185 goto Exit;
2186 }
2187
2188 if (!IkePayload->IsPayloadBufExt) {
2189 FreePool (IkePayload->PayloadBuf);
2190 }
2191
2192 IkePayload->PayloadBuf = (UINT8 *) SaData;
2193 IkePayload->IsPayloadBufExt = FALSE;
2194 break;
2195
2196 case IKEV2_PAYLOAD_TYPE_ID_INIT:
2197 case IKEV2_PAYLOAD_TYPE_ID_RSP :
2198 if (PayloadSize < sizeof (IKEV2_ID)) {
2199 Status = EFI_INVALID_PARAMETER;
2200 goto Exit;
2201 }
2202 break;
2203
2204 case IKEV2_PAYLOAD_TYPE_NOTIFY:
2205 if (PayloadSize < sizeof (IKEV2_NOTIFY)) {
2206 Status = EFI_INVALID_PARAMETER;
2207 goto Exit;
2208 }
2209
2210 NotifyPayload = (IKEV2_NOTIFY *) PayloadHdr;
2211 NotifyPayload->MessageType = NTOHS (NotifyPayload->MessageType);
2212 break;
2213
2214 case IKEV2_PAYLOAD_TYPE_DELETE:
2215 if (PayloadSize < sizeof (IKEV2_DELETE)) {
2216 Status = EFI_INVALID_PARAMETER;
2217 goto Exit;
2218 }
2219
2220 DeletePayload = (IKEV2_DELETE *) PayloadHdr;
2221 DeletePayload->NumSpis = NTOHS (DeletePayload->NumSpis);
2222 break;
2223
2224 case IKEV2_PAYLOAD_TYPE_AUTH:
2225 if (PayloadSize < sizeof (IKEV2_AUTH)) {
2226 Status = EFI_INVALID_PARAMETER;
2227 goto Exit;
2228 }
2229 break;
2230
2231 case IKEV2_PAYLOAD_TYPE_KE:
2232 KeyPayload = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;
2233 KeyPayload->DhGroup = HTONS (KeyPayload->DhGroup);
2234 break;
2235
2236 case IKEV2_PAYLOAD_TYPE_TS_INIT:
2237 case IKEV2_PAYLOAD_TYPE_TS_RSP :
2238 TsTotalSize = 0;
2239 if (PayloadSize < sizeof (IKEV2_TS)) {
2240 Status = EFI_INVALID_PARAMETER;
2241 goto Exit;
2242 }
2243 //
2244 // Parse each traffic selector and transfer network-order to host-order
2245 //
2246 TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;
2247 TsSelector = (TRAFFIC_SELECTOR *) (IkePayload->PayloadBuf + sizeof (IKEV2_TS));
2248
2249 for (Index = 0; Index < TsPayload->TSNumbers; Index++) {
2250 TsSelector->SelecorLen = NTOHS (TsSelector->SelecorLen);
2251 TsSelector->StartPort = NTOHS (TsSelector->StartPort);
2252 TsSelector->EndPort = NTOHS (TsSelector->EndPort);
2253
2254 TsTotalSize = (UINT16) (TsTotalSize + TsSelector->SelecorLen);
2255 TsSelector = (TRAFFIC_SELECTOR *) ((UINT8 *) TsSelector + TsSelector->SelecorLen);
2256 }
2257 //
2258 // Check if the total size of Traffic Selectors is correct.
2259 //
2260 if (TsTotalSize != PayloadSize - sizeof(IKEV2_TS)) {
2261 Status = EFI_INVALID_PARAMETER;
2262 }
2263
2264 case IKEV2_PAYLOAD_TYPE_CP:
2265 CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);
2266 CfgAttribute->AttritType = NTOHS (CfgAttribute->AttritType);
2267 CfgAttribute->ValueLength = NTOHS (CfgAttribute->ValueLength);
2268
2269 default:
2270 break;
2271 }
2272
2273 Exit:
2274 return Status;
2275 }
2276
2277 /**
2278 Decode the IKE packet.
2279
2280 This function first decrypts the IKE packet if needed , then separates the whole
2281 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2282
2283 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2284 some parameter used by IKE packet decoding.
2285 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2286 the decoded result on return.
2287 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2288 IKE_CHILD_TYPE are supported.
2289
2290 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2291 @retval Otherwise The IKE packet decoding is failed.
2292
2293 **/
2294 EFI_STATUS
2295 Ikev2DecodePacket (
2296 IN IKEV2_SESSION_COMMON *SessionCommon,
2297 IN OUT IKE_PACKET *IkePacket,
2298 IN UINTN IkeType
2299 )
2300 {
2301 EFI_STATUS Status;
2302 IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
2303 UINT8 PayloadType;
2304 UINTN RemainBytes;
2305 UINT16 PayloadSize;
2306 IKE_PAYLOAD *IkePayload;
2307 IKE_HEADER *IkeHeader;
2308 IKEV2_SA_SESSION *IkeSaSession;
2309
2310 IkeHeader = NULL;
2311
2312 //
2313 // Check if the IkePacket need decrypt.
2314 //
2315 if (SessionCommon->State >= IkeStateAuth) {
2316 Status = Ikev2DecryptPacket (SessionCommon, IkePacket, IkeType);
2317 if (EFI_ERROR (Status)) {
2318 return Status;
2319 }
2320 }
2321
2322 Status = EFI_SUCCESS;
2323
2324 //
2325 // If the IkePacket doesn't contain any payload return invalid parameter.
2326 //
2327 if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE) {
2328 if ((SessionCommon->State >= IkeStateAuth) &&
2329 (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INFO)
2330 ) {
2331 //
2332 // If it is Liveness check, there will be no payload load in the encrypt payload.
2333 //
2334 Status = EFI_SUCCESS;
2335 } else {
2336 Status = EFI_INVALID_PARAMETER;
2337 }
2338 }
2339
2340 //
2341 // If the PayloadTotalSize < Header length, return invalid parameter.
2342 //
2343 RemainBytes = IkePacket->PayloadTotalSize;
2344 if (RemainBytes < sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {
2345 Status = EFI_INVALID_PARAMETER;
2346 goto Exit;
2347 }
2348
2349 //
2350 // If the packet is first or second message, store whole message in
2351 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2352 // calculate.
2353 //
2354 if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {
2355 IkeHeader = AllocateZeroPool (sizeof (IKE_HEADER));
2356 if (IkeHeader == NULL) {
2357 Status = EFI_OUT_OF_RESOURCES;
2358 goto Exit;
2359 }
2360
2361 CopyMem (IkeHeader, IkePacket->Header, sizeof (IKE_HEADER));
2362
2363 //
2364 // Before store the whole packet, roll back the host order to network order,
2365 // since the header order was changed in the IkePacketFromNetbuf.
2366 //
2367 IkeHdrNetToHost (IkeHeader);
2368 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
2369 if (SessionCommon->IsInitiator) {
2370 IkeSaSession->RespPacket = AllocateZeroPool (IkePacket->Header->Length);
2371 if (IkeSaSession->RespPacket == NULL) {
2372 Status = EFI_OUT_OF_RESOURCES;
2373 goto Exit;
2374 }
2375 IkeSaSession->RespPacketSize = IkePacket->Header->Length;
2376 CopyMem (IkeSaSession->RespPacket, IkeHeader, sizeof (IKE_HEADER));
2377 CopyMem (
2378 IkeSaSession->RespPacket + sizeof (IKE_HEADER),
2379 IkePacket->PayloadsBuf,
2380 IkePacket->Header->Length - sizeof (IKE_HEADER)
2381 );
2382 } else {
2383 IkeSaSession->InitPacket = AllocateZeroPool (IkePacket->Header->Length);
2384 if (IkeSaSession->InitPacket == NULL) {
2385 Status = EFI_OUT_OF_RESOURCES;
2386 goto Exit;
2387 }
2388 IkeSaSession->InitPacketSize = IkePacket->Header->Length;
2389 CopyMem (IkeSaSession->InitPacket, IkeHeader, sizeof (IKE_HEADER));
2390 CopyMem (
2391 IkeSaSession->InitPacket + sizeof (IKE_HEADER),
2392 IkePacket->PayloadsBuf,
2393 IkePacket->Header->Length - sizeof (IKE_HEADER)
2394 );
2395 }
2396 }
2397
2398 //
2399 // Point to the first Payload
2400 //
2401 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePacket->PayloadsBuf;
2402 PayloadType = IkePacket->Header->NextPayload;
2403
2404 //
2405 // Parse each payload
2406 //
2407 while (RemainBytes >= sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {
2408 PayloadSize = NTOHS (PayloadHdr->PayloadLength);
2409
2410 //
2411 //Check the size of the payload is correct.
2412 //
2413 if (RemainBytes < PayloadSize) {
2414 Status = EFI_INVALID_PARAMETER;
2415 goto Exit;
2416 }
2417
2418 //
2419 // At certain states, it should save some datas before decoding.
2420 //
2421 if (SessionCommon->BeforeDecodePayload != NULL) {
2422 SessionCommon->BeforeDecodePayload (
2423 (UINT8 *) SessionCommon,
2424 (UINT8 *) PayloadHdr,
2425 PayloadSize,
2426 PayloadType
2427 );
2428 }
2429
2430 //
2431 // Initial IkePayload
2432 //
2433 IkePayload = IkePayloadAlloc ();
2434 if (IkePayload == NULL) {
2435 Status = EFI_OUT_OF_RESOURCES;
2436 goto Exit;
2437 }
2438
2439 IkePayload->PayloadType = PayloadType;
2440 IkePayload->PayloadBuf = (UINT8 *) PayloadHdr;
2441 IkePayload->PayloadSize = PayloadSize;
2442 IkePayload->IsPayloadBufExt = TRUE;
2443
2444 Status = Ikev2DecodePayload ((UINT8 *) SessionCommon, IkePayload);
2445 if (EFI_ERROR (Status)) {
2446 goto Exit;
2447 }
2448
2449 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload->PayloadBuf, IkePayload->PayloadSize);
2450 //
2451 // Add each payload into packet
2452 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2453 // which is before the decoding.
2454 //
2455 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);
2456
2457 RemainBytes -= PayloadSize;
2458 PayloadType = PayloadHdr->NextPayload;
2459 if (PayloadType == IKEV2_PAYLOAD_TYPE_NONE) {
2460 break;
2461 }
2462
2463 PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) ((UINT8 *) PayloadHdr + PayloadSize);
2464 }
2465
2466 if (PayloadType != IKEV2_PAYLOAD_TYPE_NONE) {
2467 Status = EFI_INVALID_PARAMETER;
2468 goto Exit;
2469 }
2470
2471 Exit:
2472 if (EFI_ERROR (Status)) {
2473 ClearAllPayloads (IkePacket);
2474 }
2475
2476 if (IkeHeader != NULL) {
2477 FreePool (IkeHeader);
2478 }
2479 return Status;
2480 }
2481
2482 /**
2483 Encode the IKE packet.
2484
2485 This function puts all Payloads into one payload then encrypt it if needed.
2486
2487 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2488 some parameter used during IKE packet encoding.
2489 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2490 and the encoded result as output.
2491 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2492 IKE_CHILD_TYPE are supportted.
2493
2494 @retval EFI_SUCCESS Encode IKE packet successfully.
2495 @retval Otherwise Encode IKE packet failed.
2496
2497 **/
2498 EFI_STATUS
2499 Ikev2EncodePacket (
2500 IN IKEV2_SESSION_COMMON *SessionCommon,
2501 IN OUT IKE_PACKET *IkePacket,
2502 IN UINTN IkeType
2503 )
2504 {
2505 IKE_PAYLOAD *IkePayload;
2506 UINTN PayloadTotalSize;
2507 LIST_ENTRY *Entry;
2508 EFI_STATUS Status;
2509 IKEV2_SA_SESSION *IkeSaSession;
2510
2511 PayloadTotalSize = 0;
2512 //
2513 // Encode each payload
2514 //
2515 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
2516 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
2517 Entry = Entry->ForwardLink;
2518 Status = Ikev2EncodePayload ((UINT8 *) SessionCommon, IkePayload);
2519 if (EFI_ERROR (Status)) {
2520 return Status;
2521 }
2522
2523 if (SessionCommon->AfterEncodePayload != NULL) {
2524 //
2525 // For certain states, save some payload for further calculation
2526 //
2527 SessionCommon->AfterEncodePayload (
2528 (UINT8 *) SessionCommon,
2529 IkePayload->PayloadBuf,
2530 IkePayload->PayloadSize,
2531 IkePayload->PayloadType
2532 );
2533 }
2534
2535 PayloadTotalSize += IkePayload->PayloadSize;
2536 }
2537 IkePacket->PayloadTotalSize = PayloadTotalSize;
2538
2539 Status = EFI_SUCCESS;
2540 if (SessionCommon->State >= IkeStateAuth) {
2541 //
2542 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2543 //
2544 Status = Ikev2EncryptPacket (SessionCommon, IkePacket);
2545 if (EFI_ERROR (Status)) {
2546 return Status;
2547 }
2548 } else {
2549 //
2550 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2551 //
2552 IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);
2553 IkeHdrHostToNet (IkePacket->Header);
2554 }
2555
2556 //
2557 // If the packet is first message, store whole message in IkeSa->InitiPacket
2558 // for following Auth Payload calculation.
2559 //
2560 if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {
2561 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
2562 if (SessionCommon->IsInitiator) {
2563 IkeSaSession->InitPacketSize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);
2564 IkeSaSession->InitPacket = AllocateZeroPool (IkeSaSession->InitPacketSize);
2565 if (IkeSaSession->InitPacket == NULL) {
2566 return EFI_OUT_OF_RESOURCES;
2567 }
2568
2569 CopyMem (IkeSaSession->InitPacket, IkePacket->Header, sizeof (IKE_HEADER));
2570 PayloadTotalSize = 0;
2571 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
2572 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
2573 Entry = Entry->ForwardLink;
2574 CopyMem (
2575 IkeSaSession->InitPacket + sizeof (IKE_HEADER) + PayloadTotalSize,
2576 IkePayload->PayloadBuf,
2577 IkePayload->PayloadSize
2578 );
2579 PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;
2580 }
2581 } else {
2582 IkeSaSession->RespPacketSize = IkePacket->PayloadTotalSize + sizeof(IKE_HEADER);
2583 IkeSaSession->RespPacket = AllocateZeroPool (IkeSaSession->RespPacketSize);
2584 if (IkeSaSession->RespPacket == NULL) {
2585 return EFI_OUT_OF_RESOURCES;
2586 }
2587
2588 CopyMem (IkeSaSession->RespPacket, IkePacket->Header, sizeof (IKE_HEADER));
2589 PayloadTotalSize = 0;
2590 for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
2591 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
2592 Entry = Entry->ForwardLink;
2593
2594 CopyMem (
2595 IkeSaSession->RespPacket + sizeof (IKE_HEADER) + PayloadTotalSize,
2596 IkePayload->PayloadBuf,
2597 IkePayload->PayloadSize
2598 );
2599 PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;
2600 }
2601 }
2602 }
2603
2604 return Status;
2605 }
2606
2607 /**
2608 Decrypt IKE packet.
2609
2610 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2611
2612 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2613 some parameter used during decrypting.
2614 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2615 and the decrypted result as output.
2616 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2617 IKE_CHILD_TYPE are supportted.
2618
2619 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2620 IKE packet length is not aligned with Algorithm Block Size
2621 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2622
2623 **/
2624 EFI_STATUS
2625 Ikev2DecryptPacket (
2626 IN IKEV2_SESSION_COMMON *SessionCommon,
2627 IN OUT IKE_PACKET *IkePacket,
2628 IN OUT UINTN IkeType
2629 )
2630 {
2631 UINT8 CryptBlockSize; // Encrypt Block Size
2632 UINTN DecryptedSize; // Encrypted IKE Payload Size
2633 UINT8 *DecryptedBuf; // Encrypted IKE Payload buffer
2634 UINTN IntegritySize;
2635 UINT8 *IntegrityBuffer;
2636 UINTN IvSize; // Iv Size
2637 UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth
2638 UINT8 *CheckSumData; // Check Sum data
2639 IKEV2_SA_SESSION *IkeSaSession;
2640 IKEV2_CHILD_SA_SESSION *ChildSaSession;
2641 EFI_STATUS Status;
2642 UINT8 PadLen;
2643 HASH_DATA_FRAGMENT Fragments[1];
2644
2645 IvSize = 0;
2646 IkeSaSession = NULL;
2647 CryptBlockSize = 0;
2648 CheckSumSize = 0;
2649
2650 //
2651 // Check if the first payload is the Encrypted payload
2652 //
2653 if (IkePacket->Header->NextPayload != IKEV2_PAYLOAD_TYPE_ENCRYPT) {
2654 return EFI_ACCESS_DENIED;
2655 }
2656 CheckSumData = NULL;
2657 DecryptedBuf = NULL;
2658 IntegrityBuffer = NULL;
2659
2660 //
2661 // Get the Block Size
2662 //
2663 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
2664
2665 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);
2666
2667 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);
2668 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
2669
2670 } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {
2671
2672 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
2673 IkeSaSession = ChildSaSession->IkeSaSession;
2674 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);
2675 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);
2676 } else {
2677 //
2678 // The type of SA Session would either be IkeSa or ChildSa.
2679 //
2680 return EFI_INVALID_PARAMETER;
2681 }
2682
2683 CheckSumData = AllocateZeroPool (CheckSumSize);
2684 if (CheckSumData == NULL) {
2685 Status = EFI_OUT_OF_RESOURCES;
2686 goto ON_EXIT;
2687 }
2688
2689 //
2690 // Fill in the Integrity buffer
2691 //
2692 IntegritySize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);
2693 IntegrityBuffer = AllocateZeroPool (IntegritySize);
2694 if (IntegrityBuffer == NULL) {
2695 Status = EFI_OUT_OF_RESOURCES;
2696 goto ON_EXIT;
2697 }
2698
2699 CopyMem (IntegrityBuffer, IkePacket->Header, sizeof(IKE_HEADER));
2700 CopyMem (IntegrityBuffer + sizeof (IKE_HEADER), IkePacket->PayloadsBuf, IkePacket->PayloadTotalSize);
2701
2702 //
2703 // Change Host order to Network order, since the header order was changed
2704 // in the IkePacketFromNetbuf.
2705 //
2706 IkeHdrHostToNet ((IKE_HEADER *)IntegrityBuffer);
2707
2708 //
2709 // Calculate the Integrity CheckSum Data
2710 //
2711 Fragments[0].Data = IntegrityBuffer;
2712 Fragments[0].DataSize = IntegritySize - CheckSumSize;
2713
2714 if (SessionCommon->IsInitiator) {
2715 Status = IpSecCryptoIoHmac (
2716 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
2717 IkeSaSession->IkeKeys->SkArKey,
2718 IkeSaSession->IkeKeys->SkArKeySize,
2719 (HASH_DATA_FRAGMENT *) Fragments,
2720 1,
2721 CheckSumData,
2722 CheckSumSize
2723 );
2724 } else {
2725 Status = IpSecCryptoIoHmac (
2726 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
2727 IkeSaSession->IkeKeys->SkAiKey,
2728 IkeSaSession->IkeKeys->SkAiKeySize,
2729 (HASH_DATA_FRAGMENT *) Fragments,
2730 1,
2731 CheckSumData,
2732 CheckSumSize
2733 );
2734 }
2735
2736 if (EFI_ERROR (Status)) {
2737 goto ON_EXIT;
2738 }
2739 //
2740 // Compare the Integrity CheckSum Data with the one in IkePacket
2741 //
2742 if (CompareMem (
2743 IkePacket->PayloadsBuf + IkePacket->PayloadTotalSize - CheckSumSize,
2744 CheckSumData,
2745 CheckSumSize
2746 ) != 0) {
2747 DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));
2748 Status = EFI_ACCESS_DENIED;
2749 goto ON_EXIT;
2750 }
2751
2752 IvSize = CryptBlockSize;
2753
2754 //
2755 // Decrypt the payload with the key.
2756 //
2757 DecryptedSize = IkePacket->PayloadTotalSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER) - IvSize - CheckSumSize;
2758 DecryptedBuf = AllocateZeroPool (DecryptedSize);
2759 if (DecryptedBuf == NULL) {
2760 Status = EFI_OUT_OF_RESOURCES;
2761 goto ON_EXIT;
2762 }
2763
2764 CopyMem (
2765 DecryptedBuf,
2766 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER) + IvSize,
2767 DecryptedSize
2768 );
2769
2770 if (SessionCommon->IsInitiator) {
2771 Status = IpSecCryptoIoDecrypt (
2772 (UINT8) SessionCommon->SaParams->EncAlgId,
2773 IkeSaSession->IkeKeys->SkErKey,
2774 IkeSaSession->IkeKeys->SkErKeySize << 3,
2775 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
2776 DecryptedBuf,
2777 DecryptedSize,
2778 DecryptedBuf
2779 );
2780 } else {
2781 Status = IpSecCryptoIoDecrypt (
2782 (UINT8) SessionCommon->SaParams->EncAlgId,
2783 IkeSaSession->IkeKeys->SkEiKey,
2784 IkeSaSession->IkeKeys->SkEiKeySize << 3,
2785 IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
2786 DecryptedBuf,
2787 DecryptedSize,
2788 DecryptedBuf
2789 );
2790 }
2791
2792 if (EFI_ERROR (Status)) {
2793 DEBUG ((DEBUG_ERROR, "Error decrypt buffer with %r\n", Status));
2794 goto ON_EXIT;
2795 }
2796
2797 //
2798 // Get the Padding length
2799 //
2800 //
2801 PadLen = (UINT8) (*(DecryptedBuf + DecryptedSize - sizeof (IKEV2_PAD_LEN)));
2802
2803 //
2804 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2805 //
2806 IkePacket->Header->NextPayload = ((IKEV2_ENCRYPTED *) IkePacket->PayloadsBuf)->Header.NextPayload;
2807
2808 //
2809 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2810 //
2811 FreePool (IkePacket->PayloadsBuf);
2812 IkePacket->PayloadsBuf = DecryptedBuf;
2813 IkePacket->PayloadTotalSize = DecryptedSize - PadLen;
2814
2815 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf, DecryptedSize);
2816
2817
2818 ON_EXIT:
2819 if (CheckSumData != NULL) {
2820 FreePool (CheckSumData);
2821 }
2822
2823 if (EFI_ERROR (Status) && DecryptedBuf != NULL) {
2824 FreePool (DecryptedBuf);
2825 }
2826
2827 if (IntegrityBuffer != NULL) {
2828 FreePool (IntegrityBuffer);
2829 }
2830
2831 return Status;
2832 }
2833
2834 /**
2835 Encrypt IKE packet.
2836
2837 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2838 is put in to IKEV2 Encrypted Payload.
2839
2840 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2841 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2842
2843 @retval EFI_SUCCESS Operation is successful.
2844 @retval Others Operation is failed.
2845
2846 **/
2847 EFI_STATUS
2848 Ikev2EncryptPacket (
2849 IN IKEV2_SESSION_COMMON *SessionCommon,
2850 IN OUT IKE_PACKET *IkePacket
2851 )
2852 {
2853 UINT8 CryptBlockSize; // Encrypt Block Size
2854 UINT8 CryptBlockSizeMask; // Block Mask
2855 UINTN EncryptedSize; // Encrypted IKE Payload Size
2856 UINT8 *EncryptedBuf; // Encrypted IKE Payload buffer
2857 UINT8 *EncryptPayloadBuf; // Contain whole Encrypted Payload
2858 UINTN EncryptPayloadSize; // Total size of the Encrypted payload
2859 UINT8 *IntegrityBuf; // Buffer to be intergity
2860 UINT8 *IvBuffer; // Initialization Vector
2861 UINT8 IvSize; // Iv Size
2862 UINT8 CheckSumSize; // Integrity Check Sum Size depends on intergrity Auth
2863 UINT8 *CheckSumData; // Check Sum data
2864 UINTN Index;
2865 IKE_PAYLOAD *EncryptPayload;
2866 IKEV2_SA_SESSION *IkeSaSession;
2867 IKEV2_CHILD_SA_SESSION *ChildSaSession;
2868 EFI_STATUS Status;
2869 LIST_ENTRY *Entry;
2870 IKE_PAYLOAD *IkePayload;
2871 HASH_DATA_FRAGMENT Fragments[1];
2872
2873 Status = EFI_SUCCESS;
2874
2875 //
2876 // Initial all buffers to NULL.
2877 //
2878 EncryptedBuf = NULL;
2879 EncryptPayloadBuf = NULL;
2880 IvBuffer = NULL;
2881 CheckSumData = NULL;
2882 IkeSaSession = NULL;
2883 CryptBlockSize = 0;
2884 CheckSumSize = 0;
2885 IntegrityBuf = NULL;
2886 //
2887 // Get the Block Size
2888 //
2889 if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
2890
2891 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);
2892 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);
2893 IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
2894
2895 } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {
2896
2897 ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
2898 IkeSaSession = ChildSaSession->IkeSaSession;
2899 CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);
2900 CheckSumSize = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);
2901 }
2902
2903 //
2904 // Calcualte the EncryptPayloadSize and the PAD length
2905 //
2906 CryptBlockSizeMask = (UINT8) (CryptBlockSize - 1);
2907 EncryptedSize = (IkePacket->PayloadTotalSize + sizeof (IKEV2_PAD_LEN) + CryptBlockSizeMask) & ~CryptBlockSizeMask;
2908 EncryptedBuf = (UINT8 *) AllocateZeroPool (EncryptedSize);
2909 if (EncryptedBuf == NULL) {
2910 Status = EFI_OUT_OF_RESOURCES;
2911 goto ON_EXIT;
2912 }
2913
2914 //
2915 // Copy all payload into EncryptedIkePayload
2916 //
2917 Index = 0;
2918 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
2919 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
2920
2921 CopyMem (EncryptedBuf + Index, IkePayload->PayloadBuf, IkePayload->PayloadSize);
2922 Index += IkePayload->PayloadSize;
2923
2924 };
2925
2926 //
2927 // Fill in the Pading Length
2928 //
2929 *(EncryptedBuf + EncryptedSize - 1) = (UINT8)(EncryptedSize - IkePacket->PayloadTotalSize - 1);
2930
2931 //
2932 // The IV size is equal with block size
2933 //
2934 IvSize = CryptBlockSize;
2935 IvBuffer = (UINT8 *) AllocateZeroPool (IvSize);
2936 if (IvBuffer == NULL) {
2937 Status = EFI_OUT_OF_RESOURCES;
2938 goto ON_EXIT;
2939 }
2940
2941 //
2942 // Generate IV
2943 //
2944 IkeGenerateIv (IvBuffer, IvSize);
2945
2946 //
2947 // Encrypt payload buf
2948 //
2949 if (SessionCommon->IsInitiator) {
2950 Status = IpSecCryptoIoEncrypt (
2951 (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,
2952 IkeSaSession->IkeKeys->SkEiKey,
2953 IkeSaSession->IkeKeys->SkEiKeySize << 3,
2954 IvBuffer,
2955 EncryptedBuf,
2956 EncryptedSize,
2957 EncryptedBuf
2958 );
2959 } else {
2960 Status = IpSecCryptoIoEncrypt (
2961 (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,
2962 IkeSaSession->IkeKeys->SkErKey,
2963 IkeSaSession->IkeKeys->SkErKeySize << 3,
2964 IvBuffer,
2965 EncryptedBuf,
2966 EncryptedSize,
2967 EncryptedBuf
2968 );
2969 }
2970 if (EFI_ERROR (Status)) {
2971 goto ON_EXIT;
2972 }
2973
2974 //
2975 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2976 //
2977 EncryptPayloadSize = sizeof(IKEV2_ENCRYPTED) + IvSize + EncryptedSize + CheckSumSize;
2978 EncryptPayloadBuf = AllocateZeroPool (EncryptPayloadSize);
2979 if (EncryptPayloadBuf == NULL) {
2980 Status = EFI_OUT_OF_RESOURCES;
2981 goto ON_EXIT;
2982 }
2983
2984 //
2985 // Fill in Header of Encrypted Payload
2986 //
2987 ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.NextPayload = IkePacket->Header->NextPayload;
2988 ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.PayloadLength = HTONS ((UINT16)EncryptPayloadSize);
2989
2990 //
2991 // Fill in Iv
2992 //
2993 CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED), IvBuffer, IvSize);
2994
2995 //
2996 // Fill in encrypted data
2997 //
2998 CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED) + IvSize, EncryptedBuf, EncryptedSize);
2999
3000 //
3001 // Fill in the IKE Packet header
3002 //
3003 IkePacket->PayloadTotalSize = EncryptPayloadSize;
3004 IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);
3005 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_ENCRYPT;
3006
3007 IntegrityBuf = AllocateZeroPool (IkePacket->Header->Length);
3008 if (IntegrityBuf == NULL) {
3009 Status = EFI_OUT_OF_RESOURCES;
3010 goto ON_EXIT;
3011 }
3012 IkeHdrHostToNet (IkePacket->Header);
3013
3014 CopyMem (IntegrityBuf, IkePacket->Header, sizeof (IKE_HEADER));
3015 CopyMem (IntegrityBuf + sizeof (IKE_HEADER), EncryptPayloadBuf, EncryptPayloadSize);
3016
3017 //
3018 // Calcualte Integrity CheckSum
3019 //
3020 Fragments[0].Data = IntegrityBuf;
3021 Fragments[0].DataSize = EncryptPayloadSize + sizeof (IKE_HEADER) - CheckSumSize;
3022
3023 CheckSumData = AllocateZeroPool (CheckSumSize);
3024 if (CheckSumData == NULL) {
3025 Status = EFI_OUT_OF_RESOURCES;
3026 goto ON_EXIT;
3027 }
3028 if (SessionCommon->IsInitiator) {
3029
3030 IpSecCryptoIoHmac (
3031 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
3032 IkeSaSession->IkeKeys->SkAiKey,
3033 IkeSaSession->IkeKeys->SkAiKeySize,
3034 (HASH_DATA_FRAGMENT *) Fragments,
3035 1,
3036 CheckSumData,
3037 CheckSumSize
3038 );
3039 } else {
3040
3041 IpSecCryptoIoHmac (
3042 (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
3043 IkeSaSession->IkeKeys->SkArKey,
3044 IkeSaSession->IkeKeys->SkArKeySize,
3045 (HASH_DATA_FRAGMENT *) Fragments,
3046 1,
3047 CheckSumData,
3048 CheckSumSize
3049 );
3050 }
3051
3052 //
3053 // Copy CheckSum into Encrypted Payload
3054 //
3055 CopyMem (EncryptPayloadBuf + EncryptPayloadSize - CheckSumSize, CheckSumData, CheckSumSize);
3056
3057 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf, EncryptPayloadSize);
3058 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData, CheckSumSize);
3059
3060 //
3061 // Clean all payload under IkePacket->PayloadList.
3062 //
3063 ClearAllPayloads (IkePacket);
3064
3065 //
3066 // Create Encrypted Payload and add into IkePacket->PayloadList
3067 //
3068 EncryptPayload = IkePayloadAlloc ();
3069 if (EncryptPayload == NULL) {
3070 Status = EFI_OUT_OF_RESOURCES;
3071 goto ON_EXIT;
3072 }
3073
3074 //
3075 // Fill the encrypted payload into the IKE_PAYLOAD structure.
3076 //
3077 EncryptPayload->PayloadBuf = EncryptPayloadBuf;
3078 EncryptPayload->PayloadSize = EncryptPayloadSize;
3079 EncryptPayload->PayloadType = IKEV2_PAYLOAD_TYPE_ENCRYPT;
3080
3081 IKE_PACKET_APPEND_PAYLOAD (IkePacket, EncryptPayload);
3082
3083 ON_EXIT:
3084 if (EncryptedBuf != NULL) {
3085 FreePool (EncryptedBuf);
3086 }
3087
3088 if (EFI_ERROR (Status) && EncryptPayloadBuf != NULL) {
3089 FreePool (EncryptPayloadBuf);
3090 }
3091
3092 if (IvBuffer != NULL) {
3093 FreePool (IvBuffer);
3094 }
3095
3096 if (CheckSumData != NULL) {
3097 FreePool (CheckSumData);
3098 }
3099
3100 if (IntegrityBuf != NULL) {
3101 FreePool (IntegrityBuf);
3102 }
3103
3104 return Status;
3105 }
3106
3107
3108 /**
3109
3110 The notification function. It will be called when the related UDP_TX_TOKEN's event
3111 is signaled.
3112
3113 This function frees the Net Buffer pointed to the input Packet.
3114
3115 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3116 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3117 address information.
3118 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3119 @param[in] Context Pointer to data passed from the caller.
3120
3121 **/
3122 VOID
3123 EFIAPI
3124 Ikev2OnPacketSent (
3125 IN NET_BUF *Packet,
3126 IN UDP_END_POINT *EndPoint,
3127 IN EFI_STATUS IoStatus,
3128 IN VOID *Context
3129 )
3130 {
3131 IKE_PACKET *IkePacket;
3132 IKEV2_SA_SESSION *IkeSaSession;
3133 IKEV2_CHILD_SA_SESSION *ChildSaSession;
3134 UINT8 Value;
3135 IPSEC_PRIVATE_DATA *Private;
3136 EFI_STATUS Status;
3137
3138 IkePacket = (IKE_PACKET *) Context;
3139 Private = NULL;
3140
3141 if (EFI_ERROR (IoStatus)) {
3142 DEBUG ((DEBUG_ERROR, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus));
3143 }
3144
3145 NetbufFree (Packet);
3146
3147 if (IkePacket->IsDeleteInfo) {
3148 //
3149 // For each RemotePeerIP, there are only one IKESA.
3150 //
3151 IkeSaSession = Ikev2SaSessionLookup (
3152 &IkePacket->Private->Ikev2EstablishedList,
3153 &IkePacket->RemotePeerIp
3154 );
3155 if (IkeSaSession == NULL) {
3156 IkePacketFree (IkePacket);
3157 return;
3158 }
3159
3160 Private = IkePacket->Private;
3161 if (IkePacket->Spi != 0 ) {
3162 //
3163 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3164 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3165 // remove it from delete list and delete it direclty.
3166 //
3167 ChildSaSession = Ikev2ChildSaSessionLookupBySpi (
3168 &IkeSaSession->ChildSaEstablishSessionList,
3169 IkePacket->Spi
3170 );
3171 if (ChildSaSession != NULL) {
3172 Ikev2ChildSaSessionRemove (
3173 &IkeSaSession->DeleteSaList,
3174 ChildSaSession->LocalPeerSpi,
3175 IKEV2_DELET_CHILDSA_LIST
3176 );
3177
3178 //
3179 // Delete the Child SA.
3180 //
3181 Ikev2ChildSaSilentDelete (
3182 IkeSaSession,
3183 IkePacket->Spi
3184 );
3185 }
3186
3187 } else {
3188 //
3189 // Delete the IKE SA
3190 //
3191 DEBUG (
3192 (DEBUG_INFO,
3193 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3194 IkeSaSession->InitiatorCookie,
3195 IkeSaSession->ResponderCookie)
3196 );
3197
3198 RemoveEntryList (&IkeSaSession->BySessionTable);
3199 Ikev2SaSessionFree (IkeSaSession);
3200 }
3201 }
3202 IkePacketFree (IkePacket);
3203
3204 //
3205 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3206 // should be changed.
3207 //
3208 if (Private != NULL && Private->IsIPsecDisabling) {
3209 //
3210 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3211 // IPsec status variable.
3212 //
3213 if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {
3214 Value = IPSEC_STATUS_DISABLED;
3215 Status = gRT->SetVariable (
3216 IPSECCONFIG_STATUS_NAME,
3217 &gEfiIpSecConfigProtocolGuid,
3218 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
3219 sizeof (Value),
3220 &Value
3221 );
3222 if (!EFI_ERROR (Status)) {
3223 //
3224 // Set the DisabledFlag in Private data.
3225 //
3226 Private->IpSec.DisabledFlag = TRUE;
3227 Private->IsIPsecDisabling = FALSE;
3228 }
3229 }
3230 }
3231 }
3232
3233 /**
3234 Send out IKEV2 packet.
3235
3236 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3237 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3238 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3239 @param[in] IkeType The type of IKE to point what's kind of the IKE
3240 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3241 and IKE_CHILD_TYPE are supportted.
3242
3243 @retval EFI_SUCCESS The operation complete successfully.
3244 @retval Otherwise The operation is failed.
3245
3246 **/
3247 EFI_STATUS
3248 Ikev2SendIkePacket (
3249 IN IKE_UDP_SERVICE *IkeUdpService,
3250 IN UINT8 *SessionCommon,
3251 IN IKE_PACKET *IkePacket,
3252 IN UINTN IkeType
3253 )
3254 {
3255 EFI_STATUS Status;
3256 NET_BUF *IkePacketNetbuf;
3257 UDP_END_POINT EndPoint;
3258 IKEV2_SESSION_COMMON *Common;
3259
3260 Common = (IKEV2_SESSION_COMMON *) SessionCommon;
3261
3262 //
3263 // Set the resend interval
3264 //
3265 if (Common->TimeoutInterval == 0) {
3266 Common->TimeoutInterval = IKE_DEFAULT_TIMEOUT_INTERVAL;
3267 }
3268
3269 //
3270 // Retransfer the packet if it is initial packet.
3271 //
3272 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {
3273 //
3274 // Set timer for next retry, this will cancel previous timer
3275 //
3276 Status = gBS->SetTimer (
3277 Common->TimeoutEvent,
3278 TimerRelative,
3279 MultU64x32 (Common->TimeoutInterval, 10000) // ms->100ns
3280 );
3281 if (EFI_ERROR (Status)) {
3282 return Status;
3283 }
3284 }
3285
3286 IKE_PACKET_REF (IkePacket);
3287 //
3288 // If the last sent packet is same with this round packet, the packet is resent packet.
3289 //
3290 if (IkePacket != Common->LastSentPacket && Common->LastSentPacket != NULL) {
3291 IkePacketFree (Common->LastSentPacket);
3292 }
3293
3294 Common->LastSentPacket = IkePacket;
3295
3296 //
3297 // Transform IkePacke to NetBuf
3298 //
3299 IkePacketNetbuf = IkeNetbufFromPacket ((UINT8 *) SessionCommon, IkePacket, IkeType);
3300 if (IkePacketNetbuf == NULL) {
3301 return EFI_OUT_OF_RESOURCES;
3302 }
3303
3304 ZeroMem (&EndPoint, sizeof (UDP_END_POINT));
3305 EndPoint.RemotePort = IKE_DEFAULT_PORT;
3306 CopyMem (&IkePacket->RemotePeerIp, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));
3307 CopyMem (&EndPoint.RemoteAddr, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));
3308 CopyMem (&EndPoint.LocalAddr, &Common->LocalPeerIp, sizeof (EFI_IP_ADDRESS));
3309
3310 IPSEC_DUMP_PACKET (IkePacket, EfiIPsecOutBound, IkeUdpService->IpVersion);
3311
3312 if (IkeUdpService->IpVersion == IP_VERSION_4) {
3313 EndPoint.RemoteAddr.Addr[0] = HTONL (EndPoint.RemoteAddr.Addr[0]);
3314 EndPoint.LocalAddr.Addr[0] = HTONL (EndPoint.LocalAddr.Addr[0]);
3315 }
3316
3317 //
3318 // Call UDPIO to send out the IKE packet.
3319 //
3320 Status = UdpIoSendDatagram (
3321 IkeUdpService->Output,
3322 IkePacketNetbuf,
3323 &EndPoint,
3324 NULL,
3325 Ikev2OnPacketSent,
3326 (VOID*)IkePacket
3327 );
3328
3329 if (EFI_ERROR (Status)) {
3330 DEBUG ((DEBUG_ERROR, "Error send packet with %r\n", Status));
3331 }
3332
3333 return Status;
3334 }
3335