]>
Commit | Line | Data |
---|---|---|
7e1f2209 JW |
1 | /** @file |
2 | The Miscellaneous Routines for TlsDxe driver. | |
3 | ||
89f06051 | 4 | Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR> |
7e1f2209 JW |
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 | ||
89f06051 | 108 | if (RecordHeaderIn->ContentType != TlsContentTypeApplicationData) { |
7e1f2209 JW |
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 | ||
89f06051 | 259 | if (RecordHeaderIn->ContentType != TlsContentTypeApplicationData) { |
7e1f2209 JW |
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 | } |