示例#1
0
static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data)
{
	struct eap_peer_config *conf;

	wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm");

	conf = eap_get_config(sm);
	if (conf == NULL)
		return -1;
	if (conf->pcsc) {
		if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
				   data->sres[0], data->kc[0]) ||
		    scard_gsm_auth(sm->scard_ctx, data->rand[1],
				   data->sres[1], data->kc[1]) ||
		    (data->num_chal > 2 &&
		     scard_gsm_auth(sm->scard_ctx, data->rand[2],
				    data->sres[2], data->kc[2]))) {
			wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM "
				   "authentication could not be completed");
			return -1;
		}
		return 0;
	}

#ifdef CONFIG_SIM_SIMULATOR
	if (conf->password) {
		u8 opc[16], k[16];
		const char *pos;
		size_t i;
		wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage "
			   "implementation for authentication");
		if (conf->password_len < 65) {
			wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage "
				   "password");
			return -1;
		}
		pos = (const char *) conf->password;
		if (hexstr2bin(pos, k, 16))
			return -1;
		pos += 32;
		if (*pos != ':')
			return -1;
		pos++;

		if (hexstr2bin(pos, opc, 16))
			return -1;

		for (i = 0; i < data->num_chal; i++) {
			if (gsm_milenage(opc, k, data->rand[i],
					 data->sres[i], data->kc[i])) {
				wpa_printf(MSG_DEBUG, "EAP-SIM: "
					   "GSM-Milenage authentication "
					   "could not be completed");
				return -1;
			}
			wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
				    data->rand[i], GSM_RAND_LEN);
			wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
					data->sres[i], EAP_SIM_SRES_LEN);
			wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
					data->kc[i], EAP_SIM_KC_LEN);
		}
		return 0;
	}
#endif /* CONFIG_SIM_SIMULATOR */

#ifdef CONFIG_SIM_HARDCODED
	/* These hardcoded Kc and SRES values are used for testing. RAND to
	 * KC/SREC mapping is very bogus as far as real authentication is
	 * concerned, but it is quite useful for cases where the AS is rotating
	 * the order of pre-configured values. */
	{
		size_t i;

		wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES "
			   "values for testing");

		for (i = 0; i < data->num_chal; i++) {
			if (data->rand[i][0] == 0xaa) {
				os_memcpy(data->kc[i],
					  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
					  EAP_SIM_KC_LEN);
				os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
					  EAP_SIM_SRES_LEN);
			} else if (data->rand[i][0] == 0xbb) {
				os_memcpy(data->kc[i],
					  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
					  EAP_SIM_KC_LEN);
				os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
					  EAP_SIM_SRES_LEN);
			} else {
				os_memcpy(data->kc[i],
					  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
					  EAP_SIM_KC_LEN);
				os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
					  EAP_SIM_SRES_LEN);
			}
		}
	}

	return 0;

#else /* CONFIG_SIM_HARDCODED */

	wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm "
		   "enabled");
	return -1;

#endif /* CONFIG_SIM_HARDCODED */
}
int main(int argc, char *argv[])
{
	u8 buf[16], buf2[16], buf3[16], buf4[16], buf5[16], opc[16];
	u8 auts[14], sqn[6], _rand[16];
	int ret = 0, res, i;
	const struct milenage_test_set *t;
	size_t res_len;

	wpa_debug_level = 0;

	printf("Milenage test sets\n");
	for (i = 0; i < NUM_TESTS; i++) {
		t = &test_sets[i];
		printf("Test Set %d\n", i + 1);

		milenage_opc(t->op, t->k, opc);
		if (memcmp(opc, t->opc, 16) != 0) {
			printf("- milenage_opc failed\n");
			ret++;
		}

		if (milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2)
		    ||  memcmp(buf, t->f1, 8) != 0) {
			printf("- milenage_f1 failed\n");
			ret++;
		}
		if (memcmp(buf2, t->f1star, 8) != 0) {
			printf("- milenage_f1* failed\n");
			ret++;
		}

		if (milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4,
				   buf5) ||
		    memcmp(buf, t->f2, 8) != 0) {
			printf("- milenage_f2 failed\n");
			ret++;
		}
		if (memcmp(buf2, t->f3, 16) != 0) {
			printf("- milenage_f3 failed\n");
			ret++;
		}
		if (memcmp(buf3, t->f4, 16) != 0) {
			printf("- milenage_f4 failed\n");
			ret++;
		}
		if (memcmp(buf4, t->f5, 6) != 0) {
			printf("- milenage_f5 failed\n");
			ret++;
		}
		if (memcmp(buf5, t->f5star, 6) != 0) {
			printf("- milenage_f5* failed\n");
			ret++;
		}
	}

	printf("milenage_auts test:\n");
	os_memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6);
	os_memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8);
	res = milenage_auts(t->opc, t->k, t->rand, auts, buf);
	printf("AUTS for test set %d: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
	       i, res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
	if (res)
		ret++;

	os_memset(_rand, 0xaa, sizeof(_rand));
	os_memcpy(auts,
		  "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67",
		  14);
	res = milenage_auts(t->opc, t->k, _rand, auts, buf);
	printf("AUTS from a test USIM: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
	       res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
	if (res)
		ret++;

	printf("milenage_generate test:\n");
	os_memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6);
	os_memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84"
		  "\x4f\xe6\x2f", 16);
	res_len = 8;
	milenage_generate(t->opc, t->amf, t->k, sqn, _rand, buf, buf2, buf3,
			  buf4, &res_len);
	wpa_hexdump(MSG_DEBUG, "SQN", sqn, 6);
	wpa_hexdump(MSG_DEBUG, "RAND", _rand, 16);
	wpa_hexdump(MSG_DEBUG, "AUTN", buf, 16);
	wpa_hexdump(MSG_DEBUG, "IK", buf2, 16);
	wpa_hexdump(MSG_DEBUG, "CK", buf3, 16);
	wpa_hexdump(MSG_DEBUG, "RES", buf4, res_len);

	printf("GSM-Milenage test sets\n");
	for (i = 0; i < NUM_GSM_TESTS; i++) {
		const struct gsm_milenage_test_set *g;
		u8 sres[4], kc[8];
		g = &gsm_test_sets[i];
		printf("Test Set %d\n", i + 1);
		gsm_milenage(g->opc, g->ki, g->rand, sres, kc);
		if (memcmp(g->kc, kc, 8) != 0) {
			printf("- gsm_milenage Kc failed\n");
			ret++;
		}
#ifdef GSM_MILENAGE_ALT_SRES
		if (memcmp(g->sres2, sres, 4) != 0) {
			printf("- gsm_milenage SRES#2 failed\n");
			ret++;
		}
#else /* GSM_MILENAGE_ALT_SRES */
		if (memcmp(g->sres1, sres, 4) != 0) {
			printf("- gsm_milenage SRES#1 failed\n");
			ret++;
		}
#endif /* GSM_MILENAGE_ALT_SRES */
	}

	if (ret)
		printf("Something failed\n");
	else
		printf("OK\n");

	return ret;
}