/*
 * NDEF(NFC Data Exchange Format) routines for Wi-Fi Protected Setup
 *   Reference is "NFCForum-TS-NDEF_1.0 2006-07-24".
 * Copyright (c) 2009-2012, Masashi Honma <masashi.honma@gmail.com>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"
#include "common.h"
#include "wps/wps.h"

#define FLAG_MESSAGE_BEGIN (1 << 7)
#define FLAG_MESSAGE_END (1 << 6)
#define FLAG_CHUNK (1 << 5)
#define FLAG_SHORT_RECORD (1 << 4)
#define FLAG_ID_LENGTH_PRESENT (1 << 3)
#define FLAG_TNF_NFC_FORUM (0x01)
#define FLAG_TNF_RFC2046 (0x02)

struct ndef_record {
	const u8 *type;
	const u8 *id;
	const u8 *payload;
	u8 type_length;
	u8 id_length;
	u32 payload_length;
	u32 total_length;
};

static const char wifi_handover_type[] = "application/vnd.wfa.wsc";
static const char p2p_handover_type[] = "application/vnd.wfa.p2p";

static int ndef_parse_record(const u8 *data, u32 size,
			     struct ndef_record *record)
{
	const u8 *pos = data + 1;

	if (size < 2)
		return -1;
	record->type_length = *pos++;
	if (data[0] & FLAG_SHORT_RECORD) {
		if (size < 3)
			return -1;
		record->payload_length = *pos++;
	} else {
		u32 len;

		if (size < 6)
			return -1;
		len = WPA_GET_BE32(pos);
		if (len > size - 6 || len > 20000)
			return -1;
		record->payload_length = len;
		pos += sizeof(u32);
	}

	if (data[0] & FLAG_ID_LENGTH_PRESENT) {
		if ((int) size < pos - data + 1)
			return -1;
		record->id_length = *pos++;
	} else
		record->id_length = 0;

	if (record->type_length > data + size - pos)
		return -1;
	record->type = record->type_length == 0 ? NULL : pos;
	pos += record->type_length;

	if (record->id_length > data + size - pos)
		return -1;
	record->id = record->id_length == 0 ? NULL : pos;
	pos += record->id_length;

	if (record->payload_length > (size_t) (data + size - pos))
		return -1;
	record->payload = record->payload_length == 0 ? NULL : pos;
	pos += record->payload_length;

	record->total_length = pos - data;
	if (record->total_length > size ||
	    record->total_length < record->payload_length)
		return -1;
	return 0;
}


static struct wpabuf * ndef_parse_records(const struct wpabuf *buf,
					  int (*filter)(struct ndef_record *))
{
	struct ndef_record record;
	int len = wpabuf_len(buf);
	const u8 *data = wpabuf_head(buf);

	while (len > 0) {
		if (ndef_parse_record(data, len, &record) < 0) {
			wpa_printf(MSG_ERROR, "NDEF : Failed to parse");
			return NULL;
		}
		if (filter == NULL || filter(&record))
			return wpabuf_alloc_copy(record.payload,
						 record.payload_length);
		data += record.total_length;
		len -= record.total_length;
	}
	wpa_printf(MSG_ERROR, "NDEF : Record not found");
	return NULL;
}


static struct wpabuf * ndef_build_record(u8 flags, const void *type,
					 u8 type_length, void *id,
					 u8 id_length,
					 const struct wpabuf *payload)
{
	struct wpabuf *record;
	size_t total_len;
	int short_record;
	u8 local_flag;
	size_t payload_length = wpabuf_len(payload);

	short_record = payload_length < 256 ? 1 : 0;

	total_len = 2; /* flag + type length */
	/* payload length */
	total_len += short_record ? sizeof(u8) : sizeof(u32);
	if (id_length > 0)
		total_len += 1;
	total_len += type_length + id_length + payload_length;
	record = wpabuf_alloc(total_len);
	if (record == NULL) {
		wpa_printf(MSG_ERROR, "NDEF : Failed to allocate "
			   "record for build");
		return NULL;
	}

	local_flag = flags;
	if (id_length > 0)
		local_flag |= FLAG_ID_LENGTH_PRESENT;
	if (short_record)
		local_flag |= FLAG_SHORT_RECORD;
	wpabuf_put_u8(record, local_flag);

	wpabuf_put_u8(record, type_length);

	if (short_record)
		wpabuf_put_u8(record, payload_length);
	else
		wpabuf_put_be32(record, payload_length);

	if (id_length > 0)
		wpabuf_put_u8(record, id_length);
	wpabuf_put_data(record, type, type_length);
	wpabuf_put_data(record, id, id_length);
	wpabuf_put_buf(record, payload);
	return record;
}


static int wifi_filter(struct ndef_record *record)
{
	if (record->type == NULL ||
	    record->type_length != os_strlen(wifi_handover_type))
		return 0;
	if (os_memcmp(record->type, wifi_handover_type,
		      os_strlen(wifi_handover_type)) != 0)
		return 0;
	return 1;
}


struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf)
{
	return ndef_parse_records(buf, wifi_filter);
}


struct wpabuf * ndef_build_wifi(const struct wpabuf *buf)
{
	return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END |
				 FLAG_TNF_RFC2046, wifi_handover_type,
				 os_strlen(wifi_handover_type), NULL, 0, buf);
}


static int p2p_filter(struct ndef_record *record)
{
	if (record->type == NULL ||
	    record->type_length != os_strlen(p2p_handover_type))
		return 0;
	if (os_memcmp(record->type, p2p_handover_type,
		      os_strlen(p2p_handover_type)) != 0)
		return 0;
	return 1;
}


struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf)
{
	return ndef_parse_records(buf, p2p_filter);
}


struct wpabuf * ndef_build_p2p(const struct wpabuf *buf)
{
	return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END |
				 FLAG_TNF_RFC2046, p2p_handover_type,
				 os_strlen(p2p_handover_type), NULL, 0, buf);
}
