1 /** @file 2 The implementation of Payloads Creation. 3 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2010 - 2016, 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 == (UINTN)(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 Save some useful payloads after accepting the Packet. 3109 3110 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the operation. 3111 @param[in] IkePacket Pointer to received IkePacet. 3112 @param[in] IkeType The type used to indicate it is in IkeSa or ChildSa or Info 3113 exchange. 3114 3115 **/ 3116 VOID 3117 Ikev2OnPacketAccepted ( 3118 IN IKEV2_SESSION_COMMON *SessionCommon, 3119 IN IKE_PACKET *IkePacket, 3120 IN UINT8 IkeType 3121 ) 3122 { 3123 return; 3124 } 3125 3126 /** 3127 3128 The notification function. It will be called when the related UDP_TX_TOKEN's event 3129 is signaled. 3130 3131 This function frees the Net Buffer pointed to the input Packet. 3132 3133 @param[in] Packet Pointer to Net buffer containing the sending IKE packet. 3134 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local 3135 address information. 3136 @param[in] IoStatus The Status of the related UDP_TX_TOKEN. 3137 @param[in] Context Pointer to data passed from the caller. 3138 3139 **/ 3140 VOID 3141 EFIAPI 3142 Ikev2OnPacketSent ( 3143 IN NET_BUF *Packet, 3144 IN UDP_END_POINT *EndPoint, 3145 IN EFI_STATUS IoStatus, 3146 IN VOID *Context 3147 ) 3148 { 3149 IKE_PACKET *IkePacket; 3150 IKEV2_SA_SESSION *IkeSaSession; 3151 IKEV2_CHILD_SA_SESSION *ChildSaSession; 3152 UINT8 Value; 3153 IPSEC_PRIVATE_DATA *Private; 3154 EFI_STATUS Status; 3155 3156 IkePacket = (IKE_PACKET *) Context; 3157 Private = NULL; 3158 3159 if (EFI_ERROR (IoStatus)) { 3160 DEBUG ((DEBUG_ERROR, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus)); 3161 } 3162 3163 NetbufFree (Packet); 3164 3165 if (IkePacket->IsDeleteInfo) { 3166 // 3167 // For each RemotePeerIP, there are only one IKESA. 3168 // 3169 IkeSaSession = Ikev2SaSessionLookup ( 3170 &IkePacket->Private->Ikev2EstablishedList, 3171 &IkePacket->RemotePeerIp 3172 ); 3173 if (IkeSaSession == NULL) { 3174 IkePacketFree (IkePacket); 3175 return; 3176 } 3177 3178 Private = IkePacket->Private; 3179 if (IkePacket->Spi != 0 ) { 3180 // 3181 // At that time, the established Child SA still in eht ChildSaEstablishSessionList. 3182 // And meanwhile, if the Child SA is in the the ChildSa in Delete list, 3183 // remove it from delete list and delete it direclty. 3184 // 3185 ChildSaSession = Ikev2ChildSaSessionLookupBySpi ( 3186 &IkeSaSession->ChildSaEstablishSessionList, 3187 IkePacket->Spi 3188 ); 3189 if (ChildSaSession != NULL) { 3190 Ikev2ChildSaSessionRemove ( 3191 &IkeSaSession->DeleteSaList, 3192 ChildSaSession->LocalPeerSpi, 3193 IKEV2_DELET_CHILDSA_LIST 3194 ); 3195 3196 // 3197 // Delete the Child SA. 3198 // 3199 Ikev2ChildSaSilentDelete ( 3200 IkeSaSession, 3201 IkePacket->Spi 3202 ); 3203 } 3204 3205 } else { 3206 // 3207 // Delete the IKE SA 3208 // 3209 DEBUG ( 3210 (DEBUG_INFO, 3211 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n", 3212 IkeSaSession->InitiatorCookie, 3213 IkeSaSession->ResponderCookie) 3214 ); 3215 3216 RemoveEntryList (&IkeSaSession->BySessionTable); 3217 Ikev2SaSessionFree (IkeSaSession); 3218 } 3219 } 3220 IkePacketFree (IkePacket); 3221 3222 // 3223 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status 3224 // should be changed. 3225 // 3226 if (Private != NULL && Private->IsIPsecDisabling) { 3227 // 3228 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in 3229 // IPsec status variable. 3230 // 3231 if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) { 3232 Value = IPSEC_STATUS_DISABLED; 3233 Status = gRT->SetVariable ( 3234 IPSECCONFIG_STATUS_NAME, 3235 &gEfiIpSecConfigProtocolGuid, 3236 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 3237 sizeof (Value), 3238 &Value 3239 ); 3240 if (!EFI_ERROR (Status)) { 3241 // 3242 // Set the DisabledFlag in Private data. 3243 // 3244 Private->IpSec.DisabledFlag = TRUE; 3245 Private->IsIPsecDisabling = FALSE; 3246 } 3247 } 3248 } 3249 } 3250 3251 /** 3252 Send out IKEV2 packet. 3253 3254 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet. 3255 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet. 3256 @param[in] IkePacket Pointer to IKE_PACKET to be sent out. 3257 @param[in] IkeType The type of IKE to point what's kind of the IKE 3258 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE 3259 and IKE_CHILD_TYPE are supportted. 3260 3261 @retval EFI_SUCCESS The operation complete successfully. 3262 @retval Otherwise The operation is failed. 3263 3264 **/ 3265 EFI_STATUS 3266 Ikev2SendIkePacket ( 3267 IN IKE_UDP_SERVICE *IkeUdpService, 3268 IN UINT8 *SessionCommon, 3269 IN IKE_PACKET *IkePacket, 3270 IN UINTN IkeType 3271 ) 3272 { 3273 EFI_STATUS Status; 3274 NET_BUF *IkePacketNetbuf; 3275 UDP_END_POINT EndPoint; 3276 IKEV2_SESSION_COMMON *Common; 3277 3278 Common = (IKEV2_SESSION_COMMON *) SessionCommon; 3279 3280 // 3281 // Set the resend interval 3282 // 3283 if (Common->TimeoutInterval == 0) { 3284 Common->TimeoutInterval = IKE_DEFAULT_TIMEOUT_INTERVAL; 3285 } 3286 3287 // 3288 // Retransfer the packet if it is initial packet. 3289 // 3290 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) { 3291 // 3292 // Set timer for next retry, this will cancel previous timer 3293 // 3294 Status = gBS->SetTimer ( 3295 Common->TimeoutEvent, 3296 TimerRelative, 3297 MultU64x32 (Common->TimeoutInterval, 10000) // ms->100ns 3298 ); 3299 if (EFI_ERROR (Status)) { 3300 return Status; 3301 } 3302 } 3303 3304 IKE_PACKET_REF (IkePacket); 3305 // 3306 // If the last sent packet is same with this round packet, the packet is resent packet. 3307 // 3308 if (IkePacket != Common->LastSentPacket && Common->LastSentPacket != NULL) { 3309 IkePacketFree (Common->LastSentPacket); 3310 } 3311 3312 Common->LastSentPacket = IkePacket; 3313 3314 // 3315 // Transform IkePacke to NetBuf 3316 // 3317 IkePacketNetbuf = IkeNetbufFromPacket ((UINT8 *) SessionCommon, IkePacket, IkeType); 3318 if (IkePacketNetbuf == NULL) { 3319 return EFI_OUT_OF_RESOURCES; 3320 } 3321 3322 ZeroMem (&EndPoint, sizeof (UDP_END_POINT)); 3323 EndPoint.RemotePort = IKE_DEFAULT_PORT; 3324 CopyMem (&IkePacket->RemotePeerIp, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS)); 3325 CopyMem (&EndPoint.RemoteAddr, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS)); 3326 CopyMem (&EndPoint.LocalAddr, &Common->LocalPeerIp, sizeof (EFI_IP_ADDRESS)); 3327 3328 IPSEC_DUMP_PACKET (IkePacket, EfiIPsecOutBound, IkeUdpService->IpVersion); 3329 3330 if (IkeUdpService->IpVersion == IP_VERSION_4) { 3331 EndPoint.RemoteAddr.Addr[0] = HTONL (EndPoint.RemoteAddr.Addr[0]); 3332 EndPoint.LocalAddr.Addr[0] = HTONL (EndPoint.LocalAddr.Addr[0]); 3333 } 3334 3335 // 3336 // Call UDPIO to send out the IKE packet. 3337 // 3338 Status = UdpIoSendDatagram ( 3339 IkeUdpService->Output, 3340 IkePacketNetbuf, 3341 &EndPoint, 3342 NULL, 3343 Ikev2OnPacketSent, 3344 (VOID*)IkePacket 3345 ); 3346 3347 if (EFI_ERROR (Status)) { 3348 DEBUG ((DEBUG_ERROR, "Error send packet with %r\n", Status)); 3349 } 3350 3351 return Status; 3352 } 3353 3354