/*! \file auth_milenage.c
 * GSM/GPRS/3G authentication core infrastructure */
/*
 * (C) 2011 by Harald Welte <laforge@gnumonks.org>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include <osmocom/crypt/auth.h>
#include <osmocom/core/bits.h>
#include "milenage/common.h"
#include "milenage/milenage.h"

/*! \addtogroup auth
 *  @{
 */

static const uint8_t *gen_opc_if_needed(const struct osmo_sub_auth_data *aud, uint8_t *gen_opc)
{
	int rc;

	/* Check if we only know OP and compute OPC if required */
	if (aud->type == OSMO_AUTH_TYPE_UMTS && aud->u.umts.opc_is_op) {
		rc = milenage_opc_gen(gen_opc, aud->u.umts.k, aud->u.umts.opc);
		if (rc < 0)
			return NULL;
		return gen_opc;
	} else
		return aud->u.umts.opc;
}

static int milenage_gen_vec(struct osmo_auth_vector *vec,
			    struct osmo_sub_auth_data *aud,
			    const uint8_t *_rand)
{
	size_t res_len = sizeof(vec->res);
	uint64_t next_sqn;
	uint8_t gen_opc[16];
	const uint8_t *opc;
	uint8_t sqn[6];
	uint64_t ind_mask;
	uint64_t seq_1;
	int rc;

	opc = gen_opc_if_needed(aud, gen_opc);
	if (!opc)
		return -1;

	/* Determine next SQN, according to 3GPP TS 33.102:
	 * SQN consists of SEQ and a lower significant part of IND bits:
	 *
	 * |----------SEQ------------|
	 * |------------------------SQN-----------|
	 *                           |-----IND----|
	 *
	 * The IND part is used as "slots": e.g. a given HLR client will always
	 * get the same IND part, called ind here, with incrementing SEQ. In
	 * the USIM, each IND slot enforces that its SEQ are used in ascending
	 * order -- as long as that constraint is satisfied, the SQN may jump
	 * forwards and backwards. For example, for ind_bitlen == 5, asking the
	 * USIM for SQN = 32, 64, 33 is allowed, because 32 and 64 are
	 * SEQ || (ind == 0), and though 33 is below 64, it is ind == 1 and
	 * allowed.  Not allowed would be 32, 96, 64, because 64 would go
	 * backwards after 96, both being ind == 0.
	 *
	 * From the last used SQN, we want to increment SEQ + 1, and then pick
	 * the matching IND part.
	 *
	 * IND size is suggested in TS 33.102 as 5 bits. SQN is 48 bits long.
	 * If ind_bitlen is passed too large here, the algorithms will break
	 * down. But at which point should we return an error? A sane limit
	 * seems to be ind_bitlen == 10, but to protect against failure,
	 * limiting ind_bitlen to 28 is enough, 28 being the number of bits
	 * suggested for the delta in 33.102, which is discussed to still
	 * require 2^15 > 32000 authentications to wrap the SQN back to the
	 * start.
	 *
	 * Note that if a caller with ind == 1 generates N vectors, the SQN
	 * stored after this will reflect SEQ + N. If then another caller with
	 * ind == 2 generates another N vectors, this will then use SEQ + N
	 * onwards and end up with SEQ + N + N. In other words, most of each
	 * SEQ's IND slots will remain unused. When looking at SQN being 48
	 * bits wide, after dropping ind_bitlen (say 5) from it, we will still
	 * have a sequence range of 2^43 = 8.8e12, eight trillion sequences,
	 * which is large enough to not bother further. With the maximum
	 * ind_bitlen of 28 enforced below, we still get more than 1 million
	 * sequences, which is also sufficiently large.
	 *
	 * An ind_bitlen of zero may be passed from legacy callers that are not
	 * aware of the IND extension. For these, below algorithm works out as
	 * before, simply incrementing SQN by 1.
	 *
	 * This is also a mechanism for tools like the osmo-auc-gen to directly
	 * request a given SQN to be used. With ind_bitlen == 0 the caller can
	 * be sure that this code will increment SQN by exactly one before
	 * generating a tuple, thus a caller would simply pass
	 * { .ind_bitlen = 0, .ind = 0, .sqn = (desired_sqn - 1) }
	 */

	if (aud->u.umts.ind_bitlen > 28)
		return -2;

	seq_1 = 1LL << aud->u.umts.ind_bitlen;
	ind_mask = ~(seq_1 - 1);

	/* the ind index must not affect the SEQ part */
	if (aud->u.umts.ind >= seq_1)
		return -3;

	/* keep the incremented SQN local until gsm_milenage() succeeded. */
	next_sqn = ((aud->u.umts.sqn + seq_1) & ind_mask) + aud->u.umts.ind;

	osmo_store64be_ext(next_sqn, sqn, 6);
	milenage_generate(opc, aud->u.umts.amf, aud->u.umts.k,
			  sqn, _rand,
			  vec->autn, vec->ik, vec->ck, vec->res, &res_len);
	vec->res_len = res_len;
	rc = gsm_milenage(opc, aud->u.umts.k, _rand, vec->sres, vec->kc);
	if (rc < 0)
		return rc;

	vec->auth_types = OSMO_AUTH_TYPE_UMTS | OSMO_AUTH_TYPE_GSM;

	/* for storage in the caller's AUC database */
	aud->u.umts.sqn = next_sqn;

	return 0;
}

static int milenage_gen_vec_auts(struct osmo_auth_vector *vec,
				 struct osmo_sub_auth_data *aud,
				 const uint8_t *auts, const uint8_t *rand_auts,
				 const uint8_t *_rand)
{
	uint8_t sqn_out[6];
	uint8_t gen_opc[16];
	const uint8_t *opc;
	int rc;

	opc = gen_opc_if_needed(aud, gen_opc);

	rc = milenage_auts(opc, aud->u.umts.k, rand_auts, auts, sqn_out);
	if (rc < 0)
		return rc;

	aud->u.umts.sqn_ms = osmo_load64be_ext(sqn_out, 6) >> 16;
	/* Update our "largest used SQN" from the USIM -- milenage_gen_vec()
	 * below will increment SQN. */
	aud->u.umts.sqn = aud->u.umts.sqn_ms;

	return milenage_gen_vec(vec, aud, _rand);
}

static struct osmo_auth_impl milenage_alg = {
	.algo = OSMO_AUTH_ALG_MILENAGE,
	.name = "MILENAGE (libosmogsm built-in)",
	.priority = 1000,
	.gen_vec = &milenage_gen_vec,
	.gen_vec_auts = &milenage_gen_vec_auts,
};

static __attribute__((constructor)) void on_dso_load_milenage(void)
{
	osmo_auth_register(&milenage_alg);
}

/*! @} */
