Stronger GTK derivation routine

If the build include SHA384, use that to derive GTK from GMK. In
addition, add more random bytes bytes to the PRF-X() context data for
longer GTK to reduce dependency on the randomness of the GMK.

GMK is 256 bits of random data and it was used with SHA256, so the
previous design was likely sufficient for all needs even with 128 bits
of additional randomness in GTK derivation. Anyway, adding up to 256
bits of new randomness and using SHA384 can be helpful extra protection
particularly for the cases using GCMP-256 or CCMP-256 as the group
cipher.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2017-11-18 17:08:11 +02:00
parent a680f4ef39
commit c6eb3e34b6

View file

@ -19,6 +19,7 @@
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/sha1.h" #include "crypto/sha1.h"
#include "crypto/sha256.h" #include "crypto/sha256.h"
#include "crypto/sha384.h"
#include "crypto/random.h" #include "crypto/random.h"
#include "eapol_auth/eapol_auth_sm.h" #include "eapol_auth/eapol_auth_sm.h"
#include "ap_config.h" #include "ap_config.h"
@ -1318,7 +1319,7 @@ continue_processing:
static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
const u8 *gnonce, u8 *gtk, size_t gtk_len) const u8 *gnonce, u8 *gtk, size_t gtk_len)
{ {
u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
u8 *pos; u8 *pos;
int ret = 0; int ret = 0;
@ -1329,21 +1330,30 @@ static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
* is done only at the Authenticator and as such, does not need to be * is done only at the Authenticator and as such, does not need to be
* exactly same. * exactly same.
*/ */
os_memset(data, 0, sizeof(data));
os_memcpy(data, addr, ETH_ALEN); os_memcpy(data, addr, ETH_ALEN);
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
pos = data + ETH_ALEN + WPA_NONCE_LEN; pos = data + ETH_ALEN + WPA_NONCE_LEN;
wpa_get_ntp_timestamp(pos); wpa_get_ntp_timestamp(pos);
pos += 8; pos += 8;
if (random_get_bytes(pos, 16) < 0) if (random_get_bytes(pos, gtk_len) < 0)
ret = -1; ret = -1;
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_SHA384
sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
#else /* CONFIG_IEEE80211W */ gtk, gtk_len) < 0)
if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len)
< 0)
ret = -1; ret = -1;
#endif /* CONFIG_IEEE80211W */ #else /* CONFIG_SHA384 */
#ifdef CONFIG_SHA256
if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
gtk, gtk_len) < 0)
ret = -1;
#else /* CONFIG_SHA256 */
if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
gtk, gtk_len) < 0)
ret = -1;
#endif /* CONFIG_SHA256 */
#endif /* CONFIG_SHA384 */
return ret; return ret;
} }