Example #1
0
inline int _compare_mem(uint8_t * x, uint8_t * y, size_t len) {
    if (0 != memcmp(x, y, len)) {
	printf ("X: %s\t", osmo_hexdump_nospc(x, len));
	printf ("Y: %s\n", osmo_hexdump_nospc(y, len));
	return 0;
    }
    return 1;
}
Example #2
0
static void dump_triplets_dat(struct osmo_auth_vector *vec)
{
	if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
		fprintf(stderr, "triplets.dat doesn't support UMTS!\n");
		return;
	}
	printf("imsi,");
	printf("%s,", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));
	printf("%s,", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
	printf("%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
}
Example #3
0
static inline void print_check(char *res, uint8_t *out, uint16_t len)
{
    uint8_t buf[len];
    osmo_hexparse(res, buf, len);
    if (0 != memcmp(buf, out, len)) {
	printf("FAIL:\n");
	printf("OUT: %s\n", osmo_hexdump_nospc(out, len));
	printf("EXP: %s\n", osmo_hexdump_nospc(buf, len));
    } else
	    printf("\n");
}
Example #4
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;
}
Example #5
0
inline bool print_a5(int n, int k, char * dir, ubit_t * out, char * block) {
    uint8_t len = 114 / 8 + 1, buf[len], res[len];
    printf("A5/%d - %s: %s => ", n, dir, osmo_ubit_dump(out, 114));
    osmo_hexparse(block, res, len);
    osmo_ubit2pbit(buf, out, 114);
    if (0 != memcmp(buf, res, len)) {
	printf("FAIL");
	printf("\nGOT: [%d] %s", k, osmo_hexdump_nospc(buf, len));
	printf("\nEXP: [%d] %s\n", k, osmo_hexdump_nospc(res, len));
	return false;
    }
    printf("OK\n");
    return true;
}
Example #6
0
/* Simulate a real life situation: voice frames with a few dropouts */
void test_fr_concealment_realistic()
{
	struct osmo_ecu_fr_state state;
	uint8_t frame[GSM_FR_BYTES];
	unsigned int frame_len;
	int rc, i = 0;

	while (fr_frames_hex[i] != NULL) {
		/* Debug print */
		printf("Frame No. %03i:\n", i);

		/* Good or bad frame? */
		frame_len = strlen(fr_frames_hex[i]) / 2;
		if (frame_len == GSM_FR_BYTES) {
			printf(" * input:  %s\n", fr_frames_hex[i]);
			osmo_hexparse(fr_frames_hex[i], frame, GSM_FR_BYTES);
			osmo_ecu_fr_reset(&state, frame);
		} else {
			printf(" * input:  (bad)\n");
			memset(frame, 0x00, GSM_FR_BYTES);
			rc = osmo_ecu_fr_conceal(&state, frame);
			OSMO_ASSERT(rc == 0);
		}

		/* Print result */
		printf(" * output: %s\n",
			osmo_hexdump_nospc(frame, GSM_FR_BYTES));

		/* Go to the next frame */
		i++;
	}
}
Example #7
0
/**
 * Start with a good voice frame and then simulate 20 consecutive bad frames,
 * watching how the error concealment decreases the XMAXC parameters.
 */
void test_fr_concealment(void)
{
	struct osmo_ecu_fr_state state;
	uint8_t frame[GSM_FR_BYTES];
	uint64_t xmaxc[4];
	int i, rc;
	int j = 0;

	while (sample_frame_hex[j] != NULL) {
		/* Parse frame from string to hex */
		osmo_hexparse(sample_frame_hex[j], frame, GSM_FR_BYTES);
		parse_xmaxc_frame(frame, xmaxc);
		printf("Start with: %s, XMAXC: [%"PRIx64", %"PRIx64", %"PRIx64", %"PRIx64"]\n",
		       sample_frame_hex[j], xmaxc[0], xmaxc[1], xmaxc[2], xmaxc[3]);

		/* Reset the ECU with the proposed known good frame */
		osmo_ecu_fr_reset(&state, frame);

		/* Now pretend that we do not receive any good frames anymore */
		for (i = 0; i < 20; i++) {

			rc = osmo_ecu_fr_conceal(&state, frame);
			OSMO_ASSERT(rc == 0);
			parse_xmaxc_frame(frame, xmaxc);

			printf("conceal: %02i, result: %s XMAXC: [%"PRIx64", %"PRIx64", %"PRIx64", %"PRIx64"]\n",
			       i, osmo_hexdump_nospc(frame, GSM_FR_BYTES),
			       xmaxc[0], xmaxc[1], xmaxc[2], xmaxc[3]);
		}

		/* Go to the next frame */
		j++;
	}
}
Example #8
0
static void test_unhex(const char *hex)
{
	int rc;
	struct bitvec b;
	uint8_t d[64] = {0};
	b.data = d;
	b.data_len = sizeof(d);
	b.cur_bit = 0;

	rc = bitvec_unhex(&b, hex);
	printf("%d -=> cur_bit=%u\n", rc, b.cur_bit);
	printf("%s\n", osmo_hexdump_nospc(d, 64));
	printf("%s\n", hex);
}
Example #9
0
static void dump_auth_vec(struct osmo_auth_vector *vec)
{
	printf("RAND:\t%s\n", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));

	if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
		printf("AUTN:\t%s\n", osmo_hexdump_nospc(vec->autn, sizeof(vec->autn)));
		printf("IK:\t%s\n", osmo_hexdump_nospc(vec->ik, sizeof(vec->ik)));
		printf("CK:\t%s\n", osmo_hexdump_nospc(vec->ck, sizeof(vec->ck)));
		printf("RES:\t%s\n", osmo_hexdump_nospc(vec->res, vec->res_len));
	}

	if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
		printf("SRES:\t%s\n", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
		printf("Kc:\t%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
	}
}
Example #10
0
static void test_7bit_ussd(const char *text, const char *encoded_hex, const char *appended_after_decode)
{
	uint8_t coded[256];
	char decoded[256];
	int octets_written;
	int buffer_size;
	int nchars;

	printf("original = %s\n", osmo_hexdump((uint8_t *)text, strlen(text)));
	gsm_7bit_encode_n_ussd(coded, sizeof(coded), text, &octets_written);
	printf("encoded = %s\n", osmo_hexdump(coded, octets_written));

	OSMO_ASSERT(strcmp(encoded_hex, osmo_hexdump_nospc(coded, octets_written)) == 0);

	gsm_7bit_decode_n_ussd(decoded, sizeof(decoded), coded, octets_written * 8 / 7);
	octets_written = strlen(decoded);
	printf("decoded = %s\n\n", osmo_hexdump((uint8_t *)decoded, octets_written));

	OSMO_ASSERT(strncmp(text, decoded, strlen(text)) == 0);
	OSMO_ASSERT(strcmp(appended_after_decode, decoded + strlen(text)) == 0);

	/* check buffer limiting */
	memset(decoded, 0xaa, sizeof(decoded));

	for (buffer_size = 1; buffer_size < sizeof(decoded) - 1; ++buffer_size)
	{
		nchars = gsm_7bit_decode_n_ussd(decoded, buffer_size, coded, octets_written * 8 / 7);
		OSMO_ASSERT(nchars <= buffer_size);
		OSMO_ASSERT(decoded[buffer_size] == (char)0xaa);
		OSMO_ASSERT(decoded[nchars] == '\0');
	}

	memset(coded, 0xaa, sizeof(coded));

	for (buffer_size = 0; buffer_size < sizeof(coded) - 1; ++buffer_size)
	{
		gsm_7bit_encode_n_ussd(coded, buffer_size, text, &octets_written);
		OSMO_ASSERT(octets_written <= buffer_size);
		OSMO_ASSERT(coded[buffer_size] == 0xaa);
	}
}
Example #11
0
static void test_oap_api(void)
{
	printf("Testing OAP API\n  - Config parsing\n");

	struct oap_config _config;
	struct oap_config *config = &_config;

	struct oap_state _state;
	struct oap_state *state = &_state;

	memset(config, 0, sizeof(*config));
	memset(state, 0, sizeof(*state));

	OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16);
	OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16);

	/* make sure filling with zeros means uninitialized */
	OSMO_ASSERT(state->state == OAP_UNINITIALIZED);

	/* invalid client_id and shared secret */
	config->client_id = 0;
	config->secret_k_present = 0;
	config->secret_opc_present = 0;
	OSMO_ASSERT( oap_init(config, state) == 0 );
	OSMO_ASSERT(state->state == OAP_DISABLED);

	/* reset state */
	memset(state, 0, sizeof(*state));

	/* only client_id is invalid */
	config->client_id = 0;
	config->secret_k_present = 1;
	config->secret_opc_present = 1;
	OSMO_ASSERT( oap_init(config, state) == 0 );
	OSMO_ASSERT(state->state == OAP_DISABLED);

	memset(state, 0, sizeof(*state));

	/* valid id, but omitted shared_secret (1/2) */
	config->client_id = 12345;
	config->secret_k_present = 0;
	config->secret_opc_present = 1;
	OSMO_ASSERT( oap_init(config, state) == 0 );
	OSMO_ASSERT(state->state == OAP_DISABLED);

	memset(state, 0, sizeof(*state));

	/* valid id, but omitted shared_secret (2/2) */
	config->client_id = 12345;
	config->secret_k_present = 1;
	config->secret_opc_present = 0;
	OSMO_ASSERT( oap_init(config, state) == 0 );
	OSMO_ASSERT(state->state == OAP_DISABLED);

	memset(state, 0, sizeof(*state));


	/* mint configuration */
	config->client_id = 12345;
	config->secret_k_present = 1;
	config->secret_opc_present = 1;
	/*config->secret_* buffers are still set from the top */
	OSMO_ASSERT( oap_init(config, state) == 0 );
	OSMO_ASSERT(state->state == OAP_INITIALIZED);

	printf("  - AUTN failures\n");

	struct oap_message oap_rx;
	struct oap_message oap_tx;
	struct msgb *msg_rx;
	struct msgb *msg_tx;

	memset(&oap_rx, 0, sizeof(oap_rx));

	/* Missing challenge data */
	oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST;
	oap_rx.rand_present = 0;
	oap_rx.autn_present = 0;
	msg_rx = oap_encoded(&oap_rx);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
	msgb_free(msg_rx);
	OSMO_ASSERT(!msg_tx);

	/* AUTN missing */
	osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
		      oap_rx.rand, 16);
	oap_rx.rand_present = 1;
	msg_rx = oap_encoded(&oap_rx);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
	msgb_free(msg_rx);
	OSMO_ASSERT(!msg_tx);

	/* RAND missing */
	oap_rx.rand_present = 0;
	osmo_hexparse("cec4e3848a33000086781158ca40f136",
		      oap_rx.autn, 16);
	oap_rx.autn_present = 1;
	msg_rx = oap_encoded(&oap_rx);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
	msgb_free(msg_rx);
	OSMO_ASSERT(!msg_tx);

	/* wrong autn (by one bit) */
	osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
		      oap_rx.rand, 16);
	osmo_hexparse("dec4e3848a33000086781158ca40f136",
		      oap_rx.autn, 16);
	oap_rx.rand_present = 1;
	oap_rx.autn_present = 1;
	msg_rx = oap_encoded(&oap_rx);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
	msgb_free(msg_rx);
	OSMO_ASSERT(!msg_tx);

	/* all data correct */
	osmo_hexparse("cec4e3848a33000086781158ca40f136",
		      oap_rx.autn, 16);
	msg_rx = oap_encoded(&oap_rx);

	/* but refuse to evaluate in uninitialized state */
	OSMO_ASSERT(state->state == OAP_INITIALIZED);

	state->state = OAP_UNINITIALIZED;
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1);
	OSMO_ASSERT(!msg_tx);

	state->state = OAP_DISABLED;
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1);
	OSMO_ASSERT(!msg_tx);

	state->state = OAP_INITIALIZED;

	/* now everything is correct */
	printf("  - AUTN success\n");
	/* a successful return value here indicates correct autn */
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
	msgb_free(msg_rx);

	/* Expect the challenge response in msg_tx */
	OSMO_ASSERT(msg_tx);
	OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0);
	OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT);
	OSMO_ASSERT(strcmp("e2d05b598c61d9ba",
			   osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres)))
		    == 0);
	OSMO_ASSERT(state->state == OAP_SENT_CHALLENGE_RESULT);
	msgb_free(msg_tx);
	msg_tx = 0;

	struct oap_state saved_state = _state;

	printf("  - Registration failure\n");

	memset(&oap_rx, 0, sizeof(oap_rx));
	oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
	oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
	msg_rx = oap_encoded(&oap_rx);

	/* Receive registration error for the first time. */
	OSMO_ASSERT(state->registration_failures == 0);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
	OSMO_ASSERT(state->registration_failures == 1);
	OSMO_ASSERT(msg_tx);
	OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0);
	OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST);
	OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE);
	msgb_free(msg_tx);
	msg_tx = 0;

	/* Receive registration error for the Nth time. */
	state->registration_failures = 999;
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -11);
	OSMO_ASSERT(!msg_tx);
	OSMO_ASSERT(state->state == OAP_INITIALIZED);
	msgb_free(msg_tx);
	msg_tx = 0;

	msgb_free(msg_rx);

	printf("  - Registration success\n");

	_state = saved_state;
	memset(&oap_rx, 0, sizeof(oap_rx));
	oap_rx.message_type = OAP_MSGT_REGISTER_RESULT;
	msg_rx = oap_encoded(&oap_rx);
	OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
	OSMO_ASSERT(!msg_tx);
	OSMO_ASSERT(state->state == OAP_REGISTERED);
	msgb_free(msg_rx);
}