mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-19 02:39:29 +01:00
peap: Add support for Crypto-Binding in PEAPv0
The Crypto Binding TLV is used to ensure that the EAP peer and the EAP server participated in both the inner and the outer EAP authentications of a PEAP authentication by cryptographically associating the phase 1 and phase 2 authentications. The usage of Crypto-Binding in PEAPv0 is optional and is triggered by the reception of the Crypto-Binding TLV from the server.
This commit is contained in:
parent
8e5f838219
commit
8884fd8bbd
170
src/eap-peap.c
170
src/eap-peap.c
@ -29,6 +29,7 @@
|
||||
#include <errno.h>
|
||||
#include <ell/ell.h>
|
||||
|
||||
#include "src/crypto.h"
|
||||
#include "src/missing.h"
|
||||
#include "src/eap.h"
|
||||
#include "src/eap-private.h"
|
||||
@ -117,9 +118,170 @@ enum eap_extensions_tlv_type {
|
||||
/* Reserved = 0x0000, */
|
||||
/* Reserved = 0x0001, */
|
||||
/* Reserved = 0x0002, */
|
||||
EAP_EXTENSIONS_TLV_TYPE_RESULT = 0x8003,
|
||||
EAP_EXTENSIONS_TLV_TYPE_RESULT = 0x8003,
|
||||
EAP_EXTENSIONS_TLV_TYPE_CRYPTOBINDING = 0x000C,
|
||||
};
|
||||
|
||||
enum TLV_CRYPTOBINDING_TYPE {
|
||||
TLV_CRYPTOBINDING_TYPE_REQUEST = 0,
|
||||
TLV_CRYPTOBINDING_TYPE_RESPONSE = 1,
|
||||
};
|
||||
|
||||
static bool cryptobinding_tlv_generate_csk(struct eap_state *eap, uint8_t *imck)
|
||||
{
|
||||
struct peap_state *peap_state = eap_tls_common_get_variant_data(eap);
|
||||
static const char *label = "Session Key Generating Function";
|
||||
|
||||
if (!prf_plus_sha1(imck, 40, label, strlen(label), "\00", 1,
|
||||
peap_state->key, sizeof(peap_state->key)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cryptobinding_tlv_generate_imck(struct eap_state *eap,
|
||||
uint8_t *imck_out)
|
||||
{
|
||||
struct peap_state *peap_state = eap_tls_common_get_variant_data(eap);
|
||||
static const char *label = "Inner Methods Compound Keys";
|
||||
uint8_t isk[32];
|
||||
|
||||
memset(isk, 0, sizeof(isk));
|
||||
|
||||
if (!prf_plus_sha1(peap_state->key, 40, label, strlen(label),
|
||||
isk, sizeof(isk), imck_out, 60))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int eap_extensions_handle_cryptobinding_tlv(struct eap_state *eap,
|
||||
const uint8_t *data,
|
||||
uint16_t tlv_value_len,
|
||||
uint8_t *response)
|
||||
{
|
||||
static const uint8_t cryptobinding_val_len = 56;
|
||||
static const uint8_t cryptobinding_compound_mac_len = 20;
|
||||
static const uint8_t cryptobinding_nonce_len = 32;
|
||||
const uint8_t *nonce;
|
||||
const uint8_t *server_compound_mac;
|
||||
uint8_t client_compound_mac[cryptobinding_compound_mac_len];
|
||||
const uint8_t *cryptobinding_tlv_value;
|
||||
uint8_t buf[61];
|
||||
uint8_t imck[60];
|
||||
|
||||
if (tlv_value_len != cryptobinding_val_len)
|
||||
return -EBADMSG;
|
||||
|
||||
cryptobinding_tlv_value = data;
|
||||
|
||||
/* Reserved byte: must be ignored on receipt. */
|
||||
data += 1;
|
||||
|
||||
/* Version byte: must be set to 0. */
|
||||
if (*data)
|
||||
return -EBADMSG;
|
||||
|
||||
data += 1;
|
||||
|
||||
/* RecvVersion byte: must be set to 0. */
|
||||
if (*data)
|
||||
return -EBADMSG;
|
||||
|
||||
data += 1;
|
||||
|
||||
/* SubType byte: cryptobinding TLV request. */
|
||||
if (*data != TLV_CRYPTOBINDING_TYPE_REQUEST)
|
||||
return -EBADMSG;
|
||||
|
||||
data += 1;
|
||||
|
||||
nonce = data;
|
||||
data += cryptobinding_nonce_len;
|
||||
|
||||
server_compound_mac = data;
|
||||
|
||||
l_put_be16(EAP_EXTENSIONS_TLV_TYPE_CRYPTOBINDING, &buf[0]);
|
||||
l_put_be16(tlv_value_len, &buf[2]);
|
||||
memcpy(&buf[4], cryptobinding_tlv_value,
|
||||
4 + cryptobinding_nonce_len);
|
||||
memset(&buf[EAP_EXTENSIONS_TLV_HEADER_LEN + 4 +
|
||||
cryptobinding_nonce_len],
|
||||
0, cryptobinding_compound_mac_len);
|
||||
buf[60] = EAP_TYPE_PEAP;
|
||||
|
||||
if (!cryptobinding_tlv_generate_imck(eap, imck)) {
|
||||
l_error("PEAP: Failed to generate IMCK to validate "
|
||||
"server compound MAC.");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!hmac_sha1(imck + 40, 20, buf, sizeof(buf), client_compound_mac,
|
||||
cryptobinding_compound_mac_len)) {
|
||||
l_error("PEAP: Failed to generate compound MAC to validate "
|
||||
"server compound MAC.");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (memcmp(server_compound_mac, client_compound_mac,
|
||||
cryptobinding_compound_mac_len)) {
|
||||
l_error("PEAP: Generated compound MAC and server compound MAC "
|
||||
"don't match.");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Build response Crypto-Binding TLV */
|
||||
data = response;
|
||||
|
||||
l_put_be16(EAP_EXTENSIONS_TLV_TYPE_CRYPTOBINDING, response);
|
||||
response += 2;
|
||||
|
||||
l_put_be16(cryptobinding_val_len, response);
|
||||
response += 2;
|
||||
|
||||
/* Reserved - must be set to 0. */
|
||||
l_put_u8(0, response);
|
||||
response += 1;
|
||||
|
||||
/* Version */
|
||||
l_put_u8(EAP_TLS_VERSION_0, response);
|
||||
response += 1;
|
||||
|
||||
/* Received Version */
|
||||
l_put_u8(EAP_TLS_VERSION_0, response);
|
||||
response += 1;
|
||||
|
||||
/* Sub-Type */
|
||||
l_put_u8(TLV_CRYPTOBINDING_TYPE_RESPONSE, response);
|
||||
response += 1;
|
||||
|
||||
memcpy(response, nonce, cryptobinding_nonce_len);
|
||||
response += cryptobinding_nonce_len;
|
||||
|
||||
memcpy(buf, data, EAP_EXTENSIONS_TLV_HEADER_LEN + 4 +
|
||||
cryptobinding_nonce_len);
|
||||
|
||||
if (!hmac_sha1(imck + 40, 20, buf, sizeof(buf), client_compound_mac,
|
||||
cryptobinding_compound_mac_len)) {
|
||||
l_error("PEAP: Failed to generate client compound MAC.");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(response, client_compound_mac, cryptobinding_compound_mac_len);
|
||||
|
||||
if (!cryptobinding_tlv_generate_csk(eap, imck)) {
|
||||
l_error("PEAP: Failed to generate Compound Session Key.");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return EAP_EXTENSIONS_TLV_HEADER_LEN + cryptobinding_val_len;
|
||||
}
|
||||
|
||||
enum eap_extensions_result {
|
||||
EAP_EXTENSIONS_RESULT_SUCCCESS = 1,
|
||||
EAP_EXTENSIONS_RESULT_FAILURE = 2,
|
||||
@ -198,6 +360,12 @@ static int eap_extensions_process_tlvs(struct eap_state *eap,
|
||||
data, tlv_value_len, response,
|
||||
result);
|
||||
|
||||
break;
|
||||
case EAP_EXTENSIONS_TLV_TYPE_CRYPTOBINDING:
|
||||
response_tlv_len =
|
||||
eap_extensions_handle_cryptobinding_tlv(eap,
|
||||
data, tlv_value_len, response);
|
||||
|
||||
break;
|
||||
default:
|
||||
if (tlv_type & EAP_EXTENSIONS_TLV_M_BIT_MASK)
|
||||
|
Loading…
Reference in New Issue
Block a user