/** * 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++; } }
/* 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++; } }
static inline void test_gea(bool v4, char *kc, uint32_t iv, int dir, uint16_t len, char *res) { uint8_t out[len], ck[256]; printf("len %d, dir %d, INPUT 0x%X -> ", len, dir, iv); osmo_hexparse(kc, ck, len); int t = gprs_cipher_run(out, len, v4 ? GPRS_ALGO_GEA4 : GPRS_ALGO_GEA3, ck, iv, dir); printf("%s ", t < 0 ? strerror(-t) : "OK"); print_check(res, out, len); }
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"); }
inline bool test_a5(int n, char * kc, uint32_t count, char * block1, char * block2) { ubit_t out[114]; int k = (n == 4) ? 16 : 8; uint8_t key[k]; osmo_hexparse(kc, key, k); osmo_a5(n, key, count, out, NULL); bool d = print_a5(n, k, "DL", out, block1); osmo_a5(n, key, count, NULL, out); bool u = print_a5(n, k, "UL", out, block2); return d & u; }
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; }
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); }
int main(int argc, char **argv) { struct osmo_auth_vector _vec; struct osmo_auth_vector *vec = &_vec; uint8_t _rand[16], _auts[16]; int rc, option_index; int rand_is_set = 0; int auts_is_set = 0; int fmt_triplets_dat = 0; printf("osmo-auc-gen (C) 2011-2012 by Harald Welte\n"); printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n"); memset(_auts, 0, sizeof(_auts)); while (1) { int c; unsigned long ul; static struct option long_options[] = { { "2g", 0, 0, '2' }, { "3g", 0, 0, '3' }, { "algorithm", 1, 0, 'a' }, { "key", 1, 0, 'k' }, { "opc", 1, 0, 'o' }, { "op", 1, 0, 'O' }, { "amf", 1, 0, 'f' }, { "sqn", 1, 0, 's' }, { "rand", 1, 0, 'r' }, { "auts", 1, 0, 'A' }, { "help", 0, 0, 'h' }, { 0, 0, 0, 0 } }; rc = 0; c = getopt_long(argc, argv, "23a:k:o:f:s:r:hO:A:I", long_options, &option_index); if (c == -1) break; switch (c) { case '2': test_aud.type = OSMO_AUTH_TYPE_GSM; break; case '3': test_aud.type = OSMO_AUTH_TYPE_UMTS; break; case 'a': rc = osmo_auth_alg_parse(optarg); if (rc < 0) break; test_aud.algo = rc; break; case 'k': switch (test_aud.type) { case OSMO_AUTH_TYPE_GSM: rc = osmo_hexparse(optarg, test_aud.u.gsm.ki, sizeof(test_aud.u.gsm.ki)); break; case OSMO_AUTH_TYPE_UMTS: rc = osmo_hexparse(optarg, test_aud.u.umts.k, sizeof(test_aud.u.umts.k)); break; default: fprintf(stderr, "please specify 2g/3g first!\n"); } break; case 'o': if (test_aud.type != OSMO_AUTH_TYPE_UMTS) { fprintf(stderr, "Only UMTS has OPC\n"); exit(2); } rc = osmo_hexparse(optarg, test_aud.u.umts.opc, sizeof(test_aud.u.umts.opc)); test_aud.u.umts.opc_is_op = 0; break; case 'O': if (test_aud.type != OSMO_AUTH_TYPE_UMTS) { fprintf(stderr, "Only UMTS has OP\n"); exit(2); } rc = osmo_hexparse(optarg, test_aud.u.umts.opc, sizeof(test_aud.u.umts.opc)); test_aud.u.umts.opc_is_op = 1; break; case 'A': if (test_aud.type != OSMO_AUTH_TYPE_UMTS) { fprintf(stderr, "Only UMTS has AUTS\n"); exit(2); } rc = osmo_hexparse(optarg, _auts, sizeof(_auts)); auts_is_set = 1; break; case 'f': if (test_aud.type != OSMO_AUTH_TYPE_UMTS) { fprintf(stderr, "Only UMTS has AMF\n"); exit(2); } rc = osmo_hexparse(optarg, test_aud.u.umts.amf, sizeof(test_aud.u.umts.amf)); break; case 's': if (test_aud.type != OSMO_AUTH_TYPE_UMTS) { fprintf(stderr, "Only UMTS has SQN\n"); exit(2); } ul = strtoul(optarg, 0, 10); test_aud.u.umts.sqn = ul; break; case 'r': rc = osmo_hexparse(optarg, _rand, sizeof(_rand)); rand_is_set = 1; break; case 'I': fmt_triplets_dat = 1; break; case 'h': help(); exit(0); default: help(); exit(1); } if (rc < 0) { fprintf(stderr, "Error parsing argument of option `%c'\n", c); exit(2); } } if (!rand_is_set) { int i; printf("WARNING: We're using really weak random numbers!\n\n"); srand(time(NULL)); for (i = 0; i < 4; ++i) { uint32_t r; r = rand(); memcpy(&_rand[i*4], &r, 4); } } if (test_aud.type == OSMO_AUTH_TYPE_NONE || test_aud.algo == OSMO_AUTH_ALG_NONE) { help(); exit(2); } memset(vec, 0, sizeof(*vec)); if (!auts_is_set) rc = osmo_auth_gen_vec(vec, &test_aud, _rand); else rc = osmo_auth_gen_vec_auts(vec, &test_aud, _auts, _rand, _rand); if (rc < 0) { if (!auts_is_set) fprintf(stderr, "error generating auth vector\n"); else fprintf(stderr, "AUTS from MS seems incorrect\n"); exit(1); } if (fmt_triplets_dat) dump_triplets_dat(vec); else dump_auth_vec(vec); if (auts_is_set) printf("AUTS success: SEQ.MS = %" PRIu64 "\n", test_aud.u.umts.sqn); exit(0); }
static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) { struct gsm_network *net = cmd->node; char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; struct gsm_subscriber* subscr; int rc; tmp = talloc_strdup(cmd, cmd->value); if (!tmp) return 1; imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); alg = strtok_r(NULL, ",", &saveptr); ki = strtok_r(NULL, ",", &saveptr); subscr = subscr_get_by_imsi(net->subscr_group, imsi); if (!subscr) subscr = subscr_create_subscriber(net->subscr_group, imsi); if (!subscr) goto fail; subscr->authorized = 1; strncpy(subscr->extension, msisdn, GSM_EXTENSION_LENGTH - 1); subscr->extension[GSM_EXTENSION_LENGTH-1] = '\0'; /* put it back to the db */ rc = db_sync_subscriber(subscr); db_subscriber_update(subscr); /* handle optional ciphering */ if (alg) { if (strcasecmp(alg, "none") == 0) db_sync_authinfo_for_subscr(NULL, subscr); else { struct gsm_auth_info ainfo = { 0, }; /* the verify should make sure that this is okay */ OSMO_ASSERT(alg); OSMO_ASSERT(ki); if (strcasecmp(alg, "xor") == 0) ainfo.auth_algo = AUTH_ALGO_XOR; else if (strcasecmp(alg, "comp128v1") == 0) ainfo.auth_algo = AUTH_ALGO_COMP128v1; rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); if (rc < 0) { subscr_put(subscr); talloc_free(tmp); cmd->reply = "Failed to parse KI"; return CTRL_CMD_ERROR; } ainfo.a3a8_ki_len = rc; db_sync_authinfo_for_subscr(&ainfo, subscr); rc = 0; } db_sync_lastauthtuple_for_subscr(NULL, subscr); } subscr_put(subscr); talloc_free(tmp); if (rc != 0) { cmd->reply = "Failed to store the record in the DB"; return CTRL_CMD_ERROR; } cmd->reply = "OK"; return CTRL_CMD_REPLY; fail: talloc_free(tmp); cmd->reply = "Failed to create subscriber"; return CTRL_CMD_ERROR; }