From: Tobias Brunner Date: Tue, 1 Sep 2020 16:50:47 +0000 (+0200) Subject: tls-hkdf: Add method that allows exporting key material X-Git-Tag: 5.9.2rc1~23^2~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2fe921cf5f5fd7940495891afe108d26c1c1ca7;p=thirdparty%2Fstrongswan.git tls-hkdf: Add method that allows exporting key material --- diff --git a/src/libtls/tls_hkdf.c b/src/libtls/tls_hkdf.c index be5d57a3d8..d31a41d79e 100644 --- a/src/libtls/tls_hkdf.c +++ b/src/libtls/tls_hkdf.c @@ -524,6 +524,54 @@ METHOD(tls_hkdf_t, derive_finished, bool, finished); } +METHOD(tls_hkdf_t, export, bool, + private_tls_hkdf_t *this, char *label, chunk_t context, + chunk_t messages, size_t length, chunk_t *key) +{ + chunk_t exporter_master, exporter, hash = chunk_empty; + + if (this->phase != HKDF_PHASE_3) + { + DBG1(DBG_TLS, "unable to export key material"); + return FALSE; + } + + /** + * Export key material according to RFC 8446, section 7.5: + * + * TLS-Exporter(label, context_value, key_length) = + * HKDF-Expand-Label(Derive-Secret(Secret, label, ""), + * "exporter", Hash(context_value), key_length) + */ + if (!generate_secret(this, TLS_HKDF_EXP_MASTER, messages, &exporter_master)) + { + DBG1(DBG_TLS, "unable to derive exporter master secret"); + return FALSE; + } + + if (!derive_secret(this, exporter_master, chunk_from_str(label), + chunk_empty, &exporter)) + { + DBG1(DBG_TLS, "unable to derive exporter secret"); + chunk_clear(&exporter_master); + return FALSE; + } + chunk_clear(&exporter_master); + + if (!this->hasher->allocate_hash(this->hasher, context, &hash) || + !expand_label(this, exporter, chunk_from_str("exporter"), hash, + length, key)) + { + DBG1(DBG_TLS, "unable to expand key material"); + chunk_clear(&exporter); + chunk_free(&hash); + return FALSE; + } + chunk_clear(&exporter); + chunk_free(&hash); + return TRUE; +} + METHOD(tls_hkdf_t, allocate_bytes, bool, private_tls_hkdf_t *this, chunk_t key, chunk_t seed, chunk_t *out) @@ -571,6 +619,7 @@ tls_hkdf_t *tls_hkdf_create(hash_algorithm_t hash_algorithm, chunk_t psk) .derive_key = _derive_key, .derive_iv = _derive_iv, .derive_finished = _derive_finished, + .export = _export, .allocate_bytes = _allocate_bytes, .destroy = _destroy, }, diff --git a/src/libtls/tls_hkdf.h b/src/libtls/tls_hkdf.h index 352d8e3996..2b2bf3e034 100644 --- a/src/libtls/tls_hkdf.h +++ b/src/libtls/tls_hkdf.h @@ -113,6 +113,19 @@ struct tls_hkdf_t { bool (*derive_finished)(tls_hkdf_t *this, bool is_server, chunk_t *finished); + /** + * Export key material. + * + * @param label exporter label + * @param context optional context + * @param messages handshake messages + * @param length key length, in bytes + * @param key exported key material + * @return TRUE if key material successfully exported + */ + bool (*export)(tls_hkdf_t *this, char *label, chunk_t context, + chunk_t messages, size_t length, chunk_t *key); + /** * Use the internal PRF to allocate data (mainly for the finished message * where the key is from derive_finished() and the seed is the transcript