+static int eap_ttls_add_chbind_request(struct eap_sm *sm,
+ struct eap_ttls_data *data,
+ struct wpabuf **resp)
+{
+ struct wpabuf *chbind_req, *res;
+ int length = 1, i;
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (!config->chbind_config || config->chbind_config_len <= 0)
+ return -1;
+
+ for (i=0; i<config->chbind_config_len; i++) {
+ length += 3 + config->chbind_config[i].req_data_len;
+ }
+
+ chbind_req = wpabuf_alloc(length);
+ if (!chbind_req)
+ return -1;
+
+ wpabuf_put_u8(chbind_req, CHBIND_CODE_REQUEST);
+ for (i=0; i<config->chbind_config_len; i++) {
+ struct eap_peer_chbind_config *chbind_config =
+ &config->chbind_config[i];
+ wpabuf_put_be16(chbind_req, chbind_config->req_data_len);
+ wpabuf_put_u8(chbind_req, chbind_config->nsid);
+ wpabuf_put_data(chbind_req, chbind_config->req_data,
+ chbind_config->req_data_len);
+ }
+ if (eap_ttls_avp_encapsulate(&chbind_req,
+ DIAMETER_ATTR_CHBIND_MESSAGE, 0) < 0)
+ return -1;
+
+ /* bleh. This will free *resp regardless of whether combined buffer
+ alloc succeeds, which is not consistent with the other error
+ condition behavior in this function */
+ *resp = wpabuf_concat(chbind_req, *resp);
+
+ return (*resp) ? 0 : -1;
+}
+
+
+static int eap_ttls_process_chbind(struct eap_sm *sm,
+ struct eap_ttls_data *data,
+ struct eap_method_ret *ret,
+ struct ttls_parse_avp *parse,
+ struct wpabuf **resp)
+{
+ size_t pos=0;
+ u8 code;
+ u16 len;
+ struct chbind_hdr *hdr;
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (parse->chbind_data == NULL) {
+ wpa_printf(MSG_WARNING, "EAP-TTLS: No channel binding message "
+ "in the packet - dropped");
+ return -1;
+ }
+ if (parse->chbind_len < 1 + sizeof(*hdr)) {
+ wpa_printf(MSG_WARNING, "EAP-TTLS: bad channel binding response "
+ "frame (len=%lu, expected %lu or more) - dropped",
+ (unsigned long) parse->chbind_len,
+ (unsigned long) sizeof(*hdr));
+ return -1;
+ }
+ code = parse->chbind_data[pos++];
+ while (pos+sizeof(*hdr) < parse->chbind_len) {
+ hdr = (struct chbind_hdr *)(&parse->chbind_data[pos]);
+ pos += sizeof(*hdr);
+ len = be_to_host16(hdr->len);
+ if (pos + len <= parse->chbind_len) {
+ int i;
+ for (i=0; i<config->chbind_config_len; i++) {
+ struct eap_peer_chbind_config *chbind_config =
+ &config->chbind_config[i];
+ if (chbind_config->nsid == hdr->nsid)
+ chbind_config->response_cb(
+ chbind_config->ctx,
+ code, hdr->nsid,
+ &parse->chbind_data[pos], len);
+ }
+ }
+ pos += len;
+ }
+ if (pos != parse->chbind_len) {
+ wpa_printf(MSG_WARNING, "EAP-TTLS: bad channel binding response "
+ "frame (parsed len=%lu, expected %lu) - dropped",
+ (unsigned long) pos,
+ (unsigned long) parse->chbind_len);
+ return -1;
+ }
+ return 0;
+}