EAP-TEAP: Fix TLS-PRF for TLS ciphersuites that use SHA384
These need to be using the HMAC-based TLS-PRF with SHA384 instead of SHA256 as the hash algorithm. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
52069c7eff
commit
a66e53c419
4 changed files with 44 additions and 24 deletions
|
@ -17,6 +17,9 @@
|
||||||
#include "eap_teap_common.h"
|
#include "eap_teap_common.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int tls_cipher_suite_mac_sha384(u16 cs);
|
||||||
|
|
||||||
|
|
||||||
void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
|
void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
|
||||||
{
|
{
|
||||||
struct teap_tlv_hdr hdr;
|
struct teap_tlv_hdr hdr;
|
||||||
|
@ -67,24 +70,27 @@ struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int eap_teap_tls_prf(const u8 *secret, size_t secret_len,
|
static int eap_teap_tls_prf(u16 tls_cs, const u8 *secret, size_t secret_len,
|
||||||
const char *label, const u8 *seed, size_t seed_len,
|
const char *label, const u8 *seed, size_t seed_len,
|
||||||
u8 *out, size_t outlen)
|
u8 *out, size_t outlen)
|
||||||
{
|
{
|
||||||
/* TODO: TLS-PRF for TLSv1.3 */
|
/* TODO: TLS-PRF for TLSv1.3 */
|
||||||
|
if (tls_cipher_suite_mac_sha384(tls_cs))
|
||||||
|
return tls_prf_sha384(secret, secret_len, label, seed, seed_len,
|
||||||
|
out, outlen);
|
||||||
return tls_prf_sha256(secret, secret_len, label, seed, seed_len,
|
return tls_prf_sha256(secret, secret_len, label, seed, seed_len,
|
||||||
out, outlen);
|
out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_teap_derive_eap_msk(const u8 *simck, u8 *msk)
|
int eap_teap_derive_eap_msk(u16 tls_cs, const u8 *simck, u8 *msk)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* RFC 7170, Section 5.4: EAP Master Session Key Generation
|
* RFC 7170, Section 5.4: EAP Master Session Key Generation
|
||||||
* MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
|
* MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN,
|
if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
|
||||||
"Session Key Generating Function", (u8 *) "", 0,
|
"Session Key Generating Function", (u8 *) "", 0,
|
||||||
msk, EAP_TEAP_KEY_LEN) < 0)
|
msk, EAP_TEAP_KEY_LEN) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -94,7 +100,7 @@ int eap_teap_derive_eap_msk(const u8 *simck, u8 *msk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk)
|
int eap_teap_derive_eap_emsk(u16 tls_cs, const u8 *simck, u8 *emsk)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* RFC 7170, Section 5.4: EAP Master Session Key Generation
|
* RFC 7170, Section 5.4: EAP Master Session Key Generation
|
||||||
|
@ -102,7 +108,7 @@ int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk)
|
||||||
* "Extended Session Key Generating Function", 64)
|
* "Extended Session Key Generating Function", 64)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN,
|
if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
|
||||||
"Extended Session Key Generating Function",
|
"Extended Session Key Generating Function",
|
||||||
(u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0)
|
(u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -112,7 +118,7 @@ int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk)
|
int eap_teap_derive_cmk_basic_pw_auth(u16 tls_cs, const u8 *s_imck_msk, u8 *cmk)
|
||||||
{
|
{
|
||||||
u8 imsk[32], imck[EAP_TEAP_IMCK_LEN];
|
u8 imsk[32], imck[EAP_TEAP_IMCK_LEN];
|
||||||
int res;
|
int res;
|
||||||
|
@ -123,7 +129,7 @@ int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk)
|
||||||
* published. For now, derive CMK[0] based on S-IMCK[0] and
|
* published. For now, derive CMK[0] based on S-IMCK[0] and
|
||||||
* IMSK of 32 octets of zeros. */
|
* IMSK of 32 octets of zeros. */
|
||||||
os_memset(imsk, 0, 32);
|
os_memset(imsk, 0, 32);
|
||||||
res = eap_teap_tls_prf(s_imck_msk, EAP_TEAP_SIMCK_LEN,
|
res = eap_teap_tls_prf(tls_cs, s_imck_msk, EAP_TEAP_SIMCK_LEN,
|
||||||
"Inner Methods Compound Keys",
|
"Inner Methods Compound Keys",
|
||||||
imsk, 32, imck, sizeof(imck));
|
imsk, 32, imck, sizeof(imck));
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
|
@ -136,7 +142,8 @@ int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
int eap_teap_derive_imck(u16 tls_cs,
|
||||||
|
const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
||||||
const u8 *msk, size_t msk_len,
|
const u8 *msk, size_t msk_len,
|
||||||
const u8 *emsk, size_t emsk_len,
|
const u8 *emsk, size_t emsk_len,
|
||||||
u8 *s_imck_msk, u8 *cmk_msk,
|
u8 *s_imck_msk, u8 *cmk_msk,
|
||||||
|
@ -170,14 +177,16 @@ int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
||||||
context[0] = 0;
|
context[0] = 0;
|
||||||
context[1] = 0;
|
context[1] = 0;
|
||||||
context[2] = 64;
|
context[2] = 64;
|
||||||
if (eap_teap_tls_prf(emsk, emsk_len, "TEAPbindkey@ietf.org",
|
if (eap_teap_tls_prf(tls_cs, emsk, emsk_len,
|
||||||
|
"TEAPbindkey@ietf.org",
|
||||||
context, sizeof(context), imsk, 64) < 0)
|
context, sizeof(context), imsk, 64) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
|
||||||
imsk, 32);
|
imsk, 32);
|
||||||
|
|
||||||
res = eap_teap_tls_prf(prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN,
|
res = eap_teap_tls_prf(tls_cs,
|
||||||
|
prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN,
|
||||||
"Inner Methods Compound Keys",
|
"Inner Methods Compound Keys",
|
||||||
imsk, 32, imck, EAP_TEAP_IMCK_LEN);
|
imsk, 32, imck, EAP_TEAP_IMCK_LEN);
|
||||||
forced_memzero(imsk, sizeof(imsk));
|
forced_memzero(imsk, sizeof(imsk));
|
||||||
|
@ -207,7 +216,7 @@ int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = eap_teap_tls_prf(prev_s_imck_msk, EAP_TEAP_SIMCK_LEN,
|
res = eap_teap_tls_prf(tls_cs, prev_s_imck_msk, EAP_TEAP_SIMCK_LEN,
|
||||||
"Inner Methods Compound Keys",
|
"Inner Methods Compound Keys",
|
||||||
imsk, 32, imck, EAP_TEAP_IMCK_LEN);
|
imsk, 32, imck, EAP_TEAP_IMCK_LEN);
|
||||||
forced_memzero(imsk, sizeof(imsk));
|
forced_memzero(imsk, sizeof(imsk));
|
||||||
|
|
|
@ -195,10 +195,12 @@ void eap_teap_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len);
|
||||||
void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type,
|
void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type,
|
||||||
const struct wpabuf *data);
|
const struct wpabuf *data);
|
||||||
struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf);
|
struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf);
|
||||||
int eap_teap_derive_eap_msk(const u8 *simck, u8 *msk);
|
int eap_teap_derive_eap_msk(u16 tls_cs, const u8 *simck, u8 *msk);
|
||||||
int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk);
|
int eap_teap_derive_eap_emsk(u16 tls_cs, const u8 *simck, u8 *emsk);
|
||||||
int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk);
|
int eap_teap_derive_cmk_basic_pw_auth(u16 tls_cs, const u8 *s_imck_msk,
|
||||||
int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
u8 *cmk);
|
||||||
|
int eap_teap_derive_imck(u16 tls_cs,
|
||||||
|
const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
|
||||||
const u8 *msk, size_t msk_len,
|
const u8 *msk, size_t msk_len,
|
||||||
const u8 *emsk, size_t emsk_len,
|
const u8 *emsk, size_t emsk_len,
|
||||||
u8 *s_imck_msk, u8 *cmk_msk,
|
u8 *s_imck_msk, u8 *cmk_msk,
|
||||||
|
|
|
@ -277,8 +277,10 @@ static int eap_teap_derive_msk(struct eap_teap_data *data)
|
||||||
{
|
{
|
||||||
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
||||||
* is used in this derivation */
|
* is used in this derivation */
|
||||||
if (eap_teap_derive_eap_msk(data->simck_msk, data->key_data) < 0 ||
|
if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
|
||||||
eap_teap_derive_eap_emsk(data->simck_msk, data->emsk) < 0)
|
data->key_data) < 0 ||
|
||||||
|
eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
|
||||||
|
data->emsk) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
data->success = 1;
|
data->success = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -680,7 +682,8 @@ static int eap_teap_get_cmk(struct eap_sm *sm, struct eap_teap_data *data,
|
||||||
data->simck_idx + 1);
|
data->simck_idx + 1);
|
||||||
|
|
||||||
if (!data->phase2_method)
|
if (!data->phase2_method)
|
||||||
return eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
|
return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
|
||||||
|
data->simck_msk,
|
||||||
cmk_msk);
|
cmk_msk);
|
||||||
|
|
||||||
if (!data->phase2_method || !data->phase2_priv) {
|
if (!data->phase2_method || !data->phase2_priv) {
|
||||||
|
@ -712,7 +715,8 @@ static int eap_teap_get_cmk(struct eap_sm *sm, struct eap_teap_data *data,
|
||||||
&emsk_len);
|
&emsk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = eap_teap_derive_imck(data->simck_msk, data->simck_emsk,
|
res = eap_teap_derive_imck(data->tls_cs,
|
||||||
|
data->simck_msk, data->simck_emsk,
|
||||||
msk, msk_len, emsk, emsk_len,
|
msk, msk_len, emsk, emsk_len,
|
||||||
data->simck_msk, cmk_msk,
|
data->simck_msk, cmk_msk,
|
||||||
data->simck_emsk, cmk_emsk);
|
data->simck_emsk, cmk_emsk);
|
||||||
|
|
|
@ -309,7 +309,8 @@ static int eap_teap_update_icmk(struct eap_sm *sm, struct eap_teap_data *data)
|
||||||
data->simck_idx + 1);
|
data->simck_idx + 1);
|
||||||
|
|
||||||
if (sm->eap_teap_auth == 1)
|
if (sm->eap_teap_auth == 1)
|
||||||
return eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
|
return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
|
||||||
|
data->simck_msk,
|
||||||
data->cmk_msk);
|
data->cmk_msk);
|
||||||
|
|
||||||
if (!data->phase2_method || !data->phase2_priv) {
|
if (!data->phase2_method || !data->phase2_priv) {
|
||||||
|
@ -332,7 +333,8 @@ static int eap_teap_update_icmk(struct eap_sm *sm, struct eap_teap_data *data)
|
||||||
&emsk_len);
|
&emsk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = eap_teap_derive_imck(data->simck_msk, data->simck_emsk,
|
res = eap_teap_derive_imck(data->tls_cs,
|
||||||
|
data->simck_msk, data->simck_emsk,
|
||||||
msk, msk_len, emsk, emsk_len,
|
msk, msk_len, emsk, emsk_len,
|
||||||
data->simck_msk, data->cmk_msk,
|
data->simck_msk, data->cmk_msk,
|
||||||
data->simck_emsk, data->cmk_emsk);
|
data->simck_emsk, data->cmk_emsk);
|
||||||
|
@ -1643,7 +1645,8 @@ static int eap_teap_process_phase2_start(struct eap_sm *sm,
|
||||||
/* FIX: Need to derive CMK here. However, how is that
|
/* FIX: Need to derive CMK here. However, how is that
|
||||||
* supposed to be done? RFC 7170 does not tell that for
|
* supposed to be done? RFC 7170 does not tell that for
|
||||||
* the no-inner-auth case. */
|
* the no-inner-auth case. */
|
||||||
eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
|
eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
|
||||||
|
data->simck_msk,
|
||||||
data->cmk_msk);
|
data->cmk_msk);
|
||||||
eap_teap_state(data, CRYPTO_BINDING);
|
eap_teap_state(data, CRYPTO_BINDING);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1853,7 +1856,8 @@ static u8 * eap_teap_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||||
|
|
||||||
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
||||||
* is used in this derivation */
|
* is used in this derivation */
|
||||||
if (eap_teap_derive_eap_msk(data->simck_msk, eapKeyData) < 0) {
|
if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
|
||||||
|
eapKeyData) < 0) {
|
||||||
os_free(eapKeyData);
|
os_free(eapKeyData);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1877,7 +1881,8 @@ static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
||||||
|
|
||||||
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
|
||||||
* is used in this derivation */
|
* is used in this derivation */
|
||||||
if (eap_teap_derive_eap_emsk(data->simck_msk, eapKeyData) < 0) {
|
if (eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
|
||||||
|
eapKeyData) < 0) {
|
||||||
os_free(eapKeyData);
|
os_free(eapKeyData);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue