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
TlsEncryptPacket(IN TLS_INSTANCE * TlsInstance,IN OUT EFI_TLS_FRAGMENT_DATA ** FragmentTable,IN UINT32 * FragmentCount)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
TlsDecryptPacket(IN TLS_INSTANCE * TlsInstance,IN OUT EFI_TLS_FRAGMENT_DATA ** FragmentTable,IN UINT32 * FragmentCount)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