/src/wolfssl/src/ssl_api_rw.c
Line | Count | Source |
1 | | /* ssl_api_rw.c |
2 | | * |
3 | | * Copyright (C) 2006-2026 wolfSSL Inc. |
4 | | * |
5 | | * This file is part of wolfSSL. |
6 | | * |
7 | | * wolfSSL is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * wolfSSL is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
20 | | */ |
21 | | |
22 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
23 | | |
24 | | #if !defined(WOLFSSL_SSL_API_RW_INCLUDED) |
25 | | #ifndef WOLFSSL_IGNORE_FILE_WARN |
26 | | #warning ssl_api_rw.c does not need to be compiled separately from ssl.c |
27 | | #endif |
28 | | #else |
29 | | |
30 | | #ifndef WOLFCRYPT_ONLY |
31 | | |
32 | | #ifndef NO_TLS |
33 | | |
34 | | #if defined(HAVE_WRITE_DUP) && defined(WOLFSSL_TLS13) |
35 | | /* Take over the TLS 1.3 work delegated by the read side. |
36 | | * |
37 | | * The read side of a write duplicate cannot send, so it records what needs to |
38 | | * be sent in the write duplicate object. Move that state across to the SSL |
39 | | * object of the write side. |
40 | | * |
41 | | * Must be called with ssl->dupWrite->dupMutex held. |
42 | | * |
43 | | * @param [in, out] ssl SSL/TLS object of the write side. |
44 | | * @return 0 on success. |
45 | | * @return Negative on error. |
46 | | */ |
47 | | static int wolfssl_write_dup_take_tls13_work(WOLFSSL* ssl) |
48 | | { |
49 | | int ret = 0; |
50 | | |
51 | | if (IsAtLeastTLSv1_3(ssl->version)) { |
52 | | /* TLS 1.3: if the read side received a KeyUpdate(update_requested) |
53 | | * it cannot respond; send the response from here. */ |
54 | | ssl->keys.keyUpdateRespond |= ssl->dupWrite->keyUpdateRespond; |
55 | | ssl->dupWrite->keyUpdateRespond = 0; |
56 | | #ifdef WOLFSSL_POST_HANDSHAKE_AUTH |
57 | | ssl->postHandshakeAuthPending |= |
58 | | ssl->dupWrite->postHandshakeAuthPending; |
59 | | ssl->dupWrite->postHandshakeAuthPending = 0; |
60 | | if (ssl->postHandshakeAuthPending) { |
61 | | /* Take ownership of the delegated auth state. */ |
62 | | CertReqCtx** tail = &ssl->dupWrite->postHandshakeCertReqCtx; |
63 | | while (*tail != NULL) { |
64 | | tail = &(*tail)->next; |
65 | | } |
66 | | *tail = ssl->certReqCtx; |
67 | | ssl->certReqCtx = ssl->dupWrite->postHandshakeCertReqCtx; |
68 | | ssl->dupWrite->postHandshakeCertReqCtx = NULL; |
69 | | FreeHandshakeHashes(ssl); |
70 | | ssl->hsHashes = ssl->dupWrite->postHandshakeHashState; |
71 | | ssl->dupWrite->postHandshakeHashState = NULL; |
72 | | ssl->options.sendVerify = ssl->dupWrite->postHandshakeSendVerify; |
73 | | ssl->options.sigAlgo = ssl->dupWrite->postHandshakeSigAlgo; |
74 | | ssl->options.hashAlgo = ssl->dupWrite->postHandshakeHashAlgo; |
75 | | } |
76 | | #endif /* WOLFSSL_POST_HANDSHAKE_AUTH */ |
77 | | #ifdef WOLFSSL_DTLS13 |
78 | | if (ssl->options.dtls) { |
79 | | /* Schedule key update to be sent. */ |
80 | | if (ssl->keys.keyUpdateRespond) { |
81 | | ssl->dtls13DoKeyUpdate = 1; |
82 | | } |
83 | | |
84 | | /* Copy over ACKs */ |
85 | | ssl->dtls13Rtx.sendAcks |= ssl->dupWrite->sendAcks; |
86 | | if (ssl->dupWrite->sendAcks) { |
87 | | /* Insert each record number so the |
88 | | * ACK message is properly ordered. */ |
89 | | struct Dtls13RecordNumber* rn; |
90 | | for (rn = ssl->dupWrite->sendAckList; rn != NULL; |
91 | | rn = rn->next) { |
92 | | ret = Dtls13RtxAddAck(ssl, rn->epoch, rn->seq); |
93 | | if (ret != 0) { |
94 | | break; |
95 | | } |
96 | | } |
97 | | /* Clear only on success so no ACKs get dropped */ |
98 | | if (ret == 0) { |
99 | | rn = ssl->dupWrite->sendAckList; |
100 | | ssl->dupWrite->sendAckList = NULL; |
101 | | ssl->dupWrite->sendAcks = 0; |
102 | | while (rn != NULL) { |
103 | | struct Dtls13RecordNumber* next = rn->next; |
104 | | XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); |
105 | | rn = next; |
106 | | } |
107 | | } |
108 | | } |
109 | | |
110 | | /* Remove KeyUpdate record from RTX list. */ |
111 | | if (ssl->dupWrite->keyUpdateAcked) { |
112 | | Dtls13RtxRemoveRecord(ssl, ssl->dupWrite->keyUpdateEpoch, |
113 | | ssl->dupWrite->keyUpdateSeq); |
114 | | } |
115 | | /* Store if KeyUpdate was ACKed. */ |
116 | | ssl->dtls13KeyUpdateAcked |= ssl->dupWrite->keyUpdateAcked; |
117 | | ssl->dupWrite->keyUpdateAcked = 0; |
118 | | } |
119 | | #endif /* WOLFSSL_DTLS13 */ |
120 | | } |
121 | | |
122 | | return ret; |
123 | | } |
124 | | |
125 | | /* Perform the TLS 1.3 work delegated by the read side. |
126 | | * |
127 | | * Must be called after ssl->dupWrite->dupMutex has been released, as the work |
128 | | * performed here sends records. |
129 | | * |
130 | | * @param [in, out] ssl SSL/TLS object of the write side. |
131 | | * @return 0 on success. |
132 | | * @return BAD_MUTEX_E when the write duplicate could not be locked. Returned |
133 | | * as-is by the caller, so ssl->error is not set for it. |
134 | | * @return WOLFSSL_FATAL_ERROR on error. Call wolfSSL_get_error() for the |
135 | | * reason. |
136 | | */ |
137 | | static int wolfssl_write_dup_do_tls13_work(WOLFSSL* ssl) |
138 | | { |
139 | | int ret = 0; |
140 | | |
141 | | if (IsAtLeastTLSv1_3(ssl->version)) { |
142 | | #ifdef WOLFSSL_POST_HANDSHAKE_AUTH |
143 | | /* Read side received a CertificateRequest but couldn't write; |
144 | | * send Certificate+CertificateVerify+Finished from the write |
145 | | * side. */ |
146 | | if (ssl->postHandshakeAuthPending) { |
147 | | /* reset handshake states */ |
148 | | ssl->postHandshakeAuthPending = 0; |
149 | | ssl->options.clientState = CLIENT_HELLO_COMPLETE; |
150 | | ssl->options.connectState = FIRST_REPLY_DONE; |
151 | | ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; |
152 | | ssl->options.processReply = 0; /* doProcessInit */ |
153 | | if (wolfSSL_connect_TLSv13(ssl) != WOLFSSL_SUCCESS) { |
154 | | if ((ssl->error != WC_NO_ERR_TRACE(WANT_WRITE)) && |
155 | | (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))) { |
156 | | WOLFSSL_MSG("Post-handshake auth send failed"); |
157 | | ssl->error = POST_HAND_AUTH_ERROR; |
158 | | } |
159 | | ret = WOLFSSL_FATAL_ERROR; |
160 | | } |
161 | | /* PHA response fully sent: publish the write side's updated |
162 | | * transcript to the read side for the next PHA round. */ |
163 | | else if ((ssl->hsHashes != NULL) && (ssl->dupWrite != NULL)) { |
164 | | if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { |
165 | | ret = BAD_MUTEX_E; |
166 | | } |
167 | | else { |
168 | | int syncRet = InitHandshakeHashesAndCopy(ssl, |
169 | | ssl->hsHashes, |
170 | | &ssl->dupWrite->postHandshakeSyncedHashState); |
171 | | if (syncRet != 0) { |
172 | | /* On failure the copy may have left a partially |
173 | | * initialized transcript. The read side only checks |
174 | | * for non-NULL before consuming it, so drop it here to |
175 | | * avoid hashing onto a corrupt transcript, and surface |
176 | | * the error to the caller. */ |
177 | | Free_HS_Hashes( |
178 | | ssl->dupWrite->postHandshakeSyncedHashState, |
179 | | ssl->heap); |
180 | | ssl->dupWrite->postHandshakeSyncedHashState = NULL; |
181 | | } |
182 | | wc_UnLockMutex(&ssl->dupWrite->dupMutex); |
183 | | if (syncRet != 0) { |
184 | | ssl->error = syncRet; |
185 | | ret = WOLFSSL_FATAL_ERROR; |
186 | | } |
187 | | } |
188 | | } |
189 | | } |
190 | | #endif /* WOLFSSL_POST_HANDSHAKE_AUTH */ |
191 | | |
192 | | if (ret == 0) { |
193 | | #ifdef WOLFSSL_DTLS13 |
194 | | if (ssl->options.dtls) { |
195 | | if (ssl->dtls13KeyUpdateAcked) { |
196 | | ret = DoDtls13KeyUpdateAck(ssl); |
197 | | } |
198 | | ssl->dtls13KeyUpdateAcked = 0; |
199 | | if (ret == 0) { |
200 | | ret = Dtls13DoScheduledWork(ssl); |
201 | | } |
202 | | } |
203 | | else |
204 | | #endif /* WOLFSSL_DTLS13 */ |
205 | | { |
206 | | /* keyUpdateRespond is cleared in SendTls13KeyUpdate. */ |
207 | | if (ssl->keys.keyUpdateRespond) { |
208 | | ret = Tls13UpdateKeys(ssl); |
209 | | } |
210 | | } |
211 | | |
212 | | if (ret != 0) { |
213 | | ssl->error = ret; |
214 | | ret = WOLFSSL_FATAL_ERROR; |
215 | | } |
216 | | } |
217 | | } |
218 | | |
219 | | return ret; |
220 | | } |
221 | | #endif /* HAVE_WRITE_DUP && WOLFSSL_TLS13 */ |
222 | | |
223 | | #ifdef HAVE_WRITE_DUP |
224 | | /* Settle the write duplicate state before application data is sent. |
225 | | * |
226 | | * Takes over the work the read side delegated and surfaces any error it |
227 | | * recorded. Both are held under ssl->dupWrite->dupMutex, so they are collected |
228 | | * with the lock held and acted on once it has been released. |
229 | | * |
230 | | * @param [in, out] ssl SSL/TLS object of the write side. |
231 | | * @return 0 when the write may proceed. |
232 | | * @return BAD_MUTEX_E when the write duplicate could not be locked. |
233 | | * @return WOLFSSL_FATAL_ERROR on error. Call wolfSSL_get_error() for the |
234 | | * reason. |
235 | | */ |
236 | | static int wolfssl_write_dup_prepare(WOLFSSL* ssl) |
237 | | { |
238 | | int ret = 0; |
239 | | |
240 | | /* Lock ssl->dupWrite to gather what needs to be done. */ |
241 | | if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { |
242 | | ret = BAD_MUTEX_E; |
243 | | } |
244 | | else { |
245 | | int dupErr = ssl->dupWrite->dupErr; /* local copy */ |
246 | | |
247 | | #ifdef WOLFSSL_TLS13 |
248 | | ret = wolfssl_write_dup_take_tls13_work(ssl); |
249 | | #endif /* WOLFSSL_TLS13 */ |
250 | | wc_UnLockMutex(&ssl->dupWrite->dupMutex); |
251 | | |
252 | | /* An error from the read side takes precedence over one hit while |
253 | | * taking over its work. */ |
254 | | if (dupErr != 0) { |
255 | | WOLFSSL_MSG("Write dup error from other side"); |
256 | | ret = dupErr; |
257 | | } |
258 | | |
259 | | if (ret != 0) { |
260 | | ssl->error = ret; |
261 | | ret = WOLFSSL_FATAL_ERROR; |
262 | | } |
263 | | #ifdef WOLFSSL_TLS13 |
264 | | else { |
265 | | /* Do the work delegated by the read side. */ |
266 | | ret = wolfssl_write_dup_do_tls13_work(ssl); |
267 | | } |
268 | | #endif /* WOLFSSL_TLS13 */ |
269 | | } |
270 | | |
271 | | return ret; |
272 | | } |
273 | | #endif /* HAVE_WRITE_DUP */ |
274 | | |
275 | | /* Write application data to the peer. |
276 | | * |
277 | | * Performs the handshake when it has not completed. When a write duplicate is |
278 | | * in use, work delegated by the read side, such as sending a key update, is |
279 | | * done here first. |
280 | | * |
281 | | * @param [in, out] ssl SSL/TLS object. |
282 | | * @param [in] data Application data to write. |
283 | | * @param [in] sz Length of data in bytes. |
284 | | * @return Number of bytes written on success. |
285 | | * @return BAD_FUNC_ARG when ssl or data is NULL. |
286 | | * @return WRITE_DUP_WRITE_E when called on the read side of a write |
287 | | * duplicate. |
288 | | * @return BAD_MUTEX_E when the write duplicate could not be locked. Neither |
289 | | * of those two sets ssl->error. |
290 | | * @return WOLFSSL_FATAL_ERROR when the handshake or write fails. Call |
291 | | * wolfSSL_get_error() for the reason. |
292 | | */ |
293 | | static int wolfSSL_write_internal(WOLFSSL* ssl, const void* data, size_t sz) |
294 | 0 | { |
295 | 0 | int ret = 0; |
296 | |
|
297 | 0 | WOLFSSL_ENTER("wolfSSL_write_internal"); |
298 | | |
299 | | /* Validate parameters. Nothing on the way to the send reports zero, so ret |
300 | | * doubles as the "keep going" flag. */ |
301 | 0 | if ((ssl == NULL) || (data == NULL)) { |
302 | 0 | ret = BAD_FUNC_ARG; |
303 | 0 | } |
304 | |
|
305 | | #ifdef WOLFSSL_QUIC |
306 | | if ((ret == 0) && (WOLFSSL_IS_QUIC(ssl))) { |
307 | | WOLFSSL_MSG("SSL_write() on QUIC not allowed"); |
308 | | ret = BAD_FUNC_ARG; |
309 | | } |
310 | | #endif |
311 | |
|
312 | | #ifdef HAVE_WRITE_DUP |
313 | | if ((ret == 0) && (ssl->dupSide == READ_DUP_SIDE)) { |
314 | | WOLFSSL_MSG("Read dup side cannot write"); |
315 | | ret = WRITE_DUP_WRITE_E; |
316 | | } |
317 | | /* Only enter special dupWrite logic when error is cleared. This will help |
318 | | * with handling async data and other edge case errors. */ |
319 | | if ((ret == 0) && (ssl->dupWrite != NULL) && (ssl->error == 0)) { |
320 | | ret = wolfssl_write_dup_prepare(ssl); |
321 | | } |
322 | | #endif |
323 | |
|
324 | 0 | if (ret == 0) { |
325 | 0 | #ifdef HAVE_ERRNO_H |
326 | 0 | errno = 0; |
327 | 0 | #endif |
328 | |
|
329 | | #ifdef OPENSSL_EXTRA |
330 | | if (ssl->CBIS != NULL) { |
331 | | ssl->CBIS(ssl, WOLFSSL_CB_WRITE, WOLFSSL_SUCCESS); |
332 | | ssl->cbmode = WOLFSSL_CB_WRITE; |
333 | | } |
334 | | #endif |
335 | 0 | ret = SendData(ssl, data, sz); |
336 | |
|
337 | 0 | WOLFSSL_LEAVE("wolfSSL_write_internal", ret); |
338 | |
|
339 | 0 | if (ret < 0) { |
340 | 0 | ret = WOLFSSL_FATAL_ERROR; |
341 | 0 | } |
342 | 0 | } |
343 | |
|
344 | 0 | return ret; |
345 | 0 | } |
346 | | |
347 | | /* Write application data to the peer. |
348 | | * |
349 | | * @param [in, out] ssl SSL/TLS object. |
350 | | * @param [in] data Application data to write. |
351 | | * @param [in] sz Length of data in bytes. |
352 | | * @return Number of bytes written on success. |
353 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is negative. |
354 | | * @return WOLFSSL_FATAL_ERROR when the write fails. Call |
355 | | * wolfSSL_get_error() for the reason. |
356 | | */ |
357 | | WOLFSSL_ABI |
358 | | int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) |
359 | 0 | { |
360 | 0 | int ret; |
361 | |
|
362 | 0 | WOLFSSL_ENTER("wolfSSL_write"); |
363 | | |
364 | | /* Validate parameter. */ |
365 | 0 | if (sz < 0) { |
366 | 0 | ret = BAD_FUNC_ARG; |
367 | 0 | } |
368 | 0 | else { |
369 | 0 | ret = wolfSSL_write_internal(ssl, data, (size_t)sz); |
370 | 0 | } |
371 | |
|
372 | 0 | return ret; |
373 | 0 | } |
374 | | |
375 | | /* Inject data into the input buffer as if it was received from the peer. |
376 | | * |
377 | | * Used when the application reads the transport itself. |
378 | | * |
379 | | * @param [in, out] ssl SSL/TLS object. |
380 | | * @param [in] data Data to inject. |
381 | | * @param [in] sz Length of data in bytes. |
382 | | * @return WOLFSSL_SUCCESS on success. |
383 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is not positive. |
384 | | * @return BUFFER_ERROR when the input buffer lengths are inconsistent. |
385 | | * @return APP_DATA_READY when the input buffer must be grown while there is |
386 | | * application data left to read. |
387 | | * @return Negative error code from growing the input buffer, such as |
388 | | * MEMORY_E. |
389 | | */ |
390 | | int wolfSSL_inject(WOLFSSL* ssl, const void* data, int sz) |
391 | 0 | { |
392 | 0 | int ret = WOLFSSL_SUCCESS; |
393 | 0 | int usedLength = 0; |
394 | 0 | int maxLength = 0; |
395 | 0 | bufferStatic* in = NULL; |
396 | |
|
397 | 0 | WOLFSSL_ENTER("wolfSSL_inject"); |
398 | | |
399 | | /* Validate parameters. */ |
400 | 0 | if ((ssl == NULL) || (data == NULL) || (sz <= 0)) { |
401 | 0 | ret = BAD_FUNC_ARG; |
402 | 0 | } |
403 | |
|
404 | 0 | if (ret == WOLFSSL_SUCCESS) { |
405 | 0 | in = &ssl->buffers.inputBuffer; |
406 | | |
407 | | /* Order the unsigned fields first. Subtracting a larger value wraps |
408 | | * and can land back in the positive int range. */ |
409 | 0 | if ((in->idx > in->length) || (in->length > in->bufferSize)) { |
410 | 0 | ret = BUFFER_ERROR; |
411 | 0 | } |
412 | 0 | else { |
413 | 0 | usedLength = (int)(in->length - in->idx); |
414 | | /* Free space past all buffered data, where new data is appended. */ |
415 | 0 | maxLength = (int)(in->bufferSize - in->length); |
416 | |
|
417 | 0 | if ((usedLength < 0) || (maxLength < 0)) { |
418 | 0 | ret = BUFFER_ERROR; |
419 | 0 | } |
420 | 0 | } |
421 | 0 | } |
422 | |
|
423 | 0 | if ((ret == WOLFSSL_SUCCESS) && (sz > maxLength)) { |
424 | | /* Need to make space */ |
425 | 0 | if (ssl->buffers.clearOutputBuffer.length > 0) { |
426 | | /* clearOutputBuffer points into so reallocating inputBuffer |
427 | | * will invalidate clearOutputBuffer and lose app data */ |
428 | 0 | WOLFSSL_MSG( |
429 | 0 | "Can't inject while there is application data to read"); |
430 | 0 | ret = APP_DATA_READY; |
431 | 0 | } |
432 | 0 | else { |
433 | | /* Compacts the unconsumed data, leaving idx 0 and length |
434 | | * usedLength. */ |
435 | 0 | int growRet = GrowInputBuffer(ssl, sz, usedLength); |
436 | |
|
437 | 0 | if (growRet < 0) { |
438 | 0 | ret = growRet; |
439 | 0 | } |
440 | 0 | } |
441 | 0 | } |
442 | |
|
443 | 0 | if (ret == WOLFSSL_SUCCESS) { |
444 | 0 | XMEMCPY(in->buffer + in->length, data, (size_t)sz); |
445 | 0 | in->length += (word32)sz; |
446 | 0 | } |
447 | |
|
448 | 0 | return ret; |
449 | 0 | } |
450 | | |
451 | | /* Write application data to the peer and return the number of bytes written. |
452 | | * |
453 | | * @param [in, out] ssl SSL/TLS object. |
454 | | * @param [in] data Application data to write. |
455 | | * @param [in] sz Length of data in bytes. |
456 | | * @param [out] wr Number of bytes written. May be NULL. |
457 | | * @return WOLFSSL_SUCCESS on success. |
458 | | * @return BAD_FUNC_ARG when ssl is NULL. |
459 | | * @return WOLFSSL_FAILURE when the write fails. Call wolfSSL_get_error() for |
460 | | * the reason. |
461 | | */ |
462 | | int wolfSSL_write_ex(WOLFSSL* ssl, const void* data, size_t sz, size_t* wr) |
463 | 0 | { |
464 | 0 | int ret; |
465 | |
|
466 | 0 | if (wr != NULL) { |
467 | 0 | *wr = 0; |
468 | 0 | } |
469 | | |
470 | | /* Validate parameter, matching wolfSSL_read_ex() and the rest of the |
471 | | * file. Reported as an error code rather than the 0 used for "nothing |
472 | | * was written", which a caller cannot tell from a short write. */ |
473 | 0 | if (ssl == NULL) { |
474 | 0 | ret = BAD_FUNC_ARG; |
475 | 0 | } |
476 | 0 | else { |
477 | 0 | ret = wolfSSL_write_internal(ssl, data, sz); |
478 | 0 | if (ret >= 0) { |
479 | 0 | if (wr != NULL) { |
480 | 0 | *wr = (size_t)ret; |
481 | 0 | } |
482 | | |
483 | | /* handle partial write cases, if not set then a partial write is |
484 | | * considered a failure case, or if set and ret is 0 then is a |
485 | | * fail */ |
486 | 0 | if ((ret == 0) && (ssl->options.partialWrite)) { |
487 | 0 | ret = 0; |
488 | 0 | } |
489 | 0 | else if (((size_t)ret < sz) && (!ssl->options.partialWrite)) { |
490 | 0 | ret = 0; |
491 | 0 | } |
492 | 0 | else { |
493 | | /* wrote out all application data, or wrote out 1 byte or more |
494 | | * with partial write flag set */ |
495 | 0 | ret = 1; |
496 | 0 | } |
497 | 0 | } |
498 | 0 | else { |
499 | 0 | ret = 0; |
500 | 0 | } |
501 | 0 | } |
502 | |
|
503 | 0 | return ret; |
504 | 0 | } |
505 | | |
506 | | /* Read application data from the peer. |
507 | | * |
508 | | * Performs the handshake when it has not completed. |
509 | | * |
510 | | * @param [in, out] ssl SSL/TLS object. |
511 | | * @param [out] data Buffer to hold application data. |
512 | | * @param [in] sz Length of buffer in bytes. |
513 | | * @param [in] peek When 1, data is not removed from the input buffer. |
514 | | * @return Number of bytes read on success. |
515 | | * @return 0 when the peer has closed the connection. |
516 | | * @return BAD_FUNC_ARG when ssl or data is NULL. |
517 | | * @return WRITE_DUP_READ_E when called on the write side of a write |
518 | | * duplicate. ssl->error is not set for it. |
519 | | * @return WOLFSSL_FATAL_ERROR when the handshake or read fails. Call |
520 | | * wolfSSL_get_error() for the reason. |
521 | | */ |
522 | | static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, size_t sz, int peek) |
523 | 0 | { |
524 | 0 | int ret = 0; |
525 | | /* A separate flag is needed rather than gating on ret: the OpenSSL |
526 | | * shutdown simulation below reports WOLFSSL_FAILURE, which is zero. */ |
527 | 0 | int done = 0; |
528 | |
|
529 | 0 | WOLFSSL_ENTER("wolfSSL_read_internal"); |
530 | | |
531 | | /* Validate parameters. */ |
532 | 0 | if ((ssl == NULL) || (data == NULL)) { |
533 | 0 | ret = BAD_FUNC_ARG; |
534 | 0 | done = 1; |
535 | 0 | } |
536 | |
|
537 | | #ifdef WOLFSSL_QUIC |
538 | | if ((!done) && (WOLFSSL_IS_QUIC(ssl))) { |
539 | | WOLFSSL_MSG("SSL_read() on QUIC not allowed"); |
540 | | ret = BAD_FUNC_ARG; |
541 | | done = 1; |
542 | | } |
543 | | #endif |
544 | | #if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA) |
545 | | /* This additional logic is meant to simulate following openSSL behavior: |
546 | | * After bidirectional SSL_shutdown complete, SSL_read returns 0 and |
547 | | * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN. |
548 | | * This behavior is used to know the disconnect of the underlying |
549 | | * transport layer. |
550 | | * |
551 | | * In this logic, CBIORecv is called with a read size of 0 to check the |
552 | | * transport layer status. It also returns WOLFSSL_FAILURE so that |
553 | | * SSL_read does not return a positive number on failure. |
554 | | */ |
555 | | |
556 | | /* make sure bidirectional TLS shutdown completes */ |
557 | | if ((!done) && ((ssl->error == WOLFSSL_ERROR_SYSCALL) || |
558 | | (ssl->options.shutdownDone))) { |
559 | | /* ask the underlying transport the connection is closed */ |
560 | | if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx) |
561 | | == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_CLOSE)) |
562 | | { |
563 | | ssl->options.isClosed = 1; |
564 | | ssl->error = WOLFSSL_ERROR_ZERO_RETURN; |
565 | | } |
566 | | ret = WOLFSSL_FAILURE; |
567 | | done = 1; |
568 | | } |
569 | | #endif |
570 | |
|
571 | | #ifdef HAVE_WRITE_DUP |
572 | | if ((!done) && (ssl->dupWrite != NULL) && |
573 | | (ssl->dupSide == WRITE_DUP_SIDE)) { |
574 | | WOLFSSL_MSG("Write dup side cannot read"); |
575 | | ret = WRITE_DUP_READ_E; |
576 | | done = 1; |
577 | | } |
578 | | #endif |
579 | |
|
580 | 0 | if (!done) { |
581 | 0 | #ifdef HAVE_ERRNO_H |
582 | 0 | errno = 0; |
583 | 0 | #endif |
584 | |
|
585 | 0 | ret = ReceiveData(ssl, (byte*)data, sz, peek); |
586 | |
|
587 | | #ifdef HAVE_WRITE_DUP |
588 | | if (ssl->dupWrite != NULL) { |
589 | | if ((ssl->error != 0) && |
590 | | (ssl->error != WC_NO_ERR_TRACE(WANT_READ)) |
591 | | #ifdef WOLFSSL_ASYNC_CRYPT |
592 | | && (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) |
593 | | #endif |
594 | | ) { |
595 | | int notifyErr; |
596 | | |
597 | | WOLFSSL_MSG("Notifying write side of fatal read error"); |
598 | | notifyErr = NotifyWriteSide(ssl, ssl->error); |
599 | | if (notifyErr < 0) { |
600 | | ret = ssl->error = notifyErr; |
601 | | } |
602 | | } |
603 | | } |
604 | | #endif |
605 | |
|
606 | 0 | WOLFSSL_LEAVE("wolfSSL_read_internal", ret); |
607 | |
|
608 | 0 | if (ret < 0) { |
609 | 0 | ret = WOLFSSL_FATAL_ERROR; |
610 | 0 | } |
611 | 0 | } |
612 | |
|
613 | 0 | return ret; |
614 | 0 | } |
615 | | |
616 | | /* Read application data from the peer without removing it. |
617 | | * |
618 | | * The same data is returned by the next call to wolfSSL_read(). |
619 | | * |
620 | | * @param [in, out] ssl SSL/TLS object. |
621 | | * @param [out] data Buffer to hold application data. |
622 | | * @param [in] sz Length of buffer in bytes. |
623 | | * @return Number of bytes read on success. |
624 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is negative. |
625 | | * @return WOLFSSL_FATAL_ERROR when the read fails. |
626 | | */ |
627 | | int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz) |
628 | 0 | { |
629 | 0 | int ret; |
630 | |
|
631 | 0 | WOLFSSL_ENTER("wolfSSL_peek"); |
632 | | |
633 | | /* Validate parameter. */ |
634 | 0 | if (sz < 0) { |
635 | 0 | ret = BAD_FUNC_ARG; |
636 | 0 | } |
637 | 0 | else { |
638 | 0 | ret = wolfSSL_read_internal(ssl, data, (size_t)sz, TRUE); |
639 | 0 | } |
640 | |
|
641 | 0 | return ret; |
642 | 0 | } |
643 | | |
644 | | /* Read application data from the peer. |
645 | | * |
646 | | * @param [in, out] ssl SSL/TLS object. |
647 | | * @param [out] data Buffer to hold application data. |
648 | | * @param [in] sz Length of buffer in bytes. |
649 | | * @return Number of bytes read on success. |
650 | | * @return 0 when the peer has closed the connection. |
651 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is negative. |
652 | | * @return WOLFSSL_FATAL_ERROR when the read fails. Call wolfSSL_get_error() |
653 | | * for the reason. |
654 | | */ |
655 | | WOLFSSL_ABI |
656 | | int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) |
657 | 0 | { |
658 | 0 | int ret; |
659 | |
|
660 | 0 | WOLFSSL_ENTER("wolfSSL_read"); |
661 | | |
662 | | /* Validate parameters. */ |
663 | 0 | if (sz < 0) { |
664 | 0 | ret = BAD_FUNC_ARG; |
665 | 0 | } |
666 | | #ifdef OPENSSL_EXTRA |
667 | | else if (ssl == NULL) { |
668 | | ret = BAD_FUNC_ARG; |
669 | | } |
670 | | #endif |
671 | 0 | else { |
672 | | #ifdef OPENSSL_EXTRA |
673 | | if (ssl->CBIS != NULL) { |
674 | | ssl->CBIS(ssl, WOLFSSL_CB_READ, WOLFSSL_SUCCESS); |
675 | | ssl->cbmode = WOLFSSL_CB_READ; |
676 | | } |
677 | | #endif |
678 | 0 | ret = wolfSSL_read_internal(ssl, data, (size_t)sz, FALSE); |
679 | 0 | } |
680 | |
|
681 | 0 | return ret; |
682 | 0 | } |
683 | | |
684 | | /* Read application data from the peer and report whether any was read. |
685 | | * |
686 | | * @param [in, out] ssl SSL/TLS object. |
687 | | * @param [out] data Buffer to hold application data. |
688 | | * @param [in] sz Length of buffer in bytes. |
689 | | * @param [out] rd Number of bytes read. May be NULL. Only set when |
690 | | * data was read. |
691 | | * @return 1 when application data was read. |
692 | | * @return 0 when no application data was read. Call wolfSSL_get_error() for |
693 | | * the reason. |
694 | | * @return BAD_FUNC_ARG when ssl is NULL. |
695 | | */ |
696 | | int wolfSSL_read_ex(WOLFSSL* ssl, void* data, size_t sz, size_t* rd) |
697 | 0 | { |
698 | 0 | int ret; |
699 | | |
700 | | /* Validate parameter. Checked unconditionally so the guarded branch does |
701 | | * not leave a standalone block. */ |
702 | 0 | if (ssl == NULL) { |
703 | 0 | ret = BAD_FUNC_ARG; |
704 | 0 | } |
705 | 0 | else { |
706 | | #ifdef OPENSSL_EXTRA |
707 | | if (ssl->CBIS != NULL) { |
708 | | ssl->CBIS(ssl, WOLFSSL_CB_READ, WOLFSSL_SUCCESS); |
709 | | ssl->cbmode = WOLFSSL_CB_READ; |
710 | | } |
711 | | #endif |
712 | 0 | ret = wolfSSL_read_internal(ssl, data, sz, FALSE); |
713 | |
|
714 | 0 | if ((ret > 0) && (rd != NULL)) { |
715 | 0 | *rd = (size_t)ret; |
716 | 0 | } |
717 | |
|
718 | 0 | ret = (ret > 0) ? 1 : 0; |
719 | 0 | } |
720 | |
|
721 | 0 | return ret; |
722 | 0 | } |
723 | | |
724 | | #ifndef WOLFSSL_LEANPSK |
725 | | |
726 | | /* Write application data to the peer with socket flags. |
727 | | * |
728 | | * Flags are set on the socket for the write and restored afterwards. |
729 | | * |
730 | | * @param [in, out] ssl SSL/TLS object. |
731 | | * @param [in] data Application data to write. |
732 | | * @param [in] sz Length of data in bytes. |
733 | | * @param [in] flags Flags to pass to the send call. |
734 | | * @return Number of bytes written on success. |
735 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is negative. |
736 | | * @return WOLFSSL_FATAL_ERROR when the write fails. |
737 | | */ |
738 | | int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags) |
739 | 0 | { |
740 | 0 | int ret; |
741 | |
|
742 | 0 | WOLFSSL_ENTER("wolfSSL_send"); |
743 | | |
744 | | /* Validate parameters. */ |
745 | 0 | if ((ssl == NULL) || (data == NULL) || (sz < 0)) { |
746 | 0 | ret = BAD_FUNC_ARG; |
747 | 0 | } |
748 | 0 | else { |
749 | 0 | int oldFlags = ssl->wflags; |
750 | |
|
751 | 0 | ssl->wflags = flags; |
752 | 0 | ret = wolfSSL_write(ssl, data, sz); |
753 | 0 | ssl->wflags = oldFlags; |
754 | |
|
755 | 0 | WOLFSSL_LEAVE("wolfSSL_send", ret); |
756 | 0 | } |
757 | |
|
758 | 0 | return ret; |
759 | 0 | } |
760 | | |
761 | | /* Read application data from the peer with socket flags. |
762 | | * |
763 | | * Flags are set on the socket for the read and restored afterwards. |
764 | | * |
765 | | * @param [in, out] ssl SSL/TLS object. |
766 | | * @param [out] data Buffer to hold application data. |
767 | | * @param [in] sz Length of buffer in bytes. |
768 | | * @param [in] flags Flags to pass to the recv call. |
769 | | * @return Number of bytes read on success. |
770 | | * @return BAD_FUNC_ARG when ssl or data is NULL, or sz is negative. |
771 | | * @return WOLFSSL_FATAL_ERROR when the read fails. |
772 | | */ |
773 | | int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags) |
774 | 0 | { |
775 | 0 | int ret; |
776 | |
|
777 | 0 | WOLFSSL_ENTER("wolfSSL_recv"); |
778 | | |
779 | | /* Validate parameters. */ |
780 | 0 | if ((ssl == NULL) || (data == NULL) || (sz < 0)) { |
781 | 0 | ret = BAD_FUNC_ARG; |
782 | 0 | } |
783 | 0 | else { |
784 | 0 | int oldFlags = ssl->rflags; |
785 | |
|
786 | 0 | ssl->rflags = flags; |
787 | 0 | ret = wolfSSL_read(ssl, data, sz); |
788 | 0 | ssl->rflags = oldFlags; |
789 | |
|
790 | 0 | WOLFSSL_LEAVE("wolfSSL_recv", ret); |
791 | 0 | } |
792 | |
|
793 | 0 | return ret; |
794 | 0 | } |
795 | | #endif |
796 | | |
797 | | /* Send a user_canceled alert to the peer and shut down the connection. |
798 | | * |
799 | | * @param [in, out] ssl SSL/TLS object. |
800 | | * @return WOLFSSL_SUCCESS on success. |
801 | | * @return WOLFSSL_SHUTDOWN_NOT_DONE when the shutdown is not complete. |
802 | | * @return WOLFSSL_FAILURE when ssl is NULL or sending the alert fails. |
803 | | */ |
804 | | int wolfSSL_SendUserCanceled(WOLFSSL* ssl) |
805 | 0 | { |
806 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
807 | 0 | WOLFSSL_ENTER("wolfSSL_SendUserCanceled"); |
808 | |
|
809 | 0 | if (ssl != NULL) { |
810 | 0 | ssl->error = SendAlert(ssl, alert_warning, user_canceled); |
811 | 0 | if (ssl->error < 0) { |
812 | 0 | WOLFSSL_ERROR(ssl->error); |
813 | 0 | } |
814 | 0 | else { |
815 | 0 | ret = wolfSSL_shutdown(ssl); |
816 | 0 | } |
817 | 0 | } |
818 | |
|
819 | 0 | WOLFSSL_LEAVE("wolfSSL_SendUserCanceled", ret); |
820 | |
|
821 | 0 | return ret; |
822 | 0 | } |
823 | | |
824 | | /* Flush an alert still sitting in the output buffer. |
825 | | * |
826 | | * A previous call may have left the close_notify alert buffered when the |
827 | | * transport reported WANT_WRITE. Get it out before doing anything else. |
828 | | * |
829 | | * @param [in, out] ssl SSL/TLS object. |
830 | | * @param [in, out] ret Result for wolfSSL_shutdown() to return. Set only on |
831 | | * the paths that reach a decision; on the others it is |
832 | | * left as the caller initialized it. Returning 0 while |
833 | | * assigning WOLFSSL_SHUTDOWN_NOT_DONE would break the |
834 | | * caller: it treats an undecided result as "no |
835 | | * close_notify can ever be sent" and converts it to a |
836 | | * failure. Every path here that reports "call again" |
837 | | * therefore returns 1. |
838 | | * @return 1 when no later step of the shutdown may run. |
839 | | * @return 0 when the caller carries on with the rest of the shutdown. The |
840 | | * result may already have been decided: the exchange can complete |
841 | | * here, and the steps that follow then leave it alone. |
842 | | */ |
843 | | static int wolfssl_shutdown_flush_alert(WOLFSSL* ssl, int* ret) |
844 | 0 | { |
845 | 0 | int done = 0; |
846 | |
|
847 | 0 | if ((ssl->error == WC_NO_ERR_TRACE(WANT_WRITE)) && |
848 | 0 | (ssl->buffers.outputBuffer.length > 0)) { |
849 | 0 | int rc = SendBuffered(ssl); |
850 | |
|
851 | 0 | if (rc != 0) { |
852 | 0 | ssl->error = rc; |
853 | | /* for error tracing */ |
854 | 0 | if (rc != WC_NO_ERR_TRACE(WANT_WRITE)) { |
855 | 0 | WOLFSSL_ERROR(rc); |
856 | 0 | } |
857 | | /* The reason has been traced above - don't trace the return |
858 | | * value as well. */ |
859 | 0 | *ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); |
860 | 0 | done = 1; |
861 | 0 | } |
862 | 0 | else { |
863 | 0 | ssl->error = WOLFSSL_ERROR_NONE; |
864 | | /* we succeeded in sending the alert now */ |
865 | 0 | if (ssl->options.sentNotify) { |
866 | | /* just after we send the alert, if we didn't receive the |
867 | | * alert from the other peer yet, return |
868 | | * WOLFSSL_SHUTDOWN_NOT_DONE */ |
869 | 0 | if (!ssl->options.closeNotify) { |
870 | 0 | *ret = WOLFSSL_SHUTDOWN_NOT_DONE; |
871 | 0 | done = 1; |
872 | 0 | } |
873 | 0 | else { |
874 | 0 | ssl->options.shutdownDone = 1; |
875 | 0 | *ret = WOLFSSL_SUCCESS; |
876 | 0 | } |
877 | 0 | } |
878 | 0 | } |
879 | 0 | } |
880 | |
|
881 | 0 | return done; |
882 | 0 | } |
883 | | |
884 | | /* Send the close_notify alert to the peer. |
885 | | * |
886 | | * Not being able to send it right away is not an error - the alert is left in |
887 | | * the output buffer and goes out eventually. |
888 | | * |
889 | | * @param [in, out] ssl SSL/TLS object. |
890 | | * @param [in, out] ret Result for wolfSSL_shutdown() to return. Set only on |
891 | | * the paths that reach a decision; on the others it is |
892 | | * left as the caller initialized it. As in |
893 | | * wolfssl_shutdown_flush_alert(), a path that reports |
894 | | * "call again" must return 1 - the caller reads an |
895 | | * undecided result as "no close_notify can ever be |
896 | | * sent" and turns it into a failure. |
897 | | * @return 1 when no later step of the shutdown may run. |
898 | | * @return 0 when the caller carries on with the rest of the shutdown. The |
899 | | * result may already have been decided: the exchange can complete |
900 | | * here, and the steps that follow then leave it alone. |
901 | | */ |
902 | | static int wolfssl_shutdown_send_close_notify(WOLFSSL* ssl, int* ret) |
903 | 0 | { |
904 | 0 | int done = 0; |
905 | | |
906 | | /* try to send close notify, not an error if can't */ |
907 | 0 | if ((!ssl->options.isClosed) && (!ssl->options.connReset) && |
908 | 0 | (!ssl->options.sentNotify)) { |
909 | 0 | ssl->error = SendAlert(ssl, alert_warning, close_notify); |
910 | | |
911 | | /* the alert is now sent or sitting in the buffer, |
912 | | * where will be sent eventually */ |
913 | 0 | if ((ssl->error == 0) || |
914 | 0 | (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))) { |
915 | 0 | ssl->options.sentNotify = 1; |
916 | 0 | } |
917 | |
|
918 | 0 | if (ssl->error < 0) { |
919 | 0 | WOLFSSL_ERROR(ssl->error); |
920 | | /* The reason has been traced above - don't trace the return |
921 | | * value as well. */ |
922 | 0 | *ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); |
923 | 0 | done = 1; |
924 | 0 | } |
925 | 0 | else if (ssl->options.closeNotify) { |
926 | 0 | *ret = WOLFSSL_SUCCESS; |
927 | 0 | ssl->options.shutdownDone = 1; |
928 | 0 | } |
929 | 0 | else { |
930 | 0 | *ret = WOLFSSL_SHUTDOWN_NOT_DONE; |
931 | 0 | done = 1; |
932 | 0 | } |
933 | 0 | } |
934 | |
|
935 | 0 | return done; |
936 | 0 | } |
937 | | |
938 | | /* Wait for the peer's close_notify alert to complete a bidirectional shutdown. |
939 | | * |
940 | | * Called when this side has sent its close_notify but has not seen the |
941 | | * peer's, i.e. wolfSSL_shutdown() called again. |
942 | | * |
943 | | * @param [in, out] ssl SSL/TLS object. |
944 | | * @return WOLFSSL_SUCCESS when the shutdown is complete. |
945 | | * @return WOLFSSL_SHUTDOWN_NOT_DONE when the peer's alert has not arrived. |
946 | | * @return WOLFSSL_FATAL_ERROR on error. Call wolfSSL_get_error() for the |
947 | | * reason. |
948 | | */ |
949 | | static int wolfssl_shutdown_recv_close_notify(WOLFSSL* ssl) |
950 | 0 | { |
951 | 0 | int ret; |
952 | | |
953 | | /* If there is still buffered application data waiting to be read, do not |
954 | | * process incoming records here. clearOutputBuffer.buffer points into |
955 | | * inputBuffer, and ProcessReply() may call GrowInputBuffer(), which frees |
956 | | * and reallocates inputBuffer. Require the pending data to be drained |
957 | | * first. */ |
958 | 0 | if (ssl->buffers.clearOutputBuffer.length > 0) { |
959 | 0 | WOLFSSL_MSG("Pending application data, read it before shutdown"); |
960 | 0 | ret = WOLFSSL_SHUTDOWN_NOT_DONE; |
961 | 0 | } |
962 | 0 | else { |
963 | 0 | ret = ProcessReply(ssl); |
964 | 0 | if ((ret == WC_NO_ERR_TRACE(ZERO_RETURN)) || |
965 | 0 | (ret == WC_NO_ERR_TRACE(SOCKET_ERROR_E))) { |
966 | | /* simulate OpenSSL behavior */ |
967 | 0 | ssl->options.shutdownDone = 1; |
968 | | /* Clear error */ |
969 | 0 | ssl->error = WOLFSSL_ERROR_NONE; |
970 | 0 | ret = WOLFSSL_SUCCESS; |
971 | 0 | } |
972 | 0 | else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) { |
973 | 0 | ret = WOLFSSL_FATAL_ERROR; |
974 | 0 | } |
975 | 0 | else if (ret == WC_NO_ERR_TRACE(WANT_READ)) { |
976 | 0 | ssl->error = ret; |
977 | 0 | ret = WOLFSSL_FATAL_ERROR; |
978 | 0 | } |
979 | 0 | else if (ssl->error == WOLFSSL_ERROR_NONE) { |
980 | 0 | ret = WOLFSSL_SHUTDOWN_NOT_DONE; |
981 | 0 | } |
982 | 0 | else { |
983 | 0 | WOLFSSL_ERROR(ssl->error); |
984 | 0 | ret = WOLFSSL_FATAL_ERROR; |
985 | 0 | } |
986 | 0 | } |
987 | |
|
988 | 0 | return ret; |
989 | 0 | } |
990 | | |
991 | | /* Shut the connection down by exchanging close_notify alerts with the peer. |
992 | | * |
993 | | * Call repeatedly while WOLFSSL_SHUTDOWN_NOT_DONE is returned to complete a |
994 | | * bidirectional shutdown. |
995 | | * |
996 | | * @param [in, out] ssl SSL/TLS object. |
997 | | * @return WOLFSSL_SUCCESS when the shutdown is complete. |
998 | | * @return WOLFSSL_SHUTDOWN_NOT_DONE when the peer's close_notify has not |
999 | | * been received yet. |
1000 | | * @return SSL_SHUTDOWN_ALREADY_DONE_E when the connection was already closed |
1001 | | * and WOLFSSL_SHUTDOWNONCE is defined. |
1002 | | * @return WOLFSSL_FATAL_ERROR when ssl is NULL or on error. Call |
1003 | | * wolfSSL_get_error() for the reason. |
1004 | | * |
1005 | | * SOCKET_PEER_CLOSED_E is reported when the connection was already |
1006 | | * closed or reset and no close_notify was ever sent, so the exchange |
1007 | | * can never complete. That covers this side closing by sending a fatal |
1008 | | * alert as much as the peer going away, and it is only used when no |
1009 | | * more specific error has been recorded. Under OPENSSL_EXTRA |
1010 | | * wolfSSL_get_error() reports it as WOLFSSL_ERROR_SYSCALL, so a locally |
1011 | | * aborted connection surfaces as a syscall error. This case used to return 0, |
1012 | | * which is WOLFSSL_SHUTDOWN_NOT_DONE under WOLFSSL_ERROR_CODE_OPENSSL, |
1013 | | * so a caller looping while the result is 0 never terminated. |
1014 | | * |
1015 | | * Recording it also appends to the OpenSSL error queue where one is built in |
1016 | | * (WOLFSSL_HAVE_ERROR_QUEUE, which OPENSSL_ALL, OPENSSL_EXTRA, WOLFSSL_NGINX |
1017 | | * and WOLFSSL_HAPROXY all enable), so an application that inspects the queue |
1018 | | * after tearing down an already-aborted connection now finds an entry where |
1019 | | * it previously found none. Clear it with wolfSSL_ERR_clear_error() if |
1020 | | * leftover entries matter to the caller. |
1021 | | */ |
1022 | | WOLFSSL_ABI |
1023 | | int wolfSSL_shutdown(WOLFSSL* ssl) |
1024 | 0 | { |
1025 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); |
1026 | |
|
1027 | 0 | WOLFSSL_ENTER("wolfSSL_shutdown"); |
1028 | | |
1029 | | /* Validate parameter. */ |
1030 | 0 | if (ssl == NULL) { |
1031 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1032 | 0 | } |
1033 | 0 | else if (ssl->options.quietShutdown) { |
1034 | 0 | WOLFSSL_MSG("quiet shutdown, no close notify sent"); |
1035 | 0 | ret = WOLFSSL_SUCCESS; |
1036 | 0 | } |
1037 | 0 | else { |
1038 | 0 | int done; |
1039 | | |
1040 | | /* Try to flush the buffer first, it might contain the alert */ |
1041 | 0 | done = wolfssl_shutdown_flush_alert(ssl, &ret); |
1042 | 0 | if (!done) { |
1043 | 0 | done = wolfssl_shutdown_send_close_notify(ssl, &ret); |
1044 | 0 | } |
1045 | |
|
1046 | | #ifdef WOLFSSL_SHUTDOWNONCE |
1047 | | if ((!done) && |
1048 | | ((ssl->options.isClosed) || (ssl->options.connReset))) { |
1049 | | /* Shutdown has already occurred. |
1050 | | * Caller is free to ignore this error. */ |
1051 | | ret = SSL_SHUTDOWN_ALREADY_DONE_E; |
1052 | | done = 1; |
1053 | | } |
1054 | | #endif |
1055 | | |
1056 | | /* wolfSSL_shutdown called again for bidirectional shutdown */ |
1057 | 0 | if ((!done) && (ssl->options.sentNotify) && |
1058 | 0 | (!ssl->options.closeNotify)) { |
1059 | 0 | ret = wolfssl_shutdown_recv_close_notify(ssl); |
1060 | 0 | } |
1061 | 0 | else if ((!done) && (!ssl->options.sentNotify) && |
1062 | 0 | (ret != WOLFSSL_SUCCESS)) { |
1063 | | /* No close_notify was sent and the exchange has not completed by |
1064 | | * other means, so it never will. Record why when nothing else |
1065 | | * has, so the caller is not left with a failure and no error to |
1066 | | * query, but keep any more specific error already set. |
1067 | | * |
1068 | | * A send can report failure without setting sentNotify and still |
1069 | | * leave the shutdown complete: SendAlert() returns a positive |
1070 | | * value when a QUIC send_alert callback fails, which is neither |
1071 | | * the success nor the negative-error case the helper checks, and |
1072 | | * the peer's close_notify may already have arrived. Leave a |
1073 | | * success decided above alone. |
1074 | | * |
1075 | | * One case is left out: being called again once the exchange has |
1076 | | * completed, with both notifies seen. Nothing has gone wrong |
1077 | | * there, so no error is recorded, and the call still reports |
1078 | | * failure. Only reachable where wolfSSL_clear() below is not |
1079 | | * compiled in to reset the flags after a success. */ |
1080 | 0 | WOLFSSL_MSG("Connection closed before close_notify was sent"); |
1081 | 0 | if (ssl->error == WOLFSSL_ERROR_NONE) { |
1082 | 0 | ssl->error = SOCKET_PEER_CLOSED_E; |
1083 | | /* Trace it as the other failing paths here do - recording the |
1084 | | * error without this leaves nothing in the error trace. */ |
1085 | 0 | WOLFSSL_ERROR(ssl->error); |
1086 | 0 | } |
1087 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1088 | 0 | } |
1089 | 0 | } |
1090 | |
|
1091 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
1092 | | /* reset WOLFSSL structure state for possible reuse */ |
1093 | | if (ret == WOLFSSL_SUCCESS) { |
1094 | | if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) { |
1095 | | WOLFSSL_MSG("could not clear WOLFSSL"); |
1096 | | ret = WOLFSSL_FATAL_ERROR; |
1097 | | } |
1098 | | } |
1099 | | #endif |
1100 | |
|
1101 | 0 | WOLFSSL_LEAVE("wolfSSL_shutdown", ret); |
1102 | |
|
1103 | 0 | return ret; |
1104 | 0 | } |
1105 | | #endif /* !NO_TLS */ |
1106 | | |
1107 | | /* Get the number of bytes of decrypted application data ready to be read. |
1108 | | * |
1109 | | * TODO This ssl parameter needs to be changed to const once our ABI checker |
1110 | | * stops flagging qualifier additions as ABI breaking. |
1111 | | * |
1112 | | * @param [in] ssl SSL/TLS object. |
1113 | | * @return Number of buffered application data bytes. |
1114 | | * @return WOLFSSL_FAILURE when ssl is NULL. |
1115 | | */ |
1116 | | WOLFSSL_ABI |
1117 | | int wolfSSL_pending(WOLFSSL* ssl) |
1118 | 0 | { |
1119 | 0 | int ret; |
1120 | |
|
1121 | 0 | WOLFSSL_ENTER("wolfSSL_pending"); |
1122 | | |
1123 | | /* Validate parameter. */ |
1124 | 0 | if (ssl == NULL) { |
1125 | 0 | ret = WOLFSSL_FAILURE; |
1126 | 0 | } |
1127 | 0 | else { |
1128 | 0 | ret = (int)ssl->buffers.clearOutputBuffer.length; |
1129 | 0 | } |
1130 | |
|
1131 | 0 | return ret; |
1132 | 0 | } |
1133 | | |
1134 | | /* Determine whether there is application data available to read. |
1135 | | * |
1136 | | * @param [in] ssl SSL/TLS object. |
1137 | | * @return 1 when there is data buffered. |
1138 | | * @return 0 when there is no data buffered. |
1139 | | * @return WOLFSSL_FAILURE when ssl is NULL. |
1140 | | */ |
1141 | | int wolfSSL_has_pending(const WOLFSSL* ssl) |
1142 | 0 | { |
1143 | 0 | int ret = 0; |
1144 | |
|
1145 | 0 | WOLFSSL_ENTER("wolfSSL_has_pending"); |
1146 | | |
1147 | | /* Validate parameter. */ |
1148 | 0 | if (ssl == NULL) { |
1149 | 0 | ret = WOLFSSL_FAILURE; |
1150 | 0 | } |
1151 | 0 | else if (ssl->buffers.clearOutputBuffer.length > 0) { |
1152 | 0 | ret = 1; |
1153 | 0 | } |
1154 | | #ifdef WOLFSSL_TLS_READ_AHEAD |
1155 | | /* Read-ahead can leave undecrypted data buffered while the socket itself |
1156 | | * has no more data. This may be a complete record or only a partial one |
1157 | | * (e.g. a coalesced read that pulled a record plus the head of the next), |
1158 | | * so a non-zero return does not guarantee wolfSSL_read() will yield |
1159 | | * application data without another socket read. Report it so a |
1160 | | * select()/poll() loop keeps draining until wolfSSL_read() reports |
1161 | | * WANT_READ, instead of stalling on buffered data. */ |
1162 | | else if (ssl->buffers.inputBuffer.length > ssl->buffers.inputBuffer.idx) { |
1163 | | ret = 1; |
1164 | | } |
1165 | | #endif |
1166 | |
|
1167 | 0 | return ret; |
1168 | 0 | } |
1169 | | |
1170 | | #ifndef USE_WINDOWS_API |
1171 | | #if !defined(NO_WRITEV) && !defined(NO_TLS) |
1172 | | |
1173 | | /* Write the data described by an array of iovecs to the peer. |
1174 | | * |
1175 | | * Simulates writev semantics, doesn't actually do block at a time though |
1176 | | * because of SSL_write behavior and because front adds may be small. The |
1177 | | * segments are gathered into one buffer and written as a single call. |
1178 | | * |
1179 | | * @param [in, out] ssl SSL/TLS object. |
1180 | | * @param [in] iov Array of buffers to write. |
1181 | | * @param [in] iovcnt Number of entries in iov. |
1182 | | * @return Number of bytes written on success. |
1183 | | * @return BAD_FUNC_ARG when ssl is NULL, iovcnt is negative, or iov is |
1184 | | * NULL with a non-zero iovcnt. |
1185 | | * @return BUFFER_E when the total length of the segments overflows. |
1186 | | * @return MEMORY_ERROR when the gather buffer cannot be allocated. |
1187 | | * @return WOLFSSL_FATAL_ERROR when the write fails. Call wolfSSL_get_error() |
1188 | | * for the reason. |
1189 | | */ |
1190 | | int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt) |
1191 | 0 | { |
1192 | | #ifdef WOLFSSL_SMALL_STACK |
1193 | | byte staticBuffer[1]; /* force heap usage */ |
1194 | | #else |
1195 | 0 | byte staticBuffer[FILE_BUFFER_SIZE]; |
1196 | 0 | #endif |
1197 | 0 | byte* myBuffer = staticBuffer; |
1198 | 0 | int dynamic = 0; |
1199 | 0 | size_t sending = 0; |
1200 | 0 | size_t idx = 0; |
1201 | 0 | int i; |
1202 | 0 | int ret = 0; |
1203 | |
|
1204 | 0 | WOLFSSL_ENTER("wolfSSL_writev"); |
1205 | | |
1206 | | /* Validate parameters before anything is read from the object. */ |
1207 | 0 | if ((ssl == NULL) || ((iov == NULL) && (iovcnt != 0)) || (iovcnt < 0)) { |
1208 | 0 | ret = BAD_FUNC_ARG; |
1209 | 0 | } |
1210 | | |
1211 | | /* Total up the length being sent, checking for overflow. */ |
1212 | 0 | for (i = 0; (ret == 0) && (i < iovcnt); i++) { |
1213 | 0 | if (!WC_SAFE_SUM_UNSIGNED(size_t, sending, iov[i].iov_len, sending)) { |
1214 | 0 | ret = BUFFER_E; |
1215 | 0 | } |
1216 | 0 | } |
1217 | | |
1218 | | /* Gather into the stack buffer, or the heap when it doesn't fit. Small |
1219 | | * stack builds have a one byte buffer, so always take the heap. */ |
1220 | 0 | if ((ret == 0) && (sending > sizeof(staticBuffer))) { |
1221 | 0 | myBuffer = (byte*)XMALLOC(sending, ssl->heap, DYNAMIC_TYPE_WRITEV); |
1222 | 0 | if (myBuffer == NULL) { |
1223 | 0 | ret = MEMORY_ERROR; |
1224 | 0 | } |
1225 | 0 | else { |
1226 | 0 | dynamic = 1; |
1227 | 0 | } |
1228 | 0 | } |
1229 | |
|
1230 | 0 | if (ret == 0) { |
1231 | | /* The loop below writes exactly the span that is read, but the |
1232 | | * compiler cannot see that. When wolfSSL_write_internal() is inlined |
1233 | | * here, the warning is reported against the SendData() call inside |
1234 | | * it rather than against the call below, and a diagnostic pragma |
1235 | | * only applies at the line the warning is reported on - so the one |
1236 | | * below cannot reach it. A definite store does. Do not remove: it is |
1237 | | * what keeps -Wmaybe-uninitialized quiet on builds that inline this, |
1238 | | * such as a powerpc64 cross build at -O2. */ |
1239 | 0 | myBuffer[0] = 0; |
1240 | |
|
1241 | 0 | for (i = 0; i < iovcnt; i++) { |
1242 | 0 | XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); |
1243 | 0 | idx += iov[i].iov_len; |
1244 | 0 | } |
1245 | | |
1246 | | /* Covers the warning when it is reported against the call itself |
1247 | | * instead, which is where it lands when there is no inlining. */ |
1248 | 0 | PRAGMA_GCC_DIAG_PUSH |
1249 | 0 | PRAGMA_GCC("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") |
1250 | 0 | ret = wolfSSL_write_internal(ssl, myBuffer, sending); |
1251 | 0 | PRAGMA_GCC_DIAG_POP |
1252 | 0 | } |
1253 | | |
1254 | | /* Only set when the allocation above succeeded, so ssl is not NULL. */ |
1255 | 0 | if (dynamic) { |
1256 | 0 | XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); |
1257 | 0 | } |
1258 | |
|
1259 | 0 | return ret; |
1260 | 0 | } |
1261 | | #endif |
1262 | | #endif |
1263 | | |
1264 | | #ifdef OPENSSL_EXTRA |
1265 | | /* Get the I/O operation the SSL/TLS object is waiting on. |
1266 | | * |
1267 | | * @param [in] ssl SSL/TLS object. |
1268 | | * @return WOLFSSL_READING when waiting for the transport to be readable. |
1269 | | * @return WOLFSSL_WRITING when waiting for the transport to be writable. |
1270 | | * @return WOLFSSL_NOTHING when not waiting on the transport or ssl is NULL. |
1271 | | */ |
1272 | | int wolfSSL_want(WOLFSSL* ssl) |
1273 | | { |
1274 | | int rw_state = WOLFSSL_NOTHING; |
1275 | | |
1276 | | if (ssl != NULL) { |
1277 | | if (ssl->error == WC_NO_ERR_TRACE(WANT_READ)) { |
1278 | | rw_state = WOLFSSL_READING; |
1279 | | } |
1280 | | else if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE)) { |
1281 | | rw_state = WOLFSSL_WRITING; |
1282 | | } |
1283 | | } |
1284 | | |
1285 | | return rw_state; |
1286 | | } |
1287 | | #endif |
1288 | | |
1289 | | /* Determine whether the last operation is waiting for the transport to be |
1290 | | * readable. |
1291 | | * |
1292 | | * @param [in] ssl SSL/TLS object. |
1293 | | * @return 1 when the current error is want read. |
1294 | | * @return 0 otherwise, including when ssl is NULL. |
1295 | | */ |
1296 | | int wolfSSL_want_read(WOLFSSL* ssl) |
1297 | 0 | { |
1298 | 0 | int ret = 0; |
1299 | |
|
1300 | 0 | WOLFSSL_ENTER("wolfSSL_want_read"); |
1301 | |
|
1302 | 0 | if ((ssl != NULL) && (ssl->error == WC_NO_ERR_TRACE(WANT_READ))) { |
1303 | 0 | ret = 1; |
1304 | 0 | } |
1305 | |
|
1306 | 0 | return ret; |
1307 | 0 | } |
1308 | | |
1309 | | /* Determine whether the last operation is waiting for the transport to be |
1310 | | * writable. |
1311 | | * |
1312 | | * @param [in] ssl SSL/TLS object. |
1313 | | * @return 1 when the current error is want write. |
1314 | | * @return 0 otherwise, including when ssl is NULL. |
1315 | | */ |
1316 | | int wolfSSL_want_write(WOLFSSL* ssl) |
1317 | 0 | { |
1318 | 0 | int ret = 0; |
1319 | |
|
1320 | 0 | WOLFSSL_ENTER("wolfSSL_want_write"); |
1321 | |
|
1322 | 0 | if ((ssl != NULL) && (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))) { |
1323 | 0 | ret = 1; |
1324 | 0 | } |
1325 | |
|
1326 | 0 | return ret; |
1327 | 0 | } |
1328 | | |
1329 | | /* Get the shutdown state of the connection. |
1330 | | * |
1331 | | * @param [in] ssl SSL/TLS object. |
1332 | | * @return Bit set of WOLFSSL_SENT_SHUTDOWN and WOLFSSL_RECEIVED_SHUTDOWN. |
1333 | | * @return 0 when ssl is NULL or no close_notify has been sent or received. |
1334 | | */ |
1335 | | int wolfSSL_get_shutdown(const WOLFSSL* ssl) |
1336 | 0 | { |
1337 | 0 | int isShutdown = 0; |
1338 | |
|
1339 | 0 | WOLFSSL_ENTER("wolfSSL_get_shutdown"); |
1340 | |
|
1341 | 0 | if (ssl != NULL) { |
1342 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
1343 | | if (ssl->options.shutdownDone) { |
1344 | | /* The SSL object was possibly cleared with wolfSSL_clear after |
1345 | | * a successful shutdown. Simulate a response for a full |
1346 | | * bidirectional shutdown. */ |
1347 | | isShutdown = WOLFSSL_SENT_SHUTDOWN | WOLFSSL_RECEIVED_SHUTDOWN; |
1348 | | } |
1349 | | else |
1350 | | #endif |
1351 | 0 | { |
1352 | | /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * |
1353 | | * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ |
1354 | 0 | if (ssl->options.sentNotify) { |
1355 | 0 | isShutdown |= WOLFSSL_SENT_SHUTDOWN; |
1356 | 0 | } |
1357 | 0 | if ((ssl->options.closeNotify) || (ssl->options.connReset)) { |
1358 | 0 | isShutdown |= WOLFSSL_RECEIVED_SHUTDOWN; |
1359 | 0 | } |
1360 | 0 | } |
1361 | 0 | } |
1362 | |
|
1363 | 0 | WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); |
1364 | 0 | return isShutdown; |
1365 | 0 | } |
1366 | | |
1367 | | #endif /* !WOLFCRYPT_ONLY */ |
1368 | | |
1369 | | #endif /* !WOLFSSL_SSL_API_RW_INCLUDED */ |