* to disable session caching and tickets.
*/
int not_resumable;
+ /*
+ * Set when this session's master key was resolved from an external PSK
+ * identity (psk_find_session_cb(), or the legacy psk_server_callback())
+ * rather than from a resumption ticket or session-cache lookup.
+ * ssl_get_prev_session() uses this to exempt such sessions from sid_ctx
+ * checks that only make sense for a real cache lookup.
+ *
+ * Deliberately not part of the SSL_SESSION ASN.1 encoding: it must not
+ * survive a real ticket round-trip (a session reconstructed by
+ * d2i_SSL_SESSION() from a genuine, previously-issued ticket is by
+ * definition not an external-PSK match, and should get the ordinary
+ * sid_ctx treatment). ssl_session_dup() resets it to 0 on every copy,
+ * mirroring not_resumable just above, for the same reason.
+ */
+ int psk_external;
/* Peer raw public key, if available */
EVP_PKEY *peer_rpk;
/* This is the cert and type for the other end. */
{
SSL_SESSION *sess = ssl_session_dup_intern(src, ticket);
- if (sess != NULL)
+ if (sess != NULL) {
sess->not_resumable = 0;
+ /*
+ * A duplicated session can land in the stateful session cache, and is
+ * not necessarily a live session just built for an external PSK. The
+ * caller must explicitly set this field non-zero after duplication as
+ * needed.
+ */
+ sess->psk_external = 0;
+ }
return sess;
}
goto err; /* treat like cache miss */
}
- if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
+ /*
+ * sid_ctx exists to keep multiple services that happen to share one
+ * session cache from resuming each other's sessions. This check is not
+ * relevant to external PSK sessions that are not restored from a cache.
+ */
+ if (!ret->psk_external
+ && (s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
/*
* We can't be sure if this session is being used out of context,
* which is especially important for SSL_VERIFY_PEER. The application
#endif /* OPENSSL_NO_PSK */
if (sess != NULL) {
- /* We found a PSK */
+ /*
+ * We found an external (not a resumption) PSK - duplicate the
+ * session, set the session id to our own, and mark it as external.
+ */
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
if (sesstmp == NULL) {
*/
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length;
- ext = 1;
+ sess->psk_external = ext = 1;
if (id == 0)
s->ext.early_data_ok = 1;
s->ext.ticket_expected = 1;
*/
s->ext.early_data_ok = 1;
}
+ /* This PSK is not external, use the correct binder label, ... */
+ ext = 0;
}
md = ssl_md(sctx, sess->cipher->algorithm2);
unsigned int context, X509 *x,
size_t chainidx)
{
- if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
+ /*
+ * Don't tell the client to expect a NewSessionTicket when any
+ * ticket we'd mint would be rejected by ssl_get_prev_session()
+ * whenever SSL_VERIFY_PEER is set with no sid_ctx configured (see
+ * the checks there). In TLS 1.2, once promised the ticket MUST
+ * be sent.
+ */
+ if (!s->ext.ticket_expected || !tls_use_ticket(s)
+ || ((s->verify_mode & SSL_VERIFY_PEER) != 0 && s->sid_ctx_length == 0)) {
s->ext.ticket_expected = 0;
return EXT_RETURN_NOT_SENT;
}
* session tickets or resumption (e.g. new_session_count = 0 or
* resumption_count = 0), this implementation does not currently
* interpret or enforce those parameters.
+ *
+ * Also skip issuance when SSL_VERIFY_PEER is set with no sid_ctx
+ * configured: any ticket minted here would be rejected by
+ * ssl_get_prev_session() in that configuration.
*/
- if (((s->options & SSL_OP_NO_TICKET) != 0
+ if (s->num_tickets <= s->sent_tickets
+ || ((s->options & SSL_OP_NO_TICKET) != 0
&& (SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER)
== 0)
- || s->ext.psk_kex_mode == TLSEXT_KEX_MODE_FLAG_NONE) {
+ || s->ext.psk_kex_mode == TLSEXT_KEX_MODE_FLAG_NONE
+ || ((s->verify_mode & SSL_VERIFY_PEER) != 0 && s->sid_ctx_length == 0))
st->hand_state = TLS_ST_OK;
- } else if (s->num_tickets > s->sent_tickets) {
+ else
st->hand_state = TLS_ST_SW_SESSION_TICKET;
- } else {
- st->hand_state = TLS_ST_OK;
- }
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_KEY_UPDATE: