mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
crypto: allow hkdf_expand/extract to use different SHA's
Rather than hard coding to SHA256, we can pass in l_checksum_type and use that SHA. This will allow for OWE/SAE/PWD to support more curves that use different SHA algorithms for hashing.
This commit is contained in:
parent
90c39afd61
commit
7bfaf182e6
36
src/crypto.c
36
src/crypto.c
@ -418,19 +418,24 @@ bool kdf_sha256(const void *key, size_t key_len,
|
|||||||
*
|
*
|
||||||
* Null key equates to a zero key (makes calls in EAP-PWD more convenient)
|
* Null key equates to a zero key (makes calls in EAP-PWD more convenient)
|
||||||
*/
|
*/
|
||||||
bool hkdf_extract_sha256(const uint8_t *key, size_t key_len, uint8_t num_args,
|
bool hkdf_extract(enum l_checksum_type type, const uint8_t *key,
|
||||||
uint8_t *out, ...)
|
size_t key_len, uint8_t num_args,
|
||||||
|
uint8_t *out, ...)
|
||||||
{
|
{
|
||||||
struct l_checksum *hmac;
|
struct l_checksum *hmac;
|
||||||
struct iovec iov[num_args];
|
struct iovec iov[num_args];
|
||||||
const uint8_t zero_key[32] = { 0 };
|
const uint8_t zero_key[64] = { 0 };
|
||||||
|
size_t dlen = l_checksum_digest_length(type);
|
||||||
const uint8_t *k = key ? key : zero_key;
|
const uint8_t *k = key ? key : zero_key;
|
||||||
size_t k_len = key ? key_len : 32;
|
size_t k_len = key ? key_len : dlen;
|
||||||
va_list va;
|
va_list va;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
hmac = l_checksum_new_hmac(L_CHECKSUM_SHA256, k, k_len);
|
if (dlen <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hmac = l_checksum_new_hmac(type, k, k_len);
|
||||||
if (!hmac)
|
if (!hmac)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -446,27 +451,32 @@ bool hkdf_extract_sha256(const uint8_t *key, size_t key_len, uint8_t num_args,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = l_checksum_get_digest(hmac, out, 32);
|
ret = l_checksum_get_digest(hmac, out, dlen);
|
||||||
l_checksum_free(hmac);
|
l_checksum_free(hmac);
|
||||||
|
|
||||||
va_end(va);
|
va_end(va);
|
||||||
return (ret == 32);
|
return (ret == (int) dlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hkdf_expand_sha256(const uint8_t *key, size_t key_len, const char *info,
|
bool hkdf_expand(enum l_checksum_type type, const uint8_t *key, size_t key_len,
|
||||||
size_t info_len, void *out, size_t out_len)
|
const char *info, size_t info_len, void *out,
|
||||||
|
size_t out_len)
|
||||||
{
|
{
|
||||||
uint8_t t[32];
|
uint8_t t[64];
|
||||||
size_t t_len = 0;
|
size_t t_len = 0;
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
struct l_checksum *hmac;
|
struct l_checksum *hmac;
|
||||||
uint8_t count = 1;
|
uint8_t count = 1;
|
||||||
uint8_t *out_ptr = out;
|
uint8_t *out_ptr = out;
|
||||||
|
size_t dlen = l_checksum_digest_length(type);
|
||||||
|
|
||||||
|
if (dlen <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
while (out_len > 0) {
|
while (out_len > 0) {
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
hmac = l_checksum_new_hmac(L_CHECKSUM_SHA256, key, key_len);
|
hmac = l_checksum_new_hmac(type, key, key_len);
|
||||||
|
|
||||||
iov[0].iov_base = t;
|
iov[0].iov_base = t;
|
||||||
iov[0].iov_len = t_len;
|
iov[0].iov_len = t_len;
|
||||||
@ -481,7 +491,7 @@ bool hkdf_expand_sha256(const uint8_t *key, size_t key_len, const char *info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = l_checksum_get_digest(hmac, t,
|
ret = l_checksum_get_digest(hmac, t,
|
||||||
(out_len > 32) ? 32 : out_len);
|
(out_len > dlen) ? dlen : out_len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
l_checksum_free(hmac);
|
l_checksum_free(hmac);
|
||||||
return false;
|
return false;
|
||||||
@ -495,7 +505,7 @@ bool hkdf_expand_sha256(const uint8_t *key, size_t key_len, const char *info,
|
|||||||
* RFC specifies that T(0) = empty string, so after the first
|
* RFC specifies that T(0) = empty string, so after the first
|
||||||
* iteration we update the length for T(1)...T(N)
|
* iteration we update the length for T(1)...T(N)
|
||||||
*/
|
*/
|
||||||
t_len = 32;
|
t_len = dlen;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
l_checksum_free(hmac);
|
l_checksum_free(hmac);
|
||||||
|
@ -89,11 +89,12 @@ bool kdf_sha256(const void *key, size_t key_len,
|
|||||||
bool prf_sha1(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 *prefix, size_t prefix_len,
|
||||||
const void *data, size_t data_len, void *output, size_t size);
|
const void *data, size_t data_len, void *output, size_t size);
|
||||||
bool hkdf_extract_sha256(const uint8_t *key, size_t key_len, uint8_t num_args,
|
bool hkdf_extract(enum l_checksum_type type, const uint8_t *key, size_t key_len,
|
||||||
uint8_t *out, ...);
|
uint8_t num_args, uint8_t *out, ...);
|
||||||
|
|
||||||
bool hkdf_expand_sha256(const uint8_t *key, size_t key_len, const char *info,
|
bool hkdf_expand(enum l_checksum_type type, const uint8_t *key, size_t key_len,
|
||||||
size_t info_len, void *out, size_t out_len);
|
const char *info, size_t info_len, void *out,
|
||||||
|
size_t out_len);
|
||||||
|
|
||||||
bool crypto_derive_pairwise_ptk(const uint8_t *pmk, size_t pmk_len,
|
bool crypto_derive_pairwise_ptk(const uint8_t *pmk, size_t pmk_len,
|
||||||
const uint8_t *addr1, const uint8_t *addr2,
|
const uint8_t *addr1, const uint8_t *addr2,
|
||||||
|
@ -293,7 +293,7 @@ static void eap_pwd_handle_id(struct eap_state *eap,
|
|||||||
|
|
||||||
while (counter < 20) {
|
while (counter < 20) {
|
||||||
/* pwd-seed = H(token|peer-ID|server-ID|password|counter) */
|
/* pwd-seed = H(token|peer-ID|server-ID|password|counter) */
|
||||||
hkdf_extract_sha256(NULL, 0, 5, pwd_seed, &token, 4,
|
hkdf_extract(L_CHECKSUM_SHA256, NULL, 0, 5, pwd_seed, &token, 4,
|
||||||
pwd->identity, strlen(pwd->identity), pkt + 9,
|
pwd->identity, strlen(pwd->identity), pkt + 9,
|
||||||
len - 9, pwd->password, strlen(pwd->password),
|
len - 9, pwd->password, strlen(pwd->password),
|
||||||
&counter, 1);
|
&counter, 1);
|
||||||
@ -488,13 +488,14 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
|||||||
* compute Confirm_P = H(kp | Element_P | Scalar_P |
|
* compute Confirm_P = H(kp | Element_P | Scalar_P |
|
||||||
* Element_S | Scalar_S | Ciphersuite)
|
* Element_S | Scalar_S | Ciphersuite)
|
||||||
*/
|
*/
|
||||||
hkdf_extract_sha256(NULL, 0, 6, confirm_p, kpx, clen, element_p, plen,
|
hkdf_extract(L_CHECKSUM_SHA256, NULL, 0, 6, confirm_p, kpx, clen,
|
||||||
scalar_p, clen, element_s, plen, scalar_s,
|
element_p, plen, scalar_p, clen, element_s,
|
||||||
clen, &pwd->ciphersuite, 4);
|
plen, scalar_s, clen, &pwd->ciphersuite, 4);
|
||||||
|
|
||||||
hkdf_extract_sha256(NULL, 0, 6, expected_confirm_s, kpx, clen,
|
hkdf_extract(L_CHECKSUM_SHA256, NULL, 0, 6, expected_confirm_s, kpx,
|
||||||
element_s, plen, scalar_s, clen, element_p,
|
clen, element_s, plen, scalar_s, clen,
|
||||||
plen, scalar_p, clen, &pwd->ciphersuite, 4);
|
element_p, plen, scalar_p, clen,
|
||||||
|
&pwd->ciphersuite, 4);
|
||||||
|
|
||||||
if (memcmp(confirm_s, expected_confirm_s, 32)) {
|
if (memcmp(confirm_s, expected_confirm_s, 32)) {
|
||||||
l_error("Confirm_S did not verify");
|
l_error("Confirm_S did not verify");
|
||||||
@ -507,7 +508,7 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
|||||||
pos += 32;
|
pos += 32;
|
||||||
|
|
||||||
/* derive MK = H(kp | Confirm_P | Confirm_S ) */
|
/* derive MK = H(kp | Confirm_P | Confirm_S ) */
|
||||||
hkdf_extract_sha256(NULL, 0, 3, mk, kpx, clen, confirm_p,
|
hkdf_extract(L_CHECKSUM_SHA256, NULL, 0, 3, mk, kpx, clen, confirm_p,
|
||||||
32, confirm_s, 32);
|
32, confirm_s, 32);
|
||||||
|
|
||||||
eap_pwd_send_response(eap, resp, pos - resp);
|
eap_pwd_send_response(eap, resp, pos - resp);
|
||||||
@ -515,8 +516,8 @@ static void eap_pwd_handle_confirm(struct eap_state *eap,
|
|||||||
eap_method_success(eap);
|
eap_method_success(eap);
|
||||||
|
|
||||||
session_id[0] = 52;
|
session_id[0] = 52;
|
||||||
hkdf_extract_sha256(NULL, 0, 3, session_id + 1, &pwd->ciphersuite, 4,
|
hkdf_extract(L_CHECKSUM_SHA256, NULL, 0, 3, session_id + 1,
|
||||||
scalar_p, clen, scalar_s, clen);
|
&pwd->ciphersuite, 4, scalar_p, clen, scalar_s, clen);
|
||||||
|
|
||||||
kdf(mk, 32, (const char *) session_id, 33, msk_emsk, 128);
|
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);
|
eap_set_key_material(eap, msk_emsk, 64, msk_emsk + 64, 64, NULL, 0);
|
||||||
|
@ -157,11 +157,11 @@ static bool owe_compute_keys(struct owe_sm *owe, const void *public_key,
|
|||||||
l_put_le16(OWE_DEFAULT_GROUP, key + 64);
|
l_put_le16(OWE_DEFAULT_GROUP, key + 64);
|
||||||
|
|
||||||
/* prk = HKDF-extract(C | A | group, z) */
|
/* prk = HKDF-extract(C | A | group, z) */
|
||||||
if (!hkdf_extract_sha256(key, 66, 1, prk, ss_buf, 32))
|
if (!hkdf_extract(L_CHECKSUM_SHA256, key, 66, 1, prk, ss_buf, 32))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
|
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
|
||||||
if (!hkdf_expand_sha256(prk, 32, "OWE Key Generation",
|
if (!hkdf_expand(L_CHECKSUM_SHA256, prk, 32, "OWE Key Generation",
|
||||||
strlen("OWE Key Generation"), pmk, 32))
|
strlen("OWE Key Generation"), pmk, 32))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ static bool sae_pwd_seed(const uint8_t *addr1, const uint8_t *addr2,
|
|||||||
memcpy(key + 6, addr1, 6);
|
memcpy(key + 6, addr1, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hkdf_extract_sha256(key, 12, 2, out, base, base_len,
|
return hkdf_extract(L_CHECKSUM_SHA256, key, 12, 2, out, base, base_len,
|
||||||
&counter, 1);
|
&counter, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user