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