diff options
Diffstat (limited to 'src/gsm')
-rw-r--r-- | src/gsm/gsm_utils.c | 48 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 1 |
2 files changed, 49 insertions, 0 deletions
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; |