aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa_supplicant/eap_gpsk_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa_supplicant/eap_gpsk_common.c')
-rw-r--r--contrib/wpa_supplicant/eap_gpsk_common.c304
1 files changed, 144 insertions, 160 deletions
diff --git a/contrib/wpa_supplicant/eap_gpsk_common.c b/contrib/wpa_supplicant/eap_gpsk_common.c
index a72b5f3da15f..7422fa6c48f9 100644
--- a/contrib/wpa_supplicant/eap_gpsk_common.c
+++ b/contrib/wpa_supplicant/eap_gpsk_common.c
@@ -18,8 +18,9 @@
#include "eap_defs.h"
#include "aes_wrap.h"
#include "crypto.h"
-#include "sha1.h"
+#ifdef EAP_GPSK_SHA256
#include "sha256.h"
+#endif /* EAP_GPSK_SHA256 */
#include "eap_gpsk_common.h"
@@ -43,31 +44,29 @@ int eap_gpsk_supported_ciphersuite(int vendor, int specifier)
}
-static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len,
- const u8 *data /* Z */, size_t data_len,
- u8 *buf, size_t len /* X */)
+static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */,
+ const u8 *data /* Z */, size_t data_len,
+ u8 *buf, size_t len /* X */)
{
u8 *opos;
size_t i, n, hashlen, left, clen;
- u8 ibuf[2], hash[SHA1_MAC_LEN];
- const u8 *addr[3];
- size_t vlen[3];
+ u8 ibuf[2], hash[16];
+ const u8 *addr[2];
+ size_t vlen[2];
- hashlen = SHA1_MAC_LEN;
- /* M_i = Hash-Function (i || Y || Z); */
+ hashlen = sizeof(hash);
+ /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */
addr[0] = ibuf;
vlen[0] = sizeof(ibuf);
- addr[1] = psk;
- vlen[1] = psk_len;
- addr[2] = data;
- vlen[2] = data_len;
+ addr[1] = data;
+ vlen[1] = data_len;
opos = buf;
left = len;
n = (len + hashlen - 1) / hashlen;
for (i = 1; i <= n; i++) {
WPA_PUT_BE16(ibuf, i);
- sha1_vector(3, addr, vlen, hash);
+ omac1_aes_128_vector(psk, 2, addr, vlen, hash);
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
@@ -78,112 +77,30 @@ static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len,
}
-static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len,
- const u8 *seed, size_t seed_len,
- u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len,
- u8 *pk, size_t *pk_len)
-{
-#define EAP_GPSK_SK_LEN_AES 16
-#define EAP_GPSK_PK_LEN_AES 16
- u8 zero_string[1], mk[32], *pos, *data;
- u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES +
- EAP_GPSK_PK_LEN_AES];
- size_t data_len;
-
- /*
- * inputString = RAND_Client || ID_Client || RAND_Server || ID_Server
- * (= seed)
- * KS = 16, PL = psk_len, CSuite_Sel = 0x000000 0x000001
- * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString)
- * MSK = GKDF-160 (MK, inputString)[0..63]
- * EMSK = GKDF-160 (MK, inputString)[64..127]
- * SK = GKDF-160 (MK, inputString)[128..143]
- * PK = GKDF-160 (MK, inputString)[144..159]
- * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel ||
- * inputString)
- * Hash-Function = SHA-1 (see [RFC3174])
- * hashlen = 20 octets (160 bits)
- */
-
- os_memset(zero_string, 0, sizeof(zero_string));
-
- data_len = 2 + psk_len + 6 + seed_len;
- data = os_malloc(data_len);
- if (data == NULL)
- return -1;
- pos = data;
- WPA_PUT_BE16(pos, psk_len);
- pos += 2;
- os_memcpy(pos, psk, psk_len);
- pos += psk_len;
- WPA_PUT_BE24(pos, 0); /* CSuite/Vendor = IETF */
- pos += 3;
- WPA_PUT_BE24(pos, EAP_GPSK_CIPHER_AES); /* CSuite/Specifier */
- pos += 3;
- os_memcpy(pos, seed, seed_len); /* inputString */
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation (AES)",
- data, data_len);
-
- if (eap_gpsk_gkdf(zero_string, sizeof(zero_string), data, data_len,
- mk, sizeof(mk)) < 0) {
- os_free(data);
- return -1;
- }
- os_free(data);
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, sizeof(mk));
-
- if (eap_gpsk_gkdf(mk, sizeof(mk), seed, seed_len,
- kdf_out, sizeof(kdf_out)) < 0)
- return -1;
-
- pos = kdf_out;
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN);
- os_memcpy(msk, pos, EAP_MSK_LEN);
- pos += EAP_MSK_LEN;
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN);
- os_memcpy(emsk, pos, EAP_EMSK_LEN);
- pos += EAP_EMSK_LEN;
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, EAP_GPSK_SK_LEN_AES);
- os_memcpy(sk, pos, EAP_GPSK_SK_LEN_AES);
- *sk_len = EAP_GPSK_SK_LEN_AES;
- pos += EAP_GPSK_SK_LEN_AES;
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, EAP_GPSK_PK_LEN_AES);
- os_memcpy(pk, pos, EAP_GPSK_PK_LEN_AES);
- *pk_len = EAP_GPSK_PK_LEN_AES;
-
- return 0;
-}
-
-
#ifdef EAP_GPSK_SHA256
-static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, size_t psk_len,
+static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */,
const u8 *data /* Z */, size_t data_len,
u8 *buf, size_t len /* X */)
{
u8 *opos;
size_t i, n, hashlen, left, clen;
u8 ibuf[2], hash[SHA256_MAC_LEN];
- const u8 *addr[3];
- size_t vlen[3];
+ const u8 *addr[2];
+ size_t vlen[2];
hashlen = SHA256_MAC_LEN;
- /* M_i = Hash-Function (i || Y || Z); */
+ /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */
addr[0] = ibuf;
vlen[0] = sizeof(ibuf);
- addr[1] = psk;
- vlen[1] = psk_len;
- addr[2] = data;
- vlen[2] = data_len;
+ addr[1] = data;
+ vlen[1] = data_len;
opos = buf;
left = len;
n = (len + hashlen - 1) / hashlen;
for (i = 1; i <= n; i++) {
WPA_PUT_BE16(ibuf, i);
- sha256_vector(3, addr, vlen, hash);
+ hmac_sha256_vector(psk, 32, 2, addr, vlen, hash);
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
@@ -192,37 +109,40 @@ static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, size_t psk_len,
return 0;
}
+#endif /* EAP_GPSK_SHA256 */
-static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len,
+static int eap_gpsk_derive_keys_helper(u32 csuite_specifier,
+ u8 *kdf_out, size_t kdf_out_len,
+ const u8 *psk, size_t psk_len,
const u8 *seed, size_t seed_len,
u8 *msk, u8 *emsk,
- u8 *sk, size_t *sk_len,
- u8 *pk, size_t *pk_len)
+ u8 *sk, size_t sk_len,
+ u8 *pk, size_t pk_len)
{
-#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN
-#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN
- u8 mk[SHA256_MAC_LEN], zero_string[1], *pos, *data;
- u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 +
- EAP_GPSK_PK_LEN_SHA256];
- size_t data_len;
+ u8 mk[32], *pos, *data;
+ size_t data_len, mk_len;
+ int (*gkdf)(const u8 *psk, const u8 *data, size_t data_len,
+ u8 *buf, size_t len);
- /*
- * inputString = RAND_Client || ID_Client || RAND_Server || ID_Server
- * (= seed)
- * KS = 32, PL = psk_len, CSuite_Sel = 0x000000 0x000002
- * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString)
- * MSK = GKDF-192 (MK, inputString)[0..63]
- * EMSK = GKDF-192 (MK, inputString)[64..127]
- * SK = GKDF-192 (MK, inputString)[128..159]
- * PK = GKDF-192 (MK, inputString)[160..191]
- * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel ||
- * inputString)
- * Hash-Function = SHA256 (see [RFC4634])
- * hashlen = 32 octets (256 bits)
- */
+ gkdf = NULL;
+ switch (csuite_specifier) {
+ case EAP_GPSK_CIPHER_AES:
+ gkdf = eap_gpsk_gkdf_cmac;
+ mk_len = 16;
+ break;
+#ifdef EAP_GPSK_SHA256
+ case EAP_GPSK_CIPHER_SHA256:
+ gkdf = eap_gpsk_gkdf_sha256;
+ mk_len = SHA256_MAC_LEN;
+ break;
+#endif /* EAP_GPSK_SHA256 */
+ default:
+ return -1;
+ }
- os_memset(zero_string, 0, sizeof(zero_string));
+ if (psk_len < mk_len)
+ return -1;
data_len = 2 + psk_len + 6 + seed_len;
data = os_malloc(data_len);
@@ -233,24 +153,22 @@ static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len,
pos += 2;
os_memcpy(pos, psk, psk_len);
pos += psk_len;
- WPA_PUT_BE24(pos, 0); /* CSuite/Vendor = IETF */
- pos += 3;
- WPA_PUT_BE24(pos, EAP_GPSK_CIPHER_SHA256); /* CSuite/Specifier */
- pos += 3;
+ WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
+ pos += 4;
+ WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
+ pos += 2;
os_memcpy(pos, seed, seed_len); /* inputString */
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation (SHA256)",
+ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation",
data, data_len);
- if (eap_gpsk_gkdf_sha256(zero_string, sizeof(zero_string),
- data, data_len, mk, sizeof(mk)) < 0) {
+ if (gkdf(psk, data, data_len, mk, mk_len) < 0) {
os_free(data);
return -1;
}
os_free(data);
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, sizeof(mk));
+ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len);
- if (eap_gpsk_gkdf_sha256(mk, sizeof(mk), seed, seed_len,
- kdf_out, sizeof(kdf_out)) < 0)
+ if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0)
return -1;
pos = kdf_out;
@@ -262,46 +180,113 @@ static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len,
os_memcpy(emsk, pos, EAP_EMSK_LEN);
pos += EAP_EMSK_LEN;
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK",
- pos, EAP_GPSK_SK_LEN_SHA256);
- os_memcpy(sk, pos, EAP_GPSK_SK_LEN_SHA256);
- *sk_len = EAP_GPSK_SK_LEN_AES;
- pos += EAP_GPSK_SK_LEN_AES;
+ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len);
+ os_memcpy(sk, pos, sk_len);
+ pos += sk_len;
- wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK",
- pos, EAP_GPSK_PK_LEN_SHA256);
- os_memcpy(pk, pos, EAP_GPSK_PK_LEN_SHA256);
- *pk_len = EAP_GPSK_PK_LEN_SHA256;
+ if (pk) {
+ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len);
+ os_memcpy(pk, pos, pk_len);
+ }
return 0;
}
+
+
+static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len,
+ const u8 *seed, size_t seed_len,
+ u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len,
+ u8 *pk, size_t *pk_len)
+{
+#define EAP_GPSK_SK_LEN_AES 16
+#define EAP_GPSK_PK_LEN_AES 16
+ u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES +
+ EAP_GPSK_PK_LEN_AES];
+
+ /*
+ * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
+ * (= seed)
+ * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001
+ * MK = GKDF-16 (PSK[0..15], PL || PSK || CSuite_Sel || inputString)
+ * MSK = GKDF-160 (MK, inputString)[0..63]
+ * EMSK = GKDF-160 (MK, inputString)[64..127]
+ * SK = GKDF-160 (MK, inputString)[128..143]
+ * PK = GKDF-160 (MK, inputString)[144..159]
+ * zero = 0x00 || 0x00 || ... || 0x00 (16 times)
+ * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
+ * CSuite_Sel || inputString)
+ */
+
+ *sk_len = EAP_GPSK_SK_LEN_AES;
+ *pk_len = EAP_GPSK_PK_LEN_AES;
+
+ return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_AES,
+ kdf_out, sizeof(kdf_out),
+ psk, psk_len, seed, seed_len,
+ msk, emsk, sk, *sk_len,
+ pk, *pk_len);
+}
+
+
+#ifdef EAP_GPSK_SHA256
+static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len,
+ const u8 *seed, size_t seed_len,
+ u8 *msk, u8 *emsk,
+ u8 *sk, size_t *sk_len)
+{
+#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN
+#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN
+ u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 +
+ EAP_GPSK_PK_LEN_SHA256];
+
+ /*
+ * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
+ * (= seed)
+ * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002
+ * MK = GKDF-32 (PSK[0..31], PL || PSK || CSuite_Sel || inputString)
+ * MSK = GKDF-160 (MK, inputString)[0..63]
+ * EMSK = GKDF-160 (MK, inputString)[64..127]
+ * SK = GKDF-160 (MK, inputString)[128..159]
+ * zero = 0x00 || 0x00 || ... || 0x00 (32 times)
+ * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
+ * CSuite_Sel || inputString)
+ */
+
+ *sk_len = EAP_GPSK_SK_LEN_SHA256;
+
+ return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_SHA256,
+ kdf_out, sizeof(kdf_out),
+ psk, psk_len, seed, seed_len,
+ msk, emsk, sk, *sk_len,
+ NULL, 0);
+}
#endif /* EAP_GPSK_SHA256 */
/**
* eap_gpsk_derive_keys - Derive EAP-GPSK keys
- * @psk: Pre-shared key (at least 16 bytes if AES is used)
+ * @psk: Pre-shared key
* @psk_len: Length of psk in bytes
* @vendor: CSuite/Vendor
* @specifier: CSuite/Specifier
- * @rand_client: 32-byte RAND_Client
+ * @rand_peer: 32-byte RAND_Peer
* @rand_server: 32-byte RAND_Server
- * @id_client: ID_Client
- * @id_client_len: Length of ID_Client
+ * @id_peer: ID_Peer
+ * @id_peer_len: Length of ID_Peer
* @id_server: ID_Server
* @id_server_len: Length of ID_Server
* @msk: Buffer for 64-byte MSK
* @emsk: Buffer for 64-byte EMSK
* @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes)
* @sk_len: Buffer for returning length of SK
- * @pk: Buffer for SK (at least EAP_GPSK_MAX_PK_LEN bytes)
+ * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes)
* @pk_len: Buffer for returning length of PK
* Returns: 0 on success, -1 on failure
*/
int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
int specifier,
- const u8 *rand_client, const u8 *rand_server,
- const u8 *id_client, size_t id_client_len,
+ const u8 *rand_peer, const u8 *rand_server,
+ const u8 *id_peer, size_t id_peer_len,
const u8 *id_server, size_t id_server_len,
u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len,
u8 *pk, size_t *pk_len)
@@ -318,8 +303,8 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
- /* Seed = RAND_Client || ID_Client || RAND_Server || ID_Server */
- seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_client_len;
+ /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */
+ seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len;
seed = os_malloc(seed_len);
if (seed == NULL) {
wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory "
@@ -328,10 +313,10 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
}
pos = seed;
- os_memcpy(pos, rand_client, EAP_GPSK_RAND_LEN);
+ os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
pos += EAP_GPSK_RAND_LEN;
- os_memcpy(pos, id_client, id_client_len);
- pos += id_client_len;
+ os_memcpy(pos, id_peer, id_peer_len);
+ pos += id_peer_len;
os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN);
pos += EAP_GPSK_RAND_LEN;
os_memcpy(pos, id_server, id_server_len);
@@ -347,8 +332,7 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
#ifdef EAP_GPSK_SHA256
case EAP_GPSK_CIPHER_SHA256:
ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len,
- msk, emsk, sk, sk_len,
- pk, pk_len);
+ msk, emsk, sk, sk_len);
break;
#endif /* EAP_GPSK_SHA256 */
default: