Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use crypto safe random numbers #2738

Merged
merged 21 commits into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,8 @@ AS_IF([test "x$enable_post_processing" = "xyes"],
[
glib-2.0 >= $glib_version
jansson >= $jansson_version
libssl >= $ssl_version
libcrypto
libavutil
libavcodec
libavformat
Expand Down
5 changes: 5 additions & 0 deletions fuzzers/rtcp_fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ gboolean janus_log_colors = FALSE;
char *janus_log_global_prefix = NULL;
int lock_debug = 0;

/* This is to avoid linking with openSSL */
int RAND_bytes(uint8_t *key, int len) {
return 0;
}

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
/* Sanity Checks */
/* Max UDP payload with MTU=1500 */
Expand Down
5 changes: 5 additions & 0 deletions fuzzers/sdp_fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ char *janus_log_global_prefix = NULL;
int lock_debug = 0;
int refcount_debug = 0;

/* This is to avoid linking with openSSL */
int RAND_bytes(uint8_t *key, int len) {
return 0;
}

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
/* Since we're fuzzing SDP, and that in our case SDP always comes
* from a Jansson call, this will need to be a valid string */
Expand Down
5 changes: 5 additions & 0 deletions janus.c
Original file line number Diff line number Diff line change
Expand Up @@ -4996,6 +4996,11 @@ gint main(int argc, char *argv[])
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* check if random pool looks ok (this does not give any guarantees for later, though) */
if(RAND_status() != 1) {
JANUS_LOG(LOG_FATAL, "\tOpenSSL PRNG is not properly seeded, cannot generate random numbers\n");
exit(1);
}
/* ... and DTLS-SRTP in particular */
const char *dtls_ciphers = NULL;
item = janus_config_get(config, config_certs, janus_config_type_item, "dtls_ciphers");
Expand Down
5 changes: 0 additions & 5 deletions plugins/janus_nosip.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,11 +786,6 @@ int janus_nosip_init(janus_callbacks *callback, const char *config_path) {
}
JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);

#ifdef HAVE_SRTP_2
/* Init randomizer (for randum numbers in SRTP) */
RAND_poll();
#endif

sessions = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)janus_nosip_session_destroy);
messages = g_async_queue_new_full((GDestroyNotify) janus_nosip_message_free);
/* This is the callback we'll need to invoke to contact the Janus core */
Expand Down
5 changes: 0 additions & 5 deletions plugins/janus_sip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1924,11 +1924,6 @@ int janus_sip_init(janus_callbacks *callback, const char *config_path) {
}
JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);

#ifdef HAVE_SRTP_2
/* Init randomizer (for randum numbers in SRTP) */
RAND_poll();
#endif

/* Setup sofia */
su_init();
if(notify_events && callback->events_is_enabled()) {
Expand Down
35 changes: 19 additions & 16 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <inttypes.h>

#include <zlib.h>
#include <openssl/rand.h>

#include "utils.h"
#include "debug.h"
Expand Down Expand Up @@ -71,23 +72,25 @@ gboolean janus_strcmp_const_time(const void *str1, const void *str2) {
}

guint32 janus_random_uint32(void) {
return g_random_int();
guint32 ret = 0;
if (RAND_bytes((void *)&ret, sizeof(ret)) != 1) {
JANUS_LOG(LOG_FATAL, "\tOpenSSL RAND_bytes() failed\n");
exit(1);
}
return ret;
}

guint64 janus_random_uint64_full(void) {
guint64 ret = 0;
if (RAND_bytes((void *)&ret, sizeof(ret)) != 1) {
JANUS_LOG(LOG_FATAL, "\tOpenSSL RAND_bytes() failed\n");
exit(1);
}
return ret;
}

guint64 janus_random_uint64(void) {
/*
* FIXME This needs to be improved, and use something that generates
* more strongly random stuff... using /dev/urandom is probably not
* a good idea, as we don't want to make it harder to cross compile Janus
*
* TODO Look into what libssl and/or libcrypto provide in that respect
*
* PS: JavaScript only supports integer up to 2^53, so we need to
* make sure the number is below 9007199254740992 for safety
*/
guint64 num = g_random_int() & 0x1FFFFF;
num = (num << 32) | g_random_int();
return num;
return janus_random_uint64_full() & 0x1FFFFFFFFFFFFF;
}

char *janus_random_uuid(void) {
Expand All @@ -100,8 +103,8 @@ char *janus_random_uuid(void) {
const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
const char *samples = "0123456789abcdef";
union { unsigned char b[16]; uint64_t word[2]; } rnd;
rnd.word[0] = janus_random_uint64();
rnd.word[1] = janus_random_uint64();
rnd.word[0] = janus_random_uint64_full();
rnd.word[1] = janus_random_uint64_full();
/* Generate the string */
char uuid[37], *dst = uuid;
const char *p = template;
Expand Down
20 changes: 17 additions & 3 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,29 @@ gboolean janus_strcmp_const_time(const void *str1, const void *str2);

/*! \brief Helper to generate random 32-bit unsigned integers (useful for SSRCs, etc.)
* @note Currently just wraps g_random_int()
* @returns A random 32-bit unsigned integer */
* @returns A (crypto-safe) random 32-bit unsigned integer */
guint32 janus_random_uint32(void);

/*! \brief Helper to generate random 64-bit unsigned integers (useful for Janus IDs)
/*! \brief Helper to generate random 64-bit unsigned integers
* @note Unlike janus_random_uint64(), which actually only generates 52 bits, this
* generates the full 64 bits. See the janus_random_uint64() docstring for details.
* @returns A random 64-bit unsigned integer */
guint64 janus_random_uint64_full(void);

/*! \brief Helper to generate random 52 bit unsigned integers
* @note The reason for 52 instead of 64 bits: Javascript does not have real integers,
* its builtin "number" type is a float64. Thus, only integer values up to
* Number.MAX_SAFE_INTEGER == 2^53 - 1 == 9007199254740991
* can be safely represented in Javascript. This method returns such numbers.
* Use this method instead of janus_random_uint64_full() whenever you generate numbers which
* might end up in Javascript (via JSON API).
* This method is called janus_random_uint64() instead of janus_random_uint52() (or similar)
* for backwards compatibility.
* @returns A (crypto-safe) random 64-bit unsigned integer */
guint64 janus_random_uint64(void);

/*! \brief Helper to generate random UUIDs (needed by some plugins)
* @returns A random UUID string, which must be deallocated with \c g_free */
* @returns A (crypto-safe) random UUID string, which must be deallocated with \c g_free */
char *janus_random_uuid(void);

/*! \brief Helper to generate an allocated copy of a guint64 number
Expand Down