SSL_CTX_SET_...IENT_CALLBACK(3ossl)
okay bestie, sit down, grab a boba π§, because we're reading the 3ossl manual page for SSL_CTX_SET_...IENT_CALLBACK and it's literally all about you (the client) telling OpenSSL "here's my identity, here's my pre-shared key, go off π
". PSK = pre-shared key, iykyk. no cap, this page is the whole blueprint.
β¨ NAME β¨
SSL_psk_client_cb_func, SSL_psk_use_session_cb_func, SSL_CTX_set_psk_client_callback, SSL_set_psk_client_callback, SSL_CTX_set_psk_use_session_callback, SSL_set_psk_use_session_callback β set PSK client callback. that's the whole assignment, periodt. π
β¨ SYNOPSIS β¨
#include <openssl/ssl.h>
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
const unsigned char **id,
size_t *idlen,
SSL_SESSION **sess);
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
SSL_psk_use_session_cb_func cb);
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
const char *hint,
char *identity,
unsigned int max_identity_len,
unsigned char *psk,
unsigned int max_psk_len);
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);
π DESCRIPTION π
π¦ TLSv1.3 girlies, this one's for you
so if you're a client app and you wanna use TLSv1.3 PSKs, you should use either SSL_CTX_set_psk_use_session_callback() or SSL_set_psk_use_session_callback(), whichever one fits your situation bestie. these functions cannot be used for TLSv1.2 and below PSKs β different era, different callback, we'll get there. π
the callback function gets handed a pointer to the SSL connection in ssl. iconic.
the first time the callback gets called for a connection, the md parameter is NULL. but in some circumstances the callback will get called a second time π β and in that case the server will have already specified a ciphersuite to use, so the PSK must be compatible with the digest for that ciphersuite. that digest shows up in md. and no stress, the PSK your callback returns is allowed to be different between the first and the second time it's called. main character flexibility. π
π what you gotta hand back
on successful completion, the callback must store a pointer to an identifier for the PSK in *id. the identifier length in bytes goes in *idlen. the memory pointed to by *id stays owned by the application, and the app should free it whenever it needs to β at any point after the handshake is complete. π«Ά
on top of that, the callback should store a pointer to an SSL_SESSION object in *sess. that's what gets used as the basis for the PSK, and at minimum it needs these fields set:
- The master key β you can set this with a call to
SSL_SESSION_set1_master_key(3). - A ciphersuite β only the handshake digest associated with the ciphersuite is actually relevant for the PSK (the server may go on to negotiate any ciphersuite that's compatible with the digest). the application can use any TLSv1.3 ciphersuite. if
mdis notNULL, then the handshake digest for the ciphersuite should be the same. you can set the ciphersuite with a call toSSL_SESSION_set_cipher(3). and you can check the handshake digest of anSSL_CIPHERobject usingSSL_CIPHER_get_handshake_digest(3). π - The protocol version β set it with a call to
SSL_SESSION_set_protocol_version(3), and it should beTLS1_3_VERSION.
also, the maximum early data value should be set via a call to SSL_SESSION_set_max_early_data(3) if the PSK is gonna be used for sending early data. β
alternatively, an SSL_SESSION created from a previous non-PSK handshake can also be used as the basis for a PSK. lowkey flexible of them.
ownership of the SSL_SESSION object gets passed to the OpenSSL library, so it should not be freed by the application. hands off, it's not yours anymore. π
π the use-after-free jumpscare
so like I said above, the callback may be called a second time during a handshake. and since ownership of the SSL_SESSION is transferred to OpenSSL on each call, if your callback wants to return the same SSL_SESSION pointer on a subsequent invocation, it must first call SSL_SESSION_up_ref(3) to increment the reference count.
failure to do so will result in a use-after-free error. not cute. not slay. π¨
alternatively, the callback can just return a different SSL_SESSION object on each call (e.g., by calling SSL_SESSION_dup(3)). problem solved, vibe preserved. β¨
πΈ "sike, no PSK actually"
it's also possible for the callback to succeed but not supply a PSK. in that case no PSK gets sent to the server, but the handshake keeps going. to pull this off, the callback should return successfully and make sure *sess is NULL. the contents of *id and *idlen get ignored. ghosting the server, but politely. π§
π TLSv1.2 and below girlies
a client application wishing to use PSK ciphersuites for TLSv1.2 and below must provide a different callback function. this one gets called when the client is sending the ClientKeyExchange message to the server.
the whole purpose of the callback function is to select the PSK identity and the pre-shared key to use during the connection setup phase.
you set the callback using SSL_CTX_set_psk_client_callback() or SSL_set_psk_client_callback(). and here's what it gets handed:
- the connection in parameter
ssl - a NUL-terminated PSK identity hint sent by the server in parameter
hint - a buffer
identityof lengthmax_identity_lenbytes (including the NUL-terminator) where the resulting NUL-terminated identity is to be stored - a buffer
pskof lengthmax_psk_lenbytes where the resulting pre-shared key is to be stored
π₯ the crossover episode
the callback for TLSv1.2 will also work in TLSv1.3, although it's recommended to use SSL_CTX_set_psk_use_session_callback() or SSL_set_psk_use_session_callback() for that purpose instead. if TLSv1.3 has been negotiated, then OpenSSL will first check whether a callback was set via SSL_CTX_set_psk_use_session_callback() or SSL_set_psk_use_session_callback() and it will use that one in preference. if no such callback is present, then it checks whether one was set via SSL_CTX_set_psk_client_callback() or SSL_set_psk_client_callback() and uses that instead. in that case, the hint value will always be NULL and the handshake digest will default to SHA-256 for any returned PSK.
and okay one more thing, super important: TLSv1.3 early data exchanges are possible in PSK connections only with the SSL_psk_use_session_cb_func callback, and are not possible with the SSL_psk_client_cb_func callback. so if early data is the dream, pick the right callback. π
π NOTES π
- note that the parameter
hintgiven to the callback may beNULL. bestie said "no comment" and meant it. - a connection established via a TLSv1.3 PSK will appear as if session resumption has occurred, so
SSL_session_reused(3)will return true. plot twist, but a cute one. π - there are no known security issues with sharing the same PSK between TLSv1.2 (or below) and TLSv1.3. however, the RFC has this note of caution:
"While there is no known way in which the same PSK might produce related output in both versions, only limited analysis has been done. Implementations can ensure safety from cross-protocol related output by not reusing PSKs between TLS 1.3 and TLS 1.2."
read it twice, bestie. π
π« RETURN VALUES π«
SSL_psk_client_cb_func
- success (callback found a PSK identity and a pre-shared key to use) β the length (> 0) of
pskin bytes is returned. π - otherwise, or on errors β the callback should return
0. in this case the connection setup fails. π
SSL_psk_use_session_cb_func
- should return
1on success, or0on failure. in the event of failure, the connection setup fails.
π«Ά SEE ALSO π«Ά
ssl(7), SSL_CTX_set_psk_find_session_callback(3), SSL_set_psk_find_session_callback(3)
π HISTORY π
SSL_CTX_set_psk_use_session_callback() and SSL_set_psk_use_session_callback() were added in OpenSSL 1.1.1. throwback era. β
πΈ COPYRIGHT πΈ
Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
and that's the whole page bestie, we ate and left no crumbs π
β¨ this was OpenSSL 3.5.9, dated 2026-09-2, from the 3ossl manual β go forth and PSK responsibly, ily, bye ππ¦π
π¦ where this page comes from
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 43: openssl-devel 1:3.5.9-1.fc43 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- fedora 44: openssl-devel 1:3.5.9-1.fc44 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms