/** * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) * @len: Pointer to length of the session ID generated * Returns: Pointer to allocated Session-Id on success or %NULL on failure * * This function derive the Session-Id based on the TLS session data * (client/server random and method type). * * The caller is responsible for freeing the returned buffer. */ u8 * eap_server_tls_derive_session_id(struct eap_sm *sm, struct eap_ssl_data *data, u8 eap_type, size_t *len) { struct tls_keys keys; u8 *out; if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) return NULL; if (keys.client_random == NULL || keys.server_random == NULL) return NULL; *len = 1 + keys.client_random_len + keys.server_random_len; out = os_malloc(*len); if (out == NULL) return NULL; /* Session-Id = EAP type || client.random || server.random */ out[0] = eap_type; os_memcpy(out + 1, keys.client_random, keys.client_random_len); os_memcpy(out + 1 + keys.client_random_len, keys.server_random, keys.server_random_len); return out; }
/** * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) * @len: Pointer to length of the session ID generated * Returns: Pointer to allocated Session-Id on success or %NULL on failure * * This function derive the Session-Id based on the TLS session data * (client/server random and method type). * * The caller is responsible for freeing the returned buffer. */ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct eap_ssl_data *data, u8 eap_type, size_t *len) { struct tls_keys keys; u8 *out; /* * TLS library did not support session ID generation, * so get the needed TLS session parameters */ if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) return NULL; if (keys.client_random == NULL || keys.server_random == NULL || keys.master_key == NULL) return NULL; *len = 1 + keys.client_random_len + keys.server_random_len; out = os_malloc(*len); if (out == NULL) return NULL; /* Session-Id = EAP type || client.random || server.random */ out[0] = eap_type; os_memcpy(out + 1, keys.client_random, keys.client_random_len); os_memcpy(out + 1 + keys.client_random_len, keys.server_random, keys.server_random_len); return out; }
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, char *label, size_t len) { struct tls_keys keys; u8 *random; u8 *out; if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) return NULL; out = malloc(len); random = malloc(keys.client_random_len + keys.server_random_len); if (out == NULL || random == NULL) { free(out); free(random); return NULL; } memcpy(random, keys.client_random, keys.client_random_len); memcpy(random + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf(keys.master_key, keys.master_key_len, label, random, keys.client_random_len + keys.server_random_len, out, len)) { free(random); free(out); return NULL; } free(random); return out; }
static int eap_ttls_v1_derive_key(struct eap_sm *sm, struct eap_ttls_data *data) { struct tls_keys keys; u8 *rnd; os_free(data->key_data); data->key_data = NULL; os_memset(&keys, 0, sizeof(keys)); if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || keys.client_random == NULL || keys.server_random == NULL || keys.inner_secret == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " "client random, or server random to derive keying " "material"); return -1; } rnd = os_malloc(keys.client_random_len + keys.server_random_len); data->key_data = os_malloc(EAP_TLS_KEY_LEN); if (rnd == NULL || data->key_data == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); os_free(rnd); os_free(data->key_data); data->key_data = NULL; return -1; } os_memcpy(rnd, keys.client_random, keys.client_random_len); os_memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf(keys.inner_secret, keys.inner_secret_len, "ttls v1 keying material", rnd, keys.client_random_len + keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); os_free(rnd); os_free(data->key_data); data->key_data = NULL; return -1; } wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", rnd, keys.client_random_len + keys.server_random_len); wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", keys.inner_secret, keys.inner_secret_len); os_free(rnd); wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", data->key_data, EAP_TLS_KEY_LEN); return 0; }
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, struct eap_ttls_data *data, size_t len) { struct tls_keys keys; u8 *challenge, *rnd; if (data->ttls_version == 0) { return eap_tls_derive_key(sm, &data->ssl, "ttls challenge", len); } os_memset(&keys, 0, sizeof(keys)); if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || keys.client_random == NULL || keys.server_random == NULL || keys.inner_secret == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " "client random, or server random to derive " "implicit challenge"); return NULL; } rnd = os_malloc(keys.client_random_len + keys.server_random_len); challenge = os_malloc(len); if (rnd == NULL || challenge == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " "challenge derivation"); os_free(rnd); os_free(challenge); return NULL; } os_memcpy(rnd, keys.server_random, keys.server_random_len); os_memcpy(rnd + keys.server_random_len, keys.client_random, keys.client_random_len); if (tls_prf(keys.inner_secret, keys.inner_secret_len, "inner application challenge", rnd, keys.client_random_len + keys.server_random_len, challenge, len)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit " "challenge"); os_free(rnd); os_free(challenge); return NULL; } os_free(rnd); wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", challenge, len); return challenge; }
/** * eap_peer_tls_derive_key - Derive a key based on TLS session data * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @label: Label string for deriving the keys, e.g., "client EAP encryption" * @len: Length of the key material to generate (usually 64 for MSK) * Returns: Pointer to allocated key on success or %NULL on failure * * This function uses TLS-PRF to generate pseudo-random data based on the TLS * session data (client/server random and master key). Each key type may use a * different label to bind the key usage into the generated material. * * The caller is responsible for freeing the returned buffer. */ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, const char *label, size_t len) { #ifndef CONFIG_FIPS struct tls_keys keys; #endif /* CONFIG_FIPS */ u8 *rnd = NULL, *out; out = os_malloc(len); if (out == NULL) return NULL; /* First, try to use TLS library function for PRF, if available. */ if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len) == 0) return out; #ifndef CONFIG_FIPS /* * TLS library did not support key generation, so get the needed TLS * session parameters and use an internal implementation of TLS PRF to * derive the key. */ if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys)) goto fail; if (keys.client_random == NULL || keys.server_random == NULL || keys.master_key == NULL) goto fail; rnd = os_malloc(keys.client_random_len + keys.server_random_len); if (rnd == NULL) goto fail; os_memcpy(rnd, keys.client_random, keys.client_random_len); os_memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, label, rnd, keys.client_random_len + keys.server_random_len, out, len)) goto fail; os_free(rnd); return out; fail: #endif /* CONFIG_FIPS */ os_free(out); os_free(rnd); return NULL; }
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, const char *label, size_t len) { struct tls_keys keys; u8 *rnd = NULL, *out; int block_size; block_size = tls_connection_get_keyblock_size(ssl_ctx, conn); if (block_size < 0) return NULL; out = os_malloc(block_size + len); if (out == NULL) return NULL; if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len) == 0) { os_memmove(out, out + block_size, len); return out; } if (tls_connection_get_keys(ssl_ctx, conn, &keys)) goto fail; rnd = os_malloc(keys.client_random_len + keys.server_random_len); if (rnd == NULL) goto fail; os_memcpy(rnd, keys.server_random, keys.server_random_len); os_memcpy(rnd + keys.server_random_len, keys.client_random, keys.client_random_len); wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " "expansion", keys.master_key, keys.master_key_len); if (tls_prf(keys.master_key, keys.master_key_len, label, rnd, keys.client_random_len + keys.server_random_len, out, block_size + len)) goto fail; os_free(rnd); os_memmove(out, out + block_size, len); return out; fail: os_free(rnd); os_free(out); return NULL; }
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, char *label, size_t len) { struct tls_keys keys; u8 *rnd; u8 *out; if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) return NULL; if (keys.eap_tls_prf && strcmp(label, "client EAP encryption") == 0) { if (len > keys.eap_tls_prf_len) return NULL; out = malloc(len); if (out == NULL) return NULL; memcpy(out, keys.eap_tls_prf, len); return out; } if (keys.client_random == NULL || keys.server_random == NULL || keys.master_key == NULL) return NULL; out = malloc(len); rnd = malloc(keys.client_random_len + keys.server_random_len); if (out == NULL || rnd == NULL) { free(out); free(rnd); return NULL; } memcpy(rnd, keys.client_random, keys.client_random_len); memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf(keys.master_key, keys.master_key_len, label, rnd, keys.client_random_len + keys.server_random_len, out, len)) { free(rnd); free(out); return NULL; } free(rnd); return out; }
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, char *label, size_t len) { struct tls_keys keys; u8 *rnd = NULL, *out; out = malloc(len); if (out == NULL) return NULL; if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 0) return out; if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) goto fail; if (keys.client_random == NULL || keys.server_random == NULL || keys.master_key == NULL) goto fail; rnd = malloc(keys.client_random_len + keys.server_random_len); if (rnd == NULL) goto fail; memcpy(rnd, keys.client_random, keys.client_random_len); memcpy(rnd + keys.client_random_len, keys.server_random, keys.server_random_len); if (tls_prf(keys.master_key, keys.master_key_len, label, rnd, keys.client_random_len + keys.server_random_len, out, len)) goto fail; free(rnd); return out; fail: free(out); free(rnd); return NULL; }