Port to new libosmogsm 'struct osmo_sub_auth_data2'

libosmogsm has recently introdcued a 'struct osmo_sub_auth_data2' as
successor to 'struct osmo_sub_auth_data', together with updated
osmo_auth_gen_vec2/osmo_auth_gen_vec_auts2 API.

The rationale of this new API is to enable
* support for AKA algorithms which use K and/or OP[c] values of 256bit
  (instead of the classic 128bit)
* support for RES length sizes of 4 and 16 bytes (instead of the classic
  8 bytes)

This commit just jumps over to the new API without adding any related
functionality to osmo-hlr.  The latter is left for subsequent commits.

Change-Id: I3207c7bfb73e9ff5471e5c26b66639549e4d48a2
Depends: libosmocore.git Ie775fedba4a3fa12314c0f7c8a369662ef6a40df
This commit is contained in:
Harald Welte 2023-05-30 17:27:32 +02:00
parent 829713a69d
commit aef6a181f1
13 changed files with 171 additions and 137 deletions

View File

@ -7,4 +7,4 @@
# If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0. # If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line #library what description / commit summary line
libosmogsm UPDATE_DEP_VER update libosmogsm version dependency after I0ee0565382c1e4515d44ff9b1752685c0a66ae39 is released libosmogsm UPDATE_DEP_VER update libosmogsm version dependency after Ie775fedba4a3fa12314c0f7c8a369662ef6a40df is released

View File

@ -3,6 +3,6 @@
#include <osmocom/crypt/auth.h> #include <osmocom/crypt/auth.h>
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data *aud2g, struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data *aud3g, struct osmo_sub_auth_data2 *aud3g,
const uint8_t *rand_auts, const uint8_t *auts); const uint8_t *rand_auts, const uint8_t *auts);

View File

@ -70,8 +70,8 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_log
/* obtain the authentication data for a given imsi */ /* obtain the authentication data for a given imsi */
int db_get_auth_data(struct db_context *dbc, const char *imsi, int db_get_auth_data(struct db_context *dbc, const char *imsi,
struct osmo_sub_auth_data *aud2g, struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data *aud3g, struct osmo_sub_auth_data2 *aud3g,
int64_t *subscr_id); int64_t *subscr_id);
int db_update_sqn(struct db_context *dbc, int64_t id, int db_update_sqn(struct db_context *dbc, int64_t id,
@ -121,7 +121,7 @@ struct hlr_subscriber {
* See https://sqlite.org/lang_datefunc.html, function datetime(). */ * See https://sqlite.org/lang_datefunc.html, function datetime(). */
#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S" #define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"
/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation. /* Like struct osmo_sub_auth_data2, but the keys are in hexdump representation.
* This is useful because SQLite requires them in hexdump format, and callers * This is useful because SQLite requires them in hexdump format, and callers
* like the VTY and CTRL interface also have them available as hexdump to begin * like the VTY and CTRL interface also have them available as hexdump to begin
* with. In the binary format, a VTY command would first need to hexparse, * with. In the binary format, a VTY command would first need to hexparse,

View File

@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org> /* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@ -32,8 +32,8 @@
/* compute given number of vectors using either aud2g or aud2g or a combination /* compute given number of vectors using either aud2g or aud2g or a combination
* of both. Handles re-synchronization if rand_auts and auts are set */ * of both. Handles re-synchronization if rand_auts and auts are set */
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data *aud2g, struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data *aud3g, struct osmo_sub_auth_data2 *aud3g,
const uint8_t *rand_auts, const uint8_t *auts) const uint8_t *rand_auts, const uint8_t *auts)
{ {
unsigned int i; unsigned int i;
@ -93,10 +93,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
: "2G only", : "2G only",
auts? ", with AUTS resync" : ""); auts? ", with AUTS resync" : "");
if (aud3g) { if (aud3g) {
DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k)); DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len));
DBGP("3G: %s = %s\n", DBGP("3G: %s = %s\n",
aud3g->u.umts.opc_is_op? "OP" : "opc", aud3g->u.umts.opc_is_op? "OP" : "opc",
hexb(aud3g->u.umts.opc)); hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len));
DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n", DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
aud3g->u.umts.ind, aud3g->u.umts.sqn); aud3g->u.umts.ind, aud3g->u.umts.sqn);
} }
@ -115,6 +115,9 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
if (aud3g) { if (aud3g) {
/* 3G or 3G + 2G case */ /* 3G or 3G + 2G case */
/* backwards-compatibiliy: We assume all RES are 8 bytes long */
vec[i].res_len = 8;
/* Do AUTS only for the first vector or we would use /* Do AUTS only for the first vector or we would use
* the same SQN for each following key. */ * the same SQN for each following key. */
if ((i == 0) && auts) { if ((i == 0) && auts) {
@ -123,10 +126,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
DBGP("vector [%u]: resync: rand_auts = %s\n", DBGP("vector [%u]: resync: rand_auts = %s\n",
i, hex(rand_auts, 16)); i, hex(rand_auts, 16));
rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts, rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts,
rand_auts, rand); rand_auts, rand);
} else { } else {
rc = osmo_auth_gen_vec(vec+i, aud3g, rand); rc = osmo_auth_gen_vec2(vec+i, aud3g, rand);
} }
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 3G vector " LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
@ -154,7 +157,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
DBGP("vector [%u]: calculating 2G separately\n", i); DBGP("vector [%u]: calculating 2G separately\n", i);
rc = osmo_auth_gen_vec(&vtmp, aud2g, rand); rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand);
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector" LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
"generation: [%u]: rc = %d\n", i, rc); "generation: [%u]: rc = %d\n", i, rc);
@ -165,7 +168,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
vec[i].auth_types |= OSMO_AUTH_TYPE_GSM; vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
} else { } else {
/* 2G only case */ /* 2G only case */
rc = osmo_auth_gen_vec(vec+i, aud2g, rand); rc = osmo_auth_gen_vec2(vec+i, aud2g, rand);
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector " LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
"generation: [%u]: rc = %d\n", i, rc); "generation: [%u]: rc = %d\n", i, rc);

View File

@ -1,6 +1,6 @@
/* OsmoHLR Control Interface implementation */ /* OsmoHLR Control Interface implementation */
/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de> /* (C) 2017-2023 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved * All Rights Reserved
* *
* Author: Max Suraev <msuraev@sysmocom.de> * Author: Max Suraev <msuraev@sysmocom.de>
@ -166,7 +166,7 @@ static void print_subscr_info(struct ctrl_cmd *cmd,
); );
} }
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud) static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
{ {
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
return; return;
@ -178,7 +178,7 @@ static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
hexdump_buf(aud->u.gsm.ki)); hexdump_buf(aud->u.gsm.ki));
} }
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud) static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
{ {
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
return; return;
@ -187,7 +187,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
"\naud3g.k\t%s" "\naud3g.k\t%s"
, ,
osmo_auth_alg_name(aud->algo), osmo_auth_alg_name(aud->algo),
hexdump_buf(aud->u.umts.k)); osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len));
/* hexdump uses a static string buffer, hence only one hexdump per /* hexdump uses a static string buffer, hence only one hexdump per
* printf(). */ * printf(). */
ctrl_cmd_reply_printf(cmd, ctrl_cmd_reply_printf(cmd,
@ -196,7 +196,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
"\naud3g.sqn\t%" PRIu64 "\naud3g.sqn\t%" PRIu64
, ,
aud->u.umts.opc_is_op? "op" : "opc", aud->u.umts.opc_is_op? "op" : "opc",
hexdump_buf(aud->u.umts.opc), osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len),
aud->u.umts.ind_bitlen, aud->u.umts.ind_bitlen,
aud->u.umts.sqn); aud->u.umts.sqn);
} }
@ -291,8 +291,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data) static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
{ {
const char *imsi; const char *imsi;
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
int rc; int rc;
@ -327,8 +327,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data) static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
{ {
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
int rc; int rc;
@ -492,8 +492,8 @@ static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g_unused; struct osmo_sub_auth_data2 aud3g_unused;
int rc; int rc;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@ -592,8 +592,8 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
struct osmo_sub_auth_data aud2g_unused; struct osmo_sub_auth_data2 aud2g_unused;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
int rc; int rc;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@ -618,9 +618,9 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
} }
cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo), cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)), osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, aud3g.u.umts.k_len),
aud3g.u.umts.opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc_is_op ? "OP" : "OPC",
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)), osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len),
aud3g.u.umts.ind_bitlen); aud3g.u.umts.ind_bitlen);
return CTRL_CMD_REPLY; return CTRL_CMD_REPLY;
} }

View File

@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org> /* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@ -74,9 +74,9 @@ out:
} }
/* hexparse a specific column of a sqlite prepared statement into dst (with length check) /* hexparse a specific column of a sqlite prepared statement into dst (with length check)
* returns 0 for success, -EIO on error */ * returns byte length in case of success, -EIO on error */
static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int col, const char *col_name, static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, sqlite3_stmt *stmt,
const char *imsi) int col, const char *col_name, const char *imsi)
{ {
const uint8_t *text; const uint8_t *text;
size_t col_len; size_t col_len;
@ -84,9 +84,15 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
/* Bytes are stored as hex strings in database, hence divide length by two */ /* Bytes are stored as hex strings in database, hence divide length by two */
col_len = sqlite3_column_bytes(stmt, col) / 2; col_len = sqlite3_column_bytes(stmt, col) / 2;
if (col_len != dst_len) { if (col_len < dst_len_min) {
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name, LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected min length %lu but has length %lu\n", col_name,
dst_len, col_len); dst_len_min, col_len);
return -EIO;
}
if (col_len > dst_len_max) {
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected max length %lu but has length %lu\n", col_name,
dst_len_max, col_len);
return -EIO; return -EIO;
} }
@ -96,10 +102,10 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
return -EIO; return -EIO;
} }
if (osmo_hexparse((void *)text, dst, dst_len) != col_len) if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
return -EINVAL; return -EINVAL;
return 0; return col_len;
} }
/* obtain the authentication data for a given imsi /* obtain the authentication data for a given imsi
@ -107,8 +113,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
* -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data, * -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
* -EIO on db failure */ * -EIO on db failure */
int db_get_auth_data(struct db_context *dbc, const char *imsi, int db_get_auth_data(struct db_context *dbc, const char *imsi,
struct osmo_sub_auth_data *aud2g, struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data *aud3g, struct osmo_sub_auth_data2 *aud3g,
int64_t *subscr_id) int64_t *subscr_id)
{ {
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI]; sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
@ -142,7 +148,8 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
/* obtain result values using sqlite3_column_*() */ /* obtain result values using sqlite3_column_*() */
if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) { if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
/* we do have some 2G authentication data */ /* we do have some 2G authentication data */
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), stmt, 2, "Ki", imsi)) if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), sizeof(aud2g->u.gsm.ki),
stmt, 2, "Ki", imsi) < 0)
goto end_2g; goto end_2g;
aud2g->algo = sqlite3_column_int(stmt, 1); aud2g->algo = sqlite3_column_int(stmt, 1);
aud2g->type = OSMO_AUTH_TYPE_GSM; aud2g->type = OSMO_AUTH_TYPE_GSM;
@ -151,24 +158,30 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
end_2g: end_2g:
if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) { if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
/* we do have some 3G authentication data */ /* we do have some 3G authentication data */
if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) { rc = hexparse_stmt(aud3g->u.umts.k, 16, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi);
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.k_len = rc;
aud3g->algo = sqlite3_column_int(stmt, 3); aud3g->algo = sqlite3_column_int(stmt, 3);
/* UMTS Subscribers can have either OP or OPC */ /* UMTS Subscribers can have either OP or OPC */
if (sqlite3_column_text(stmt, 5)) { if (sqlite3_column_text(stmt, 5)) {
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) { rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi);
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.opc_len = rc;
aud3g->u.umts.opc_is_op = 1; aud3g->u.umts.opc_is_op = 1;
} else { } else {
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) { rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi);
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.opc_len = rc;
aud3g->u.umts.opc_is_op = 0; aud3g->u.umts.opc_is_op = 0;
} }
aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7); aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
@ -194,7 +207,7 @@ int db_get_auc(struct db_context *dbc, const char *imsi,
unsigned int num_vec, const uint8_t *rand_auts, unsigned int num_vec, const uint8_t *rand_auts,
const uint8_t *auts, bool separation_bit) const uint8_t *auts, bool separation_bit)
{ {
struct osmo_sub_auth_data aud2g, aud3g; struct osmo_sub_auth_data2 aud2g, aud3g;
int64_t subscr_id; int64_t subscr_id;
int ret = 0; int ret = 0;
int rc; int rc;

View File

@ -1,4 +1,4 @@
/* (C) 2015 by Harald Welte <laforge@gnumonks.org> /* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@ -286,12 +286,12 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
break; break;
if (!osmo_is_hexstr(aud->u.umts.k, 32, 32, true)) { if (!osmo_is_hexstr(aud->u.umts.k, 32, 64, true)) {
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" Invalid K: '%s'\n", aud->u.umts.k); " Invalid K: '%s'\n", aud->u.umts.k);
return -EINVAL; return -EINVAL;
} }
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 32, true)) { if (!osmo_is_hexstr(aud->u.umts.opc, 32, 64, true)) {
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc); " Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
return -EINVAL; return -EINVAL;

View File

@ -724,7 +724,7 @@ static void signal_hdlr(int signal)
} }
static const char vlr_copyright[] = static const char vlr_copyright[] =
"Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n" "Copyright (C) 2016-2023 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n" "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n" "This is free software: you are free to change and redistribute it.\r\n"
"There is NO WARRANTY, to the extent permitted by law.\r\n"; "There is NO WARRANTY, to the extent permitted by law.\r\n";

View File

@ -1,5 +1,5 @@
/* OsmoHLR subscriber management VTY implementation */ /* OsmoHLR subscriber management VTY implementation */
/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> /* (C) 2017-2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved * All Rights Reserved
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -77,8 +77,8 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr) static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
{ {
int rc; int rc;
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE); vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
@ -137,12 +137,12 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) { if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE); vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
aud2g = (struct osmo_sub_auth_data){}; aud2g = (struct osmo_sub_auth_data2){};
} }
if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) { if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE); vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
aud3g = (struct osmo_sub_auth_data){}; aud3g = (struct osmo_sub_auth_data2){};
} }
if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) { if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
@ -154,9 +154,10 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) { if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE); vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE); vty_out(vty, " K=%s%s",
osmo_hexdump_nospc(aud3g.u.umts.k, aud3g.u.umts.k_len), VTY_NEWLINE);
vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC", vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE); osmo_hexdump_nospc(aud3g.u.umts.opc, aud3g.u.umts.opc_len), VTY_NEWLINE);
vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen); vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
if (aud3g.u.umts.sqn) if (aud3g.u.umts.sqn)
vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn); vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);

View File

@ -116,14 +116,14 @@ int rand_get(uint8_t *rand, unsigned int len)
/* Subscriber with 2G-only (COMP128v1) authentication data */ /* Subscriber with 2G-only (COMP128v1) authentication data */
static void test_gen_vectors_2g_only(void) static void test_gen_vectors_2g_only(void)
{ {
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data){ aud2g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
@ -131,7 +131,7 @@ static void test_gen_vectors_2g_only(void)
osmo_hexparse("EB215756028D60E3275E613320AEC880", osmo_hexparse("EB215756028D60E3275E613320AEC880",
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki)); aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
aud3g = (struct osmo_sub_auth_data){ 0 }; aud3g = (struct osmo_sub_auth_data2){ 0 };
next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true); next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
@ -179,14 +179,14 @@ static void test_gen_vectors_2g_only(void)
* reflects the default configuration of sysmoUSIM-SJS1 */ * reflects the default configuration of sysmoUSIM-SJS1 */
static void test_gen_vectors_2g_plus_3g(void) static void test_gen_vectors_2g_plus_3g(void)
{ {
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data){ aud2g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
@ -194,9 +194,11 @@ static void test_gen_vectors_2g_plus_3g(void)
osmo_hexparse("EB215756028D60E3275E613320AEC880", osmo_hexparse("EB215756028D60E3275E613320AEC880",
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki)); aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
aud3g = (struct osmo_sub_auth_data){ aud3g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}; };
@ -292,8 +294,8 @@ void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
* tuples are suitable for both 2G and 3G authentication */ * tuples are suitable for both 2G and 3G authentication */
static void test_gen_vectors_3g_only(void) static void test_gen_vectors_3g_only(void)
{ {
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
struct osmo_auth_vector vecs[3]; struct osmo_auth_vector vecs[3];
uint8_t auts[14]; uint8_t auts[14];
@ -302,11 +304,13 @@ static void test_gen_vectors_3g_only(void)
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data){ 0 }; aud2g = (struct osmo_sub_auth_data2){ 0 };
aud3g = (struct osmo_sub_auth_data){ aud3g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}; };
@ -466,18 +470,20 @@ static void test_gen_vectors_3g_only(void)
* 2G and 3G authentication */ * 2G and 3G authentication */
static void test_gen_vectors_3g_xor(void) static void test_gen_vectors_3g_xor(void)
{ {
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data){ 0 }; aud2g = (struct osmo_sub_auth_data2){ 0 };
aud3g = (struct osmo_sub_auth_data){ aud3g = (struct osmo_sub_auth_data2){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_XOR_3G, .algo = OSMO_AUTH_ALG_XOR_3G,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 0, .u.umts.sqn = 0,
}; };
@ -517,39 +523,43 @@ void test_gen_vectors_bad_args(void)
int rc; int rc;
int i; int i;
struct osmo_sub_auth_data aud2g = { struct osmo_sub_auth_data2 aud2g = {
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
struct osmo_sub_auth_data aud3g = { struct osmo_sub_auth_data2 aud3g = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
}; };
struct osmo_sub_auth_data aud2g_noalg = { struct osmo_sub_auth_data2 aud2g_noalg = {
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
}; };
struct osmo_sub_auth_data aud3g_noalg = { struct osmo_sub_auth_data2 aud3g_noalg = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
}; };
struct osmo_sub_auth_data aud_notype = { struct osmo_sub_auth_data2 aud_notype = {
.type = OSMO_AUTH_TYPE_NONE, .type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
}; };
struct osmo_sub_auth_data no_aud = { struct osmo_sub_auth_data2 no_aud = {
.type = OSMO_AUTH_TYPE_NONE, .type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
}; };
struct { struct {
struct osmo_sub_auth_data *aud2g; struct osmo_sub_auth_data2 *aud2g;
struct osmo_sub_auth_data *aud3g; struct osmo_sub_auth_data2 *aud3g;
uint8_t *rand_auts; uint8_t *rand_auts;
uint8_t *auts; uint8_t *auts;
const char *label; const char *label;

View File

@ -24,18 +24,20 @@
static void {func_name}(void) static void {func_name}(void)
{{ {{
struct osmo_sub_auth_data aud2g; struct osmo_sub_auth_data2 aud2g;
struct osmo_sub_auth_data aud3g; struct osmo_sub_auth_data2 aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data){{ 0 }}; aud2g = (struct osmo_sub_auth_data2){{ 0 }};
aud3g = (struct osmo_sub_auth_data){{ aud3g = (struct osmo_sub_auth_data2){{
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}}; }};
@ -48,6 +50,7 @@ static void {func_name}(void)
fake_rand, sizeof(fake_rand)); fake_rand, sizeof(fake_rand));
vec = (struct osmo_auth_vector){{ {{0}} }}; vec = (struct osmo_auth_vector){{ {{0}} }};
vec.res_len = 8;
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64); VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL); rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
VERBOSE_ASSERT(rc, == 1, "%d"); VERBOSE_ASSERT(rc, == 1, "%d");

View File

@ -122,16 +122,16 @@ static void _fill_invalid(void *dest, size_t size)
/* Not linking the real auc_compute_vectors(), just returning num_vec. /* Not linking the real auc_compute_vectors(), just returning num_vec.
* This gets called by db_get_auc(), but we're only interested in its rc. */ * This gets called by db_get_auc(), but we're only interested in its rc. */
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data *aud2g, struct osmo_sub_auth_data2 *aud2g,
struct osmo_sub_auth_data *aud3g, struct osmo_sub_auth_data2 *aud3g,
const uint8_t *rand_auts, const uint8_t *auts) const uint8_t *rand_auts, const uint8_t *auts)
{ return num_vec; } { return num_vec; }
static struct db_context *dbc = NULL; static struct db_context *dbc = NULL;
static void *ctx = NULL; static void *ctx = NULL;
static struct hlr_subscriber g_subscr; static struct hlr_subscriber g_subscr;
static struct osmo_sub_auth_data g_aud2g; static struct osmo_sub_auth_data2 g_aud2g;
static struct osmo_sub_auth_data g_aud3g; static struct osmo_sub_auth_data2 g_aud3g;
static int g_rc; static int g_rc;
static int64_t g_id; static int64_t g_id;
@ -180,18 +180,21 @@ void dump_subscr(struct hlr_subscriber *subscr)
#undef Pb #undef Pb
} }
void dump_aud(const char *label, struct osmo_sub_auth_data *aud) void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
{ {
if (aud->type == OSMO_AUTH_TYPE_NONE) { if (aud->type == OSMO_AUTH_TYPE_NONE) {
fprintf(stderr, "%s: none\n", label); fprintf(stderr, "%s: none\n", label);
return; return;
} }
fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label); fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label);
#define Pf(name, fmt) \ #define Pf(name, fmt) \
Pfo(name, fmt, aud) Pfo(name, fmt, aud)
#define Phex(name) \ #define Phex(name) \
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name))) Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
#define Phexl(name, len) \
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
Pfv(type, "%s", osmo_sub_auth_type_name(aud->type)); Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
Pfv(algo, "%s", osmo_auth_alg_name(aud->algo)); Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
@ -200,9 +203,9 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
Phex(u.gsm.ki); Phex(u.gsm.ki);
break; break;
case OSMO_AUTH_TYPE_UMTS: case OSMO_AUTH_TYPE_UMTS:
Phex(u.umts.opc); Phexl(u.umts.opc, u.umts.opc_len);
Pf(u.umts.opc_is_op, "%u"); Pf(u.umts.opc_is_op, "%u");
Phex(u.umts.k); Phexl(u.umts.k, u.umts.k_len);
Phex(u.umts.amf); Phex(u.umts.amf);
if (aud->u.umts.sqn) { if (aud->u.umts.sqn) {
Pf(u.umts.sqn, "%"PRIu64); Pf(u.umts.sqn, "%"PRIu64);
@ -219,6 +222,7 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
#undef Pf #undef Pf
#undef Phex #undef Phex
#undef Phexl
} }
void db_raw_sql(struct db_context *dbc, const char *sql) void db_raw_sql(struct db_context *dbc, const char *sql)

View File

@ -824,7 +824,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v1, .algo = COMP128v1,
.u.gsm.ki = '0123456789abcdef0123456789abcdef', .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@ -841,7 +841,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v1, .algo = COMP128v1,
.u.gsm.ki = '0123456789abcdef0123456789abcdef', .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@ -853,7 +853,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBe
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v2, .algo = COMP128v2,
.u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade', .u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade',
@ -865,7 +865,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBedd
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf', .u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf',
@ -877,7 +877,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEfface
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = XOR-2G, .algo = XOR-2G,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
@ -905,7 +905,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEfface
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = XOR-2G, .algo = XOR-2G,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
@ -932,7 +932,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -954,7 +954,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -970,7 +970,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d', .u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d',
@ -985,7 +985,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1001,7 +1001,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef', .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@ -1033,7 +1033,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef', .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@ -1069,12 +1069,12 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_3g(OSMO_AUTH_ALG_MILENAGE, "BeefedCaf
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1097,12 +1097,12 @@ DAUC Cannot update auth tokens: Unknown auth algo: 99999
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1117,12 +1117,12 @@ DAUC Cannot update auth tokens: Invalid KI: 'f000000000000f00000000000f000000f00
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1137,12 +1137,12 @@ DAUC Cannot update auth tokens: Invalid KI: 'f00'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1157,12 +1157,12 @@ DAUC Cannot update auth tokens: auth algo not suited for 2G: MILENAGE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1177,12 +1177,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: '0f000000000000f00000000000f0000
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1197,12 +1197,12 @@ DAUC Cannot update auth tokens: Invalid K: '000000000000f00000000000f000000'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1217,12 +1217,12 @@ DAUC Cannot update auth tokens: Invalid ind_bitlen: 29
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1237,12 +1237,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: 'X000000000000f00000000000f00000
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1257,12 +1257,12 @@ DAUC Cannot update auth tokens: Invalid K: 'f000000000000 f00000000000 f000000'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data { 2G: struct osmo_sub_auth_data2 {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1338,7 +1338,7 @@ sqlite3_prepare_v2(dbc->db, sql, -1, &stmt, NULL) --> SQLITE_OK
sqlite3_step(stmt) --> SQLITE_DONE sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY
DAUC IMSI='123456789000000': Error reading Ki, expected length 16 but has length 15 DAUC IMSI='123456789000000': Error reading Ki, expected min length 16 but has length 15
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
@ -1359,7 +1359,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading K, expected length 16 but has length 15 DAUC IMSI='123456789000000': Error reading K, expected min length 16 but has length 15
@ -1374,7 +1374,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading OP, expected length 16 but has length 15 DAUC IMSI='123456789000000': Error reading OP, expected min length 16 but has length 15
@ -1389,7 +1389,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading OPC, expected length 16 but has length 15 DAUC IMSI='123456789000000': Error reading OPC, expected min length 16 but has length 15
@ -1458,7 +1458,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1477,7 +1477,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1495,7 +1495,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1513,7 +1513,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1534,7 +1534,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1550,7 +1550,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1568,7 +1568,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@ -1586,7 +1586,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data { 3G: struct osmo_sub_auth_data2 {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',