/* Authentication related functions */

/*
 * (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
 *
 * All Rights Reserved
 *
 * 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 <openbsc/db.h>
#include <openbsc/debug.h>
#include <openbsc/auth.h>
#include <openbsc/gsm_data.h>

#include <osmocom/gsm/comp128.h>

#include <openssl/rand.h>

#include <stdlib.h>

const struct value_string auth_action_names[] = {
#define AUTH_ACTION_STR(X) { X, #X }
	AUTH_ACTION_STR(AUTH_ERROR),
	AUTH_ACTION_STR(AUTH_NOT_AVAIL),
	AUTH_ACTION_STR(AUTH_DO_AUTH_THEN_CIPH),
	AUTH_ACTION_STR(AUTH_DO_CIPH),
	AUTH_ACTION_STR(AUTH_DO_AUTH),
#undef AUTH_ACTION_STR
};

static int
_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
{
	int i, l = ainfo->a3a8_ki_len;

	if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
		LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
			ainfo->a3a8_ki_len,
			osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
		return -1;
	}

	for (i=0; i<4; i++)
		atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
	for (i=4; i<12; i++)
		atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];

	return 0;
}

static int
_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
{
	if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
		LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
			ainfo->a3a8_ki_len,
			osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
		return -1;
	}

	comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);

	return 0;
}

/* Return values 
 *  -1 -> Internal error
 *   0 -> Not available
 *   1 -> Tuple returned, need to do auth, then enable cipher
 *   2 -> Tuple returned, need to enable cipher
 */
int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
                              struct gsm_subscriber *subscr, int key_seq)
{
	struct gsm_auth_info ainfo;
	int rc;

	/* Get subscriber info (if any) */
	rc = db_get_authinfo_for_subscr(&ainfo, subscr);
	if (rc < 0) {
		LOGP(DMM, LOGL_NOTICE,
			"No retrievable Ki for subscriber, skipping auth\n");
		return rc == -ENOENT ? AUTH_NOT_AVAIL : AUTH_ERROR;
	}

	/* If possible, re-use the last tuple and skip auth */
	rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
	if ((rc == 0) &&
	    (key_seq != GSM_KEY_SEQ_INVAL) &&
	    (key_seq == atuple->key_seq) &&
	    (atuple->use_count < 3))
	{
		atuple->use_count++;
		db_sync_lastauthtuple_for_subscr(atuple, subscr);
		DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
		return AUTH_DO_CIPH;
	}

	/* Generate a new one */
	if (rc != 0) {
		/* If db_get_lastauthtuple_for_subscr() returned nothing, make
		 * sure the atuple memory is initialized to zero and thus start
		 * off with key_seq = 0. */
		memset(atuple, 0, sizeof(*atuple));
	} else {
		/* If db_get_lastauthtuple_for_subscr() returned a previous
		 * tuple, use the next key_seq. */
		atuple->key_seq = (atuple->key_seq + 1) % 7;
	}
	atuple->use_count = 1;

	if (RAND_bytes(atuple->rand, sizeof(atuple->rand)) != 1) {
		LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n");
		return AUTH_ERROR;
	}

	switch (ainfo.auth_algo) {
	case AUTH_ALGO_NONE:
		DEBUGP(DMM, "No authentication for subscriber\n");
		return AUTH_NOT_AVAIL;

	case AUTH_ALGO_XOR:
		if (_use_xor(&ainfo, atuple))
			return AUTH_NOT_AVAIL;
		break;

	case AUTH_ALGO_COMP128v1:
		if (_use_comp128_v1(&ainfo, atuple))
			return AUTH_NOT_AVAIL;
		break;

	default:
		DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
			ainfo.auth_algo);
		return AUTH_NOT_AVAIL;
	}

        db_sync_lastauthtuple_for_subscr(atuple, subscr);

	DEBUGP(DMM, "Need to do authentication and ciphering\n");
	return AUTH_DO_AUTH_THEN_CIPH;
}

