laforge has submitted this change. (
https://gerrit.osmocom.org/c/osmo-tetra/+/33953 )
Change subject: Added calls to stub decryption functions for MAC resources
......................................................................
Added calls to stub decryption functions for MAC resources
The tcs (Tetra Crypto State) struct now maintains information relevant for decryption,
such as the current network, colour code, hyperframe, etcetera.
Also, the upper mac now calls a stub decryption function when receiving an encrypted
resource.
Change-Id: I92d718789d6b7e84c1901d09165fce59cdf8c1ca
---
M src/crypto/tetra_crypto.c
M src/crypto/tetra_crypto.h
M src/lower_mac/tetra_lower_mac.c
M src/tetra_upper_mac.c
M src/tetra_upper_mac.h
5 files changed, 112 insertions(+), 34 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 5313459..67997e1 100644
--- a/src/crypto/tetra_crypto.c
+++ b/src/crypto/tetra_crypto.c
@@ -149,17 +149,17 @@
return ((tm->tn - 1) | (tm->fn << 2) | (tm->mn << 7) | ((hn &
0x7FFF) << 13) | (dir << 28));
}
-int decrypt_identity(struct tetra_addr *addr)
+int decrypt_identity(struct tetra_crypto_state *tcs, struct tetra_addr *addr)
{
return 0;
}
-int decrypt_mac_element(struct tetra_tmvsap_prim *tmvp, struct tetra_key *key, int
l1_len, int tmpdu_offset)
+int decrypt_mac_element(struct tetra_crypto_state *tcs, struct tetra_tmvsap_prim *tmvp,
struct tetra_key *key, int l1_len, int tmpdu_offset)
{
return 0;
}
-int decrypt_voice_timeslot(struct tetra_tdma_time *tdma_time, int16_t *type1_block)
+int decrypt_voice_timeslot(struct tetra_crypto_state *tcs, struct tetra_tdma_time
*tdma_time, int16_t *type1_block)
{
return 0;
}
diff --git a/src/crypto/tetra_crypto.h b/src/crypto/tetra_crypto.h
index a1801cc..0f36e1f 100644
--- a/src/crypto/tetra_crypto.h
+++ b/src/crypto/tetra_crypto.h
@@ -114,13 +114,13 @@
/* Keystream generation and decryption functions */
uint32_t tea_build_iv(struct tetra_tdma_time *tm, uint16_t hn, uint8_t dir);
-int decrypt_identity(struct tetra_addr *addr);
-int decrypt_mac_element(struct tetra_tmvsap_prim *tmvp, struct tetra_key *key, int
l1_len, int tmpdu_offset);
-int decrypt_voice_timeslot(struct tetra_tdma_time *tdma_time, int16_t *type1_bits);
+int decrypt_identity(struct tetra_crypto_state *tcs, struct tetra_addr *addr);
+int decrypt_mac_element(struct tetra_crypto_state *tcs, struct tetra_tmvsap_prim *tmvp,
struct tetra_key *key, int l1_len, int tmpdu_offset);
+int decrypt_voice_timeslot(struct tetra_crypto_state *tcs, struct tetra_tdma_time
*tdma_time, int16_t *type1_bits);
/* Key selection and crypto state management */
-struct tetra_key *get_ksg_key(struct tetra_crypto_state *tcs, int addr);
struct tetra_netinfo *get_network_info(int mcc, int mnc);
+struct tetra_key *get_ksg_key(struct tetra_crypto_state *tcs, int addr);
void update_current_network(struct tetra_crypto_state *tcs, int mcc, int mnc);
void update_current_cck(struct tetra_crypto_state *tcs);
diff --git a/src/lower_mac/tetra_lower_mac.c b/src/lower_mac/tetra_lower_mac.c
index 907f1dc..21998f7 100644
--- a/src/lower_mac/tetra_lower_mac.c
+++ b/src/lower_mac/tetra_lower_mac.c
@@ -40,6 +40,7 @@
#include <tetra_prim.h>
#include "tetra_upper_mac.h"
#include <lower_mac/viterbi.h>
+#include <crypto/tetra_crypto.h>
struct tetra_blk_param {
const char *name;
@@ -149,6 +150,7 @@
const struct tetra_blk_param *tbp = &tetra_blk_param[type];
struct tetra_mac_state *tms = priv;
+ struct tetra_crypto_state *tcs = tms->tcs;
const char *time_str;
/* TMV-SAP.UNITDATA.ind primitive which we will send to the upper MAC */
@@ -299,6 +301,12 @@
/* update the PHY layer time */
memcpy(&t_phy_state.time, &tcd->time, sizeof(t_phy_state.time));
tup->lchan = TETRA_LC_BSCH;
+
+ /* Update colour code and network info for crypto IV generation */
+ tcs->cc = tcd->colour_code;
+ if (tcs->mcc != tcd->mcc || tcs->mnc != tcd->mnc)
+ update_current_network(tcs, tcd->mcc, tcd->mnc);
+
break;
case TPSAP_T_SB2:
case TPSAP_T_NDB:
diff --git a/src/tetra_upper_mac.c b/src/tetra_upper_mac.c
index ef5ce39..94a58ce 100644
--- a/src/tetra_upper_mac.c
+++ b/src/tetra_upper_mac.c
@@ -27,6 +27,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
+#include "crypto/tetra_crypto.h"
#include "tetra_common.h"
#include "tetra_prim.h"
#include "tetra_upper_mac.h"
@@ -84,6 +85,7 @@
static int rx_bcast(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
struct msgb *msg = tmvp->oph.msg;
+ struct tetra_crypto_state *tcs = tms->tcs;
struct tetra_si_decoded sid;
uint32_t dl_freq, ul_freq;
int i;
@@ -114,6 +116,19 @@
sid.mle_si.bs_service_details & (1 << i) ? 1 : 0);
memcpy(&tms->last_sid, &sid, sizeof(sid));
+
+ /* Update crypto state */
+ tcs->la = sid.mle_si.la;
+ tcs->cn = sid.main_carrier; /* FIXME this won't work when not tuned to the main
carier */
+ if (sid.cck_valid_no_hf) {
+ if (sid.cck_id != tcs->cck_id) {
+ tcs->cck_id = sid.cck_id;
+ update_current_cck(tcs);
+ }
+ } else {
+ tcs->hn = sid.hyperframe_number;
+ }
+
return -1; /* FIXME check this indeed fills slot */
}
@@ -142,8 +157,10 @@
static int rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
struct msgb *msg = tmvp->oph.msg;
+ struct tetra_crypto_state *tcs = tms->tcs;
struct tetra_resrc_decoded rsd;
struct msgb *fragmsgb;
+ struct tetra_key *key = 0;
int tmpdu_offset, slot;
int pdu_bits; /* Full length of pdu, including fill bits */
@@ -151,12 +168,12 @@
tmpdu_offset = macpdu_decode_resource(&rsd, msg->l1h, 0);
if (rsd.macpdu_length == MACPDU_LEN_2ND_STOLEN) {
- pdu_bits = -1; /* Fills slot */
- printf("WARNING pdu with MACPDU_LEN_2ND_STOLEN, not implemented\n");
+ pdu_bits = -1; /* Fills slot */
+ tms->cur_burst.blk2_stolen = true; /* Next block is also stolen */
} else if (rsd.macpdu_length == MACPDU_LEN_START_FRAG) {
- pdu_bits = -1; /* Fills slot */
+ pdu_bits = -1; /* Fills slot */
} else {
- pdu_bits = rsd.macpdu_length * 8; /* Length given */
+ pdu_bits = rsd.macpdu_length * 8; /* Length given */
msg->tail = msg->head + pdu_bits;
}
@@ -166,14 +183,34 @@
msg->tail -= num_fill_bits;
}
+ /* Decrypt buffer if encrypted and key available */
+ if (rsd.is_encrypted && tcdb->num_keys) {
+ decrypt_identity(tcs, &rsd.addr);
+ key = get_ksg_key(tcs, rsd.addr.ssi);
+
+ if (key) {
+ rsd.is_encrypted = !decrypt_mac_element(tcs, tmvp, key, msgb_l1len(msg),
tmpdu_offset);
+ if (rsd.chan_alloc_pres) {
+ // Re-decode the channel allocation element to get accurate L2 start
+ tmpdu_offset += macpdu_decode_chan_alloc(&rsd.cad, msg->l1h + tmpdu_offset);
+ }
+ }
+ }
+
/* We now have accurate length and start of TM-SDU, set LLC start in msg->l2h */
msg->l2h = msg->l1h + tmpdu_offset;
- printf("RESOURCE Encr=%u len_field=%d l1_len=%d l2_len %d Addr=%s",
- rsd.encryption_mode, rsd.macpdu_length, msgb_l1len(msg), msgb_l2len(msg),
+ printf("RESOURCE Encr=%u%s len_field=%d l1_len=%d l2_len=%d Addr=%s",
+ rsd.encryption_mode,
+ rsd.encryption_mode && !rsd.is_encrypted ? " DECRYPTED" :
"",
+ rsd.macpdu_length, msgb_l1len(msg), msgb_l2len(msg),
tetra_addr_dump(&rsd.addr));
- if (rsd.chan_alloc_pres)
- printf(" ChanAlloc=%s", tetra_alloc_dump(&rsd.cad, tms));
+ if (rsd.chan_alloc_pres) {
+ if (!rsd.is_encrypted)
+ printf(" ChanAlloc=%s", tetra_alloc_dump(&rsd.cad, tms));
+ else
+ printf(" ChanAlloc=ENCRYPTED");
+ }
if (rsd.slot_granting.pres)
printf(" SlotGrant=%u/%u", rsd.slot_granting.nr_slots,
@@ -183,16 +220,20 @@
pdu_bits = -1; /* No more PDUs in slot */
goto out;
}
- if (msgb_l2len(msg) == 0) {
+ tms->ssi = rsd.addr.ssi;
+ tms->usage_marker = rsd.addr.usage_marker;
+ tms->addr_type = rsd.addr.type;
+
+ if (msgb_l2len(msg) == 0)
goto out; /* No l2 data */
- }
+
+ if (rsd.is_encrypted)
+ goto out; /* Can't parse any further */
printf(": %s\n", osmo_ubit_dump(msg->l2h, msgb_l2len(msg)));
if (rsd.macpdu_length != MACPDU_LEN_START_FRAG || !REASSEMBLE_FRAGMENTS) {
/* Non-fragmented resource (or no reassembly desired) */
- if (!rsd.is_encrypted) {
- rx_tm_sdu(tms, msg, msgb_l2len(msg));
- }
+ rx_tm_sdu(tms, msg, msgb_l2len(msg));
} else {
/* Fragmented resource */
slot = tmvp->u.unitdata.tdma_time.tn;
@@ -205,6 +246,7 @@
fragmsgb = fragslots[slot].msgb;
/* Copy l2 part to fragmsgb. l3h is constructed once all fragments are merged */
+ fragmsgb = fragslots[slot].msgb;
fragmsgb->l1h = msgb_put(fragmsgb, msgb_l1len(msg));
fragmsgb->l2h = fragmsgb->l1h + tmpdu_offset;
fragmsgb->l3h = 0;
@@ -215,10 +257,9 @@
fragslots[slot].num_frags = 1;
fragslots[slot].length = msgb_l2len(msg);
fragslots[slot].encryption = rsd.encryption_mode > 0;
+ fragslots[slot].key = key;
}
- tms->ssi = rsd.addr.ssi;
-
out:
printf("\n");
return pdu_bits;
@@ -243,6 +284,7 @@
static int rx_macfrag(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
struct msgb *msg = tmvp->oph.msg;
+ struct msgb *fragmsgb;
int slot = tmvp->u.unitdata.tdma_time.tn;
uint8_t *bits = msg->l1h;
uint8_t fillbits_present;
@@ -258,11 +300,15 @@
/* MAC-FRAG will always fill remainder of the slot, but fill bits may be present */
if (fillbits_present) {
int num_fill_bits = get_num_fill_bits(msg->l1h, msgb_l1len(msg));
- msgb_get(msg, num_fill_bits);
+ msg->tail -= num_fill_bits;
}
+ /* Decrypt (if required) */
+ fragmsgb = fragslots[slot].msgb;
+ if (fragslots[slot].encryption && fragslots[slot].key)
+ decrypt_mac_element(tms->tcs, tmvp, fragslots[slot].key, msgb_l1len(msg), n);
+
/* Add frag to fragslot buffer */
- struct msgb *fragmsgb = fragslots[slot].msgb;
append_frag_bits(slot, msg->l2h, msgb_l2len(msg));
printf("FRAG-CONT slot=%d added=%d msgb=%s\n", slot, msgb_l2len(msg),
osmo_ubit_dump(fragmsgb->l2h, msgb_l2len(fragmsgb)));
} else {
@@ -308,16 +354,21 @@
msg->tail -= num_fill_bits;
}
+ /* Decrypt (if required) */
+ if (fragslots[slot].encryption && fragslots[slot].key)
+ decrypt_mac_element(tms->tcs, tmvp, fragslots[slot].key, msgb_l1len(msg), n);
+
/* Parse chanalloc element (if present) and update l2 offsets */
if (chanalloc_present) {
m = macpdu_decode_chan_alloc(&rsd.cad, bits + n); n = n + m;
}
+
msg->l2h = msg->l1h + n;
append_frag_bits(slot, msg->l2h, msgb_l2len(msg));
printf("FRAG-END slot=%d added=%d msgb=%s\n", slot, msgb_l2len(msg),
osmo_ubit_dump(fragmsgb->l2h, msgb_l2len(fragmsgb)));
/* Message is completed inside fragmsgb now */
- if (!fragslots[slot].encryption) {
+ if (!fragslots[slot].encryption || fragslots[slot].key) {
rx_tm_sdu(tms, fragmsgb, fragslots[slot].length);
}
} else {
@@ -343,17 +394,17 @@
{
uint8_t slot_granting = *(msg->l1h + 17);
if (slot_granting)
- tmpdu_offset = 17+1+8;
+ tmpdu_offset = 17 + 1 + 8;
else
- tmpdu_offset = 17+1;
+ tmpdu_offset = 17 + 1;
}
#endif
printf("SUPPLEMENTARY MAC-D-BLOCK ");
//if (sud.encryption_mode == 0)
- msg->l2h = msg->l1h + tmpdu_offset;
- rx_tm_sdu(tms, msg, 100);
+ msg->l2h = msg->l1h + tmpdu_offset;
+ rx_tm_sdu(tms, msg, 100);
printf("\n");
return -1; /* TODO FIXME check length */
@@ -385,10 +436,15 @@
printf("UL_USAGE: %s ", tetra_get_ul_usage_name(aad.ul_usage));
/* save the state whether the current burst is traffic or not */
- if (aad.dl_usage > 3)
+ if (aad.dl_usage > 3) {
tms->cur_burst.is_traffic = aad.dl_usage;
- else
+ } else {
tms->cur_burst.is_traffic = 0;
+ }
+
+ /* Reset slot stealing flags */
+ tms->cur_burst.blk1_stolen = false;
+ tms->cur_burst.blk2_stolen = false;
printf("\n");
}
@@ -426,10 +482,11 @@
if (gsmtap_msg)
tetra_gsmtap_sendmsg(gsmtap_msg);
- /* age out old fragments */
- if (REASSEMBLE_FRAGMENTS && tup->tdma_time.fn == 18) {
+
+ if (tup->tdma_time.fn == 18 && REASSEMBLE_FRAGMENTS)
+ /* Age out old fragments */
+ /* FIXME: also age out old event labels */
age_fragslots();
- }
len_parsed = -1; /* Default for cases where slot is filled or otherwise irrelevant */
switch (tup->lchan) {
diff --git a/src/tetra_upper_mac.h b/src/tetra_upper_mac.h
index d7a420d..e399729 100644
--- a/src/tetra_upper_mac.h
+++ b/src/tetra_upper_mac.h
@@ -14,6 +14,7 @@
int num_frags; /* Maintains the number of fragments appended in the msgb */
int length; /* Maintains the number of bits appended in the msgb */
bool encryption; /* Set to true if the fragments were received encrypted */
+ struct tetra_key *key; /* Holds pointer to the key to be used for this slot */
struct msgb *msgb; /* Message buffer in which fragments are appended */
};
--
To view, visit
https://gerrit.osmocom.org/c/osmo-tetra/+/33953
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-tetra
Gerrit-Branch: master
Gerrit-Change-Id: I92d718789d6b7e84c1901d09165fce59cdf8c1ca
Gerrit-Change-Number: 33953
Gerrit-PatchSet: 5
Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged