1 /** @file 2 Common operation of the IKE 3 4 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "Ike.h" 17 #include "IkeCommon.h" 18 #include "IpSecConfigImpl.h" 19 #include "IpSecDebug.h" 20 21 /** 22 Check whether the new generated Spi has existed. 23 24 @param[in] IkeSaSession Pointer to the Child SA Session. 25 @param[in] SpiValue SPI Value. 26 27 @retval TRUE This SpiValue has existed in the Child SA Session 28 @retval FALSE This SpiValue doesn't exist in the Child SA Session. 29 30 **/ 31 BOOLEAN 32 IkeSpiValueExisted ( 33 IN IKEV2_SA_SESSION *IkeSaSession, 34 IN UINT32 SpiValue 35 ) 36 { 37 LIST_ENTRY *Entry; 38 LIST_ENTRY *Next; 39 IKEV2_CHILD_SA_SESSION *SaSession; 40 41 Entry = NULL; 42 Next = NULL; 43 SaSession = NULL; 44 45 // 46 // Check whether the SPI value has existed in ChildSaEstablishSessionList. 47 // 48 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaEstablishSessionList) { 49 SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry); 50 if (SaSession->LocalPeerSpi == SpiValue) { 51 return TRUE; 52 } 53 } 54 55 // 56 // Check whether the SPI value has existed in ChildSaSessionList. 57 // 58 NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaSessionList) { 59 SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry); 60 if (SaSession->LocalPeerSpi == SpiValue) { 61 return TRUE; 62 } 63 } 64 65 return FALSE; 66 } 67 68 /** 69 Call Crypto Lib to generate a random value with eight-octet length. 70 71 @return the 64 byte vaule. 72 73 **/ 74 UINT64 75 IkeGenerateCookie ( 76 VOID 77 ) 78 { 79 UINT64 Cookie; 80 EFI_STATUS Status; 81 82 Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)&Cookie, sizeof (UINT64)); 83 if (EFI_ERROR (Status)) { 84 return 0; 85 } else { 86 return Cookie; 87 } 88 } 89 90 /** 91 Generate the random data for Nonce payload. 92 93 @param[in] NonceSize Size of the data in bytes. 94 95 @return Buffer which contains the random data of the spcified size. 96 97 **/ 98 UINT8 * 99 IkeGenerateNonce ( 100 IN UINTN NonceSize 101 ) 102 { 103 UINT8 *Nonce; 104 EFI_STATUS Status; 105 106 Nonce = AllocateZeroPool (NonceSize); 107 if (Nonce == NULL) { 108 return NULL; 109 } 110 111 Status = IpSecCryptoIoGenerateRandomBytes (Nonce, NonceSize); 112 if (EFI_ERROR (Status)) { 113 FreePool (Nonce); 114 return NULL; 115 } else { 116 return Nonce; 117 } 118 } 119 120 /** 121 Convert the IKE Header from Network order to Host order. 122 123 @param[in, out] Header The pointer of the IKE_HEADER. 124 125 **/ 126 VOID 127 IkeHdrNetToHost ( 128 IN OUT IKE_HEADER *Header 129 ) 130 { 131 Header->InitiatorCookie = NTOHLL (Header->InitiatorCookie); 132 Header->ResponderCookie = NTOHLL (Header->ResponderCookie); 133 Header->MessageId = NTOHL (Header->MessageId); 134 Header->Length = NTOHL (Header->Length); 135 } 136 137 /** 138 Convert the IKE Header from Host order to Network order. 139 140 @param[in, out] Header The pointer of the IKE_HEADER. 141 142 **/ 143 VOID 144 IkeHdrHostToNet ( 145 IN OUT IKE_HEADER *Header 146 ) 147 { 148 Header->InitiatorCookie = HTONLL (Header->InitiatorCookie); 149 Header->ResponderCookie = HTONLL (Header->ResponderCookie); 150 Header->MessageId = HTONL (Header->MessageId); 151 Header->Length = HTONL (Header->Length); 152 } 153 154 /** 155 Allocate a buffer of IKE_PAYLOAD and set its Signature. 156 157 @return A buffer of IKE_PAYLOAD. 158 159 **/ 160 IKE_PAYLOAD * 161 IkePayloadAlloc ( 162 VOID 163 ) 164 { 165 IKE_PAYLOAD *IkePayload; 166 167 IkePayload = (IKE_PAYLOAD *) AllocateZeroPool (sizeof (IKE_PAYLOAD)); 168 if (IkePayload == NULL) { 169 return NULL; 170 } 171 172 IkePayload->Signature = IKE_PAYLOAD_SIGNATURE; 173 174 return IkePayload; 175 } 176 177 /** 178 Free a specified IKE_PAYLOAD buffer. 179 180 @param[in] IkePayload Pointer of IKE_PAYLOAD to be freed. 181 182 **/ 183 VOID 184 IkePayloadFree ( 185 IN IKE_PAYLOAD *IkePayload 186 ) 187 { 188 if (IkePayload == NULL) { 189 return; 190 } 191 // 192 // If this IkePayload is not referred by others, free it. 193 // 194 if (!IkePayload->IsPayloadBufExt && (IkePayload->PayloadBuf != NULL)) { 195 FreePool (IkePayload->PayloadBuf); 196 } 197 198 FreePool (IkePayload); 199 } 200 201 /** 202 Generate an new SPI. 203 204 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA 205 Session. 206 @param[in, out] SpiValue Pointer to the new generated SPI value. 207 208 @retval EFI_SUCCESS The operation performs successfully. 209 @retval Otherwise The operation is failed. 210 211 **/ 212 EFI_STATUS 213 IkeGenerateSpi ( 214 IN IKEV2_SA_SESSION *IkeSaSession, 215 IN OUT UINT32 *SpiValue 216 ) 217 { 218 EFI_STATUS Status; 219 220 Status = EFI_SUCCESS; 221 222 while (TRUE) { 223 // 224 // Generate SPI randomly 225 // 226 Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)SpiValue, sizeof (UINT32)); 227 if (EFI_ERROR (Status)) { 228 break; 229 } 230 231 // 232 // The set of SPI values in the range 1 through 255 are reserved by the 233 // Internet Assigned Numbers Authority (IANA) for future use; a reserved 234 // SPI value will not normally be assigned by IANA unless the use of the 235 // assigned SPI value is specified in an RFC. 236 // 237 if (*SpiValue < IKE_SPI_BASE) { 238 *SpiValue += IKE_SPI_BASE; 239 } 240 241 // 242 // Check whether the new generated SPI has existed. 243 // 244 if (!IkeSpiValueExisted (IkeSaSession, *SpiValue)) { 245 break; 246 } 247 } 248 249 return Status; 250 } 251 252 /** 253 Generate a random data for IV 254 255 @param[in] IvBuffer The pointer of the IV buffer. 256 @param[in] IvSize The IV size. 257 258 @retval EFI_SUCCESS Create a random data for IV. 259 @retval otherwise Failed. 260 261 **/ 262 EFI_STATUS 263 IkeGenerateIv ( 264 IN UINT8 *IvBuffer, 265 IN UINTN IvSize 266 ) 267 { 268 return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize); 269 } 270 271 272 /** 273 Find SPD entry by a specified SPD selector. 274 275 @param[in] SpdSel Point to SPD Selector to be searched for. 276 277 @retval Point to SPD Entry if the SPD entry found. 278 @retval NULL if not found. 279 280 **/ 281 IPSEC_SPD_ENTRY * 282 IkeSearchSpdEntry ( 283 IN EFI_IPSEC_SPD_SELECTOR *SpdSel 284 ) 285 { 286 IPSEC_SPD_ENTRY *SpdEntry; 287 LIST_ENTRY *SpdList; 288 LIST_ENTRY *Entry; 289 290 SpdList = &mConfigData[IPsecConfigDataTypeSpd]; 291 292 NET_LIST_FOR_EACH (Entry, SpdList) { 293 SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry); 294 295 // 296 // Find the required SPD entry 297 // 298 if (CompareSpdSelector ( 299 (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel, 300 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector 301 )) { 302 return SpdEntry; 303 } 304 305 } 306 307 return NULL; 308 } 309 310 /** 311 Get the IKE Version from the IKE_SA_SESSION. 312 313 @param[in] Session Pointer of the IKE_SA_SESSION. 314 315 **/ 316 UINT8 317 IkeGetVersionFromSession ( 318 IN UINT8 *Session 319 ) 320 { 321 if (*(UINT32 *) Session == IKEV2_SA_SESSION_SIGNATURE) { 322 return ((IKEV2_SA_SESSION *) Session)->SessionCommon.IkeVer; 323 } else { 324 // 325 // Add IKEv1 support here. 326 // 327 return 0; 328 } 329 } 330 331