CryptoPkg/TlsLib: sanitize lib classes in internal header and INF
[mirror_edk2.git] / CryptoPkg / Library / TlsLib / TlsProcess.c
CommitLineData
264702a0
HW
1/** @file\r
2 SSL/TLS Process Library Wrapper Implementation over OpenSSL.\r
3 The process includes the TLS handshake and packet I/O.\r
4\r
5Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
6(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "InternalTlsLib.h"\r
18\r
19#define MAX_BUFFER_SIZE 32768\r
20\r
21/**\r
22 Checks if the TLS handshake was done.\r
23\r
24 This function will check if the specified TLS handshake was done.\r
25\r
26 @param[in] Tls Pointer to the TLS object for handshake state checking.\r
27\r
28 @retval TRUE The TLS handshake was done.\r
29 @retval FALSE The TLS handshake was not done.\r
30\r
31**/\r
32BOOLEAN\r
33EFIAPI\r
34TlsInHandshake (\r
35 IN VOID *Tls\r
36 )\r
37{\r
38 TLS_CONNECTION *TlsConn;\r
39\r
40 TlsConn = (TLS_CONNECTION *) Tls;\r
41 if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
42 return FALSE;\r
43 }\r
44\r
45 //\r
46 // Return the status which indicates if the TLS handshake was done.\r
47 //\r
48 return !SSL_is_init_finished (TlsConn->Ssl);\r
49}\r
50\r
51/**\r
52 Perform a TLS/SSL handshake.\r
53\r
54 This function will perform a TLS/SSL handshake.\r
55\r
56 @param[in] Tls Pointer to the TLS object for handshake operation.\r
57 @param[in] BufferIn Pointer to the most recently received TLS Handshake packet.\r
58 @param[in] BufferInSize Packet size in bytes for the most recently received TLS\r
59 Handshake packet.\r
60 @param[out] BufferOut Pointer to the buffer to hold the built packet.\r
61 @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is\r
62 the buffer size provided by the caller. On output, it\r
63 is the buffer size in fact needed to contain the\r
64 packet.\r
65\r
66 @retval EFI_SUCCESS The required TLS packet is built successfully.\r
67 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
68 Tls is NULL.\r
69 BufferIn is NULL but BufferInSize is NOT 0.\r
70 BufferInSize is 0 but BufferIn is NOT NULL.\r
71 BufferOutSize is NULL.\r
72 BufferOut is NULL if *BufferOutSize is not zero.\r
73 @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet.\r
74 @retval EFI_ABORTED Something wrong during handshake.\r
75\r
76**/\r
77EFI_STATUS\r
78EFIAPI\r
79TlsDoHandshake (\r
80 IN VOID *Tls,\r
81 IN UINT8 *BufferIn, OPTIONAL\r
82 IN UINTN BufferInSize, OPTIONAL\r
83 OUT UINT8 *BufferOut, OPTIONAL\r
84 IN OUT UINTN *BufferOutSize\r
85 )\r
86{\r
87 TLS_CONNECTION *TlsConn;\r
88 UINTN PendingBufferSize;\r
89 INTN Ret;\r
90 UINTN ErrorCode;\r
91\r
92 TlsConn = (TLS_CONNECTION *) Tls;\r
93 PendingBufferSize = 0;\r
94 Ret = 1;\r
95\r
96 if (TlsConn == NULL || \\r
97 TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
98 BufferOutSize == NULL || \\r
99 (BufferIn == NULL && BufferInSize != 0) || \\r
100 (BufferIn != NULL && BufferInSize == 0) || \\r
101 (BufferOut == NULL && *BufferOutSize != 0)) {\r
102 return EFI_INVALID_PARAMETER;\r
103 }\r
104\r
105 if(BufferIn == NULL && BufferInSize == 0) {\r
106 //\r
107 // If RequestBuffer is NULL and RequestSize is 0, and TLS session\r
108 // status is EfiTlsSessionNotStarted, the TLS session will be initiated\r
109 // and the response packet needs to be ClientHello.\r
110 //\r
111 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
112 if (PendingBufferSize == 0) {\r
113 SSL_set_connect_state (TlsConn->Ssl);\r
114 Ret = SSL_do_handshake (TlsConn->Ssl);\r
115 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
116 }\r
117 } else {\r
118 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
119 if (PendingBufferSize == 0) {\r
120 BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);\r
121 Ret = SSL_do_handshake (TlsConn->Ssl);\r
122 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
123 }\r
124 }\r
125\r
126 if (Ret < 1) {\r
127 Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);\r
128 if (Ret == SSL_ERROR_SSL ||\r
129 Ret == SSL_ERROR_SYSCALL ||\r
130 Ret == SSL_ERROR_ZERO_RETURN) {\r
131 DEBUG ((\r
132 DEBUG_ERROR,\r
133 "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",\r
134 __FUNCTION__,\r
135 SSL_get_state (TlsConn->Ssl),\r
136 Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN"\r
137 ));\r
138 DEBUG_CODE_BEGIN ();\r
139 while (TRUE) {\r
140 ErrorCode = ERR_get_error ();\r
141 if (ErrorCode == 0) {\r
142 break;\r
143 }\r
144 DEBUG ((\r
145 DEBUG_ERROR,\r
146 "%a ERROR 0x%x=L%x:F%x:R%x\n",\r
147 __FUNCTION__,\r
148 ErrorCode,\r
149 ERR_GET_LIB (ErrorCode),\r
150 ERR_GET_FUNC (ErrorCode),\r
151 ERR_GET_REASON (ErrorCode)\r
152 ));\r
153 }\r
154 DEBUG_CODE_END ();\r
155 return EFI_ABORTED;\r
156 }\r
157 }\r
158\r
159 if (PendingBufferSize > *BufferOutSize) {\r
160 *BufferOutSize = PendingBufferSize;\r
161 return EFI_BUFFER_TOO_SMALL;\r
162 }\r
163\r
164 if (PendingBufferSize > 0) {\r
165 *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);\r
166 } else {\r
167 *BufferOutSize = 0;\r
168 }\r
169\r
170 return EFI_SUCCESS;\r
171}\r
172\r
173/**\r
174 Handle Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,\r
175 TLS session has errors and the response packet needs to be Alert message based on error type.\r
176\r
177 @param[in] Tls Pointer to the TLS object for state checking.\r
178 @param[in] BufferIn Pointer to the most recently received TLS Alert packet.\r
179 @param[in] BufferInSize Packet size in bytes for the most recently received TLS\r
180 Alert packet.\r
181 @param[out] BufferOut Pointer to the buffer to hold the built packet.\r
182 @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is\r
183 the buffer size provided by the caller. On output, it\r
184 is the buffer size in fact needed to contain the\r
185 packet.\r
186\r
187 @retval EFI_SUCCESS The required TLS packet is built successfully.\r
188 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
189 Tls is NULL.\r
190 BufferIn is NULL but BufferInSize is NOT 0.\r
191 BufferInSize is 0 but BufferIn is NOT NULL.\r
192 BufferOutSize is NULL.\r
193 BufferOut is NULL if *BufferOutSize is not zero.\r
194 @retval EFI_ABORTED An error occurred.\r
195 @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet.\r
196\r
197**/\r
198EFI_STATUS\r
199EFIAPI\r
200TlsHandleAlert (\r
201 IN VOID *Tls,\r
202 IN UINT8 *BufferIn, OPTIONAL\r
203 IN UINTN BufferInSize, OPTIONAL\r
204 OUT UINT8 *BufferOut, OPTIONAL\r
205 IN OUT UINTN *BufferOutSize\r
206 )\r
207{\r
208 TLS_CONNECTION *TlsConn;\r
209 UINTN PendingBufferSize;\r
210 UINT8 *TempBuffer;\r
211 INTN Ret;\r
212\r
213 TlsConn = (TLS_CONNECTION *) Tls;\r
214 PendingBufferSize = 0;\r
215 TempBuffer = NULL;\r
216 Ret = 0;\r
217\r
218 if (TlsConn == NULL || \\r
219 TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
220 BufferOutSize == NULL || \\r
221 (BufferIn == NULL && BufferInSize != 0) || \\r
222 (BufferIn != NULL && BufferInSize == 0) || \\r
223 (BufferOut == NULL && *BufferOutSize != 0)) {\r
224 return EFI_INVALID_PARAMETER;\r
225 }\r
226\r
227 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
228 if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {\r
229 Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);\r
230 if (Ret != (INTN) BufferInSize) {\r
231 return EFI_ABORTED;\r
232 }\r
233\r
234 TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);\r
235\r
236 //\r
237 // ssl3_send_alert() will be called in ssl3_read_bytes() function.\r
238 // TempBuffer is invalid since it's a Alert message, so just ignore it.\r
239 //\r
240 SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);\r
241\r
242 OPENSSL_free (TempBuffer);\r
243\r
244 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
245 }\r
246\r
247 if (PendingBufferSize > *BufferOutSize) {\r
248 *BufferOutSize = PendingBufferSize;\r
249 return EFI_BUFFER_TOO_SMALL;\r
250 }\r
251\r
252 if (PendingBufferSize > 0) {\r
253 *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);\r
254 } else {\r
255 *BufferOutSize = 0;\r
256 }\r
257\r
258 return EFI_SUCCESS;\r
259}\r
260\r
261/**\r
262 Build the CloseNotify packet.\r
263\r
264 @param[in] Tls Pointer to the TLS object for state checking.\r
265 @param[in, out] Buffer Pointer to the buffer to hold the built packet.\r
266 @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is\r
267 the buffer size provided by the caller. On output, it\r
268 is the buffer size in fact needed to contain the\r
269 packet.\r
270\r
271 @retval EFI_SUCCESS The required TLS packet is built successfully.\r
272 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
273 Tls is NULL.\r
274 BufferSize is NULL.\r
275 Buffer is NULL if *BufferSize is not zero.\r
276 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet.\r
277\r
278**/\r
279EFI_STATUS\r
280EFIAPI\r
281TlsCloseNotify (\r
282 IN VOID *Tls,\r
283 IN OUT UINT8 *Buffer,\r
284 IN OUT UINTN *BufferSize\r
285 )\r
286{\r
287 TLS_CONNECTION *TlsConn;\r
288 UINTN PendingBufferSize;\r
289\r
290 TlsConn = (TLS_CONNECTION *) Tls;\r
291 PendingBufferSize = 0;\r
292\r
293 if (TlsConn == NULL || \\r
294 TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
295 BufferSize == NULL || \\r
296 (Buffer == NULL && *BufferSize != 0)) {\r
297 return EFI_INVALID_PARAMETER;\r
298 }\r
299\r
300 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
301 if (PendingBufferSize == 0) {\r
302 //\r
303 // ssl3_send_alert() and ssl3_dispatch_alert() function will be called.\r
304 //\r
305 SSL_shutdown (TlsConn->Ssl);\r
306 PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
307 }\r
308\r
309 if (PendingBufferSize > *BufferSize) {\r
310 *BufferSize = PendingBufferSize;\r
311 return EFI_BUFFER_TOO_SMALL;\r
312 }\r
313\r
314 if (PendingBufferSize > 0) {\r
315 *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32) PendingBufferSize);\r
316 } else {\r
317 *BufferSize = 0;\r
318 }\r
319\r
320 return EFI_SUCCESS;\r
321}\r
322\r
323/**\r
324 Attempts to read bytes from one TLS object and places the data in Buffer.\r
325\r
326 This function will attempt to read BufferSize bytes from the TLS object\r
327 and places the data in Buffer.\r
328\r
329 @param[in] Tls Pointer to the TLS object.\r
330 @param[in,out] Buffer Pointer to the buffer to store the data.\r
331 @param[in] BufferSize The size of Buffer in bytes.\r
332\r
333 @retval >0 The amount of data successfully read from the TLS object.\r
334 @retval <=0 No data was successfully read.\r
335\r
336**/\r
337INTN\r
338EFIAPI\r
339TlsCtrlTrafficOut (\r
340 IN VOID *Tls,\r
341 IN OUT VOID *Buffer,\r
342 IN UINTN BufferSize\r
343 )\r
344{\r
345 TLS_CONNECTION *TlsConn;\r
346\r
347 TlsConn = (TLS_CONNECTION *) Tls;\r
348 if (TlsConn == NULL || TlsConn->OutBio == 0) {\r
349 return -1;\r
350 }\r
351\r
352 //\r
353 // Read and return the amount of data from the BIO.\r
354 //\r
355 return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize);\r
356}\r
357\r
358/**\r
359 Attempts to write data from the buffer to TLS object.\r
360\r
361 This function will attempt to write BufferSize bytes data from the Buffer\r
362 to the TLS object.\r
363\r
364 @param[in] Tls Pointer to the TLS object.\r
365 @param[in] Buffer Pointer to the data buffer.\r
366 @param[in] BufferSize The size of Buffer in bytes.\r
367\r
368 @retval >0 The amount of data successfully written to the TLS object.\r
369 @retval <=0 No data was successfully written.\r
370\r
371**/\r
372INTN\r
373EFIAPI\r
374TlsCtrlTrafficIn (\r
375 IN VOID *Tls,\r
376 IN VOID *Buffer,\r
377 IN UINTN BufferSize\r
378 )\r
379{\r
380 TLS_CONNECTION *TlsConn;\r
381\r
382 TlsConn = (TLS_CONNECTION *) Tls;\r
383 if (TlsConn == NULL || TlsConn->InBio == 0) {\r
384 return -1;\r
385 }\r
386\r
387 //\r
388 // Write and return the amount of data to the BIO.\r
389 //\r
390 return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize);\r
391}\r
392/**\r
393 Attempts to read bytes from the specified TLS connection into the buffer.\r
394\r
395 This function tries to read BufferSize bytes data from the specified TLS\r
396 connection into the Buffer.\r
397\r
398 @param[in] Tls Pointer to the TLS connection for data reading.\r
399 @param[in,out] Buffer Pointer to the data buffer.\r
400 @param[in] BufferSize The size of Buffer in bytes.\r
401\r
402 @retval >0 The read operation was successful, and return value is the\r
403 number of bytes actually read from the TLS connection.\r
404 @retval <=0 The read operation was not successful.\r
405\r
406**/\r
407INTN\r
408EFIAPI\r
409TlsRead (\r
410 IN VOID *Tls,\r
411 IN OUT VOID *Buffer,\r
412 IN UINTN BufferSize\r
413 )\r
414{\r
415 TLS_CONNECTION *TlsConn;\r
416\r
417 TlsConn = (TLS_CONNECTION *) Tls;\r
418 if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
419 return -1;\r
420 }\r
421\r
422 //\r
423 // Read bytes from the specified TLS connection.\r
424 //\r
425 return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize);\r
426}\r
427\r
428/**\r
429 Attempts to write data to a TLS connection.\r
430\r
431 This function tries to write BufferSize bytes data from the Buffer into the\r
432 specified TLS connection.\r
433\r
434 @param[in] Tls Pointer to the TLS connection for data writing.\r
435 @param[in] Buffer Pointer to the data buffer.\r
436 @param[in] BufferSize The size of Buffer in bytes.\r
437\r
438 @retval >0 The write operation was successful, and return value is the\r
439 number of bytes actually written to the TLS connection.\r
440 @retval <=0 The write operation was not successful.\r
441\r
442**/\r
443INTN\r
444EFIAPI\r
445TlsWrite (\r
446 IN VOID *Tls,\r
447 IN VOID *Buffer,\r
448 IN UINTN BufferSize\r
449 )\r
450{\r
451 TLS_CONNECTION *TlsConn;\r
452\r
453 TlsConn = (TLS_CONNECTION *) Tls;\r
454 if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
455 return -1;\r
456 }\r
457\r
458 //\r
459 // Write bytes to the specified TLS connection.\r
460 //\r
461 return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize);\r
462}\r
463\r