summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--include/osmocom/gsm/gsm_utils.h5
-rw-r--r--src/gsm/gsm_utils.c48
-rw-r--r--src/gsm/libosmogsm.map1
-rw-r--r--utils/osmo-auc-gen.c14
5 files changed, 63 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index 33c151e7..d9390cf8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,9 @@ AC_ARG_ENABLE(doxygen,
AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false && test "x$doxygen" = "xyes")
+# check for syscal fallback on glibc < 2.25 - can be removed once glibc version requirement is bumped
+AC_CHECK_DECLS([SYS_getrandom], [], [], [[#include <sys/syscall.h>]])
+
# The following test is taken from WebKit's webkit.m4
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=hidden "
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index bfcef08b..83e29cac 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -38,6 +38,9 @@
#define GSM_MAX_FN (26*51*2048)
+/* Max length of random identifier which can be requested via osmo_get_rand_id() */
+#define OSMO_MAX_RAND_ID_LEN 16
+
struct gsm_time {
uint32_t fn; /* FN count */
uint16_t t1; /* FN div (26*51) */
@@ -60,6 +63,8 @@ enum gsm_band {
const char *gsm_band_name(enum gsm_band band);
enum gsm_band gsm_band_parse(const char *mhz);
+int osmo_get_rand_id(uint8_t *out, size_t len);
+
/*!
* Decode a sequence of GSM 03.38 encoded 7 bit characters.
*
diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c
index 477f076d..f572c643 100644
--- a/src/gsm/gsm_utils.c
+++ b/src/gsm/gsm_utils.c
@@ -91,9 +91,18 @@
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>
+#include <time.h>
+#include <unistd.h>
#include "../../config.h"
+/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
+#include <linux/random.h>
+#elif HAVE_DECL_SYS_GETRANDOM
+#include <sys/syscall.h>
+#endif
+
/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
* Greek symbols at hex positions 0x10 and 0x12-0x1a
* left out as they can't be handled with a char and
@@ -387,6 +396,45 @@ int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *oct
return y;
}
+/*! Generate random identifier
+ * We use /dev/urandom (default when GRND_RANDOM flag is not set).
+ * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
+ * See also RFC4086.
+ * \param[out] out Buffer to be filled with random data
+ * \param[in] len Number of random bytes required
+ * \returns 0 on success, or a negative error code on error.
+ */
+int osmo_get_rand_id(uint8_t *out, size_t len)
+{
+ int rc;
+
+ /* this function is intended for generating short identifiers only, not arbitrary-length random data */
+ if (len > OSMO_MAX_RAND_ID_LEN)
+ return -E2BIG;
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
+ rc = getrandom(out, len, GRND_NONBLOCK);
+#elif HAVE_DECL_SYS_GETRANDOM
+#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
+ /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
+ rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
+#else
+#pragma message ("Secure random unavailable: calls to osmo_get_rand_id() will always fail!")
+ return -ENOTSUP;
+#endif
+ /* getrandom() failed entirely: */
+ if (rc < 0)
+ return -errno;
+
+ /* getrandom() failed partially due to signal interruption:
+ this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
+ because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
+ if (rc != len)
+ return -EAGAIN;
+
+ return 0;
+}
+
/*! Build the RSL uplink measurement IE (3GPP TS 08.58 ยง 9.3.25)
* \param[in] mru Unidirectional measurement report structure
* \param[in] dtxd_used Indicates if DTXd was used during measurement report
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 95b2ca9f..5598859a 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -39,6 +39,7 @@ abis_nm_get_sw_desc_len;
osmo_sitype_strs;
osmo_c4;
+osmo_get_rand_id;
bitvec_add_range1024;
comp128;
comp128v2;
diff --git a/utils/osmo-auc-gen.c b/utils/osmo-auc-gen.c
index 1f5c8386..9d1215c8 100644
--- a/utils/osmo-auc-gen.c
+++ b/utils/osmo-auc-gen.c
@@ -34,6 +34,7 @@
#include <osmocom/crypt/auth.h>
#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm_utils.h>
static void dump_triplets_dat(struct osmo_auth_vector *vec)
{
@@ -247,14 +248,11 @@ int main(int argc, char **argv)
}
if (!rand_is_set) {
- int i;
- printf("WARNING: We're using really weak random numbers!\n\n");
- srand(time(NULL));
-
- for (i = 0; i < 4; ++i) {
- uint32_t r;
- r = rand();
- memcpy(&_rand[i*4], &r, 4);
+ rc = osmo_get_rand_id(_rand, 16);
+ if (rc < 0) {
+ fprintf(stderr, "\nError: unable to obtain secure random numbers: %s!\n",
+ strerror(-rc));
+ exit(3);
}
}