18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-pwd (RFC 5931) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010, Dan Harkins <dharkins@lounge.org> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 1204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "crypto/sha256.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_pwd_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_pwd_data { 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_peer; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_peer_len; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *id_server; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t id_server_len; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *password; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t password_len; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 group_num; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PWD_group *grp; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct wpabuf *inbuf; 31c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt size_t in_frag_pos; 32c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct wpabuf *outbuf; 33c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt size_t out_frag_pos; 34c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt size_t mtu; 35c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *k; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *private_value; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *server_scalar; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *my_scalar; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT *my_element; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT *server_element; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_CTX *bnctx; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_pwd_state_txt(int state) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PWD_ID_Req: 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PWD-ID-Req"; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PWD_Commit_Req: 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PWD-Commit-Req"; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PWD_Confirm_Req: 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PWD-Confirm-Req"; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PWD-UNK"; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pwd_state(struct eap_pwd_data *data, int state) 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 73c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PWD: %s -> %s", 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state_txt(data->state), eap_pwd_state_txt(state)); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_pwd_init(struct eap_sm *sm) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (password == NULL) { 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: No password configured!"); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: No identity configured!"); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data = os_zalloc(sizeof(*data))) == NULL) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: memory allocation data fail"); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->bnctx = BN_CTX_new()) == NULL) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail"); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->id_peer = os_malloc(identity_len)) == NULL) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail"); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_CTX_free(data->bnctx); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_peer, identity, identity_len); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer_len = identity_len; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->password = os_malloc(password_len)) == NULL) { 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail"); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_CTX_free(data->bnctx); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_peer); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->password, password, password_len); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->password_len = password_len; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 128c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->out_frag_pos = data->in_frag_pos = 0; 129c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->inbuf = data->outbuf = NULL; 130c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->mtu = 1020; /* default from RFC 5931, make it configurable! */ 131c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PWD_ID_Req; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pwd_deinit(struct eap_sm *sm, void *priv) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data = priv; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->private_value); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->server_scalar); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->my_scalar); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->k); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_CTX_free(data->bnctx); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT_free(data->my_element); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT_free(data->server_element); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_peer); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->id_server); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->password); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->grp) { 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_GROUP_free(data->grp->group); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT_free(data->grp->pwe); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->grp->order); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(data->grp->prime); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->grp); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len) 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data = priv; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 182c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, size_t payload_len) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_id *id; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PWD_ID_Req) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 192c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 193c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (payload_len < sizeof(struct eap_pwd_id)) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 198c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 199c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = (struct eap_pwd_id *) payload; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_num = be_to_host16(id->group_num); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) || 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (id->prf != EAP_PWD_DEFAULT_PRF)) { 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 207c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 208c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 211c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d", 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_num); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server = os_malloc(payload_len - sizeof(struct eap_pwd_id)); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_server == NULL) { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail"); 217c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 218c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server_len = payload_len - sizeof(struct eap_pwd_id); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->id_server, id->identity, data->id_server_len); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of", 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((data->grp = (EAP_PWD_group *) os_malloc(sizeof(EAP_PWD_group))) == 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL) { 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for " 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group"); 229c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 230c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute PWE */ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (compute_password_element(data->grp, data->group_num, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->password, data->password_len, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_server, data->id_server_len, 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_peer, data->id_peer_len, 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id->token)) { 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE"); 240c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 241c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 244c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...", 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_num_bits(data->grp->prime)); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 247c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) + 248c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->id_peer_len); 249c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) { 250c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_state(data, FAILURE); 251c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 252c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 253c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_be16(data->outbuf, data->group_num); 254c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC); 255c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF); 256c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->outbuf, id->token, sizeof(id->token)); 257c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE); 258c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->outbuf, data->id_peer, data->id_peer_len); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, PWD_Commit_Req); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 264c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, size_t payload_len) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT *K = NULL, *point = NULL; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 offset; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ptr, *scalar = NULL, *element = NULL; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (((data->private_value = BN_new()) == NULL) || 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((cofactor = BN_new()) == NULL) || 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((data->my_scalar = BN_new()) == NULL) || 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((mask = BN_new()) == NULL)) { 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail"); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor " 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for curve"); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_rand_range(data->private_value, data->grp->order); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_rand_range(mask, data->grp->order); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_add(data->my_scalar, data->private_value, mask); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_mod(data->my_scalar, data->my_scalar, data->grp->order, 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_mul(data->grp->group, data->my_element, NULL, 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->grp->pwe, mask, data->bnctx)) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation " 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fail"); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, FAILURE); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx)) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail"); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(mask); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (((x = BN_new()) == NULL) || 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((y = BN_new()) == NULL)) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail"); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* process the request */ 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (((data->server_scalar = BN_new()) == NULL) || 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((data->k = BN_new()) == NULL) || 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((K = EC_POINT_new(data->grp->group)) == NULL) || 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((point = EC_POINT_new(data->grp->group)) == NULL) || 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((data->server_element = EC_POINT_new(data->grp->group)) == NULL)) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation " 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fail"); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* element, x then y, followed by scalar */ 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr = (u8 *) payload; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr += BN_num_bytes(data->grp->prime); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr += BN_num_bytes(data->grp->prime); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->server_element, x, y, 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element " 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fail"); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* check to ensure server's element is not in a small sub-group */ 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (BN_cmp(cofactor, BN_value_one())) { 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_mul(data->grp->group, point, NULL, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->server_element, cofactor, NULL)) { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server element by order!\n"); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (EC_POINT_is_at_infinity(data->grp->group, point)) { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): server element " 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "is at infinity!\n"); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute the shared key, k */ 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->server_scalar, data->bnctx)) || 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!EC_POINT_add(data->grp->group, K, K, data->server_element, 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) || 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx))) { 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key " 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fail"); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ensure that the shared key isn't in a small sub-group */ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (BN_cmp(cofactor, BN_value_one())) { 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL)) { 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "shared key point by order"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This check is strictly speaking just for the case above where 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * co-factor > 1 but it was suggested that even though this is probably 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * never going to happen it is a simple and safe check "just to be 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sure" so let's be safe. 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (EC_POINT_is_at_infinity(data->grp->group, K)) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at " 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "infinity!\n"); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, data->bnctx)) { 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract " 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "shared secret from point"); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* now do the response */ 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->my_element, x, y, 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail"); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) || 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) == 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL)) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail"); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * bignums occupy as little memory as possible so one that is 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sufficiently smaller than the prime or order might need pre-pending 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with zeros. 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(scalar, 0, BN_num_bytes(data->grp->order)); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offset = BN_num_bytes(data->grp->order) - 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_num_bytes(data->my_scalar); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bn2bin(data->my_scalar, scalar + offset); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bn2bin(x, element + offset); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 431c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) + 432c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 2 * BN_num_bytes(data->grp->prime)); 433c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* we send the element as (x,y) follwed by the scalar */ 437c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->outbuf, element, 438c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 2 * BN_num_bytes(data->grp->prime)); 439c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order)); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfin: 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(scalar); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(element); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(x); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(y); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(cofactor); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT_free(K); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EC_POINT_free(point); 449c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, FAILURE); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, PWD_Confirm_Req); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 456c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *payload, size_t payload_len) 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BIGNUM *x = NULL, *y = NULL; 46304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct crypto_hash *hash; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 cs; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 grp; 46604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr; 4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int offset; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * first build up the ciphersuite which is group | random_function | 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prf 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt grp = htons(data->group_num); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr = (u8 *) &cs; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ptr, &grp, sizeof(u16)); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr += sizeof(u16); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ptr = EAP_PWD_DEFAULT_RAND_FUNC; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr += sizeof(u8); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ptr = EAP_PWD_DEFAULT_PRF; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* each component of the cruft will be at most as big as the prime */ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { 484c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation " 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fail"); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * server's commit is H(k | server_element | server_scalar | 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peer_element | peer_scalar | ciphersuite) 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 49304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hash = eap_pwd_h_init(); 49404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hash == NULL) 49504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fin; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * zero the memory each time because this is mod prime math and some 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value may start with a few zeros and the previous one did not. 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k); 5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->k, cruft + offset); 50404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server element: x, y */ 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->server_element, x, y, 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assignment fail"); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(x, cruft + offset); 51704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(y, cruft + offset); 52104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server scalar */ 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->order) - 5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_num_bytes(data->server_scalar); 5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->server_scalar, cruft + offset); 52804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* my element: x, y */ 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->my_element, x, y, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assignment fail"); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); 5411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(x, cruft + offset); 54204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(y, cruft + offset); 54604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* my scalar */ 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->order) - 5511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_num_bytes(data->my_scalar); 5521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->my_scalar, cruft + offset); 55304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* the ciphersuite */ 55604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* random function fin */ 55904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_final(hash, conf); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptr = (u8 *) payload; 56204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify"); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified"); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * compute confirm: 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * H(k | peer_element | peer_scalar | server_element | server_scalar | 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ciphersuite) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 57404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hash = eap_pwd_h_init(); 57504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hash == NULL) 57604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fin; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* k */ 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k); 5811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->k, cruft + offset); 58204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* my element */ 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->my_element, x, y, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assignment fail"); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); 5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(x, cruft + offset); 59504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); 5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(y, cruft + offset); 59904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* my scalar */ 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->order) - 6041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_num_bytes(data->my_scalar); 6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->my_scalar, cruft + offset); 60604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server element: x, y */ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->server_element, x, y, 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->bnctx)) { 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assignment fail"); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); 6181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(x, cruft + offset); 61904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); 6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(y, cruft + offset); 62304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server scalar */ 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); 6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = BN_num_bytes(data->grp->order) - 6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_num_bytes(data->server_scalar); 6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt BN_bn2bin(data->server_scalar, cruft + offset); 63004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* the ciphersuite */ 63304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* all done */ 63604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_pwd_h_final(hash, conf); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (compute_keys(data->grp, data->bnctx, data->k, 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->my_scalar, data->server_scalar, conf, ptr, 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cs, data->msk, data->emsk) < 0) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | " 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EMSK"); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fin; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->outbuf = wpabuf_alloc(SHA256_MAC_LEN); 647c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) 648c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt goto fin; 649c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 65004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN); 651c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfin: 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cruft); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(x); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BN_free(y); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 657c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, FAILURE); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pwd_state(data, SUCCESS); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data = priv; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp = NULL; 673c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *pos, *buf; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 675c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt u16 tot_len = 0; 676c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt u8 lm_exch; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, reqData, &len); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((pos == NULL) || (len < 1)) { 680c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and " 681c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "len is %d", 682c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos == NULL ? "NULL" : "not NULL", (int) len); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 692c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt lm_exch = *pos; 693c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos++; /* skip over the bits and the exch */ 694c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len--; 695c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 696c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 697c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * we're fragmenting so send out the next fragment 698c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 699c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->out_frag_pos) { 700c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 701c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * this should be an ACK 702c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 703c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (len) 704c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_INFO, "Bad Response! Fragmenting but " 705c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "not an ACK"); 706c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 707c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Got an ACK for a fragment"); 708c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 709c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * check if there are going to be more fragments 710c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 711c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len = wpabuf_len(data->outbuf) - data->out_frag_pos; 712c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if ((len + EAP_PWD_HDR_SIZE) > data->mtu) { 713c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len = data->mtu - EAP_PWD_HDR_SIZE; 714c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_SET_MORE_BIT(lm_exch); 715c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 716c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 717c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_HDR_SIZE + len, 718c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 719c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (resp == NULL) { 720c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_INFO, "Unable to allocate memory for " 721c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "next fragment!"); 722c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; 723c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 724c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(resp, lm_exch); 725c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt buf = wpabuf_head_u8(data->outbuf); 726c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(resp, buf + data->out_frag_pos, len); 727c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->out_frag_pos += len; 728c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 729c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * this is the last fragment so get rid of the out buffer 730c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 731c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->out_frag_pos >= wpabuf_len(data->outbuf)) { 732c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_free(data->outbuf); 73304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->outbuf = NULL; 734c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->out_frag_pos = 0; 735c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 736c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Send %s fragment of %d bytes", 737c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->out_frag_pos == 0 ? "last" : "next", 738c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (int) len); 739c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return resp; 740c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 741c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 742c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 743c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * see if this is a fragment that needs buffering 744c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * 745c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if it's the first fragment there'll be a length field 746c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 747c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) { 748c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt tot_len = WPA_GET_BE16(pos); 749c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose " 750c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "total length = %d", tot_len); 751c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->inbuf = wpabuf_alloc(tot_len); 752c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->inbuf == NULL) { 753c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_INFO, "Out of memory to buffer " 754c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "fragments!"); 755c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; 756c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 757c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos += sizeof(u16); 758c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len -= sizeof(u16); 759c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 760c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 761c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * buffer and ACK the fragment 762c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 763c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (EAP_PWD_GET_MORE_BIT(lm_exch)) { 764c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->in_frag_pos += len; 765c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->in_frag_pos > wpabuf_size(data->inbuf)) { 766c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack " 767c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "detected (%d vs. %d)!", 768c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (int) data->in_frag_pos, 769c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (int) wpabuf_len(data->inbuf)); 770c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_free(data->inbuf); 771c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->in_frag_pos = 0; 772c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; 773c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 774c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->inbuf, pos, len); 775c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 776c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 777c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_HDR_SIZE, 778c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 779c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (resp != NULL) 780c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(resp, (EAP_PWD_GET_EXCHANGE(lm_exch))); 781c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a %d byte fragment", 782c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (int) len); 783c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return resp; 784c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 785c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 786c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * we're buffering and this is the last fragment 787c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 788c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->in_frag_pos) { 789c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(data->inbuf, pos, len); 790c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes", 791c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (int) len); 792c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->in_frag_pos += len; 793c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos = wpabuf_head_u8(data->inbuf); 794c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len = data->in_frag_pos; 795c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 796c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: processing frame: exch %d, len %d", 797c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_GET_EXCHANGE(lm_exch), (int) len); 798c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 799c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt switch (EAP_PWD_GET_EXCHANGE(lm_exch)) { 800c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt case EAP_PWD_OPCODE_ID_EXCH: 801c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_perform_id_exchange(sm, data, ret, reqData, 802c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos, len); 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 804c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt case EAP_PWD_OPCODE_COMMIT_EXCH: 805c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_perform_commit_exchange(sm, data, ret, reqData, 806c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos, len); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 808c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt case EAP_PWD_OPCODE_CONFIRM_EXCH: 809c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_pwd_perform_confirm_exchange(sm, data, ret, reqData, 810c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pos, len); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 812c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt default: 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-pwd: Ignoring message with unknown " 814c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "opcode %d", lm_exch); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 817c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 818c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if we buffered the just processed input now's the time to free it 819c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 820c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->in_frag_pos) { 821c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_free(data->inbuf); 822c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->in_frag_pos = 0; 823c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 824c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 825c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (data->outbuf == NULL) 826c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; /* generic failure */ 827c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 828c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 829c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * we have output! Do we need to fragment it? 830c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 831c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len = wpabuf_len(data->outbuf); 832c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if ((len + EAP_PWD_HDR_SIZE) > data->mtu) { 833c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, data->mtu, 834c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 835c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 836c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if so it's the first so include a length field 837c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 838c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_SET_LENGTH_BIT(lm_exch); 839c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_SET_MORE_BIT(lm_exch); 840c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt tot_len = len; 841c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 842c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * keep the packet at the MTU 843c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 844c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt len = data->mtu - EAP_PWD_HDR_SIZE - sizeof(u16); 845c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, total " 846c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "length = %d", tot_len); 847c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 848c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 849c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_PWD_HDR_SIZE + len, 850c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 851c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 852c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (resp == NULL) 853c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; 854c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 855c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_u8(resp, lm_exch); 856c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) { 857c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_be16(resp, tot_len); 858c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->out_frag_pos += len; 859c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 860c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt buf = wpabuf_head_u8(data->outbuf); 861c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_put_data(resp, buf, len); 862c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 863c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if we're not fragmenting then there's no need to carry this around 864c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 86504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (data->out_frag_pos == 0) { 866c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpabuf_free(data->outbuf); 86704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->outbuf = NULL; 86804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->out_frag_pos = 0; 86904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv) 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data = priv; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pwd_data *data = priv; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((key = os_malloc(EAP_EMSK_LEN)) == NULL) 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_pwd_register(void) 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EVP_add_digest(EVP_sha256()); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD"); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_pwd_init; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_pwd_deinit; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_pwd_process; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_pwd_key_available; 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_pwd_getkey; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_pwd_get_emsk; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 923