static void eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_method_ret *ret, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) { BIGNUM *x = NULL, *y = NULL; struct crypto_hash *hash; u32 cs; u16 grp; u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr; int offset; /* * first build up the ciphersuite which is group | random_function | * prf */ grp = htons(data->group_num); ptr = (u8 *) &cs; os_memcpy(ptr, &grp, sizeof(u16)); ptr += sizeof(u16); *ptr = EAP_PWD_DEFAULT_RAND_FUNC; ptr += sizeof(u8); *ptr = EAP_PWD_DEFAULT_PRF; /* each component of the cruft will be at most as big as the prime */ if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation " "fail"); goto fin; } /* * server's commit is H(k | server_element | server_scalar | * peer_element | peer_scalar | ciphersuite) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fin; /* * zero the memory each time because this is mod prime math and some * value may start with a few zeros and the previous one did not. */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k); BN_bn2bin(data->k, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->server_scalar); BN_bn2bin(data->server_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* my element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* my scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->my_scalar); BN_bn2bin(data->my_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* the ciphersuite */ eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); /* random function fin */ eap_pwd_h_final(hash, conf); ptr = (u8 *) payload; if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify"); goto fin; } wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified"); /* * compute confirm: * H(k | peer_element | peer_scalar | server_element | server_scalar | * ciphersuite) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fin; /* k */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k); BN_bn2bin(data->k, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* my element */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* my scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->my_scalar); BN_bn2bin(data->my_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->server_scalar); BN_bn2bin(data->server_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* the ciphersuite */ eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); /* all done */ eap_pwd_h_final(hash, conf); if (compute_keys(data->grp, data->bnctx, data->k, data->my_scalar, data->server_scalar, conf, ptr, &cs, data->msk, data->emsk) < 0) { wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | " "EMSK"); goto fin; } data->outbuf = wpabuf_alloc(SHA256_MAC_LEN); if (data->outbuf == NULL) goto fin; wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN); fin: os_free(cruft); BN_free(x); BN_free(y); ret->methodState = METHOD_DONE; if (data->outbuf == NULL) { ret->decision = DECISION_FAIL; eap_pwd_state(data, FAILURE); } else { ret->decision = DECISION_UNCOND_SUCC; eap_pwd_state(data, SUCCESS); } }
static void eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data, const u8 *payload, size_t payload_len) { BIGNUM *x = NULL, *y = NULL; HMAC_CTX ctx; u32 cs; u16 grp; u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr; /* build up the ciphersuite: group | random_function | prf */ grp = htons(data->group_num); ptr = (u8 *) &cs; os_memcpy(ptr, &grp, sizeof(u16)); ptr += sizeof(u16); *ptr = EAP_PWD_DEFAULT_RAND_FUNC; ptr += sizeof(u8); *ptr = EAP_PWD_DEFAULT_PRF; /* each component of the cruft will be at most as big as the prime */ if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail"); goto fin; } /* * commit is H(k | peer_element | peer_scalar | server_element | * server_scalar | ciphersuite) */ H_Init(&ctx); /* k */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->k, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* peer element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->peer_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* peer scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->peer_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->my_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* ciphersuite */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); H_Update(&ctx, (u8 *)&cs, sizeof(u32)); /* all done */ H_Final(&ctx, conf); ptr = (u8 *) payload; if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not " "verify"); goto fin; } wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified"); if (compute_keys(data->grp, data->bnctx, data->k, data->peer_scalar, data->my_scalar, conf, data->my_confirm, &cs, data->msk, data->emsk) < 0) eap_pwd_state(data, FAILURE); else eap_pwd_state(data, SUCCESS); fin: os_free(cruft); BN_free(x); BN_free(y); }
static void eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data, const u8 *payload, size_t payload_len) { BIGNUM *x = NULL, *y = NULL; struct crypto_hash *hash; u32 cs; u16 grp; u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr; int offset; if (payload_len != SHA256_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-pwd: Unexpected Confirm payload length %u (expected %u)", (unsigned int) payload_len, SHA256_MAC_LEN); goto fin; } /* build up the ciphersuite: group | random_function | prf */ grp = htons(data->group_num); ptr = (u8 *) &cs; os_memcpy(ptr, &grp, sizeof(u16)); ptr += sizeof(u16); *ptr = EAP_PWD_DEFAULT_RAND_FUNC; ptr += sizeof(u8); *ptr = EAP_PWD_DEFAULT_PRF; /* each component of the cruft will be at most as big as the prime */ if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail"); goto fin; } /* * commit is H(k | peer_element | peer_scalar | server_element | * server_scalar | ciphersuite) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fin; /* k */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k); BN_bn2bin(data->k, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* peer element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->peer_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* peer scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->peer_scalar); BN_bn2bin(data->peer_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); offset = BN_num_bytes(data->grp->order) - BN_num_bytes(data->my_scalar); BN_bn2bin(data->my_scalar, cruft + offset); eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order)); /* ciphersuite */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); /* all done */ eap_pwd_h_final(hash, conf); ptr = (u8 *) payload; if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not " "verify"); goto fin; } wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified"); if (compute_keys(data->grp, data->bnctx, data->k, data->peer_scalar, data->my_scalar, conf, data->my_confirm, &cs, data->msk, data->emsk, data->session_id) < 0) eap_pwd_state(data, FAILURE); else eap_pwd_state(data, SUCCESS); fin: bin_clear_free(cruft, BN_num_bytes(data->grp->prime)); BN_clear_free(x); BN_clear_free(y); }
static int mod_authenticate (void *arg, eap_handler_t *handler) { pwd_session_t *pwd_session; pwd_hdr *hdr; pwd_id_packet *id; eap_packet_t *response; REQUEST *request, *fake; VALUE_PAIR *pw, *vp; EAP_DS *eap_ds; int len, ret = 0; eap_pwd_t *inst = (eap_pwd_t *)arg; uint16_t offset; uint8_t exch, *buf, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN]; uint8_t peer_confirm[SHA256_DIGEST_LENGTH]; BIGNUM *x = NULL, *y = NULL; if ((!handler) || ((eap_ds = handler->eap_ds) == NULL) || (!inst)) { return 0; } pwd_session = (pwd_session_t *)handler->opaque; request = handler->request; response = handler->eap_ds->response; hdr = (pwd_hdr *)response->type.data; buf = hdr->data; len = response->type.length - sizeof(pwd_hdr); /* * see if we're fragmenting, if so continue until we're done */ if (pwd_session->out_buf_pos) { if (len) { RDEBUG2("pwd got something more than an ACK for a fragment"); } return send_pwd_request(pwd_session, eap_ds); } /* * the first fragment will have a total length, make a * buffer to hold all the fragments */ if (EAP_PWD_GET_LENGTH_BIT(hdr)) { if (pwd_session->in_buf) { RDEBUG2("pwd already alloced buffer for fragments"); return 0; } pwd_session->in_buf_len = ntohs(buf[0] * 256 | buf[1]); if ((pwd_session->in_buf = talloc_zero_array(pwd_session, uint8_t, pwd_session->in_buf_len)) == NULL) { RDEBUG2("pwd cannot allocate %d buffer to hold fragments", pwd_session->in_buf_len); return 0; } memset(pwd_session->in_buf, 0, pwd_session->in_buf_len); pwd_session->in_buf_pos = 0; buf += sizeof(uint16_t); len -= sizeof(uint16_t); } /* * all fragments, including the 1st will have the M(ore) bit set, * buffer those fragments! */ if (EAP_PWD_GET_MORE_BIT(hdr)) { rad_assert(pwd_session->in_buf != NULL); if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) { RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent."); return 0; } memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len); pwd_session->in_buf_pos += len; /* * send back an ACK for this fragment */ exch = EAP_PWD_GET_EXCHANGE(hdr); eap_ds->request->code = PW_EAP_REQUEST; eap_ds->request->type.num = PW_EAP_PWD; eap_ds->request->type.length = sizeof(pwd_hdr); if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) { return 0; } hdr = (pwd_hdr *)eap_ds->request->type.data; EAP_PWD_SET_EXCHANGE(hdr, exch); return 1; } if (pwd_session->in_buf) { /* * the last fragment... */ if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) { RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent."); return 0; } memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len); buf = pwd_session->in_buf; len = pwd_session->in_buf_len; } switch (pwd_session->state) { case PWD_STATE_ID_REQ: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) { RDEBUG2("pwd exchange is incorrect: not ID"); return 0; } id = (pwd_id_packet *)buf; if ((id->prf != EAP_PWD_DEF_PRF) || (id->random_function != EAP_PWD_DEF_RAND_FUN) || (id->prep != EAP_PWD_PREP_NONE) || (memcmp(id->token, (char *)&pwd_session->token, 4)) || (id->group_num != ntohs(pwd_session->group_num))) { RDEBUG2("pwd id response is invalid"); return 0; } /* * we've agreed on the ciphersuite, record it... */ ptr = (uint8_t *)&pwd_session->ciphersuite; memcpy(ptr, (char *)&id->group_num, sizeof(uint16_t)); ptr += sizeof(uint16_t); *ptr = EAP_PWD_DEF_RAND_FUN; ptr += sizeof(uint8_t); *ptr = EAP_PWD_DEF_PRF; pwd_session->peer_id_len = len - sizeof(pwd_id_packet); if (pwd_session->peer_id_len >= sizeof(pwd_session->peer_id)) { RDEBUG2("pwd id response is malformed"); return 0; } memcpy(pwd_session->peer_id, id->identity, pwd_session->peer_id_len); pwd_session->peer_id[pwd_session->peer_id_len] = '\0'; /* * make fake request to get the password for the usable ID */ if ((fake = request_alloc_fake(handler->request)) == NULL) { RDEBUG("pwd unable to create fake request!"); return 0; } fake->username = pairmake_packet("User-Name", "", T_OP_EQ); if (!fake->username) { RDEBUG("pwd unanable to create value pair for username!"); request_free(&fake); return 0; } memcpy(fake->username->vp_strvalue, pwd_session->peer_id, pwd_session->peer_id_len); fake->username->length = pwd_session->peer_id_len; fake->username->vp_strvalue[fake->username->length] = 0; if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) { fake->server = vp->vp_strvalue; } else if (inst->conf->virtual_server) { fake->server = inst->conf->virtual_server; } /* else fake->server == request->server */ if ((debug_flag > 0) && fr_log_fp) { RDEBUG("Sending tunneled request"); debug_pair_list(fake->packet->vps); fprintf(fr_log_fp, "server %s {\n", (!fake->server) ? "" : fake->server); } /* * Call authorization recursively, which will * get the password. */ process_authorize(0, fake); /* * Note that we don't do *anything* with the reply * attributes. */ if ((debug_flag > 0) && fr_log_fp) { fprintf(fr_log_fp, "} # server %s\n", (!fake->server) ? "" : fake->server); RDEBUG("Got tunneled reply code %d", fake->reply->code); debug_pair_list(fake->reply->vps); } if ((pw = pairfind(fake->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) { DEBUG2("failed to find password for %s to do pwd authentication", pwd_session->peer_id); request_free(&fake); return 0; } if (compute_password_element(pwd_session, pwd_session->group_num, pw->data.strvalue, strlen(pw->data.strvalue), inst->conf->server_id, strlen(inst->conf->server_id), pwd_session->peer_id, strlen(pwd_session->peer_id), &pwd_session->token)) { DEBUG2("failed to obtain password element :-("); request_free(&fake); return 0; } request_free(&fake); /* * compute our scalar and element */ if (compute_scalar_element(pwd_session, inst->bnctx)) { DEBUG2("failed to compute server's scalar and element"); return 0; } if (((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { DEBUG2("server point allocation failed"); return 0; } /* * element is a point, get both coordinates: x and y */ if (!EC_POINT_get_affine_coordinates_GFp(pwd_session->group, pwd_session->my_element, x, y, inst->bnctx)) { DEBUG2("server point assignment failed"); BN_free(x); BN_free(y); return 0; } /* * construct request */ pwd_session->out_buf_len = BN_num_bytes(pwd_session->order) + (2 * BN_num_bytes(pwd_session->prime)); if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t, pwd_session->out_buf_len)) == NULL) { return 0; } memset(pwd_session->out_buf, 0, pwd_session->out_buf_len); ptr = pwd_session->out_buf; offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(x); BN_bn2bin(x, ptr + offset); ptr += BN_num_bytes(pwd_session->prime); offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(y); BN_bn2bin(y, ptr + offset); ptr += BN_num_bytes(pwd_session->prime); offset = BN_num_bytes(pwd_session->order) - BN_num_bytes(pwd_session->my_scalar); BN_bn2bin(pwd_session->my_scalar, ptr + offset); pwd_session->state = PWD_STATE_COMMIT; ret = send_pwd_request(pwd_session, eap_ds); break; case PWD_STATE_COMMIT: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } /* * process the peer's commit and generate the shared key, k */ if (process_peer_commit(pwd_session, buf, inst->bnctx)) { RDEBUG2("failed to process peer's commit"); return 0; } /* * compute our confirm blob */ if (compute_server_confirm(pwd_session, pwd_session->my_confirm, inst->bnctx)) { ERROR("rlm_eap_pwd: failed to compute confirm!"); return 0; } /* * construct a response...which is just our confirm blob */ pwd_session->out_buf_len = SHA256_DIGEST_LENGTH; if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t, pwd_session->out_buf_len)) == NULL) { return 0; } memset(pwd_session->out_buf, 0, pwd_session->out_buf_len); memcpy(pwd_session->out_buf, pwd_session->my_confirm, SHA256_DIGEST_LENGTH); pwd_session->state = PWD_STATE_CONFIRM; ret = send_pwd_request(pwd_session, eap_ds); break; case PWD_STATE_CONFIRM: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } if (compute_peer_confirm(pwd_session, peer_confirm, inst->bnctx)) { RDEBUG2("pwd exchange cannot compute peer's confirm"); return 0; } if (memcmp(peer_confirm, buf, SHA256_DIGEST_LENGTH)) { RDEBUG2("pwd exchange fails: peer confirm is incorrect!"); return 0; } if (compute_keys(pwd_session, peer_confirm, msk, emsk)) { RDEBUG2("pwd exchange cannot generate (E)MSK!"); return 0; } eap_ds->request->code = PW_EAP_SUCCESS; /* * return the MSK (in halves) */ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN); eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk+MPPE_KEY_LEN, MPPE_KEY_LEN); ret = 1; break; default: RDEBUG2("unknown PWD state"); return 0; } /* * we processed the buffered fragments, get rid of them */ if (pwd_session->in_buf) { talloc_free(pwd_session->in_buf); pwd_session->in_buf = NULL; } return ret; }
static int mod_process(void *arg, eap_handler_t *handler) { pwd_session_t *session; pwd_hdr *hdr; pwd_id_packet_t *packet; eap_packet_t *response; REQUEST *request, *fake; VALUE_PAIR *pw, *vp; EAP_DS *eap_ds; size_t in_len; int ret = 0; eap_pwd_t *inst = (eap_pwd_t *)arg; uint16_t offset; uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN]; uint8_t peer_confirm[SHA256_DIGEST_LENGTH]; if (((eap_ds = handler->eap_ds) == NULL) || !inst) return 0; session = (pwd_session_t *)handler->opaque; request = handler->request; response = handler->eap_ds->response; hdr = (pwd_hdr *)response->type.data; /* * The header must be at least one byte. */ if (!hdr || (response->type.length < sizeof(pwd_hdr))) { RDEBUG("Packet with insufficient data"); return 0; } in = hdr->data; in_len = response->type.length - sizeof(pwd_hdr); /* * see if we're fragmenting, if so continue until we're done */ if (session->out_pos) { if (in_len) RDEBUG2("pwd got something more than an ACK for a fragment"); return send_pwd_request(session, eap_ds); } /* * the first fragment will have a total length, make a * buffer to hold all the fragments */ if (EAP_PWD_GET_LENGTH_BIT(hdr)) { if (session->in) { RDEBUG2("pwd already alloced buffer for fragments"); return 0; } if (in_len < 2) { RDEBUG("Invalid packet: length bit set, but no length field"); return 0; } session->in_len = ntohs(in[0] * 256 | in[1]); if ((session->in = talloc_zero_array(session, uint8_t, session->in_len)) == NULL) { RDEBUG2("pwd cannot allocate %zd buffer to hold fragments", session->in_len); return 0; } memset(session->in, 0, session->in_len); session->in_pos = 0; in += sizeof(uint16_t); in_len -= sizeof(uint16_t); } /* * all fragments, including the 1st will have the M(ore) bit set, * buffer those fragments! */ if (EAP_PWD_GET_MORE_BIT(hdr)) { rad_assert(session->in != NULL); if ((session->in_pos + in_len) > session->in_len) { RDEBUG2("Fragment overflows packet."); return 0; } memcpy(session->in + session->in_pos, in, in_len); session->in_pos += in_len; /* * send back an ACK for this fragment */ exch = EAP_PWD_GET_EXCHANGE(hdr); eap_ds->request->code = PW_EAP_REQUEST; eap_ds->request->type.num = PW_EAP_PWD; eap_ds->request->type.length = sizeof(pwd_hdr); if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) { return 0; } hdr = (pwd_hdr *)eap_ds->request->type.data; EAP_PWD_SET_EXCHANGE(hdr, exch); return 1; } if (session->in) { /* * the last fragment... */ if ((session->in_pos + in_len) > session->in_len) { RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent"); return 0; } memcpy(session->in + session->in_pos, in, in_len); in = session->in; in_len = session->in_len; } switch (session->state) { case PWD_STATE_ID_REQ: { BIGNUM *x = NULL, *y = NULL; if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) { RDEBUG2("pwd exchange is incorrect: not ID"); return 0; } packet = (pwd_id_packet_t *) in; if (in_len < sizeof(*packet)) { RDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet)); return 0; } if ((packet->prf != EAP_PWD_DEF_PRF) || (packet->random_function != EAP_PWD_DEF_RAND_FUN) || (packet->prep != EAP_PWD_PREP_NONE) || (CRYPTO_memcmp(packet->token, &session->token, 4)) || (packet->group_num != ntohs(session->group_num))) { RDEBUG2("pwd id response is invalid"); return 0; } /* * we've agreed on the ciphersuite, record it... */ ptr = (uint8_t *)&session->ciphersuite; memcpy(ptr, (char *)&packet->group_num, sizeof(uint16_t)); ptr += sizeof(uint16_t); *ptr = EAP_PWD_DEF_RAND_FUN; ptr += sizeof(uint8_t); *ptr = EAP_PWD_DEF_PRF; session->peer_id_len = in_len - sizeof(pwd_id_packet_t); if (session->peer_id_len >= sizeof(session->peer_id)) { RDEBUG2("pwd id response is malformed"); return 0; } memcpy(session->peer_id, packet->identity, session->peer_id_len); session->peer_id[session->peer_id_len] = '\0'; /* * make fake request to get the password for the usable ID */ if ((fake = request_alloc_fake(handler->request)) == NULL) { RDEBUG("pwd unable to create fake request!"); return 0; } fake->username = fr_pair_afrom_num(fake->packet, PW_USER_NAME, 0); if (!fake->username) { RDEBUG("Failed creating pair for peer id"); talloc_free(fake); return 0; } fr_pair_value_bstrncpy(fake->username, session->peer_id, session->peer_id_len); fr_pair_add(&fake->packet->vps, fake->username); if ((vp = fr_pair_find_by_num(request->config, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) { fake->server = vp->vp_strvalue; } else if (inst->virtual_server) { fake->server = inst->virtual_server; } /* else fake->server == request->server */ RDEBUG("Sending tunneled request"); rdebug_pair_list(L_DBG_LVL_1, request, fake->packet->vps, NULL); if (fake->server) { RDEBUG("server %s {", fake->server); } else { RDEBUG("server {"); } /* * Call authorization recursively, which will * get the password. */ RINDENT(); process_authorize(0, fake); REXDENT(); /* * Note that we don't do *anything* with the reply * attributes. */ if (fake->server) { RDEBUG("} # server %s", fake->server); } else { RDEBUG("}"); } RDEBUG("Got tunneled reply code %d", fake->reply->code); rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL); if ((pw = fr_pair_find_by_num(fake->config, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) { DEBUG2("failed to find password for %s to do pwd authentication", session->peer_id); talloc_free(fake); return 0; } if (compute_password_element(session, session->group_num, pw->data.strvalue, strlen(pw->data.strvalue), inst->server_id, strlen(inst->server_id), session->peer_id, strlen(session->peer_id), &session->token)) { DEBUG2("failed to obtain password element"); talloc_free(fake); return 0; } TALLOC_FREE(fake); /* * compute our scalar and element */ if (compute_scalar_element(session, inst->bnctx)) { DEBUG2("failed to compute server's scalar and element"); return 0; } MEM(x = BN_new()); MEM(y = BN_new()); /* * element is a point, get both coordinates: x and y */ if (!EC_POINT_get_affine_coordinates_GFp(session->group, session->my_element, x, y, inst->bnctx)) { DEBUG2("server point assignment failed"); BN_clear_free(x); BN_clear_free(y); return 0; } /* * construct request */ session->out_len = BN_num_bytes(session->order) + (2 * BN_num_bytes(session->prime)); if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) { return 0; } memset(session->out, 0, session->out_len); ptr = session->out; offset = BN_num_bytes(session->prime) - BN_num_bytes(x); BN_bn2bin(x, ptr + offset); BN_clear_free(x); ptr += BN_num_bytes(session->prime); offset = BN_num_bytes(session->prime) - BN_num_bytes(y); BN_bn2bin(y, ptr + offset); BN_clear_free(y); ptr += BN_num_bytes(session->prime); offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar); BN_bn2bin(session->my_scalar, ptr + offset); session->state = PWD_STATE_COMMIT; ret = send_pwd_request(session, eap_ds); } break; case PWD_STATE_COMMIT: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } /* * process the peer's commit and generate the shared key, k */ if (process_peer_commit(session, in, in_len, inst->bnctx)) { RDEBUG2("failed to process peer's commit"); return 0; } /* * compute our confirm blob */ if (compute_server_confirm(session, session->my_confirm, inst->bnctx)) { ERROR("rlm_eap_pwd: failed to compute confirm!"); return 0; } /* * construct a response...which is just our confirm blob */ session->out_len = SHA256_DIGEST_LENGTH; if ((session->out = talloc_array(session, uint8_t, session->out_len)) == NULL) { return 0; } memset(session->out, 0, session->out_len); memcpy(session->out, session->my_confirm, SHA256_DIGEST_LENGTH); session->state = PWD_STATE_CONFIRM; ret = send_pwd_request(session, eap_ds); break; case PWD_STATE_CONFIRM: if (in_len < SHA256_DIGEST_LENGTH) { RDEBUG("Peer confirm is too short (%zd < %d)", in_len, SHA256_DIGEST_LENGTH); return 0; } if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } if (compute_peer_confirm(session, peer_confirm, inst->bnctx)) { RDEBUG2("pwd exchange cannot compute peer's confirm"); return 0; } if (CRYPTO_memcmp(peer_confirm, in, SHA256_DIGEST_LENGTH)) { RDEBUG2("pwd exchange fails: peer confirm is incorrect!"); return 0; } if (compute_keys(session, peer_confirm, msk, emsk)) { RDEBUG2("pwd exchange cannot generate (E)MSK!"); return 0; } eap_ds->request->code = PW_EAP_SUCCESS; /* * return the MSK (in halves) */ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN); eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk + MPPE_KEY_LEN, MPPE_KEY_LEN); ret = 1; break; default: RDEBUG2("unknown PWD state"); return 0; } /* * we processed the buffered fragments, get rid of them */ if (session->in) { talloc_free(session->in); session->in = NULL; } return ret; }
int main(int argc, char **argv) { mpz_t x; /* witness */ unsigned int e; /* random boolean vector (challenge) */ mpz_t y; /* response */ int proof; int sockfd; /* socket file descriptor */ int index; int j; char buf[MAXDATASIZE]; printf("Feige-Fiat-Shamir ZKP implementation\n"); if (argc != 2) { fprintf(stderr, "ZKP Server Usage: %s hostname\n", argv[0]); exit(1); } else { fastseed = TRUE; // printf("Warning: fastseed enabled, using a bad random seed value!\n"); } printf("\n"); mpz_init(rndseed); mpz_init(n); mpz_set_str(n, N, 10); /* Connect to server, T times */ for (j=0; j < T; j++) { printf("Iteration %d: ", j); timestamp(stdout); printf("\n"); mpz_init(x); mpz_init(y); e = 0; proof = 0; index = 0; // gmp_printf("n = %Zd\n", n); // printf("Computing keys.\n"); compute_keys(); /* Prover chooses public/private keys */ sockfd = zkp_connect(argv[1]); if (sockfd == 2) { return(0); } /* Prover sends public key, i[K] */ itoa(K, buf, 10); zkp_send(buf, sockfd); // 5 = K printf("Sent 1.\n"); for (index = 0; index < K; index++) { // gmp_printf("Sending: %i %Zd\n", index, i[index]); mpz_get_str(buf, 10, i[index]); zkp_send(buf, sockfd); sleep(1); } /* Prover sends the witness */ witness(x); mpz_get_str(buf, 10, x); zkp_send(buf, sockfd); /* end, Prover sends the witness */ /* Verifier/server sends the challenge, we receive */ zkp_recv(sockfd, buf); e = atoi(buf); printf("Client: got e: %i\n", e); /* End server sends the challenge */ /* Send the response to the server */ response(y, e); /* Prover sends the response */ mpz_get_str(buf, 10, y); zkp_send(buf, sockfd); /* Verifier/server sends the authentication response */ if (!zkp_recv(sockfd, buf)) { printf("Client ZKP: Error receiving client data.\n"); return(0); } proof = atoi(buf); zkp_disconnect(sockfd); if (proof) { printf("Authentication successful!\n"); } else { printf("Authentication failed!\n"); } mpz_clear(x); mpz_clear(y); printf("Iteration %d finished at: ", j); timestamp(stdout); printf("\n\n"); } mpz_clear(n); mpz_clear(rndseed); return (1); }
void octree::sort_bodies(tree_structure &tree, my_dev::dev_mem<float4> &bodies_pos, my_dev::dev_mem<uint> &sortPermutation, int n_bodies) { //We assume the bodies are already onthe GPU devContext.startTiming(); this->allocateParticleSpecificBuffers(n_bodies); //Call the GPUSort function, since we made it general //into a uint4 so we can extend the tree to 96bit key //we have to convert to 64bit key to a 96bit for sorting //and back from 96 to 64 my_dev::dev_mem<uint4> srcValues(devContext); my_dev::dev_mem<uint4> output(devContext); my_dev::dev_mem<uint4> bodies_key(devContext); //Allocate memory for the generalBuffer //The generalBuffer1 has size uint*4*N*3 //this buffer gets part: 0-uint*4*N srcValues.cmalloc_copy(tree.generalBuffer1.get_pinned(), tree.generalBuffer1.get_flags(), tree.generalBuffer1.get_devMem(), &tree.generalBuffer1[0], 0, n_bodies, getAllignmentOffset(0)); //this buffer gets part: uint*4*N-uint*4*N*2 output.cmalloc_copy(tree.generalBuffer1.get_pinned(), tree.generalBuffer1.get_flags(), tree.generalBuffer1.get_devMem(), &tree.generalBuffer1[4*n_bodies], 4*n_bodies, n_bodies, getAllignmentOffset(4*n_bodies)); int prevOffset = getAllignmentOffset(4*n_bodies); bodies_key.cmalloc_copy(tree.generalBuffer1.get_pinned(), tree.generalBuffer1.get_flags(), tree.generalBuffer1.get_devMem(), &tree.generalBuffer1[8*n_bodies], 8*n_bodies, n_bodies, prevOffset + getAllignmentOffset(8*n_bodies + prevOffset)); //This function computes the keys, seperate since we compute keys also before //buidling the tree-structure //Corner and size are not stored, since we can use sorting without building a tree float4 corner; float domain_fac; compute_keys(bodies_pos, bodies_key, n_bodies, corner, domain_fac); //Extract the keys convertKey64to96.set_arg<cl_mem>(0, bodies_key.p()); convertKey64to96.set_arg<cl_mem>(1, srcValues.p()); convertKey64to96.set_arg<int>(2, &n_bodies); convertKey64to96.setWork(n_bodies, 256); convertKey64to96.execute(); //Sort the keys // If srcValues (2nd argument) and buffer (4th argument) are different, then the original values // are preserved, if they are the same srcValues will be overwritten gpuSort(devContext, srcValues, output, srcValues, n_bodies, 32, 3, tree); //Extract the keys and get the permuation required to sort the other //properties of the particles //Extract the sorted keys extractKeyAndPerm.set_arg<cl_mem>(0, output.p()); extractKeyAndPerm.set_arg<cl_mem>(1, bodies_key.p()); extractKeyAndPerm.set_arg<cl_mem>(2, sortPermutation.p()); extractKeyAndPerm.set_arg<int>(3, &n_bodies); extractKeyAndPerm.setWork(n_bodies, 256); extractKeyAndPerm.execute(); devContext.stopTiming("Sorting", 0); }
static struct wpabuf * eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_method_ret *ret, const struct wpabuf *reqData, const u8 *payload, size_t payload_len) { struct wpabuf *resp = NULL; BIGNUM *x = NULL, *y = NULL; HMAC_CTX ctx; u32 cs; u16 grp; u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr; /* * first build up the ciphersuite which is group | random_function | * prf */ grp = htons(data->group_num); ptr = (u8 *) &cs; os_memcpy(ptr, &grp, sizeof(u16)); ptr += sizeof(u16); *ptr = EAP_PWD_DEFAULT_RAND_FUNC; ptr += sizeof(u8); *ptr = EAP_PWD_DEFAULT_PRF; /* each component of the cruft will be at most as big as the prime */ if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation " "fail"); goto fin; } /* * server's commit is H(k | server_element | server_scalar | * peer_element | peer_scalar | ciphersuite) */ H_Init(&ctx); /* * zero the memory each time because this is mod prime math and some * value may start with a few zeros and the previous one did not. */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->k, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->server_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* my element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* my scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->my_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* the ciphersuite */ H_Update(&ctx, (u8 *) &cs, sizeof(u32)); /* random function fin */ H_Final(&ctx, conf); ptr = (u8 *) payload; if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify"); goto fin; } wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified"); /* * compute confirm: * H(k | peer_element | peer_scalar | server_element | server_scalar | * ciphersuite) */ H_Init(&ctx); /* k */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->k, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* my element */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->my_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* my scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->my_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, data->server_element, x, y, data->bnctx)) { wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " "assignment fail"); goto fin; } os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(x, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(y, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); /* server scalar */ os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); BN_bn2bin(data->server_scalar, cruft); H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); /* the ciphersuite */ H_Update(&ctx, (u8 *) &cs, sizeof(u32)); /* all done */ H_Final(&ctx, conf); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH, EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) goto fin; wpabuf_put_u8(resp, EAP_PWD_OPCODE_CONFIRM_EXCH); wpabuf_put_data(resp, conf, SHA256_DIGEST_LENGTH); if (compute_keys(data->grp, data->bnctx, data->k, data->my_scalar, data->server_scalar, conf, ptr, &cs, data->msk, data->emsk) < 0) { wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | " "EMSK"); goto fin; } fin: os_free(cruft); BN_free(x); BN_free(y); ret->methodState = METHOD_DONE; if (resp == NULL) { ret->decision = DECISION_FAIL; eap_pwd_state(data, FAILURE); } else { ret->decision = DECISION_UNCOND_SUCC; eap_pwd_state(data, SUCCESS); } return resp; }
int main(int argc, char **argv) { unsigned char reg; unsigned int num; int i; unsigned int mode; unsigned long long source_ksv = 0LL; unsigned long long sink_ksv = 0LL; unsigned long long ksv_temp = 0LL; unsigned long long Km = 0LL; unsigned long long Kmp = 0LL; unsigned long long old_Km = 0LL; unsigned long long source_pkey[40]; unsigned long long sink_pkey[40]; unsigned char compctl; unsigned char snoopctl; FILE *km_file; if(argc != 1) { fprintf(stderr, "Usage: %s\n", argv[0]); return 1; } // km sense changed to be a "semaphore" bit, use it here accordingly. ///////////// // this region should be atomic compctl = read_byte(0x3); printf( "Checking semaphore...\n" ); if( (compctl & 0x80) ) { // semaphore is set printf( "Semaphore set, someone else is running: exiting.\n" ); return 1; } // however, atomicity can be broken here: on the other hand, structurally, // we guarantee nobody can steal the lock here by never triggering the HPD // event between the read and the modify-write // if we have atomicity problems, the solution is to implement the RMW operation // in the FPGA (i.e., a command that can read and grab the semaphore in one operation) compctl |= 0x80; // set the semaphore write_byte( 0x3, compctl ); printf( "Grabbed semaphore!\n" ); // this region should be atomic ////////////// fflush(stdout); for( i = 6; i >= 0; i-- ) { old_Km <<= 8; old_Km |= read_byte( i + 0x19 ) & 0xff; } for( i = 0; i < 5; i++ ) { sink_ksv <<= 8; sink_ksv |= (snoop_hdcp_byte(4 - i) & 0xff); } for( i = 0; i < 5; i++ ) { source_ksv <<= 8; source_ksv |= (snoop_hdcp_byte(4 - i + 0x10) & 0xff); } printf( "source public ksv: %010llx\n", source_ksv ); printf( "sink public ksv: %010llx\n", sink_ksv ); compute_keys( source_ksv, SOURCE, source_pkey ); compute_keys( sink_ksv, SINK, sink_pkey ); ksv_temp = source_ksv; // source Ksv num = 0; for( i = 0; i < 40; i++ ) { if( ksv_temp & 1LL ) { num++; Km += sink_pkey[i]; // used to select sink's keys Km %= 72057594037927936LL; // printf( "Km %014llx\n", Km ); } ksv_temp >>= 1LL; } // printf( "num 1's: %d\n", num ); // km is the sink km ksv_temp = sink_ksv; // sink Ksv num = 0; for( i = 0; i < 40; i++ ) { if( ksv_temp & 1LL ) { num++; Kmp += source_pkey[i]; // used to select source's keys Kmp %= 72057594037927936LL; // printf( "Kmp %014llx\n", Kmp ); } ksv_temp >>= 1LL; } // printf( "num 1's: %d\n", num ); // Kmp is the source Km Km &= 0xFFFFFFFFFFFFFFLL; Kmp &= 0xFFFFFFFFFFFFFFLL; printf( "\n" ); printf( "Km : %014llx\n", Km ); printf( "Km': %014llx\n", Kmp ); fflush(stdout); if( Km != Kmp ) { printf( "Km is not equal to Km', can't encrypt this stream.\n" ); printf( "Releasing semaphore.\n" ); compctl = read_byte(0x3); // refresh compctl in case other bits changed compctl &= 0x7F; // release semaphore write_byte( 0x3, compctl ); exit(0); } if( Km == old_Km ) { printf( "Km is same as cached value, doing nothing.\n" ); printf( "Releasing semaphore.\n" ); compctl = read_byte(0x3); // refresh compctl in case other bits changed compctl &= 0x7F; // release semaphore write_byte( 0x3, compctl ); // don't need to do anything, Km is correct return 0; } else if( Km == 0 ) { printf( "Km is zero. This probably means derive_km was fired spuriously on disconnect.\n" ); printf( "Aborting without doing anything, since Km = 0 is never a correct condition\n" ); printf( "Releasing semaphore.\n" ); compctl = read_byte(0x3); // refresh compctl in case other bits changed compctl &= 0x7F; // release semaphore write_byte( 0x3, compctl ); return 0; } else { km_file = fopen( "/psp/km_cache", "wb" ); if( km_file == NULL ) { printf( "can't open km_file to write cache...but letting life go on.\n" ); } else { // write out the Km to the cache file // this is a totally-device and compiler-dependent way to do this // but it's fast and easy and it's just cache data so who cares fwrite(&Km, sizeof(unsigned long long), 1, km_file); fflush(km_file); fclose(km_file); } // now commit Km to the fpga for( i = 0; i < 7; i++ ) { write_byte( i + 0x19, Km & 0xFF ); Km >>= 8; } // invoke HPD to re-load the stream snoopctl = read_byte(0x0); snoopctl |= 0x08; // force HPD, leave all other bits intact write_byte( 0x0, snoopctl ); // hpd is now forcing printf( "Km has changed since last value, initiating HPD reset of stream and updating cache. This will take 3 seconds."); fflush(stdout); // wait sleep(2); printf( "." ); fflush(stdout); snoopctl &= 0xF7; write_byte( 0x0, snoopctl ); // hpd is now releasing // wait for( i = 0; i < 2; i ++ ) { printf( "." ); fflush(stdout); sleep(1); // this is the dead-zone where we try to keep the semaphore locked down // to prevent a recursive derive_km/HPD loop nightmare // if someone is just jamming cables in and out really fast, it could cause // problems } printf( "\nDone. Releasing semaphore.\n" ); // then release semaphore compctl = read_byte(0x3); // refresh compctl in case other bits changed compctl &= 0x7F; // release semaphore write_byte( 0x3, compctl ); } return 0; }