/* Osmocom Authentication Protocol API */

/* (C) 2015 by Sysmocom s.f.m.c. GmbH
 * All Rights Reserved
 *
 * Author: Neels Hofmeyr
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <string.h>
#include <errno.h>

#include <osmocom/core/utils.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/gsm/oap.h>

#include <osmocom/msc/oap_client.h>
#include <osmocom/msc/debug.h>

int oap_client_init(struct oap_client_config *config,
		    struct oap_client_state *state)
{
	OSMO_ASSERT(state->state == OAP_UNINITIALIZED);

	if (!config)
		goto disable;

	if (config->client_id == 0)
		goto disable;

	if (config->secret_k_present == 0) {
		LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n");
		goto disable;
	}

	if (config->secret_opc_present == 0) {
		LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n");
		goto disable;
	}

	state->client_id = config->client_id;
	memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k));
	memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc));
	state->state = OAP_INITIALIZED;
	return 0;

disable:
	state->state = OAP_DISABLED;
	return 0;
}

/* From the given state and received RAND and AUTN octets, validate the
 * server's authenticity and formulate the matching milenage reply octets in
 * *tx_xres. The state is not modified.
 * On success, and if tx_res is not NULL, exactly 8 octets will be written to
 * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8
 * octets. The caller will want to send XRES back to the server in a challenge
 * response message and update the state.
 * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail
 * the authentication check; -3 for any other errors. */
static int oap_evaluate_challenge(const struct oap_client_state *state,
				  const uint8_t *rx_random,
				  const uint8_t *rx_autn,
				  uint8_t *tx_xres)
{
	struct osmo_auth_vector vec;

	struct osmo_sub_auth_data auth = {
		.type		= OSMO_AUTH_TYPE_UMTS,
		.algo		= OSMO_AUTH_ALG_MILENAGE,
	};

	osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k)
			   == sizeof(state->secret_k), _secret_k_size_match);
	osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc)
			   == sizeof(state->secret_opc), _secret_opc_size_match);

	switch (state->state) {
	case OAP_UNINITIALIZED:
	case OAP_DISABLED:
		return -1;
	default:
		break;
	}

	memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k));
	memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc));
	memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf));
	auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */

	memset(&vec, 0, sizeof(vec));
	osmo_auth_gen_vec(&vec, &auth, rx_random);

	if (vec.res_len != 8) {
		LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n",
		     vec.res_len);
		return -3;
	}

	if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) {
		LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n");
		LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n",
		     osmo_hexdump_nospc(rx_autn, sizeof(vec.autn)));
		LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected:    %s\n",
		     osmo_hexdump_nospc(vec.autn, sizeof(vec.autn)));
		return -2;
	}

	if (tx_xres != NULL)
		memcpy(tx_xres, vec.res, 8);
	return 0;
}

struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg)
{
	struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__);
	OSMO_ASSERT(msg);
	osmo_oap_encode(msg, oap_msg);
	return msg;
}

/* Create a new msgb containing an OAP registration message.
 * On error, return NULL. */
static struct msgb* oap_msg_register(uint16_t client_id)
{
	struct osmo_oap_message oap_msg = {0};

	if (client_id < 1) {
		LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id);
		return NULL;
	}

	oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST;
	oap_msg.client_id = client_id;
	return oap_client_encoded(&oap_msg);
}

int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx)
{
	*msg_tx = oap_msg_register(state->client_id);
	if (!(*msg_tx))
		return -1;

	state->state = OAP_REQUESTED_CHALLENGE;
	return 0;
}

/* Create a new msgb containing an OAP challenge response message.
 * xres must point at 8 octets to return as challenge response.
 * On error, return NULL. */
static struct msgb* oap_msg_challenge_response(uint8_t *xres)
{
	struct osmo_oap_message oap_reply = {0};

	oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT;
	memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres));
	oap_reply.xres_present = 1;
	return oap_client_encoded(&oap_reply);
}

static int handle_challenge(struct oap_client_state *state,
			    struct osmo_oap_message *oap_rx,
			    struct msgb **msg_tx)
{
	int rc;
	uint8_t xres[8];

	if (!(oap_rx->rand_present && oap_rx->autn_present)) {
		LOGP(DLOAP, LOGL_ERROR,
		     "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n",
		     oap_rx->rand_present, oap_rx->autn_present);
		rc = -2;
		goto failure;
	}

	rc = oap_evaluate_challenge(state,
				    oap_rx->rand,
				    oap_rx->autn,
				    xres);
	if (rc < 0)
		goto failure;

	*msg_tx = oap_msg_challenge_response(xres);
	if ((*msg_tx) == NULL) {
		rc = -1;
		goto failure;
	}

	state->state = OAP_SENT_CHALLENGE_RESULT;
	return 0;

failure:
	OSMO_ASSERT(rc < 0);
	state->state = OAP_INITIALIZED;
	return rc;
}

int oap_client_handle(struct oap_client_state *state,
		      const struct msgb *msg_rx, struct msgb **msg_tx)
{
	uint8_t *data = msgb_l2(msg_rx);
	size_t data_len = msgb_l2len(msg_rx);
	struct osmo_oap_message oap_msg = {0};
	int rc = 0;

	*msg_tx = NULL;

	OSMO_ASSERT(data);

	rc = osmo_oap_decode(&oap_msg, data, data_len);
	if (rc < 0) {
		LOGP(DLOAP, LOGL_ERROR,
		     "Decoding OAP message failed with error '%s' (%d)\n",
		     get_value_string(gsm48_gmm_cause_names, -rc), -rc);
		return -10;
	}

	switch (state->state) {
	case OAP_UNINITIALIZED:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received OAP message %d, but the OAP client is"
		     " not initialized\n", oap_msg.message_type);
		return -ENOTCONN;
	case OAP_DISABLED:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received OAP message %d, but the OAP client is"
		     " disabled\n", oap_msg.message_type);
		return -ENOTCONN;
	default:
		break;
	}

	switch (oap_msg.message_type) {
	case OAP_MSGT_CHALLENGE_REQUEST:
		return handle_challenge(state, &oap_msg, msg_tx);

	case OAP_MSGT_REGISTER_RESULT:
		/* successfully registered */
		state->state = OAP_REGISTERED;
		break;

	case OAP_MSGT_REGISTER_ERROR:
		LOGP(DLOAP, LOGL_ERROR,
		     "OAP registration failed\n");
		state->state = OAP_INITIALIZED;
		if (state->registration_failures < 3) {
			state->registration_failures++;
			return oap_client_register(state, msg_tx);
		}
		return -11;

	case OAP_MSGT_REGISTER_REQUEST:
	case OAP_MSGT_CHALLENGE_RESULT:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received invalid OAP message type for OAP client side: %d\n",
		     (int)oap_msg.message_type);
		return -12;

	default:
		LOGP(DLOAP, LOGL_ERROR,
		     "Unknown OAP message type: %d\n",
		     (int)oap_msg.message_type);
		return -13;
	}

	return 0;
}
