aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-07-05 15:19:12 +0200
committerHarald Welte <laforge@gnumonks.org>2016-07-16 21:03:30 +0000
commit4011e728d22a9affbe41fb2bfc8e69c14bd706ab (patch)
treeb0d6d66b7511cbd52a8204bb19535732e14f2d65 /openbsc
parent9759374adbb632ff5f8a4b739e0f62a9c9017622 (diff)
SGSN: use unique AUTH REQ reference
The A&C reference number specified in 3GPP TS 24.008 § 10.5.5.19 identifies particular request sent by network with the related response sent by MS. The value transparently copied from request to response by MS: the spec do not specify what exactly should be in there so we use rand() to decrease chance for collisions. Note: variable named 'rand' clashes with standard function rand() so it was renamed. Change-Id: I3638821a9b4a0532b28dbbb50faa30c4082579f6 Related: OS#1582
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h2
-rw-r--r--openbsc/src/gprs/gprs_gmm.c30
-rw-r--r--openbsc/src/gprs/sgsn_main.c2
-rw-r--r--openbsc/tests/sgsn/Makefile.am1
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c19
5 files changed, 46 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 0e574d816..96040849b 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -158,6 +158,8 @@ struct sgsn_mm_ctx {
/* Iu: CK, IK, KSI */
/* CKSN */
enum gprs_ciph_algo ciph_algo;
+ /* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
+ uint8_t ac_ref_nr_used;
struct {
uint8_t len;
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 5db69ddad..7f10b0712 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -31,6 +31,8 @@
#include <arpa/inet.h>
#include <netdb.h>
+#include <openssl/rand.h>
+
#include <openbsc/db.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
@@ -417,16 +419,16 @@ static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
}
/* Section 9.4.9: Authentication and Ciphering Request */
-static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rand,
+static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rnd,
uint8_t key_seq, uint8_t algo)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REQ");
struct gsm48_hdr *gh;
struct gsm48_auth_ciph_req *acreq;
- uint8_t *m_rand, *m_cksn;
+ uint8_t *m_rand, *m_cksn, rbyte;
LOGMMCTXP(LOGL_INFO, mm, "<- GPRS AUTH AND CIPHERING REQ (rand = %s)\n",
- osmo_hexdump(rand, 16));
+ osmo_hexdump(rnd, 16));
mmctx2msgid(msg, mm);
@@ -438,13 +440,20 @@ static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rand,
acreq->ciph_alg = algo & 0xf;
acreq->imeisv_req = 0x1;
acreq->force_stby = 0x0;
- acreq->ac_ref_nr = 0x0; /* FIXME: increment this? */
+ /* 3GPP TS 24.008 § 10.5.5.19: */
+ if (RAND_bytes(&rbyte, 1) != 1) {
+ LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed for A&C ref, falling "
+ "back to rand()\n");
+ acreq->ac_ref_nr = rand();
+ } else
+ acreq->ac_ref_nr = rbyte;
+ mm->ac_ref_nr_used = acreq->ac_ref_nr;
/* Only if authentication is requested we need to set RAND + CKSN */
- if (rand) {
+ if (rnd) {
m_rand = msgb_put(msg, 16+1);
m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
- memcpy(m_rand+1, rand, 16);
+ memcpy(m_rand + 1, rnd, 16);
m_cksn = msgb_put(msg, 1);
m_cksn[0] = (GSM48_IE_GMM_CIPH_CKSN << 4) | (key_seq & 0x07);
@@ -490,14 +499,19 @@ static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
return 0;
}
+ if (acr->ac_ref_nr != ctx->ac_ref_nr_used) {
+ LOGMMCTXP(LOGL_NOTICE, ctx, "Reference mismatch for Auth & Ciph"
+ " Response: %u received, %u expected\n",
+ acr->ac_ref_nr, ctx->ac_ref_nr_used);
+ return 0;
+ }
+
/* Stop T3360 */
mmctx_timer_stop(ctx, 3360);
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)) {
/* TODO: missing mandatory IE, return STATUS or REJ? */
diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c
index c852840db..44751363c 100644
--- a/openbsc/src/gprs/sgsn_main.c
+++ b/openbsc/src/gprs/sgsn_main.c
@@ -21,6 +21,7 @@
#include <unistd.h>
#include <stdio.h>
+#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
@@ -306,6 +307,7 @@ int main(int argc, char **argv)
struct gsm_network dummy_network;
int rc;
+ srand(time(NULL));
tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index e3cec5086..b6036c75c 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -7,6 +7,7 @@ noinst_PROGRAMS = sgsn_test
sgsn_test_SOURCES = sgsn_test.c
sgsn_test_LDFLAGS = \
+ -Wl,--wrap=RAND_bytes \
-Wl,--wrap=sgsn_update_subscriber_data \
-Wl,--wrap=gprs_subscr_request_update_location \
-Wl,--wrap=gprs_subscr_request_auth_info \
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index d568807dd..e8e05f6e9 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -101,6 +101,25 @@ int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
return 0;
}
+/* override, requires '-Wl,--wrap=RAND_bytes' */
+int __real_RAND_bytes(unsigned char *buf, int num);
+int mock_RAND_bytes(unsigned char *buf, int num);
+int (*RAND_bytes_cb)(unsigned char *, int) =
+ &mock_RAND_bytes;
+
+int __wrap_RAND_bytes(unsigned char *buf, int num)
+{
+ return (*RAND_bytes_cb)(buf, num);
+}
+/* make results of A&C ref predictable */
+int mock_RAND_bytes(unsigned char *buf, int num)
+{
+ if (num > 1)
+ return __real_RAND_bytes(buf, num);
+ buf[0] = 0;
+ return 1;
+}
+
/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =