|
@@ -340,6 +340,141 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static int eap_gpsk_derive_mid_helper(u32 csuite_specifier,
|
|
|
+ u8 *kdf_out, size_t kdf_out_len,
|
|
|
+ const u8 *psk, const u8 *seed,
|
|
|
+ size_t seed_len, u8 method_type)
|
|
|
+{
|
|
|
+ u8 *pos, *data;
|
|
|
+ size_t data_len;
|
|
|
+ int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len,
|
|
|
+ u8 *buf, size_t len);
|
|
|
+
|
|
|
+ gkdf = NULL;
|
|
|
+ switch (csuite_specifier) {
|
|
|
+ case EAP_GPSK_CIPHER_AES:
|
|
|
+ gkdf = eap_gpsk_gkdf_cmac;
|
|
|
+ break;
|
|
|
+#ifdef EAP_GPSK_SHA256
|
|
|
+ case EAP_GPSK_CIPHER_SHA256:
|
|
|
+ gkdf = eap_gpsk_gkdf_sha256;
|
|
|
+ break;
|
|
|
+#endif /* EAP_GPSK_SHA256 */
|
|
|
+ default:
|
|
|
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d used in "
|
|
|
+ "Session-Id derivation", csuite_specifier);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+#define SID_LABEL "Method ID"
|
|
|
+ /* "Method ID" || EAP_Method_Type || CSuite_Sel || inputString */
|
|
|
+ data_len = strlen(SID_LABEL) + 1 + 6 + seed_len;
|
|
|
+ data = os_malloc(data_len);
|
|
|
+ if (data == NULL)
|
|
|
+ return -1;
|
|
|
+ pos = data;
|
|
|
+ os_memcpy(pos, SID_LABEL, strlen(SID_LABEL));
|
|
|
+ pos += strlen(SID_LABEL);
|
|
|
+#undef SID_LABEL
|
|
|
+ os_memcpy(pos, &method_type, 1);
|
|
|
+ pos += 1;
|
|
|
+ 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(MSG_DEBUG, "EAP-GPSK: Data to Method ID derivation",
|
|
|
+ data, data_len);
|
|
|
+
|
|
|
+ if (gkdf(psk, data, data_len, kdf_out, kdf_out_len) < 0) {
|
|
|
+ os_free(data);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ os_free(data);
|
|
|
+ wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Method ID", kdf_out, kdf_out_len);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * eap_gpsk_session_id - Derive EAP-GPSK Session ID
|
|
|
+ * @psk: Pre-shared key
|
|
|
+ * @psk_len: Length of psk in bytes
|
|
|
+ * @vendor: CSuite/Vendor
|
|
|
+ * @specifier: CSuite/Specifier
|
|
|
+ * @rand_peer: 32-byte RAND_Peer
|
|
|
+ * @rand_server: 32-byte RAND_Server
|
|
|
+ * @id_peer: ID_Peer
|
|
|
+ * @id_peer_len: Length of ID_Peer
|
|
|
+ * @id_server: ID_Server
|
|
|
+ * @id_server_len: Length of ID_Server
|
|
|
+ * @method_type: EAP Authentication Method Type
|
|
|
+ * @sid: Buffer for 17-byte Session ID
|
|
|
+ * @sid_len: Buffer for returning length of Session ID
|
|
|
+ * Returns: 0 on success, -1 on failure
|
|
|
+ */
|
|
|
+int eap_gpsk_derive_session_id(const u8 *psk, size_t psk_len, int vendor,
|
|
|
+ int specifier,
|
|
|
+ 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 method_type, u8 *sid, size_t *sid_len)
|
|
|
+{
|
|
|
+ u8 *seed, *pos;
|
|
|
+ u8 kdf_out[16];
|
|
|
+ size_t seed_len;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving Session ID(%d:%d)",
|
|
|
+ vendor, specifier);
|
|
|
+
|
|
|
+ if (vendor != EAP_GPSK_VENDOR_IETF)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
|
|
|
+ * (= seed)
|
|
|
+ * KS = 16, CSuite_Sel = 0x00000000 0x0001
|
|
|
+ * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
|
|
|
+ * CSuite_Sel || inputString)
|
|
|
+ */
|
|
|
+ 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 "
|
|
|
+ "for Session-Id derivation");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ pos = seed;
|
|
|
+ os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN);
|
|
|
+ pos += EAP_GPSK_RAND_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);
|
|
|
+ pos += id_server_len;
|
|
|
+ wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len);
|
|
|
+
|
|
|
+ ret = eap_gpsk_derive_mid_helper(specifier,
|
|
|
+ kdf_out, sizeof(kdf_out),
|
|
|
+ psk, seed, seed_len,
|
|
|
+ method_type);
|
|
|
+
|
|
|
+ sid[0] = method_type;
|
|
|
+ os_memcpy(sid + 1, kdf_out, sizeof(kdf_out));
|
|
|
+ *sid_len = 1 + sizeof(kdf_out);
|
|
|
+
|
|
|
+ os_free(seed);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* eap_gpsk_mic_len - Get the length of the MIC
|
|
|
* @vendor: CSuite/Vendor
|