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