laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-hlr/+/33098 )


Change subject: db: extend database schema to support 256bit K and/or OP[c] 
values
......................................................................

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
---
M sql/hlr.sql
M src/ctrl.c
M src/db.c
M src/hlr_vty_subscr.c
M tests/db_upgrade/db_upgrade_test.ok
M tests/test_subscriber.vty
6 files changed, 95 insertions(+), 29 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-hlr refs/changes/98/33098/1

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_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 @@

 -- 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 @@
        }
        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 @@
        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 @@
        }
        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 @@
                }

                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 23dcbbc..b186775 100644
--- a/src/db.c
+++ b/src/db.c
@@ -1,4 +1,4 @@
-/* (C) 2015 by Harald Welte <[email protected]>
+/* (C) 2015-2023 by Harald Welte <[email protected]>
  *
  * 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 @@
        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 *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 6\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 @@
        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/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index 191a87d..708359a 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -473,8 +473,15 @@
        "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 +504,10 @@
        } 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 +563,7 @@
                .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 +622,13 @@
       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 +647,7 @@
                },
        };

-       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 +655,7 @@
        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,8 +699,8 @@
                },
        };

-       if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen)) {
-               vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", 
VTY_NEWLINE);
+       if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, 
NULL)) {
+               vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", 
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 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 @@
 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 @@
 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 @@
   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

--
To view, visit https://gerrit.osmocom.org/c/osmo-hlr/+/33098
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-hlr
Gerrit-Branch: master
Gerrit-Change-Id: Ibbde68484c904507a15c35cbfdf88cd47d0c7039
Gerrit-Change-Number: 33098
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <[email protected]>
Gerrit-MessageType: newchange

Reply via email to