laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-tetra/+/33997 )

Change subject: Added keyfile parsing code and various crypto improvements
......................................................................

Added keyfile parsing code and various crypto improvements

Added keyfile parsing code, as well as various other improvements such as 
definition/enum updates and freeing the tetra_crypto_context when done

Change-Id: I1c7afeeb2dcf97ece44bb4b604f44ba88882b93f
---
M src/crypto/tetra_crypto.c
M src/crypto/tetra_crypto.h
M src/tetra-rx.c
3 files changed, 118 insertions(+), 16 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved




diff --git a/src/crypto/tetra_crypto.c b/src/crypto/tetra_crypto.c
index 67997e1..9515a25 100644
--- a/src/crypto/tetra_crypto.c
+++ b/src/crypto/tetra_crypto.c
@@ -38,9 +38,9 @@

 static const struct value_string tetra_key_types[] = {
        { KEYTYPE_UNDEFINED,            "UNDEFINED" },
+       { KEYTYPE_CCK_SCK,              "CCK/SCK" },
        { KEYTYPE_DCK,                  "DCK" },
        { KEYTYPE_MGCK,                 "MGCK" },
-       { KEYTYPE_CCK_SCK,              "CCK/SCK" },
        { KEYTYPE_GCK,                  "GCK" },
        { 0, NULL }
 };
@@ -50,7 +50,7 @@
        return get_value_string(tetra_key_types, key_type);
 }

-static const struct value_string tetra_tea_types[] = {
+static const struct value_string tetra_ksg_types[] = {
        { UNKNOWN,                      "UNKNOWN" },
        { KSG_TEA1,                     "TEA1" },
        { KSG_TEA2,                     "TEA2" },
@@ -66,9 +66,9 @@
 const char *tetra_get_ksg_type_name(enum tetra_ksg_type ksg_type)
 {
        if (ksg_type >= KSG_PROPRIETARY)
-               return tetra_tea_types[KSG_PROPRIETARY].str;
+               return tetra_ksg_types[KSG_PROPRIETARY].str;
        else
-               return get_value_string(tetra_tea_types, ksg_type);
+               return get_value_string(tetra_ksg_types, ksg_type);
 }

 static const struct value_string tetra_security_classes[] = {
@@ -86,14 +86,15 @@

 void tetra_crypto_state_init(struct tetra_crypto_state *tcs)
 {
-       /* Initialize tetra_crypto_state */
-       tcs = talloc_zero(NULL, struct tetra_crypto_state);
+       /* Initialize network info fields to -1 to designate unknown */
        tcs->mnc = -1;
        tcs->mcc = -1;
        tcs->cck_id = -1;
        tcs->hn =  -1;
        tcs->la =  -1;
        tcs->cc =  -1;
+
+       /* Initialize database key/network pointers to zero */
        tcs->cck = 0;
        tcs->network = 0;
 }
@@ -116,8 +117,8 @@
 {
        static char pbuf[1024];

-       int c = snprintf(pbuf, sizeof(pbuf), "MCC %4d MNC %4d key_type %02X",
-               k->mcc, k->mnc, k->key_type);
+       int c = snprintf(pbuf, sizeof(pbuf), "MCC %4d MNC %4d key_type %s",
+               k->mcc, k->mnc, tetra_get_key_type_name(k->key_type));

        if (k->key_type & (KEYTYPE_DCK | KEYTYPE_MGCK))
                c += snprintf(pbuf + c, sizeof(pbuf) - c, " addr: %8d", 
k->addr);
@@ -166,6 +167,98 @@

 int load_keystore(char *tetra_keyfile)
 {
+       /* Keystore file:
+        * Each line contains network or key definition.
+        * Lines starting with # are ignored as comments.
+        *
+        *   network mcc 123 mnc 456 ksg_type 1 security_class 2
+        *   - ksg_type: decimal, see enum tetra_ksg_type
+        *   - security_class: 2 for SCK, 3 for CCK (and DCK per ISSI)
+        *
+        *   key mcc 123 mnc 456 addr 00000000 key_type 1 key_num 002 key 
1234deadbeefcafebabe
+        *   - addr: decimal, leave zero for key type 1 (CCK/SCK)
+        *   - key_type: 1 CCK/SCK, 2 DCK, 3 MGCK, 4 GCK
+        *   - key_num: SCK_VN or group key number depending on type
+        *   - key: 80-bit key hex string
+        */
+
+       int i, c;
+       char buf[1000]; // max line len
+       FILE *fp;
+
+       tetra_crypto_db_init();
+
+       fp = fopen(tetra_keyfile, "r");
+       if (!fp) {
+               printf("tetra_crypto: cannot read keyfile\n");
+               exit(1);
+       }
+
+       while (fgets(buf, sizeof(buf), fp)) {
+
+               if (strlen(buf) <= 1 || buf[0] == '#') {
+                       // Commented/empty line
+                       continue;
+
+               } else if (!strncmp(buf, "network ", 8)) {
+
+                       /* Network definition */
+                       i = tcdb->num_nets;
+                       if (i > 0 && (i % TCDB_ALLOC_BLOCK_SIZE == 0))
+                               tcdb->nets = talloc_realloc(NULL, tcdb->nets, 
struct tetra_netinfo, i + TCDB_ALLOC_BLOCK_SIZE);
+
+                       c = sscanf(buf, "network mcc %d mnc %d ksg_type %d 
security_class %d\n",
+                               &tcdb->nets[i].mcc, &tcdb->nets[i].mnc,
+                               (uint32_t *) &tcdb->nets[i].ksg_type,
+                               (uint32_t *) &tcdb->nets[i].security_class);
+
+                       if (c != 4) {
+                               printf("tetra_crypto: Failed to parse network 
info element %d [%s] (%d)\n", i, buf, c);
+                               exit(1);
+                       }
+                       printf("tetra_crypto: Loaded MNC [%s]\n", 
dump_network_info(&tcdb->nets[i]));
+                       tcdb->num_nets++;
+
+               } else if (!strncmp(buf, "key ", 4)) {
+
+                       /* Key definition */
+                       i = tcdb->num_keys;
+                       if (i > 0 && (i % TCDB_ALLOC_BLOCK_SIZE == 0))
+                               tcdb->keys = talloc_realloc(NULL, tcdb->keys, 
struct tetra_key, i + TCDB_ALLOC_BLOCK_SIZE);
+
+                       c = sscanf(buf, "key mcc %d mnc %d addr %d key_type %d 
key_num %d key %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+                               &tcdb->keys[i].mcc, &tcdb->keys[i].mnc, 
&tcdb->keys[i].addr,
+                               (uint32_t *) &tcdb->keys[i].key_type, 
&tcdb->keys[i].key_num,
+                               (uint32_t *) &tcdb->keys[i].key[0], (uint32_t 
*) &tcdb->keys[i].key[1],
+                               (uint32_t *) &tcdb->keys[i].key[2], (uint32_t 
*) &tcdb->keys[i].key[3],
+                               (uint32_t *) &tcdb->keys[i].key[4], (uint32_t 
*) &tcdb->keys[i].key[5],
+                               (uint32_t *) &tcdb->keys[i].key[6], (uint32_t 
*) &tcdb->keys[i].key[7],
+                               (uint32_t *) &tcdb->keys[i].key[8], (uint32_t 
*) &tcdb->keys[i].key[9]);
+                       tcdb->keys[i].index = i;
+                       if (c != 15) {
+                               printf("tetra_crypto: Failed to parse key %d 
[%s] (%d)\n", i, buf, c);
+                               exit(1);
+                       }
+                       printf("tetra_crypto: Loaded key [%s]\n", 
dump_key(&tcdb->keys[i]));
+                       tcdb->num_keys++;
+
+               } else {
+                       printf("tetra_crypto: Could not parse line: %s\n", buf);
+                       exit(1);
+               }
+       }
+
+       /* Check network info available for each key and set ptrs for 
convenience */
+       for (i = 0; i < tcdb->num_keys; i++) {
+               struct tetra_netinfo *network_info_ptr = 
get_network_info(tcdb->keys[i].mcc, tcdb->keys[i].mnc);
+               if (!network_info_ptr) {
+                       printf("tetra_crypto: Required network info is missing 
for %4d", tcdb->keys[i].mnc);
+                       exit(1);
+               }
+               tcdb->keys[i].network_info = network_info_ptr;
+       }
+
+       fclose(fp);
        return 0;
 }

diff --git a/src/crypto/tetra_crypto.h b/src/crypto/tetra_crypto.h
index 0f36e1f..e50a45e 100644
--- a/src/crypto/tetra_crypto.h
+++ b/src/crypto/tetra_crypto.h
@@ -35,15 +35,13 @@
 #define TCDB_ALLOC_BLOCK_SIZE 16

 enum tetra_key_type {
-       KEYTYPE_UNDEFINED               = 0x00,
+       KEYTYPE_UNDEFINED               = 0,

        /* Keytypes usable as ECK after applying TB5 */
-       KEYTYPE_DCK                     = 0x01,
-       KEYTYPE_MGCK                    = 0x02,
-       KEYTYPE_CCK_SCK                 = 0x04, /* SCK in class 2, CCK in class 
3 networks */
-
-       /* Can be combined with SCK/CCK to get MGCK */
-       KEYTYPE_GCK                     = 0x20,
+       KEYTYPE_CCK_SCK                 = 1, /* SCK in class 2, CCK in class 3 
networks */
+       KEYTYPE_DCK                     = 2, /* FIXME: add support for DCK */
+       KEYTYPE_MGCK                    = 4, /* FIXME: add support for MGCK */
+       KEYTYPE_GCK                     = 8, /* FIXME: add support. Used with 
SCK/CCK to derive MGCK */
 };

 enum tetra_ksg_type {
@@ -109,7 +107,6 @@

 /* Key loading / unloading */
 void tetra_crypto_state_init(struct tetra_crypto_state *tcs);
-void tetra_crypto_db_init(void);
 int load_keystore(char *filename);

 /* Keystream generation and decryption functions */
diff --git a/src/tetra-rx.c b/src/tetra-rx.c
index 2fe95b5..b37b4c0 100644
--- a/src/tetra-rx.c
+++ b/src/tetra-rx.c
@@ -93,6 +93,7 @@

        free(tms->dumpdir);
        talloc_free(trs);
+       talloc_free(tms->tcs);
        talloc_free(tms);

        exit(0);

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

Gerrit-Project: osmo-tetra
Gerrit-Branch: master
Gerrit-Change-Id: I1c7afeeb2dcf97ece44bb4b604f44ba88882b93f
Gerrit-Change-Number: 33997
Gerrit-PatchSet: 2
Gerrit-Owner: wbokslag <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-MessageType: merged

Reply via email to