18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NFC routines for Wi-Fi Protected Setup
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2009-2012, Masashi Honma <masashi.honma@gmail.com>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * This software may be distributed under the terms of the BSD license.
604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wps_nfc_data {
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct oob_nfc_device_data *oob_nfc_dev;
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * init_nfc(struct wps_context *wps,
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       struct oob_device_data *oob_dev, int registrar)
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct oob_nfc_device_data *oob_nfc_dev;
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_nfc_data *data;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	oob_nfc_dev = wps_get_oob_nfc_device(oob_dev->device_name);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (oob_nfc_dev == NULL) {
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPS (NFC): Unknown NFC device (%s)",
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   oob_dev->device_name);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (oob_nfc_dev->init_func(oob_dev->device_path) < 0)
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL) {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "nfc data area");
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->oob_nfc_dev = oob_nfc_dev;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * read_nfc(void *priv)
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_nfc_data *data = priv;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wifi, *buf;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *raw_data;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	raw_data = data->oob_nfc_dev->read_func(&len);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (raw_data == NULL)
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wifi = wpabuf_alloc_copy(raw_data, len);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(raw_data);
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wifi == NULL) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "nfc read area");
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = ndef_parse_wifi(wifi);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(wifi);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to unwrap");
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int write_nfc(void *priv, struct wpabuf *buf)
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_nfc_data *data = priv;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *wifi;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wifi = ndef_build_wifi(buf);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wifi == NULL) {
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to wrap");
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = data->oob_nfc_dev->write_func(wpabuf_mhead(wifi),
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    wpabuf_len(wifi));
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(wifi);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void deinit_nfc(void *priv)
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wps_nfc_data *data = priv;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->oob_nfc_dev->deinit_func();
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct oob_device_data oob_nfc_device_data = {
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.device_name	= NULL,
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.device_path	= NULL,
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.init_func	= init_nfc,
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.read_func	= read_nfc,
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.write_func	= write_nfc,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	.deinit_func	= deinit_nfc,
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
112