# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
# define SSL_MAX_KEY_ARG_LENGTH 8
# define SSL_MAX_MASTER_KEY_LENGTH 48
-# define TLS13_MAX_RESUMPTION_MASTER_LENGTH 64
/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES 32
goto err;
if (!ssl_session_memcpy(ret->master_key, &tmpl,
- as->master_key, TLS13_MAX_RESUMPTION_MASTER_LENGTH))
+ as->master_key, TLS13_MAX_RESUMPTION_PSK_LENGTH))
goto err;
ret->master_key_length = tmpl;
long (*ssl_ctx_callback_ctrl) (SSL_CTX *s, int cb_id, void (*fp) (void));
};
+# define TLS13_MAX_RESUMPTION_PSK_LENGTH 64
+
/*-
* Lets make this into an ASN.1 type structure as follows
* SSL_SESSION_ID ::= SEQUENCE {
unsigned char early_secret[EVP_MAX_MD_SIZE];
/*
* For <=TLS1.2 this is the master_key. For TLS1.3 this is the resumption
- * master secret
+ * PSK
*/
- unsigned char master_key[TLS13_MAX_RESUMPTION_MASTER_LENGTH];
+ unsigned char master_key[TLS13_MAX_RESUMPTION_PSK_LENGTH];
/* session_id - valid? */
size_t session_id_length;
unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
*/
uint32_t mac_flags;
/*
- * The TLS1.3 secrets. The resumption master secret is stored in the
- * session.
+ * The TLS1.3 secrets.
*/
unsigned char early_secret[EVP_MAX_MD_SIZE];
unsigned char handshake_secret[EVP_MAX_MD_SIZE];
unsigned char master_secret[EVP_MAX_MD_SIZE];
+ unsigned char resumption_master_secret[EVP_MAX_MD_SIZE];
unsigned char client_finished_secret[EVP_MAX_MD_SIZE];
unsigned char server_finished_secret[EVP_MAX_MD_SIZE];
unsigned char server_finished_hash[EVP_MAX_MD_SIZE];
size_t num_tickets;
/* The number of TLS1.3 tickets actually sent so far */
size_t sent_tickets;
+ /* The next nonce value to use when we send a ticket on this connection */
+ uint64_t next_ticket_nonce;
};
/*
EVP_MD_CTX *mctx = NULL;
unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
- unsigned char tmppsk[EVP_MAX_MD_SIZE];
- unsigned char *early_secret, *psk;
- const char resumption_label[] = "res binder";
- const char external_label[] = "ext binder";
- const char nonce_label[] = "resumption";
- const char *label;
- size_t bindersize, labelsize, psklen, hashsize;
+ unsigned char *early_secret;
+ static const unsigned char resumption_label[] = "res binder";
+ static const unsigned char external_label[] = "ext binder";
+ const unsigned char *label;
+ size_t bindersize, labelsize, hashsize;
int hashsizei = EVP_MD_size(md);
int ret = -1;
int usepskfored = 0;
labelsize = sizeof(resumption_label) - 1;
}
- if (external) {
- psk = sess->master_key;
- psklen = sess->master_key_length;
- } else {
- psk = tmppsk;
- psklen = hashsize;
- if (!tls13_hkdf_expand(s, md, sess->master_key,
- (const unsigned char *)nonce_label,
- sizeof(nonce_label) - 1, sess->ext.tick_nonce,
- sess->ext.tick_nonce_len, psk, hashsize)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-
/*
* Generate the early_secret. On the server side we've selected a PSK to
* resume with (internal or external) so we always do this. On the client
early_secret = (unsigned char *)s->early_secret;
else
early_secret = (unsigned char *)sess->early_secret;
- if (!tls13_generate_secret(s, md, NULL, psk, psklen, early_secret)) {
+
+ if (!tls13_generate_secret(s, md, NULL, sess->master_key,
+ sess->master_key_length, early_secret)) {
/* SSLfatal() already called */
goto err;
}
}
/* Generate the binder key */
- if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label,
- labelsize, hash, hashsize, binderkey, hashsize)) {
+ if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash,
+ hashsize, binderkey, hashsize)) {
/* SSLfatal() already called */
goto err;
}
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
+#include <internal/cryptlib.h>
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
/* This is a standalone message in TLSv1.3, so there is no more to read */
if (SSL_IS_TLS13(s)) {
+ const EVP_MD *md = ssl_handshake_md(s);
+ int hashleni = EVP_MD_size(md);
+ size_t hashlen;
+ static const unsigned char nonce_label[] = "resumption";
+
+ /* Ensure cast to size_t is safe */
+ if (!ossl_assert(hashleni >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
+
+ if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
+ nonce_label,
+ sizeof(nonce_label) - 1,
+ s->session->ext.tick_nonce,
+ s->session->ext.tick_nonce_len,
+ s->session->master_key,
+ hashlen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ s->session->master_key_length = hashlen;
+
OPENSSL_free(exts);
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
return MSG_PROCESS_FINISHED_READING;
#include <openssl/bn.h>
#include <openssl/md5.h>
+#define TICKET_NONCE_SIZE 8
+
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
/*
} age_add_u;
if (SSL_IS_TLS13(s)) {
+ size_t i, hashlen;
+ uint64_t nonce;
+ const char nonce_label[] = "resumption";
+ const EVP_MD *md = ssl_handshake_md(s);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ int hashleni = EVP_MD_size(md);
+
+ /* Ensure cast to size_t is safe */
+ if (!ossl_assert(hashleni >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
if (s->info_callback != NULL)
cb = s->info_callback;
goto err;
}
s->session->ext.tick_age_add = age_add_u.age_add;
- /*
- * ticket_nonce is set to a single 0 byte because we only ever send a
- * single ticket per connection. IMPORTANT: If we ever support multiple
- * tickets per connection then this will need to be changed.
- */
+
OPENSSL_free(s->session->ext.tick_nonce);
- s->session->ext.tick_nonce = OPENSSL_zalloc(sizeof(char));
+ s->session->ext.tick_nonce = OPENSSL_zalloc(TICKET_NONCE_SIZE);
if (s->session->ext.tick_nonce == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_MALLOC_FAILURE);
goto err;
}
- s->session->ext.tick_nonce_len = 1;
+ nonce = s->next_ticket_nonce;
+ for (i = TICKET_NONCE_SIZE; nonce > 0 && i > 0; i--) {
+ s->session->ext.tick_nonce[i - 1] = nonce & 0xff;
+ nonce >>= 8;
+ }
+ s->session->ext.tick_nonce_len = TICKET_NONCE_SIZE;
+
+ if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
+ (const unsigned char *)nonce_label,
+ sizeof(nonce_label) - 1,
+ s->session->ext.tick_nonce,
+ s->session->ext.tick_nonce_len,
+ s->session->master_key,
+ hashlen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ s->session->master_key_length = hashlen;
+
s->session->time = (long)time(NULL);
if (s->s3->alpn_selected != NULL) {
OPENSSL_free(s->session->ext.alpn_selected);
/* SSLfatal() already called */
goto err;
}
+ /*
+ * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
+ * gets reset to 0 if we send more tickets following a post-handshake
+ * auth, but |next_ticket_nonce| does not.
+ */
s->sent_tickets++;
+ s->next_ticket_nonce++;
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
}
EVP_CIPHER_CTX_free(ctx);
if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
resumption_master_secret,
sizeof(resumption_master_secret) - 1,
- hashval, hashlen, s->session->master_key,
+ hashval, hashlen, s->resumption_master_secret,
hashlen)) {
/* SSLfatal() already called */
goto err;
}
- s->session->master_key_length = hashlen;
}
if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,