mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-26 02:19:26 +01:00
crypto: update FT derivation functions to use sha384
FILS-FT requires the SHA384 KDF to derive the FT keys
This commit is contained in:
parent
aafb3fa7ed
commit
bc381bd8c3
92
src/crypto.c
92
src/crypto.c
@ -840,17 +840,18 @@ bool crypto_derive_pmk_r0(const uint8_t *xxkey, size_t xxkey_len,
|
|||||||
const uint8_t *ssid, size_t ssid_len,
|
const uint8_t *ssid, size_t ssid_len,
|
||||||
uint16_t mdid,
|
uint16_t mdid,
|
||||||
const uint8_t *r0khid, size_t r0kh_len,
|
const uint8_t *r0khid, size_t r0kh_len,
|
||||||
const uint8_t *s0khid, uint8_t *out_pmk_r0,
|
const uint8_t *s0khid, bool sha384,
|
||||||
uint8_t *out_pmk_r0_name)
|
uint8_t *out_pmk_r0, uint8_t *out_pmk_r0_name)
|
||||||
{
|
{
|
||||||
uint8_t context[512];
|
uint8_t context[512];
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
uint8_t output[48];
|
uint8_t output[64];
|
||||||
struct l_checksum *sha256;
|
size_t offset = sha384 ? 48 : 32;
|
||||||
|
struct l_checksum *sha;
|
||||||
bool r = false;
|
bool r = false;
|
||||||
struct iovec iov[2] = {
|
struct iovec iov[2] = {
|
||||||
[0] = { .iov_base = "FT-R0N", .iov_len = 6 },
|
[0] = { .iov_base = "FT-R0N", .iov_len = 6 },
|
||||||
[1] = { .iov_base = output + 32, .iov_len = 16 },
|
[1] = { .iov_base = output + offset, .iov_len = 16 },
|
||||||
};
|
};
|
||||||
|
|
||||||
context[pos++] = ssid_len;
|
context[pos++] = ssid_len;
|
||||||
@ -869,25 +870,32 @@ bool crypto_derive_pmk_r0(const uint8_t *xxkey, size_t xxkey_len,
|
|||||||
memcpy(context + pos, s0khid, ETH_ALEN);
|
memcpy(context + pos, s0khid, ETH_ALEN);
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
if (!kdf_sha256(xxkey, xxkey_len, "FT-R0", 5, context, pos, output, 48))
|
if (sha384) {
|
||||||
|
if (!kdf_sha384(xxkey, xxkey_len, "FT-R0", 5, context, pos,
|
||||||
|
output, 64))
|
||||||
|
goto exit;
|
||||||
|
} else {
|
||||||
|
if (!kdf_sha256(xxkey, xxkey_len, "FT-R0", 5, context, pos,
|
||||||
|
output, 48))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha = l_checksum_new((sha384) ? L_CHECKSUM_SHA384 : L_CHECKSUM_SHA256);
|
||||||
|
if (!sha)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
sha256 = l_checksum_new(L_CHECKSUM_SHA256);
|
l_checksum_updatev(sha, iov, 2);
|
||||||
if (!sha256)
|
l_checksum_get_digest(sha, out_pmk_r0_name, 16);
|
||||||
goto exit;
|
|
||||||
|
|
||||||
l_checksum_updatev(sha256, iov, 2);
|
l_checksum_free(sha);
|
||||||
l_checksum_get_digest(sha256, out_pmk_r0_name, 16);
|
|
||||||
|
|
||||||
l_checksum_free(sha256);
|
memcpy(out_pmk_r0, output, offset);
|
||||||
|
|
||||||
memcpy(out_pmk_r0, output, 32);
|
|
||||||
|
|
||||||
r = true;
|
r = true;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
explicit_bzero(context, pos);
|
explicit_bzero(context, pos);
|
||||||
explicit_bzero(output, 48);
|
explicit_bzero(output, 64);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -895,12 +903,12 @@ exit:
|
|||||||
/* Defined in 802.11-2012, Section 11.6.1.7.4 PMK-R1 */
|
/* Defined in 802.11-2012, Section 11.6.1.7.4 PMK-R1 */
|
||||||
bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
|
bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
|
||||||
const uint8_t *r1khid, const uint8_t *s1khid,
|
const uint8_t *r1khid, const uint8_t *s1khid,
|
||||||
const uint8_t *pmk_r0_name,
|
const uint8_t *pmk_r0_name, bool sha384,
|
||||||
uint8_t *out_pmk_r1,
|
uint8_t *out_pmk_r1,
|
||||||
uint8_t *out_pmk_r1_name)
|
uint8_t *out_pmk_r1_name)
|
||||||
{
|
{
|
||||||
uint8_t context[2 * ETH_ALEN];
|
uint8_t context[2 * ETH_ALEN];
|
||||||
struct l_checksum *sha256;
|
struct l_checksum *sha;
|
||||||
bool r = false;
|
bool r = false;
|
||||||
struct iovec iov[3] = {
|
struct iovec iov[3] = {
|
||||||
[0] = { .iov_base = "FT-R1N", .iov_len = 6 },
|
[0] = { .iov_base = "FT-R1N", .iov_len = 6 },
|
||||||
@ -912,20 +920,26 @@ bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
|
|||||||
|
|
||||||
memcpy(context + ETH_ALEN, s1khid, ETH_ALEN);
|
memcpy(context + ETH_ALEN, s1khid, ETH_ALEN);
|
||||||
|
|
||||||
if (!kdf_sha256(pmk_r0, 32, "FT-R1", 5, context, sizeof(context),
|
if (sha384) {
|
||||||
out_pmk_r1, 32))
|
if (!kdf_sha384(pmk_r0, 48, "FT-R1", 5, context,
|
||||||
goto exit;
|
sizeof(context), out_pmk_r1, 48))
|
||||||
|
goto exit;
|
||||||
|
} else {
|
||||||
|
if (!kdf_sha256(pmk_r0, 32, "FT-R1", 5, context,
|
||||||
|
sizeof(context), out_pmk_r1, 32))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
sha256 = l_checksum_new(L_CHECKSUM_SHA256);
|
sha = l_checksum_new((sha384) ? L_CHECKSUM_SHA384 : L_CHECKSUM_SHA256);
|
||||||
if (!sha256) {
|
if (!sha) {
|
||||||
explicit_bzero(out_pmk_r1, 32);
|
explicit_bzero(out_pmk_r1, 48);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
l_checksum_updatev(sha256, iov, 3);
|
l_checksum_updatev(sha, iov, 3);
|
||||||
l_checksum_get_digest(sha256, out_pmk_r1_name, 16);
|
l_checksum_get_digest(sha, out_pmk_r1_name, 16);
|
||||||
|
|
||||||
l_checksum_free(sha256);
|
l_checksum_free(sha);
|
||||||
|
|
||||||
r = true;
|
r = true;
|
||||||
|
|
||||||
@ -939,11 +953,11 @@ exit:
|
|||||||
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
|
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
|
||||||
const uint8_t *addr1, const uint8_t *addr2,
|
const uint8_t *addr1, const uint8_t *addr2,
|
||||||
const uint8_t *nonce1, const uint8_t *nonce2,
|
const uint8_t *nonce1, const uint8_t *nonce2,
|
||||||
uint8_t *out_ptk, size_t ptk_len,
|
bool sha384, uint8_t *out_ptk, size_t ptk_len,
|
||||||
uint8_t *out_ptk_name)
|
uint8_t *out_ptk_name)
|
||||||
{
|
{
|
||||||
uint8_t context[ETH_ALEN * 2 + 64];
|
uint8_t context[ETH_ALEN * 2 + 64];
|
||||||
struct l_checksum *sha256;
|
struct l_checksum *sha;
|
||||||
bool r = false;
|
bool r = false;
|
||||||
struct iovec iov[3] = {
|
struct iovec iov[3] = {
|
||||||
[0] = { .iov_base = (uint8_t *) pmk_r1_name, .iov_len = 16 },
|
[0] = { .iov_base = (uint8_t *) pmk_r1_name, .iov_len = 16 },
|
||||||
@ -959,20 +973,26 @@ bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
|
|||||||
|
|
||||||
memcpy(context + 64 + ETH_ALEN, addr2, ETH_ALEN);
|
memcpy(context + 64 + ETH_ALEN, addr2, ETH_ALEN);
|
||||||
|
|
||||||
if (!kdf_sha256(pmk_r1, 32, "FT-PTK", 6, context, sizeof(context),
|
if (sha384) {
|
||||||
out_ptk, ptk_len))
|
if (!kdf_sha384(pmk_r1, 48, "FT-PTK", 6, context,
|
||||||
goto exit;
|
sizeof(context), out_ptk, ptk_len))
|
||||||
|
goto exit;
|
||||||
|
} else {
|
||||||
|
if (!kdf_sha256(pmk_r1, 32, "FT-PTK", 6, context,
|
||||||
|
sizeof(context), out_ptk, ptk_len))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
sha256 = l_checksum_new(L_CHECKSUM_SHA256);
|
sha = l_checksum_new((sha384) ? L_CHECKSUM_SHA384 : L_CHECKSUM_SHA256);
|
||||||
if (!sha256) {
|
if (!sha) {
|
||||||
explicit_bzero(out_ptk, ptk_len);
|
explicit_bzero(out_ptk, ptk_len);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
l_checksum_updatev(sha256, iov, 3);
|
l_checksum_updatev(sha, iov, 3);
|
||||||
l_checksum_get_digest(sha256, out_ptk_name, 16);
|
l_checksum_get_digest(sha, out_ptk_name, 16);
|
||||||
|
|
||||||
l_checksum_free(sha256);
|
l_checksum_free(sha);
|
||||||
|
|
||||||
r = true;
|
r = true;
|
||||||
|
|
||||||
|
@ -120,17 +120,17 @@ bool crypto_derive_pmk_r0(const uint8_t *xxkey, size_t xxkey_len,
|
|||||||
const uint8_t *ssid, size_t ssid_len,
|
const uint8_t *ssid, size_t ssid_len,
|
||||||
uint16_t mdid,
|
uint16_t mdid,
|
||||||
const uint8_t *r0khid, size_t r0kh_len,
|
const uint8_t *r0khid, size_t r0kh_len,
|
||||||
const uint8_t *s0khid, uint8_t *out_pmk_r0,
|
const uint8_t *s0khid, bool sha384,
|
||||||
uint8_t *out_pmk_r0_name);
|
uint8_t *out_pmk_r0, uint8_t *out_pmk_r0_name);
|
||||||
bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
|
bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
|
||||||
const uint8_t *r1khid, const uint8_t *s1khid,
|
const uint8_t *r1khid, const uint8_t *s1khid,
|
||||||
const uint8_t *pmk_r0_name,
|
const uint8_t *pmk_r0_name, bool sha384,
|
||||||
uint8_t *out_pmk_r1,
|
uint8_t *out_pmk_r1,
|
||||||
uint8_t *out_pmk_r1_name);
|
uint8_t *out_pmk_r1_name);
|
||||||
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
|
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
|
||||||
const uint8_t *addr1, const uint8_t *addr2,
|
const uint8_t *addr1, const uint8_t *addr2,
|
||||||
const uint8_t *nonce1, const uint8_t *nonce2,
|
const uint8_t *nonce1, const uint8_t *nonce2,
|
||||||
uint8_t *out_ptk, size_t ptk_len,
|
bool sha384, uint8_t *out_ptk, size_t ptk_len,
|
||||||
uint8_t *out_ptk_name);
|
uint8_t *out_ptk_name);
|
||||||
|
|
||||||
bool crypto_derive_pmkid(const uint8_t *pmk,
|
bool crypto_derive_pmkid(const uint8_t *pmk,
|
||||||
|
@ -434,18 +434,19 @@ bool handshake_state_derive_ptk(struct handshake_state *s)
|
|||||||
|
|
||||||
if (!crypto_derive_pmk_r0(xxkey, 32, s->ssid, s->ssid_len, mdid,
|
if (!crypto_derive_pmk_r0(xxkey, 32, s->ssid, s->ssid_len, mdid,
|
||||||
s->r0khid, s->r0khid_len,
|
s->r0khid, s->r0khid_len,
|
||||||
s->spa,
|
s->spa, false,
|
||||||
s->pmk_r0, s->pmk_r0_name))
|
s->pmk_r0, s->pmk_r0_name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!crypto_derive_pmk_r1(s->pmk_r0, s->r1khid, s->spa,
|
if (!crypto_derive_pmk_r1(s->pmk_r0, s->r1khid, s->spa,
|
||||||
s->pmk_r0_name,
|
s->pmk_r0_name, false,
|
||||||
s->pmk_r1, s->pmk_r1_name))
|
s->pmk_r1, s->pmk_r1_name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!crypto_derive_ft_ptk(s->pmk_r1, s->pmk_r1_name, s->aa,
|
if (!crypto_derive_ft_ptk(s->pmk_r1, s->pmk_r1_name, s->aa,
|
||||||
s->spa, s->snonce, s->anonce,
|
s->spa, s->snonce, s->anonce,
|
||||||
s->ptk, ptk_size, ptk_name))
|
false, s->ptk, ptk_size,
|
||||||
|
ptk_name))
|
||||||
return false;
|
return false;
|
||||||
} else
|
} else
|
||||||
if (!crypto_derive_pairwise_ptk(s->pmk, s->pmk_len, s->spa,
|
if (!crypto_derive_pairwise_ptk(s->pmk, s->pmk_len, s->spa,
|
||||||
|
Loading…
Reference in New Issue
Block a user