aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2023-05-30 18:28:15 +0200
committerlaforge <laforge@osmocom.org>2023-08-29 13:42:41 +0000
commit626f5eb74008f0f4e94485c53ac52e27bd7183cd (patch)
treeb457f79e06a3c2d5ba364cc247784a7844fb4dee
parent5800f3add5d158be31017233ba286f3ca148f743 (diff)
db: extend database schema to support 256bit K and/or OP[c] values
Other UMTS AKA algorithms than MILENAGE (notably TUAK) support K sizes of up to 256bit, or mandate a OP/OPc size of 256 bit. Let's extend our database schema to accommodate such larger sizes. Change-Id: Ibbde68484c904507a15c35cbfdf88cd47d0c7039
-rw-r--r--sql/hlr.sql8
-rw-r--r--src/ctrl.c12
-rw-r--r--src/db.c45
-rw-r--r--src/db_hlr.c6
-rw-r--r--src/hlr_vty_subscr.c29
-rw-r--r--tests/db_upgrade/db_upgrade_test.ok9
-rw-r--r--tests/test_subscriber.vty4
7 files changed, 82 insertions, 31 deletions
diff --git a/sql/hlr.sql b/sql/hlr.sql
index e855a6c..4c87f43 100644
--- a/sql/hlr.sql
+++ b/sql/hlr.sql
@@ -71,9 +71,9 @@ CREATE TABLE auc_2g (
CREATE TABLE auc_3g (
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value
- k VARCHAR(32) NOT NULL, -- hex string: subscriber's secret key (128bit)
- op VARCHAR(32), -- hex string: operator's secret key (128bit)
- opc VARCHAR(32), -- hex string: derived from OP and K (128bit)
+ k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)
+ op VARCHAR(64), -- hex string: operator's secret key (128/256bit)
+ opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)
sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage
-- nr of index bits at lower SQN end
ind_bitlen INTEGER NOT NULL DEFAULT 5
@@ -91,4 +91,4 @@ CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
-- Set HLR database schema version number
-- Note: This constant is currently duplicated in src/db.c and must be kept in sync!
-PRAGMA user_version = 6;
+PRAGMA user_version = 7;
diff --git a/src/ctrl.c b/src/ctrl.c
index f0f2ee6..e04195d 100644
--- a/src/ctrl.c
+++ b/src/ctrl.c
@@ -39,7 +39,7 @@
#define SEL_BY_ID SEL_BY "id-"
extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
- int *minlen, int *maxlen);
+ int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc);
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
@@ -550,7 +550,7 @@ static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
}
if (strcmp(tok, "none") == 0) {
aud2g.algo = OSMO_AUTH_ALG_NONE;
- } else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
+ } else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR;
}
@@ -630,8 +630,8 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
struct hlr *hlr = data;
const char *by_selector = cmd->node;
char *tmp = NULL, *tok, *saveptr;
- int minlen = 0;
- int maxlen = 0;
+ int minlen = 0, minlen_opc = 0;
+ int maxlen = 0, maxlen_opc = 0;
struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS,
.u.umts = {
@@ -657,7 +657,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
}
if (strcmp(tok, "none") == 0) {
aud3g.algo = OSMO_AUTH_ALG_NONE;
- } else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
+ } else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR;
}
@@ -699,7 +699,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
}
aud3g.u.umts.opc = tok;
- if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
+ if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) {
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
return CTRL_CMD_ERROR;
}
diff --git a/src/db.c b/src/db.c
index cfe34c3..7b8a415 100644
--- a/src/db.c
+++ b/src/db.c
@@ -1,4 +1,4 @@
-/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -28,7 +28,7 @@
#include "db_bootstrap.h"
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
-#define CURRENT_SCHEMA_VERSION 6
+#define CURRENT_SCHEMA_VERSION 7
#define SEL_COLUMNS \
"id," \
@@ -513,6 +513,46 @@ static int db_upgrade_v6(struct db_context *dbc)
return rc;
}
+static int db_upgrade_v7(struct db_context *dbc)
+{
+ int rc;
+ /* SQLite doesn't allow us to change the column type in-place, so we
+ * first rename the old table, create a new table and then copy
+ * the data over before deleting the old table */
+#define CREATE_AUC_3G_V7 \
+"CREATE TABLE auc_3g (\n" \
+" subscriber_id INTEGER PRIMARY KEY, -- subscriber.id\n" \
+" algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value\n" \
+" k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)\n" \
+" op VARCHAR(64), -- hex string: operator's secret key (128/256bit)\n" \
+" opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)\n" \
+" sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage\n" \
+" -- nr of index bits at lower SQN end\n" \
+" ind_bitlen INTEGER NOT NULL DEFAULT 5\n" \
+");"
+ const char * const statements[] = {
+ "BEGIN TRANSACTION",
+ /* rename old table */
+ "ALTER TABLE auc_3g RENAME TO old_auc_3g",
+ /* create new table */
+ CREATE_AUC_3G_V7,
+ /* copy over old data */
+ "INSERT INTO auc_3g SELECT subscriber_id, algo_id_3g, k, op, opc,sqn, ind_bitlen FROM old_auc_3g",
+ /* delete old table */
+ "DROP TABLE old_auc_3g",
+ /* update user_version */
+ "PRAGMA user_version = 7",
+ "COMMIT",
+ };
+
+ rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
+ if (rc != SQLITE_DONE) {
+ LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
+ return rc;
+ }
+ return rc;
+}
+
typedef int (*db_upgrade_func_t)(struct db_context *dbc);
static db_upgrade_func_t db_upgrade_path[] = {
db_upgrade_v1,
@@ -521,6 +561,7 @@ static db_upgrade_func_t db_upgrade_path[] = {
db_upgrade_v4,
db_upgrade_v5,
db_upgrade_v6,
+ db_upgrade_v7,
};
static int db_get_user_version(struct db_context *dbc)
diff --git a/src/db_hlr.c b/src/db_hlr.c
index 8dfbb15..aa2e365 100644
--- a/src/db_hlr.c
+++ b/src/db_hlr.c
@@ -1,4 +1,4 @@
-/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
*
* 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)
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:"
" Invalid K: '%s'\n", aud->u.umts.k);
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:"
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
return -EINVAL;
diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index 191a87d..28cc5b3 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -473,8 +473,14 @@ static bool is_hexkey_valid(struct vty *vty, const char *label,
"Use Milenage algorithm\n"
bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
- int *minlen, int *maxlen)
+ int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc)
{
+ /* Default: no OP[c]. True for all 2G algorithms, and 3G-XOR. Overridden below for real 3G AKA algorithms. */
+ if (minlen_opc)
+ *minlen_opc = 0;
+ if (maxlen_opc)
+ *maxlen_opc = 0;
+
if (!strcasecmp(alg_str, "none")) {
*algo = OSMO_AUTH_ALG_NONE;
*minlen = *maxlen = 0;
@@ -497,6 +503,10 @@ bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
} else if (!strcasecmp(alg_str, "milenage")) {
*algo = OSMO_AUTH_ALG_MILENAGE;
*minlen = *maxlen = MILENAGE_KEY_LEN;
+ if (minlen_opc)
+ *minlen_opc = MILENAGE_KEY_LEN;
+ if (maxlen_opc)
+ *maxlen_opc = MILENAGE_KEY_LEN;
} else
return false;
return true;
@@ -552,7 +562,7 @@ DEFUN(subscriber_aud2g,
.u.gsm.ki = ki,
};
- if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
+ if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -611,13 +621,13 @@ DEFUN(subscriber_aud3g,
SUBSCR_UPDATE_HELP
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
AUTH_ALG_TYPES_3G_HELP
- "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
- "Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
+ "Set Encryption Key K\n" "K as 32/64 hexadecimal characters\n"
+ "Set OP key\n" "Set OPC key\n" "OP or OPC as 32/64 hexadecimal characters\n"
"Set IND bit length\n" "IND bit length value (default: 5)\n")
{
struct hlr_subscriber subscr;
- int minlen = 0;
- int maxlen = 0;
+ int minlen = 0, minlen_opc = 0;
+ int maxlen = 0, maxlen_opc = 0;
int rc;
const char *id_type = argv[0];
const char *id = argv[1];
@@ -636,7 +646,7 @@ DEFUN(subscriber_aud3g,
},
};
- if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
+ if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -644,8 +654,7 @@ DEFUN(subscriber_aud3g,
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
return CMD_WARNING;
- if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
- MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
+ if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc, minlen_opc, maxlen_opc))
return CMD_WARNING;
if (get_subscr_by_argv(vty, id_type, id, &subscr))
@@ -689,7 +698,7 @@ DEFUN(subscriber_aud3g_xor,
},
};
- if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen)) {
+ if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE);
return CMD_WARNING;
}
diff --git a/tests/db_upgrade/db_upgrade_test.ok b/tests/db_upgrade/db_upgrade_test.ok
index ce5b17c..c719498 100644
--- a/tests/db_upgrade/db_upgrade_test.ok
+++ b/tests/db_upgrade/db_upgrade_test.ok
@@ -86,6 +86,7 @@ DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 3
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 4
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 5
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6
+DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 7
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
Resulting db:
@@ -106,9 +107,9 @@ Table: auc_3g
name|type|notnull|dflt_value|pk
algo_id_3g|INTEGER|1||0
ind_bitlen|INTEGER|1|5|0
-k|VARCHAR(32)|1||0
-op|VARCHAR(32)|0||0
-opc|VARCHAR(32)|0||0
+k|VARCHAR(64)|1||0
+op|VARCHAR(64)|0||0
+opc|VARCHAR(64)|0||0
sqn|INTEGER|1|0|0
subscriber_id|INTEGER|0||1
@@ -179,5 +180,5 @@ osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg
rc = 0
DMAIN hlr starting
DDB using database: <PATH>test.db
-DDB Database <PATH>test.db' has HLR DB schema version 6
+DDB Database <PATH>test.db' has HLR DB schema version 7
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
diff --git a/tests/test_subscriber.vty b/tests/test_subscriber.vty
index dbe9327..9036fb8 100644
--- a/tests/test_subscriber.vty
+++ b/tests/test_subscriber.vty
@@ -275,14 +275,14 @@ OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ?
k Set Encryption Key K
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k ?
- K K as 32 hexadecimal characters
+ K K as 32/64 hexadecimal characters
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d ?
op Set OP key
opc Set OPC key
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc ?
- OP_C OP or OPC as 32 hexadecimal characters
+ OP_C OP or OPC as 32/64 hexadecimal characters
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ?
[ind-bitlen] Set IND bit length