summaryrefslogtreecommitdiff
path: root/lib/prf.c
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-11-24 11:07:20 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-02-19 15:29:35 +0100
commitb5838d7080ee5a864c0b87c3930367662f6e3532 (patch)
treeaaae5ddc740c1e82a0d40b74268eb96cc7f95c2a /lib/prf.c
parent9afe3bb4e47f8e70193d30f659065c0d100d6485 (diff)
downloadgnutls-b5838d7080ee5a864c0b87c3930367662f6e3532.tar.gz
gnutls_prf_rfc5705: calculate exporter using HKDF if TLS 1.3
Signed-off-by: Daiki Ueno <dueno@redhat.com>
Diffstat (limited to 'lib/prf.c')
-rw-r--r--lib/prf.c80
1 files changed, 62 insertions, 18 deletions
diff --git a/lib/prf.c b/lib/prf.c
index 7ac1090d92..b5dd8888fa 100644
--- a/lib/prf.c
+++ b/lib/prf.c
@@ -27,10 +27,13 @@
#include "gnutls_int.h"
#include "errors.h"
+#include "secrets.h"
#include <num.h>
#include <state.h>
#include <algorithms.h>
+#define EXPORTER_LABEL "exporter"
+
/**
* gnutls_prf_raw:
* @session: is a #gnutls_session_t type.
@@ -44,6 +47,10 @@
* Apply the TLS Pseudo-Random-Function (PRF) on the master secret
* and the provided data.
*
+ * This function only works with the TLS versions prior to 1.3. In
+ * TLS 1.3, the use of PRF is replaced with HKDF (HMAC-based Key
+ * Derivation Function) based on the multi-stage key scheduling.
+ *
* The @label variable usually contains a string denoting the purpose
* for the generated data. The @seed usually contains data such as the
* client and server random, perhaps together with some additional
@@ -88,15 +95,18 @@ gnutls_prf_raw(gnutls_session_t session,
* @outsize: size of pre-allocated output buffer to hold the output.
* @out: pre-allocated buffer to hold the generated data.
*
- * Applies the TLS Pseudo-Random-Function (PRF) on the master secret
- * and the provided data, seeded with the client and server random fields,
+ * Exports keyring material from TLS/DTLS session to an application,
* as specified in RFC5705.
*
+ * In the TLS versions prior to 1.3, it applies the TLS
+ * Pseudo-Random-Function (PRF) on the master secret and the provided
+ * data, seeded with the client and server random fields.
+ *
+ * In TLS 1.3, it applies HKDF on the exporter master secret derived
+ * from the master secret.
+ *
* The @label variable usually contains a string denoting the purpose
- * for the generated data. The @server_random_first indicates whether
- * the client random field or the server random field should be first
- * in the seed. Non-zero indicates that the server random field is first,
- * 0 that the client random field is first.
+ * for the generated data.
*
* The @context variable can be used to add more data to the seed, after
* the random variables. It can be used to make sure the
@@ -118,7 +128,7 @@ gnutls_prf_rfc5705(gnutls_session_t session,
size_t context_size, const char *context,
size_t outsize, char *out)
{
- char *pctx = NULL;
+ const version_entry_st *vers = get_version(session);
int ret;
if (context != NULL && context_size > 65535) {
@@ -126,22 +136,52 @@ gnutls_prf_rfc5705(gnutls_session_t session,
return GNUTLS_E_INVALID_REQUEST;
}
- if (context != NULL) {
- pctx = gnutls_malloc(context_size+2);
- if (!pctx) {
+ if (vers && vers->tls13_sem) {
+ uint8_t secret[MAX_HASH_SIZE];
+ uint8_t digest[MAX_HASH_SIZE];
+ unsigned digest_size = session->security_parameters.prf->output_size;
+
+ /* exporter_master_secret might not be set, when
+ * handshake is in progress */
+ if (session->internals.handshake_in_progress) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
+ return GNUTLS_E_INVALID_REQUEST;
}
- memcpy(pctx+2, context, context_size);
- _gnutls_write_uint16(context_size, (void*)pctx);
- context_size += 2;
- }
+ ret = _tls13_derive_secret(session, label, label_size, NULL, 0,
+ session->key.ap_expkey, secret);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_hash_fast((gnutls_digest_algorithm_t)session->security_parameters.prf->id,
+ context, context_size, digest);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _tls13_expand_secret(session, EXPORTER_LABEL, sizeof(EXPORTER_LABEL)-1,
+ digest, digest_size,
+ secret, outsize, out);
+ } else {
+ char *pctx = NULL;
- ret = gnutls_prf(session, label_size, label, 0,
- context_size, pctx, outsize, out);
+ if (context != NULL) {
+ pctx = gnutls_malloc(context_size+2);
+ if (!pctx) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ memcpy(pctx+2, context, context_size);
+ _gnutls_write_uint16(context_size, (void*)pctx);
+ context_size += 2;
+ }
+
+ ret = gnutls_prf(session, label_size, label, 0,
+ context_size, pctx, outsize, out);
+
+ gnutls_free(pctx);
+ }
- gnutls_free(pctx);
return ret;
}
@@ -160,6 +200,10 @@ gnutls_prf_rfc5705(gnutls_session_t session,
* and the provided data, seeded with the client and server random fields.
* For the key expansion specified in RFC5705 see gnutls_prf_rfc5705().
*
+ * This function only works with the TLS versions prior to 1.3. In
+ * TLS 1.3, the use of PRF is replaced with HKDF (HMAC-based Key
+ * Derivation Function) based on the multi-stage key scheduling.
+ *
* The @label variable usually contains a string denoting the purpose
* for the generated data. The @server_random_first indicates whether
* the client random field or the server random field should be first