1 /** @file 2 The Implementations for Information Exchange. 3 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR> 5 Copyright (c) 2010, 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 21 /** 22 Generate Information Packet. 23 24 The information Packet may contain one Delete Payload, or Notify Payload, which 25 dependes on the Context's parameters. 26 27 @param[in] SaSession Pointer to IKE SA Session or Child SA Session which is 28 related to the information Exchange. 29 @param[in] Context The Data passed from the caller. If the Context is not NULL 30 it should contain the information for Notification Data. 31 32 @retval Pointer of IKE_PACKET generated. 33 34 **/ 35 IKE_PACKET * 36 Ikev2InfoGenerator ( 37 IN UINT8 *SaSession, 38 IN VOID *Context 39 ) 40 { 41 IKEV2_SA_SESSION *IkeSaSession; 42 IKEV2_CHILD_SA_SESSION *ChildSaSession; 43 IKE_PACKET *IkePacket; 44 IKE_PAYLOAD *IkePayload; 45 IKEV2_INFO_EXCHANGE_CONTEXT *InfoContext; 46 47 InfoContext = NULL; 48 IkeSaSession = (IKEV2_SA_SESSION *) SaSession; 49 IkePacket = IkePacketAlloc (); 50 ASSERT (IkePacket != NULL); 51 52 // 53 // Fill IkePacket Header. 54 // 55 IkePacket->Header->ExchangeType = IKEV2_EXCHANGE_TYPE_INFO; 56 IkePacket->Header->Version = (UINT8) (2 << 4); 57 58 if (Context != NULL) { 59 InfoContext = (IKEV2_INFO_EXCHANGE_CONTEXT *) Context; 60 } 61 62 // 63 // For Liveness Check 64 // 65 if (InfoContext != NULL && 66 (InfoContext->InfoType == Ikev2InfoLiveCheck || InfoContext->InfoType == Ikev2InfoNotify) 67 ) { 68 IkePacket->Header->MessageId = InfoContext->MessageId; 69 IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie; 70 IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie; 71 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NONE; 72 IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND; 73 // 74 // TODO: add Notify Payload for Notification Information. 75 // 76 return IkePacket; 77 } 78 79 // 80 // For delete SAs 81 // 82 if (IkeSaSession->SessionCommon.IkeSessionType == IkeSessionTypeIkeSa) { 83 84 IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie; 85 IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie; 86 87 // 88 // If the information message is response message,the MessageId should 89 // be same as the request MessageId which passed through the Context. 90 // 91 if (InfoContext != NULL) { 92 IkePacket->Header->MessageId = InfoContext->MessageId; 93 } else { 94 IkePacket->Header->MessageId = IkeSaSession->MessageId; 95 Ikev2SaSessionIncreaseMessageId (IkeSaSession); 96 } 97 // 98 // If the state is on deleting generate a Delete Payload for it. 99 // 100 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting ) { 101 IkePayload = Ikev2GenerateDeletePayload ( 102 IkeSaSession, 103 IKEV2_PAYLOAD_TYPE_NONE, 104 0, 105 0, 106 NULL 107 ); 108 if (IkePayload == NULL) { 109 goto ERROR_EXIT; 110 } 111 // 112 // Fill the next payload in IkePacket's Header. 113 // 114 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE; 115 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload); 116 IkePacket->Private = IkeSaSession->SessionCommon.Private; 117 IkePacket->Spi = 0; 118 IkePacket->IsDeleteInfo = TRUE; 119 120 } else if (Context != NULL) { 121 // 122 // TODO: If contest is not NULL Generate a Notify Payload. 123 // 124 } else { 125 // 126 // The input parameter is not correct. 127 // 128 goto ERROR_EXIT; 129 } 130 } else { 131 // 132 // Delete the Child SA Information Exchagne 133 // 134 ChildSaSession = (IKEV2_CHILD_SA_SESSION *) SaSession; 135 IkeSaSession = ChildSaSession->IkeSaSession; 136 IkePacket->Header->InitiatorCookie = ChildSaSession->IkeSaSession->InitiatorCookie; 137 IkePacket->Header->ResponderCookie = ChildSaSession->IkeSaSession->ResponderCookie; 138 139 // 140 // If the information message is response message,the MessageId should 141 // be same as the request MessageId which passed through the Context. 142 // 143 if (InfoContext != NULL && InfoContext->MessageId != 0) { 144 IkePacket->Header->MessageId = InfoContext->MessageId; 145 } else { 146 IkePacket->Header->MessageId = ChildSaSession->IkeSaSession->MessageId; 147 Ikev2SaSessionIncreaseMessageId (IkeSaSession); 148 } 149 150 IkePayload = Ikev2GenerateDeletePayload ( 151 ChildSaSession->IkeSaSession, 152 IKEV2_PAYLOAD_TYPE_DELETE, 153 4, 154 1, 155 (UINT8 *)&ChildSaSession->LocalPeerSpi 156 ); 157 if (IkePayload == NULL) { 158 goto ERROR_EXIT; 159 } 160 // 161 // Fill the Next Payload in IkePacket's Header. 162 // 163 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE; 164 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload); 165 166 IkePacket->Private = IkeSaSession->SessionCommon.Private; 167 IkePacket->Spi = ChildSaSession->LocalPeerSpi; 168 IkePacket->IsDeleteInfo = TRUE; 169 170 if (!ChildSaSession->SessionCommon.IsInitiator) { 171 // 172 // If responder, use the MessageId fromt the initiator. 173 // 174 IkePacket->Header->MessageId = ChildSaSession->MessageId; 175 } 176 177 // 178 // Change the IsOnDeleting Flag 179 // 180 ChildSaSession->SessionCommon.IsOnDeleting = TRUE; 181 } 182 183 if (InfoContext == NULL) { 184 IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT; 185 } else { 186 IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND; 187 } 188 return IkePacket; 189 190 ERROR_EXIT: 191 if (IkePacket != NULL) { 192 FreePool (IkePacket); 193 } 194 return NULL; 195 196 } 197 198 /** 199 Parse the Info Exchange. 200 201 @param[in] SaSession Pointer to IKEV2_SA_SESSION. 202 @param[in] IkePacket Pointer to IkePacket related to the Information Exchange. 203 204 @retval EFI_SUCCESS The operation finised successed. 205 206 **/ 207 EFI_STATUS 208 Ikev2InfoParser ( 209 IN UINT8 *SaSession, 210 IN IKE_PACKET *IkePacket 211 ) 212 { 213 IKEV2_CHILD_SA_SESSION *ChildSaSession; 214 IKEV2_SA_SESSION *IkeSaSession; 215 IKE_PAYLOAD *DeletePayload; 216 IKE_PAYLOAD *IkePayload; 217 IKEV2_DELETE *Delete; 218 LIST_ENTRY *Entry; 219 LIST_ENTRY *ListEntry; 220 UINT8 Index; 221 UINT32 Spi; 222 UINT8 *SpiBuffer; 223 IPSEC_PRIVATE_DATA *Private; 224 UINT8 Value; 225 EFI_STATUS Status; 226 IKE_PACKET *RespondPacket; 227 228 IKEV2_INFO_EXCHANGE_CONTEXT Context; 229 230 IkeSaSession = (IKEV2_SA_SESSION *) SaSession; 231 232 DeletePayload = NULL; 233 Private = NULL; 234 RespondPacket = NULL; 235 Status = EFI_SUCCESS; 236 237 // 238 // For Liveness Check 239 // 240 if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE && 241 (IkePacket->PayloadTotalSize == 0) 242 ) { 243 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) { 244 // 245 // If it is Liveness check request, reply it. 246 // 247 Context.InfoType = Ikev2InfoLiveCheck; 248 Context.MessageId = IkePacket->Header->MessageId; 249 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context); 250 251 if (RespondPacket == NULL) { 252 Status = EFI_INVALID_PARAMETER; 253 return Status; 254 } 255 Status = Ikev2SendIkePacket ( 256 IkeSaSession->SessionCommon.UdpService, 257 (UINT8 *)(&IkeSaSession->SessionCommon), 258 RespondPacket, 259 0 260 ); 261 262 } else { 263 // 264 // Todo: verify the liveness check response packet. 265 // 266 } 267 return Status; 268 } 269 270 // 271 // For SA Delete 272 // 273 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) { 274 275 // 276 // Iterate payloads to find the Delete/Notify Payload. 277 // 278 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry); 279 280 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_DELETE) { 281 DeletePayload = IkePayload; 282 Delete = (IKEV2_DELETE *)DeletePayload->PayloadBuf; 283 284 if (Delete->SpiSize == 0) { 285 // 286 // Delete IKE SA. 287 // 288 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) { 289 RemoveEntryList (&IkeSaSession->BySessionTable); 290 Ikev2SaSessionFree (IkeSaSession); 291 // 292 // Checking the Private status. 293 // 294 // 295 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec 296 // status should be changed. 297 // 298 Private = IkeSaSession->SessionCommon.Private; 299 if (Private != NULL && Private->IsIPsecDisabling) { 300 // 301 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in 302 // IPsec status variable. 303 // 304 if (IsListEmpty (&Private->Ikev1EstablishedList) && 305 (IsListEmpty (&Private->Ikev2EstablishedList)) 306 ) { 307 Value = IPSEC_STATUS_DISABLED; 308 Status = gRT->SetVariable ( 309 IPSECCONFIG_STATUS_NAME, 310 &gEfiIpSecConfigProtocolGuid, 311 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 312 sizeof (Value), 313 &Value 314 ); 315 if (!EFI_ERROR (Status)) { 316 // 317 // Set the DisabledFlag in Private data. 318 // 319 Private->IpSec.DisabledFlag = TRUE; 320 Private->IsIPsecDisabling = FALSE; 321 } 322 } 323 } 324 } else { 325 IkeSaSession->SessionCommon.State = IkeStateSaDeleting; 326 Context.InfoType = Ikev2InfoDelete; 327 Context.MessageId = IkePacket->Header->MessageId; 328 329 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context); 330 if (RespondPacket == NULL) { 331 Status = EFI_INVALID_PARAMETER; 332 return Status; 333 } 334 Status = Ikev2SendIkePacket ( 335 IkeSaSession->SessionCommon.UdpService, 336 (UINT8 *)(&IkeSaSession->SessionCommon), 337 RespondPacket, 338 0 339 ); 340 } 341 } else if (Delete->SpiSize == 4) { 342 // 343 // Move the Child SAs to DeleteList 344 // 345 SpiBuffer = (UINT8 *)(Delete + 1); 346 for (Index = 0; Index < Delete->NumSpis; Index++) { 347 Spi = ReadUnaligned32 ((UINT32 *)SpiBuffer); 348 for (ListEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink; 349 ListEntry != &IkeSaSession->ChildSaEstablishSessionList; 350 ) { 351 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry); 352 ListEntry = ListEntry->ForwardLink; 353 354 if (ChildSaSession->RemotePeerSpi == HTONL(Spi)) { 355 if (ChildSaSession->SessionCommon.State != IkeStateSaDeleting) { 356 357 // 358 // Insert the ChildSa Session into Delete List. 359 // 360 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete); 361 ChildSaSession->SessionCommon.State = IkeStateSaDeleting; 362 ChildSaSession->SessionCommon.IsInitiator = FALSE; 363 ChildSaSession->MessageId = IkePacket->Header->MessageId; 364 365 Context.InfoType = Ikev2InfoDelete; 366 Context.MessageId = IkePacket->Header->MessageId; 367 368 RespondPacket = Ikev2InfoGenerator ((UINT8 *)ChildSaSession, &Context); 369 if (RespondPacket == NULL) { 370 Status = EFI_INVALID_PARAMETER; 371 return Status; 372 } 373 Status = Ikev2SendIkePacket ( 374 ChildSaSession->SessionCommon.UdpService, 375 (UINT8 *)(&ChildSaSession->SessionCommon), 376 RespondPacket, 377 0 378 ); 379 } else { 380 // 381 // Delete the Child SA. 382 // 383 Ikev2ChildSaSilentDelete (IkeSaSession, Spi); 384 RemoveEntryList (&ChildSaSession->ByDelete); 385 } 386 } 387 } 388 SpiBuffer = SpiBuffer + sizeof (Spi); 389 } 390 } 391 } 392 } 393 394 return Status; 395 } 396 397 GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Info = { 398 Ikev2InfoParser, 399 Ikev2InfoGenerator 400 }; 401