1 /** @file 2 The Miscellaneous Routines for TlsDxe driver. 3 4 Copyright (c) 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 "TlsImpl.h" 17 18 /** 19 Encrypt the message listed in fragment. 20 21 @param[in] TlsInstance The pointer to the TLS instance. 22 @param[in, out] FragmentTable Pointer to a list of fragment. 23 On input these fragments contain the TLS header and 24 plain text TLS payload; 25 On output these fragments contain the TLS header and 26 cipher text TLS payload. 27 @param[in] FragmentCount Number of fragment. 28 29 @retval EFI_SUCCESS The operation completed successfully. 30 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. 31 @retval EFI_ABORTED TLS session state is incorrect. 32 @retval Others Other errors as indicated. 33 **/ 34 EFI_STATUS 35 TlsEncryptPacket ( 36 IN TLS_INSTANCE *TlsInstance, 37 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, 38 IN UINT32 *FragmentCount 39 ) 40 { 41 EFI_STATUS Status; 42 UINTN Index; 43 UINT32 BytesCopied; 44 UINT32 BufferInSize; 45 UINT8 *BufferIn; 46 UINT8 *BufferInPtr; 47 TLS_RECORD_HEADER *RecordHeaderIn; 48 UINT16 ThisPlainMessageSize; 49 TLS_RECORD_HEADER *TempRecordHeader; 50 UINT16 ThisMessageSize; 51 UINT32 BufferOutSize; 52 UINT8 *BufferOut; 53 INTN Ret; 54 55 Status = EFI_SUCCESS; 56 BytesCopied = 0; 57 BufferInSize = 0; 58 BufferIn = NULL; 59 BufferInPtr = NULL; 60 RecordHeaderIn = NULL; 61 TempRecordHeader = NULL; 62 BufferOutSize = 0; 63 BufferOut = NULL; 64 Ret = 0; 65 66 // 67 // Calculate the size according to the fragment table. 68 // 69 for (Index = 0; Index < *FragmentCount; Index++) { 70 BufferInSize += (*FragmentTable)[Index].FragmentLength; 71 } 72 73 // 74 // Allocate buffer for processing data. 75 // 76 BufferIn = AllocateZeroPool (BufferInSize); 77 if (BufferIn == NULL) { 78 Status = EFI_OUT_OF_RESOURCES; 79 goto ERROR; 80 } 81 82 // 83 // Copy all TLS plain record header and payload into BufferIn. 84 // 85 for (Index = 0; Index < *FragmentCount; Index++) { 86 CopyMem ( 87 (BufferIn + BytesCopied), 88 (*FragmentTable)[Index].FragmentBuffer, 89 (*FragmentTable)[Index].FragmentLength 90 ); 91 BytesCopied += (*FragmentTable)[Index].FragmentLength; 92 } 93 94 BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); 95 if (BufferOut == NULL) { 96 Status = EFI_OUT_OF_RESOURCES; 97 goto ERROR; 98 } 99 100 // 101 // Parsing buffer. 102 // 103 BufferInPtr = BufferIn; 104 TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; 105 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { 106 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; 107 108 if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { 109 Status = EFI_INVALID_PARAMETER; 110 goto ERROR; 111 } 112 113 ThisPlainMessageSize = RecordHeaderIn->Length; 114 115 TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize); 116 117 Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize); 118 119 if (Ret > 0) { 120 ThisMessageSize = (UINT16) Ret; 121 } else { 122 // 123 // No data was successfully encrypted, continue to encrypt other messages. 124 // 125 DEBUG ((EFI_D_WARN, "TlsEncryptPacket: No data read from TLS object.\n")); 126 127 ThisMessageSize = 0; 128 } 129 130 BufferOutSize += ThisMessageSize; 131 132 BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize; 133 TempRecordHeader += ThisMessageSize; 134 } 135 136 FreePool (BufferIn); 137 BufferIn = NULL; 138 139 // 140 // The caller will be responsible to handle the original fragment table. 141 // 142 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); 143 if (*FragmentTable == NULL) { 144 Status = EFI_OUT_OF_RESOURCES; 145 goto ERROR; 146 } 147 148 (*FragmentTable)[0].FragmentBuffer = BufferOut; 149 (*FragmentTable)[0].FragmentLength = BufferOutSize; 150 *FragmentCount = 1; 151 152 return Status; 153 154 ERROR: 155 156 if (BufferIn != NULL) { 157 FreePool (BufferIn); 158 BufferIn = NULL; 159 } 160 161 if (BufferOut != NULL) { 162 FreePool (BufferOut); 163 BufferOut = NULL; 164 } 165 166 return Status; 167 } 168 169 /** 170 Decrypt the message listed in fragment. 171 172 @param[in] TlsInstance The pointer to the TLS instance. 173 @param[in, out] FragmentTable Pointer to a list of fragment. 174 On input these fragments contain the TLS header and 175 cipher text TLS payload; 176 On output these fragments contain the TLS header and 177 plain text TLS payload. 178 @param[in] FragmentCount Number of fragment. 179 180 @retval EFI_SUCCESS The operation completed successfully. 181 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. 182 @retval EFI_ABORTED TLS session state is incorrect. 183 @retval Others Other errors as indicated. 184 **/ 185 EFI_STATUS 186 TlsDecryptPacket ( 187 IN TLS_INSTANCE *TlsInstance, 188 IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, 189 IN UINT32 *FragmentCount 190 ) 191 { 192 EFI_STATUS Status; 193 UINTN Index; 194 UINT32 BytesCopied; 195 UINT8 *BufferIn; 196 UINT32 BufferInSize; 197 UINT8 *BufferInPtr; 198 TLS_RECORD_HEADER *RecordHeaderIn; 199 UINT16 ThisCipherMessageSize; 200 TLS_RECORD_HEADER *TempRecordHeader; 201 UINT16 ThisPlainMessageSize; 202 UINT8 *BufferOut; 203 UINT32 BufferOutSize; 204 INTN Ret; 205 206 Status = EFI_SUCCESS; 207 BytesCopied = 0; 208 BufferIn = NULL; 209 BufferInSize = 0; 210 BufferInPtr = NULL; 211 RecordHeaderIn = NULL; 212 TempRecordHeader = NULL; 213 BufferOut = NULL; 214 BufferOutSize = 0; 215 Ret = 0; 216 217 // 218 // Calculate the size according to the fragment table. 219 // 220 for (Index = 0; Index < *FragmentCount; Index++) { 221 BufferInSize += (*FragmentTable)[Index].FragmentLength; 222 } 223 224 // 225 // Allocate buffer for processing data 226 // 227 BufferIn = AllocateZeroPool (BufferInSize); 228 if (BufferIn == NULL) { 229 Status = EFI_OUT_OF_RESOURCES; 230 goto ERROR; 231 } 232 233 // 234 // Copy all TLS plain record header and payload to BufferIn 235 // 236 for (Index = 0; Index < *FragmentCount; Index++) { 237 CopyMem ( 238 (BufferIn + BytesCopied), 239 (*FragmentTable)[Index].FragmentBuffer, 240 (*FragmentTable)[Index].FragmentLength 241 ); 242 BytesCopied += (*FragmentTable)[Index].FragmentLength; 243 } 244 245 BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); 246 if (BufferOut == NULL) { 247 Status = EFI_OUT_OF_RESOURCES; 248 goto ERROR; 249 } 250 251 // 252 // Parsing buffer. Received packet may have multiple TLS record messages. 253 // 254 BufferInPtr = BufferIn; 255 TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; 256 while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { 257 RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; 258 259 if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { 260 Status = EFI_INVALID_PARAMETER; 261 goto ERROR; 262 } 263 264 ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length); 265 266 Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize); 267 if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) { 268 TlsInstance->TlsSessionState = EfiTlsSessionError; 269 Status = EFI_ABORTED; 270 goto ERROR; 271 } 272 273 Ret = 0; 274 Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE - BufferOutSize); 275 276 if (Ret > 0) { 277 ThisPlainMessageSize = (UINT16) Ret; 278 } else { 279 // 280 // No data was successfully decrypted, continue to decrypt other messages. 281 // 282 DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n")); 283 284 ThisPlainMessageSize = 0; 285 } 286 287 CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN); 288 TempRecordHeader->Length = ThisPlainMessageSize; 289 BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize; 290 291 BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize; 292 TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize; 293 } 294 295 FreePool (BufferIn); 296 BufferIn = NULL; 297 298 // 299 // The caller will be responsible to handle the original fragment table 300 // 301 *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); 302 if (*FragmentTable == NULL) { 303 Status = EFI_OUT_OF_RESOURCES; 304 goto ERROR; 305 } 306 307 (*FragmentTable)[0].FragmentBuffer = BufferOut; 308 (*FragmentTable)[0].FragmentLength = BufferOutSize; 309 *FragmentCount = 1; 310 311 return Status; 312 313 ERROR: 314 315 if (BufferIn != NULL) { 316 FreePool (BufferIn); 317 BufferIn = NULL; 318 } 319 320 if (BufferOut != NULL) { 321 FreePool (BufferOut); 322 BufferOut = NULL; 323 } 324 325 return Status; 326 } 327