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