Use tls_connection_prf() for all EAP TLS-based key derivation
tls_openssl.c is the only remaining TLS/crypto wrapper that needs the internal PRF implementation for EAP-FAST (since SSL_export_keying_material() is not available in older versions and does not support server-random-before-client case). As such, it is cleaner to assume that TLS libraries support tls_connection_prf() and move the additional support code for the otherwise unsupported cases into tls_openssl.c. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
df8191d0b8
commit
fa0e715100
4 changed files with 75 additions and 101 deletions
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
#include "sha1.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
|
||||||
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
|
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
|
||||||
|
@ -2644,6 +2645,60 @@ int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
|
||||||
|
const char *label, int server_random_first,
|
||||||
|
u8 *out, size_t out_len)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_FIPS
|
||||||
|
wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
|
||||||
|
"mode");
|
||||||
|
return -1;
|
||||||
|
#else /* CONFIG_FIPS */
|
||||||
|
SSL *ssl;
|
||||||
|
u8 *rnd;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TLS library did not support key generation, so get the needed TLS
|
||||||
|
* session parameters and use an internal implementation of TLS PRF to
|
||||||
|
* derive the key.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (conn == NULL)
|
||||||
|
return -1;
|
||||||
|
ssl = conn->ssl;
|
||||||
|
if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
|
||||||
|
ssl->s3->client_random == NULL || ssl->s3->server_random == NULL ||
|
||||||
|
ssl->session->master_key == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
|
||||||
|
if (rnd == NULL)
|
||||||
|
return -1;
|
||||||
|
if (server_random_first) {
|
||||||
|
os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
|
||||||
|
os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
|
||||||
|
SSL3_RANDOM_SIZE);
|
||||||
|
} else {
|
||||||
|
os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
|
||||||
|
os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
|
||||||
|
SSL3_RANDOM_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: TLSv1.2 may need another PRF. This could use something closer
|
||||||
|
* to SSL_export_keying_material() design. */
|
||||||
|
if (tls_prf_sha1_md5(ssl->session->master_key,
|
||||||
|
ssl->session->master_key_length,
|
||||||
|
label, rnd, 2 * SSL3_RANDOM_SIZE,
|
||||||
|
out, out_len) == 0)
|
||||||
|
ret = 0;
|
||||||
|
os_free(rnd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif /* CONFIG_FIPS */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||||
const char *label, int server_random_first,
|
const char *label, int server_random_first,
|
||||||
u8 *out, size_t out_len)
|
u8 *out, size_t out_len)
|
||||||
|
@ -2653,7 +2708,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (server_random_first)
|
if (server_random_first)
|
||||||
return -1;
|
return openssl_tls_prf(tls_ctx, conn, label,
|
||||||
|
server_random_first, out, out_len);
|
||||||
ssl = conn->ssl;
|
ssl = conn->ssl;
|
||||||
if (SSL_export_keying_material(ssl, out, out_len, label,
|
if (SSL_export_keying_material(ssl, out, out_len, label,
|
||||||
os_strlen(label), NULL, 0, 0) == 1) {
|
os_strlen(label), NULL, 0, 0) == 1) {
|
||||||
|
@ -2661,7 +2717,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
|
||||||
|
out, out_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,7 @@ void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
|
||||||
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
|
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
|
||||||
const char *label, size_t len)
|
const char *label, size_t len)
|
||||||
{
|
{
|
||||||
struct tls_keys keys;
|
u8 *out;
|
||||||
u8 *rnd = NULL, *out;
|
|
||||||
int block_size;
|
int block_size;
|
||||||
|
|
||||||
block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
|
block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
|
||||||
|
@ -108,39 +107,17 @@ u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
|
if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len))
|
||||||
== 0) {
|
{
|
||||||
os_memmove(out, out + block_size, len);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tls_connection_get_keys(ssl_ctx, conn, &keys))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
|
||||||
if (rnd == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
os_memcpy(rnd, keys.server_random, keys.server_random_len);
|
|
||||||
os_memcpy(rnd + keys.server_random_len, keys.client_random,
|
|
||||||
keys.client_random_len);
|
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
|
|
||||||
"expansion", keys.master_key, keys.master_key_len);
|
|
||||||
if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
|
|
||||||
label, rnd, keys.client_random_len +
|
|
||||||
keys.server_random_len, out, block_size + len))
|
|
||||||
goto fail;
|
|
||||||
os_free(rnd);
|
|
||||||
os_memmove(out, out + block_size, len);
|
|
||||||
return out;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
os_free(rnd);
|
|
||||||
os_free(out);
|
os_free(out);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_memmove(out, out + block_size, len);
|
||||||
|
os_memset(out + len, 0, block_size);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
|
void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
|
||||||
{
|
{
|
||||||
|
|
|
@ -313,55 +313,20 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
|
||||||
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||||
const char *label, size_t len)
|
const char *label, size_t len)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_FIPS
|
u8 *out;
|
||||||
struct tls_keys keys;
|
|
||||||
#endif /* CONFIG_FIPS */
|
|
||||||
u8 *rnd = NULL, *out;
|
|
||||||
|
|
||||||
out = os_malloc(len);
|
out = os_malloc(len);
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* First, try to use TLS library function for PRF, if available. */
|
if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)) {
|
||||||
if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
|
|
||||||
== 0)
|
|
||||||
return out;
|
|
||||||
|
|
||||||
#ifndef CONFIG_FIPS
|
|
||||||
/*
|
|
||||||
* TLS library did not support key generation, so get the needed TLS
|
|
||||||
* session parameters and use an internal implementation of TLS PRF to
|
|
||||||
* derive the key.
|
|
||||||
*/
|
|
||||||
if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (keys.client_random == NULL || keys.server_random == NULL ||
|
|
||||||
keys.master_key == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
|
||||||
if (rnd == NULL)
|
|
||||||
goto fail;
|
|
||||||
os_memcpy(rnd, keys.client_random, keys.client_random_len);
|
|
||||||
os_memcpy(rnd + keys.client_random_len, keys.server_random,
|
|
||||||
keys.server_random_len);
|
|
||||||
|
|
||||||
if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
|
|
||||||
label, rnd, keys.client_random_len +
|
|
||||||
keys.server_random_len, out, len))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
os_free(rnd);
|
|
||||||
return out;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
#endif /* CONFIG_FIPS */
|
|
||||||
os_free(out);
|
os_free(out);
|
||||||
os_free(rnd);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
|
* eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
|
||||||
|
|
|
@ -100,45 +100,20 @@ void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
|
||||||
u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||||
char *label, size_t len)
|
char *label, size_t len)
|
||||||
{
|
{
|
||||||
struct tls_keys keys;
|
u8 *out;
|
||||||
u8 *rnd = NULL, *out;
|
|
||||||
|
|
||||||
out = os_malloc(len);
|
out = os_malloc(len);
|
||||||
if (out == NULL)
|
if (out == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
|
if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len)) {
|
||||||
0)
|
|
||||||
return out;
|
|
||||||
|
|
||||||
if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (keys.client_random == NULL || keys.server_random == NULL ||
|
|
||||||
keys.master_key == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
|
|
||||||
if (rnd == NULL)
|
|
||||||
goto fail;
|
|
||||||
os_memcpy(rnd, keys.client_random, keys.client_random_len);
|
|
||||||
os_memcpy(rnd + keys.client_random_len, keys.server_random,
|
|
||||||
keys.server_random_len);
|
|
||||||
|
|
||||||
if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
|
|
||||||
label, rnd, keys.client_random_len +
|
|
||||||
keys.server_random_len, out, len))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
os_free(rnd);
|
|
||||||
return out;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
os_free(out);
|
os_free(out);
|
||||||
os_free(rnd);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
|
* eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
|
||||||
|
|
Loading…
Reference in a new issue