mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 09:39:25 +01:00
crypto: pwd: sae: Made H function common
The "H" function used by SAE and EAP-PWD was effectively the same function, EAP-PWD just used a zero key for its calls. This removes the duplicate implementations and merges them into crypto.c as "hkdf_256". Since EAP-PWD always uses a zero'ed key, passing in a NULL key to hkdf_256 will actually use a 32 byte zero'ed array as the key. This avoids the need for EAP-PWD to store or create a zero'ed key for every call. Both the original "H" functions never called va_end, so that was added to hkdf_256.
This commit is contained in:
parent
5db022041c
commit
397bf9c0bd
42
src/crypto.c
42
src/crypto.c
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Wireless daemon for Linux
|
||||
*
|
||||
* Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013-2018 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -406,6 +406,46 @@ bool kdf_sha256(const void *key, size_t key_len,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Defined in RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function
|
||||
*
|
||||
* Null key equates to a zero key (makes calls in EAP-PWD more convenient)
|
||||
*/
|
||||
bool hkdf_256(const uint8_t *key, size_t key_len, uint8_t num_args,
|
||||
uint8_t *out, ...)
|
||||
{
|
||||
struct l_checksum *hmac;
|
||||
struct iovec iov[num_args];
|
||||
const uint8_t zero_key[32] = { 0 };
|
||||
const uint8_t *k = key ? key : zero_key;
|
||||
size_t k_len = key ? key_len : 32;
|
||||
va_list va;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
hmac = l_checksum_new_hmac(L_CHECKSUM_SHA256, k, k_len);
|
||||
if (!hmac)
|
||||
return false;
|
||||
|
||||
va_start(va, out);
|
||||
|
||||
for (i = 0; i < num_args; i++) {
|
||||
iov[i].iov_base = va_arg(va, void *);
|
||||
iov[i].iov_len = va_arg(va, size_t);
|
||||
}
|
||||
|
||||
if (!l_checksum_updatev(hmac, iov, num_args)) {
|
||||
va_end(va);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = l_checksum_get_digest(hmac, out, 32);
|
||||
l_checksum_free(hmac);
|
||||
|
||||
va_end(va);
|
||||
return (ret == 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* 802.11, Section 11.6.6.7:
|
||||
* PTK = PRF-X(PMK, "Pairwise key expansion", Min(AA, SA) || Max(AA, SA) ||
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Wireless daemon for Linux
|
||||
*
|
||||
* Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2013-2018 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -92,6 +92,8 @@ bool kdf_sha256(const void *key, size_t key_len,
|
||||
bool prf_sha1(const void *key, size_t key_len,
|
||||
const void *prefix, size_t prefix_len,
|
||||
const void *data, size_t data_len, void *output, size_t size);
|
||||
bool hkdf_256(const uint8_t *key, size_t key_len, uint8_t num_args,
|
||||
uint8_t *out, ...);
|
||||
|
||||
bool crypto_derive_pairwise_ptk(const uint8_t *pmk,
|
||||
const uint8_t *addr1, const uint8_t *addr2,
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "eap.h"
|
||||
#include "eap-private.h"
|
||||
#include "crypto.h"
|
||||
#include "util.h"
|
||||
#include "ecc.h"
|
||||
|
||||
@ -82,35 +83,6 @@ struct eap_pwd_handle {
|
||||
|
||||
static uint64_t curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
|
||||
|
||||
static bool H(uint8_t num_args, uint8_t *out, ...)
|
||||
{
|
||||
struct l_checksum *hmac;
|
||||
struct iovec iov[num_args];
|
||||
uint8_t k[32] = { 0 };
|
||||
va_list va;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
va_start(va, out);
|
||||
|
||||
hmac = l_checksum_new_hmac(L_CHECKSUM_SHA256, k, 32);
|
||||
if (!hmac)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < num_args; i++) {
|
||||
iov[i].iov_base = va_arg(va, void *);
|
||||
iov[i].iov_len = va_arg(va, size_t);
|
||||
}
|
||||
|
||||
if (!l_checksum_updatev(hmac, iov, num_args))
|
||||
return false;
|
||||
|
||||
ret = l_checksum_get_digest(hmac, out, 32);
|
||||
l_checksum_free(hmac);
|
||||
|
||||
return (ret == 32);
|
||||
}
|
||||
|
||||
/* RFC 5931, Section 2.5 - Key Derivation Function */
|
||||
static bool kdf(uint8_t *key, size_t key_len, const char *label,
|
||||
size_t label_len, void *out, size_t olen)
|
||||
@ -310,9 +282,10 @@ static void eap_pwd_handle_id(struct eap_state *eap,
|
||||
|
||||
while (counter < 20) {
|
||||
/* pwd-seed = H(token|peer-ID|server-ID|password|counter) */
|
||||
H(5, pwd_seed, &token, 4, pwd->identity, strlen(pwd->identity),
|
||||
pkt + 9, len - 9, pwd->password,
|
||||
strlen(pwd->password), &counter, 1);
|
||||
hkdf_256(NULL, 0, 5, pwd_seed, &token, 4, pwd->identity,
|
||||
strlen(pwd->identity), pkt + 9, len - 9,
|
||||
pwd->password, strlen(pwd->password),
|
||||
&counter, 1);
|
||||
|
||||
/*
|
||||
* pwd-value = KDF(pwd-seed, "EAP-pwd Hunting And Pecking",
|
||||
@ -519,15 +492,15 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
||||
* compute Confirm_P = H(kp | Element_P | Scalar_P |
|
||||
* Element_S | Scalar_S | Ciphersuite)
|
||||
*/
|
||||
H(8, confirm_p, kp.x, ECC_BYTES, pwd->element_p.x, ECC_BYTES,
|
||||
pwd->element_p.y, ECC_BYTES, pwd->scalar_p,
|
||||
hkdf_256(NULL, 0, 8, confirm_p, kp.x, ECC_BYTES, pwd->element_p.x,
|
||||
ECC_BYTES, pwd->element_p.y, ECC_BYTES, pwd->scalar_p,
|
||||
ECC_BYTES, pwd->element_s.x, ECC_BYTES,
|
||||
pwd->element_s.y, ECC_BYTES, pwd->scalar_s,
|
||||
ECC_BYTES, &pwd->ciphersuite, 4);
|
||||
|
||||
H(8, expected_confirm_s, kp.x, ECC_BYTES, pwd->element_s.x,
|
||||
ECC_BYTES, pwd->element_s.y, ECC_BYTES,
|
||||
pwd->scalar_s, ECC_BYTES, pwd->element_p.x,
|
||||
hkdf_256(NULL, 0, 8, expected_confirm_s, kp.x, ECC_BYTES,
|
||||
pwd->element_s.x, ECC_BYTES, pwd->element_s.y,
|
||||
ECC_BYTES, pwd->scalar_s, ECC_BYTES, pwd->element_p.x,
|
||||
ECC_BYTES, pwd->element_p.y, ECC_BYTES,
|
||||
pwd->scalar_p, ECC_BYTES, &pwd->ciphersuite, 4);
|
||||
|
||||
@ -542,7 +515,7 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
||||
pos += 32;
|
||||
|
||||
/* derive MK = H(kp | Confirm_P | Confirm_S ) */
|
||||
H(3, mk, kp.x, ECC_BYTES, confirm_p, ECC_BYTES,
|
||||
hkdf_256(NULL, 0, 3, mk, kp.x, ECC_BYTES, confirm_p, ECC_BYTES,
|
||||
confirm_s, ECC_BYTES);
|
||||
|
||||
eap_pwd_send_response(eap, resp, pos - resp);
|
||||
@ -550,8 +523,8 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
||||
eap_method_success(eap);
|
||||
|
||||
session_id[0] = 52;
|
||||
H(3, session_id + 1, &pwd->ciphersuite, 4, pwd->scalar_p, ECC_BYTES,
|
||||
pwd->scalar_s, ECC_BYTES);
|
||||
hkdf_256(NULL, 0, 3, session_id + 1, &pwd->ciphersuite, 4,
|
||||
pwd->scalar_p, ECC_BYTES, pwd->scalar_s, ECC_BYTES);
|
||||
kdf(mk, 32, (const char *) session_id, 33, msk_emsk, 128);
|
||||
eap_set_key_material(eap, msk_emsk, 64, msk_emsk + 64, 64, NULL, 0);
|
||||
|
||||
|
31
src/sae.c
31
src/sae.c
@ -72,35 +72,6 @@ struct sae_sm {
|
||||
static uint64_t curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
|
||||
static uint64_t curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
|
||||
|
||||
static bool H(const uint8_t *key, size_t key_len, uint8_t num_args,
|
||||
uint8_t *out, ...)
|
||||
{
|
||||
struct l_checksum *hmac;
|
||||
struct iovec iov[num_args];
|
||||
va_list va;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
va_start(va, out);
|
||||
|
||||
hmac = l_checksum_new_hmac(L_CHECKSUM_SHA256, key, key_len);
|
||||
if (!hmac)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < num_args; i++) {
|
||||
iov[i].iov_base = va_arg(va, void *);
|
||||
iov[i].iov_len = va_arg(va, size_t);
|
||||
}
|
||||
|
||||
if (!l_checksum_updatev(hmac, iov, num_args))
|
||||
return false;
|
||||
|
||||
ret = l_checksum_get_digest(hmac, out, 32);
|
||||
l_checksum_free(hmac);
|
||||
|
||||
return (ret == 32);
|
||||
}
|
||||
|
||||
/* calculate random quadratic residue */
|
||||
static void sae_get_qr(uint64_t *qr)
|
||||
{
|
||||
@ -166,7 +137,7 @@ static bool sae_pwd_seed(const uint8_t *addr1, const uint8_t *addr2,
|
||||
memcpy(key + 6, addr1, 6);
|
||||
}
|
||||
|
||||
return H(key, 12, 2, out, base, base_len, &counter, 1);
|
||||
return hkdf_256(key, 12, 2, out, base, base_len, &counter, 1);
|
||||
}
|
||||
|
||||
static bool sae_pwd_value(uint8_t *pwd_seed, uint64_t *pwd_value)
|
||||
|
Loading…
Reference in New Issue
Block a user