[SGSN] Initial work on GMM authentication and ciphering
This commit is contained in:
parent
3e2e159707
commit
4b6ac1edb9
|
@ -63,6 +63,7 @@
|
||||||
#define GPRS_UPD_T_PERIODIC 3
|
#define GPRS_UPD_T_PERIODIC 3
|
||||||
|
|
||||||
enum gsm48_gprs_ie_mm {
|
enum gsm48_gprs_ie_mm {
|
||||||
|
GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */
|
||||||
GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
|
GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
|
||||||
GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
|
GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
|
||||||
GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
|
GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
|
||||||
|
@ -120,6 +121,22 @@ struct gsm48_attach_ack {
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Chapter 9.4.9 / Table 9.4.9 */
|
||||||
|
struct gsm48_auth_ciph_req {
|
||||||
|
uint8_t ciph_alg:4, /* 10.5.5.3 */
|
||||||
|
imeisv_req:4; /* 10.5.5.10 */
|
||||||
|
uint8_t force_stby:4, /* 10.5.5.7 */
|
||||||
|
ac_ref_nr:4; /* 10.5.5.19 */
|
||||||
|
uint8_t data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
/* optional: TV RAND, TV CKSN */
|
||||||
|
|
||||||
|
struct gsm48_auth_ciph_resp {
|
||||||
|
uint8_t ac_ref_nr:4,
|
||||||
|
spare:4;
|
||||||
|
uint8_t data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* Chapter 9.5.1 / Table 9.5.1 */
|
/* Chapter 9.5.1 / Table 9.5.1 */
|
||||||
struct gsm48_act_pdp_ctx_req {
|
struct gsm48_act_pdp_ctx_req {
|
||||||
uint8_t req_nsapi;
|
uint8_t req_nsapi;
|
||||||
|
|
|
@ -167,13 +167,14 @@ const struct value_string gprs_det_t_mo_strs[] = {
|
||||||
|
|
||||||
static const struct tlv_definition gsm48_gmm_att_tlvdef = {
|
static const struct tlv_definition gsm48_gmm_att_tlvdef = {
|
||||||
.def = {
|
.def = {
|
||||||
|
[GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 },
|
||||||
[GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
|
[GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
|
||||||
[GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_TV, 3 },
|
[GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
|
||||||
[GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_TV, 16 },
|
[GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 },
|
||||||
[GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_TV, 4 },
|
[GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 },
|
||||||
[GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_TV, 2 },
|
[GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 },
|
||||||
[GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
|
||||||
|
@ -189,8 +190,8 @@ static const struct tlv_definition gsm48_sm_att_tlvdef = {
|
||||||
[GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
|
[GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
|
||||||
[GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
|
||||||
[GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_TV, 1 },
|
[GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_FIXED, 1 },
|
||||||
[GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_TV, 7 },
|
[GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_FIXED, 7 },
|
||||||
[GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
|
[GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -447,6 +448,92 @@ static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
|
||||||
return gsm48_gmm_sendmsg(msg, 1, mm);
|
return gsm48_gmm_sendmsg(msg, 1, mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Section 9.4.9: Authentication and Ciphering Request */
|
||||||
|
static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rand,
|
||||||
|
uint8_t key_seq, uint8_t algo)
|
||||||
|
{
|
||||||
|
struct msgb *msg = gsm48_msgb_alloc();
|
||||||
|
struct gsm48_hdr *gh;
|
||||||
|
struct gsm48_auth_ciph_req *acreq;
|
||||||
|
uint8_t *m_rand, *m_cksn;
|
||||||
|
|
||||||
|
DEBUGP(DMM, "<- GPRS AUTH AND CIPHERING REQ (rand = %s)\n",
|
||||||
|
hexdump(rand, 16));
|
||||||
|
|
||||||
|
mmctx2msgid(msg, mm);
|
||||||
|
|
||||||
|
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
|
||||||
|
gh->proto_discr = GSM48_PDISC_MM_GPRS;
|
||||||
|
gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REQ;
|
||||||
|
|
||||||
|
acreq = (struct gsm48_auth_ciph_req *) msgb_put(msg, sizeof(*acreq));
|
||||||
|
acreq->ciph_alg = algo & 0xf;
|
||||||
|
acreq->imeisv_req = 0x1;
|
||||||
|
acreq->force_stby = 0x0;
|
||||||
|
acreq->ac_ref_nr = 0x0; /* FIXME: increment this? */
|
||||||
|
|
||||||
|
/* Only if authentication is requested we need to set RAND + CKSN */
|
||||||
|
if (rand) {
|
||||||
|
m_rand = msgb_put(msg, 16+1);
|
||||||
|
m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
|
||||||
|
memcpy(m_rand+1, rand, 16);
|
||||||
|
|
||||||
|
m_cksn = msgb_put(msg, 1+1);
|
||||||
|
m_cksn[0] = GSM48_IE_GMM_CIPH_CKSN;
|
||||||
|
m_cksn[1] = key_seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start T3360 */
|
||||||
|
mmctx_timer_start(mm, 3360, GSM0408_T3360_SECS);
|
||||||
|
|
||||||
|
/* FIXME: make sure we don't send any other messages to the MS */
|
||||||
|
|
||||||
|
return gsm48_gmm_sendmsg(msg, 1, mm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section 9.4.11: Authentication and Ciphering Reject */
|
||||||
|
static int gsm48_tx_gmm_auth_ciph_rej(struct sgsn_mm_ctx *mm)
|
||||||
|
{
|
||||||
|
struct msgb *msg = gsm48_msgb_alloc();
|
||||||
|
struct gsm48_hdr *gh;
|
||||||
|
|
||||||
|
DEBUGP(DMM, "<- GPRS AUTH AND CIPH REJECT\n");
|
||||||
|
|
||||||
|
mmctx2msgid(msg, mm);
|
||||||
|
|
||||||
|
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
|
||||||
|
gh->proto_discr = GSM48_PDISC_MM_GPRS;
|
||||||
|
gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ;
|
||||||
|
|
||||||
|
return gsm48_gmm_sendmsg(msg, 0, mm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section 9.4.10: Authentication and Ciphering Response */
|
||||||
|
static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
|
||||||
|
struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
|
||||||
|
struct gsm48_auth_ciph_resp *acr = (struct gsm48_auth_ciph_resp *)gh->data;
|
||||||
|
struct tlv_parsed tp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* FIXME: Stop T3360 */
|
||||||
|
|
||||||
|
rc = tlv_parse(&tp, &gsm48_gmm_att_tlvdef, acr->data,
|
||||||
|
(msg->data + msg->len) - acr->data, 0, 0);
|
||||||
|
|
||||||
|
/* FIXME: compare ac_ref? */
|
||||||
|
|
||||||
|
if (!TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_SRES) ||
|
||||||
|
!TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV)) {
|
||||||
|
/* FIXME: missing mandatory IE */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: compare SRES with what we expected */
|
||||||
|
/* FIXME: enable LLC cipheirng */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we can already authorize a subscriber */
|
/* Check if we can already authorize a subscriber */
|
||||||
static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
|
static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
|
||||||
enum gprs_t3350_mode t3350_mode)
|
enum gprs_t3350_mode t3350_mode)
|
||||||
|
@ -925,9 +1012,7 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
||||||
//gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, GPRS_ALGO_GEA0, NULL);
|
//gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, GPRS_ALGO_GEA0, NULL);
|
||||||
break;
|
break;
|
||||||
case GSM48_MT_GMM_AUTH_CIPH_RESP:
|
case GSM48_MT_GMM_AUTH_CIPH_RESP:
|
||||||
DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n",
|
rc = gsm48_rx_gmm_auth_ciph_resp(mmctx, msg);
|
||||||
gh->msg_type);
|
|
||||||
rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
|
DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
|
||||||
|
@ -967,6 +1052,15 @@ static void mmctx_timer_cb(void *_mm)
|
||||||
}
|
}
|
||||||
bsc_schedule_timer(&mm->timer, GSM0408_T3350_SECS, 0);
|
bsc_schedule_timer(&mm->timer, GSM0408_T3350_SECS, 0);
|
||||||
break;
|
break;
|
||||||
|
case 3360: /* waiting for AUTH AND CIPH RESP */
|
||||||
|
if (mm->num_T_exp >= 5) {
|
||||||
|
LOGP(DMM, LOGL_NOTICE, "T3360 expired >= 5 times\n");
|
||||||
|
mm->mm_state = GMM_DEREGISTERED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FIXME: re-transmit the respective msg and re-start timer */
|
||||||
|
bsc_schedule_timer(&mm->timer, GSM0408_T3360_SECS, 0);
|
||||||
|
break;
|
||||||
case 3370: /* waiting for IDENTITY RESPONSE */
|
case 3370: /* waiting for IDENTITY RESPONSE */
|
||||||
if (mm->num_T_exp >= 5) {
|
if (mm->num_T_exp >= 5) {
|
||||||
LOGP(DMM, LOGL_NOTICE, "T3370 expired >= 5 times\n");
|
LOGP(DMM, LOGL_NOTICE, "T3370 expired >= 5 times\n");
|
||||||
|
|
Loading…
Reference in New Issue