SSL_GET_ERROR(3)
π SSL_GET_ERROR(3) β the "so what did my TLS call actually do" manual
okay bestie, settle in π this one's a libssl / libcrypto page (yes, that's the #include <openssl/ssl.h> family), and it's genuinely iconic β it's the function that tells you why your TLS/SSL I/O call did the thing it did. no cap, you will need this.
β¨ NAME β¨
SSL_get_error β obtain result code for TLS/SSL I/O operation π
πΈ SYNOPSIS πΈ
#include <openssl/ssl.h>
int
SSL_get_error(const SSL *ssl, int ret);
π¦ DESCRIPTION π¦
so here's the vibe: SSL_get_error() hands you back a result code β and yes, it's suitable for the C switch statement, so you can be all neat and tidy about it β for a preceding call to SSL_connect(3), SSL_accept(3), SSL_do_handshake(3), SSL_read(3), SSL_peek(3), or SSL_write(3) on ssl. the value that TLS/SSL I/O function returned? that's what you pass in as the ret parameter. literally just hand it back, she'll know what to do π
here's the part people forget and then cry about π β on top of ssl and ret, SSL_get_error() also peeks at the current thread's OpenSSL error queue. so:
- you must call
SSL_get_error()in the same thread that performed the TLS/SSL I/O operation - and no other OpenSSL function calls should sneak in between them, okay? none. zero. π
- and the current thread's error queue must be empty before you attempt the TLS/SSL I/O operation in the first place β otherwise
SSL_get_error()will not work reliably. big deal, bestie π₯
π RETURN VALUES π
the following return values can currently occur β let's go through them one by one, each one's got main character energy:
SSL_ERROR_NONEβ the TLS/SSL I/O operation completed, slay β¨ this result code is returned if and only ifret > 0.SSL_ERROR_ZERO_RETURNβ the TLS/SSL connection has been closed. if the protocol version is SSL 3.0 or TLS 1.0, this result code is returned only if a closure alert has occurred in the protocol, i.e. if the connection has been closed cleanly. and note this carefully: in this caseSSL_ERROR_ZERO_RETURNdoes not necessarily indicate that the underlying transport has been closed. two different things, don't conflate them π«ΆSSL_ERROR_WANT_READ,SSL_ERROR_WANT_WRITEβ the operation did not complete, so you should call the same TLS/SSL I/O function again later. if, by then, the underlying BIO has data available for reading (when the result code isSSL_ERROR_WANT_READ) or allows writing data (when it'sSSL_ERROR_WANT_WRITE), then some TLS/SSL protocol progress will take place β i.e. at least part of a TLS/SSL record will be read or written. heads up though: the retry may again lead to anSSL_ERROR_WANT_READorSSL_ERROR_WANT_WRITEcondition. there is no fixed upper limit for the number of iterations that may be necessary until progress becomes visible at application protocol level π³ just keep looping, it's fine, it's fineβ
for socket BIOs (e.g. when SSL_set_fd() was used), select(2) or poll(2) on the underlying socket can be used to find out when the TLS/SSL I/O function should be retried. classic move π
β οΈ Caveat, and this one's important: any TLS/SSL I/O function can lead to either ofSSL_ERROR_WANT_READandSSL_ERROR_WANT_WRITE. in particular,SSL_read(3)orSSL_peek(3)may want to write data andSSL_write(3)may want to read data. this is mainly because TLS/SSL handshakes may occur at any time during the protocol (initiated by either the client or the server);SSL_read(3),SSL_peek(3), andSSL_write(3)will handle any pending handshakes. so likeβ¦ they're not as predictable as you'd think π
SSL_ERROR_WANT_CONNECT,SSL_ERROR_WANT_ACCEPTβ the operation did not complete; the same TLS/SSL I/O function should be called again later. the underlying BIO was not connected yet to the peer and the call would block inconnect(2)/accept(2). the SSL function should be called again when the connection is established. these messages can only appear with aBIO_s_connect(3)orBIO_s_accept(3)BIO, respectively π§ in order to find out when the connection has been successfully established, on many platformsselect(2)orpoll(2)for writing on the socket file descriptor can be used.SSL_ERROR_WANT_X509_LOOKUPβ the operation did not complete because an application callback set bySSL_CTX_set_client_cert_cb(3)has asked to be called again. the TLS/SSL I/O function should be called again later. the details depend on the application π (yes, that's the whole explanation. it's giving "read the room", iykyk.)SSL_ERROR_SYSCALLβ some I/O error occurred π the OpenSSL error queue may contain more information on the error. if the error queue is empty (i.e.ERR_get_error()returns0),retcan be used to find out more about the error:- if
ret == 0, an EOF was observed that violates the protocol. - if
ret == β1, the underlying BIO reported an I/O error (for socket I/O on Unix systems, consulterrnofor details π).
- if
SSL_ERROR_SSLβ a failure in the SSL library occurred, usually a protocol error. the OpenSSL error queue contains more information on the error. go read it, bestie, the answer is in there π
π SEE ALSO π
err(3), ssl(3) β go read them, they're both gorgeous and they're right there π«Ά
β HISTORY β
SSL_get_error() first appeared in SSLeay 0.8.0 and have been available since OpenBSD 2.4. vintage! antique! still relevant! π
that's the whole page, bestie β every flag, every code, every caveat, nothing skipped π now go forth and switch on your return values like the icon you are.
signing off from the Debian edition, dated June 8, 2025 β SSL_GET_ERROR(3), Library Functions Manual. mwah π
π¦ where this page comes from
- alpine 3.24: libressl-doc 4.3.1-r0 Β· custom
- arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
- Copyright (c) 2000, 2001, 2002, 2005 The OpenSSL Project. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms