aboutsummaryrefslogtreecommitdiff
path: root/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'ssl')
-rw-r--r--ssl/ssl_lib.c12
-rw-r--r--ssl/ssl_locl.h6
-rw-r--r--ssl/statem/statem.c15
-rw-r--r--ssl/statem/statem.h1
-rw-r--r--ssl/tls13_enc.c70
5 files changed, 104 insertions, 0 deletions
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 00e02f4..59b507e 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2810,6 +2810,18 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
contextlen, use_context);
}
+int SSL_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *context,
+ size_t contextlen)
+{
+ if (s->version != TLS1_3_VERSION)
+ return 0;
+
+ return tls13_export_keying_material_early(s, out, olen, label, llen,
+ context, contextlen);
+}
+
static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
const unsigned char *session_id = a->session_id;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index b590b53..0dd2a7b 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1111,6 +1111,7 @@ struct ssl_st {
unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char exporter_master_secret[EVP_MAX_MD_SIZE];
+ unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */
EVP_MD_CTX *read_hash; /* used for mac generation */
@@ -2406,6 +2407,11 @@ __owur int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *context,
size_t contextlen, int use_context);
+__owur int tls13_export_keying_material_early(SSL *s, unsigned char *out,
+ size_t olen, const char *label,
+ size_t llen,
+ const unsigned char *context,
+ size_t contextlen);
__owur int tls1_alert_code(int code);
__owur int tls13_alert_code(int code);
__owur int ssl3_alert_code(int code);
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index 818e648..a574853 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -951,3 +951,18 @@ int ossl_statem_export_allowed(SSL *s)
return s->s3->previous_server_finished_len != 0
&& s->statem.hand_state != TLS_ST_SW_FINISHED;
}
+
+/*
+ * Return 1 if early TLS exporter is ready to export keying material,
+ * or 0 if otherwise.
+ */
+int ossl_statem_export_early_allowed(SSL *s)
+{
+ /*
+ * The early exporter secret is only present on the server if we
+ * have accepted early_data. It is present on the client as long
+ * as we have sent early_data.
+ */
+ return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
+ || (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
+}
diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h
index 58cc4f4..1935718 100644
--- a/ssl/statem/statem.h
+++ b/ssl/statem/statem.h
@@ -133,6 +133,7 @@ void ossl_statem_check_finish_init(SSL *s, int send);
void ossl_statem_set_hello_verify_done(SSL *s);
__owur int ossl_statem_app_data_allowed(SSL *s);
__owur int ossl_statem_export_allowed(SSL *s);
+__owur int ossl_statem_export_early_allowed(SSL *s);
/* Flush the write BIO */
int statem_flush(SSL *s);
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 9311866..6332804 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -365,6 +365,7 @@ int tls13_change_cipher_state(SSL *s, int which)
static const unsigned char server_application_traffic[] = "s ap traffic";
static const unsigned char exporter_master_secret[] = "exp master";
static const unsigned char resumption_master_secret[] = "res master";
+ static const unsigned char early_exporter_master_secret[] = "e exp master";
unsigned char *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
@@ -481,6 +482,16 @@ int tls13_change_cipher_state(SSL *s, int which)
}
hashlen = hashlenui;
EVP_MD_CTX_free(mdctx);
+
+ if (!tls13_hkdf_expand(s, md, insecret,
+ early_exporter_master_secret,
+ sizeof(early_exporter_master_secret) - 1,
+ hashval, hashlen,
+ s->early_exporter_master_secret, hashlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
} else if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->client_finished_secret;
@@ -690,3 +701,62 @@ int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
EVP_MD_CTX_free(ctx);
return ret;
}
+
+int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
+ const char *label, size_t llen,
+ const unsigned char *context,
+ size_t contextlen)
+{
+ static const unsigned char exporterlabel[] = "exporter";
+ unsigned char exportsecret[EVP_MAX_MD_SIZE];
+ unsigned char hash[EVP_MAX_MD_SIZE], data[EVP_MAX_MD_SIZE];
+ const EVP_MD *md;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ unsigned int hashsize, datalen;
+ int ret = 0;
+ const SSL_CIPHER *sslcipher;
+
+ if (ctx == NULL || !ossl_statem_export_early_allowed(s))
+ goto err;
+
+ if (!s->server && s->max_early_data > 0
+ && s->session->ext.max_early_data == 0)
+ sslcipher = SSL_SESSION_get0_cipher(s->psksession);
+ else
+ sslcipher = SSL_SESSION_get0_cipher(s->session);
+
+ md = ssl_md(sslcipher->algorithm2);
+
+ /*
+ * Calculate the hash value and store it in |data|. The reason why
+ * the empty string is used is that the definition of TLS-Exporter
+ * is like so:
+ *
+ * TLS-Exporter(label, context_value, key_length) =
+ * HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
+ * "exporter", Hash(context_value), key_length)
+ *
+ * Derive-Secret(Secret, Label, Messages) =
+ * HKDF-Expand-Label(Secret, Label,
+ * Transcript-Hash(Messages), Hash.length)
+ *
+ * Here Transcript-Hash is the cipher suite hash algorithm.
+ */
+ if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
+ || EVP_DigestUpdate(ctx, context, contextlen) <= 0
+ || EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
+ || EVP_DigestInit_ex(ctx, md, NULL) <= 0
+ || EVP_DigestFinal_ex(ctx, data, &datalen) <= 0
+ || !tls13_hkdf_expand(s, md, s->early_exporter_master_secret,
+ (const unsigned char *)label, llen,
+ data, datalen, exportsecret, hashsize)
+ || !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
+ sizeof(exporterlabel) - 1, hash, hashsize,
+ out, olen))
+ goto err;
+
+ ret = 1;
+ err:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}