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