/soc/2015/mmcc/rand: b7dd584225be: Initial addition of a randomn...

Michael McConville mmcconville at mykolab.com
Fri Aug 14 18:34:50 EDT 2015


Changeset: b7dd584225bed9a28e210d9a2907778662036511
Author:	 Michael McConville <mmcconville at mykolab.com>
Date:	 2015-08-14 18:34 -0400
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/mmcc/rand/rev/b7dd584225be

Description:

Initial addition of a randomness API. The next steps are:

 * make the /dev/urandrom read logic a little less fail-happy
 * sweep through the tree, replacing all creative randomness methods

Optionally, we can add libgcrypt support for those without SSL libraries, and
(more optionally) arc4random(), getrandom() et al. support for kernels with
randomness syscalls.

diffstat:

 libpurple/plugins/ssl/ssl-gnutls.c  |   8 ++++++++
 libpurple/plugins/ssl/ssl-nss.c     |   7 +++++++
 libpurple/protocols/jabber/jabber.c |   5 ++++-
 libpurple/sslconn.c                 |   8 ++++++++
 libpurple/sslconn.h                 |  22 +++++++++++++++++++++-
 libpurple/util.c                    |  32 ++++++++++++++++++++++++++++++++
 libpurple/util.h                    |  17 +++++++++++++++++
 7 files changed, 97 insertions(+), 2 deletions(-)

diffs (211 lines):

diff --git a/libpurple/plugins/ssl/ssl-gnutls.c b/libpurple/plugins/ssl/ssl-gnutls.c
--- a/libpurple/plugins/ssl/ssl-gnutls.c
+++ b/libpurple/plugins/ssl/ssl-gnutls.c
@@ -31,6 +31,7 @@
 
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
+#include <gnutls/crypto.h>
 
 typedef struct
 {
@@ -1367,6 +1368,12 @@ static PurpleCertificateScheme x509_gnut
 
 };
 
+static int
+ssl_gnutls_rand_bytes(void *buf, size_t len)
+{
+	return gnutls_rnd(GNUTLS_RND_RANDOM, buf, len);
+}
+
 static PurpleSslOps ssl_ops =
 {
 	ssl_gnutls_init,
@@ -1376,6 +1383,7 @@ static PurpleSslOps ssl_ops =
 	ssl_gnutls_read,
 	ssl_gnutls_write,
 	ssl_gnutls_get_peer_certificates,
+	ssl_gnutls_rand_bytes,
 
 	/* padding */
 	NULL,
diff --git a/libpurple/plugins/ssl/ssl-nss.c b/libpurple/plugins/ssl/ssl-nss.c
--- a/libpurple/plugins/ssl/ssl-nss.c
+++ b/libpurple/plugins/ssl/ssl-nss.c
@@ -1208,6 +1208,12 @@ static PurpleCertificateScheme x509_nss 
 	NULL
 };
 
+static int
+ssl_nss_rand_bytes(void *buf, size_t len)
+{
+	return (int)PK11_GenerateRandom(buf, len);
+}
+
 static PurpleSslOps ssl_ops =
 {
 	ssl_nss_init,
@@ -1217,6 +1223,7 @@ static PurpleSslOps ssl_ops =
 	ssl_nss_read,
 	ssl_nss_write,
 	ssl_nss_peer_certs,
+	ssl_nss_rand_bytes,
 
 	/* padding */
 	NULL,
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -659,11 +659,14 @@ jabber_recv_cb_ssl(gpointer data, Purple
 {
 	PurpleConnection *gc = data;
 	JabberStream *js = purple_connection_get_protocol_data(gc);
-	int len;
+	int len, x, err;
 	static char buf[4096];
 
 	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
 
+	err = purple_util_random((void*)&x, sizeof(int));
+	purple_debug_error("MIKE", "err: %d - data: %x", err, x);
+
 	while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) {
 		purple_connection_update_last_received(gc);
 		buf[len] = '\0';
diff --git a/libpurple/sslconn.c b/libpurple/sslconn.c
--- a/libpurple/sslconn.c
+++ b/libpurple/sslconn.c
@@ -293,6 +293,14 @@ purple_ssl_get_peer_certificates(PurpleS
 	return (ops->get_peer_certificates)(gsc);
 }
 
+int
+purple_ssl_rand_bytes(void *buf, size_t len)
+{
+	PurpleSslOps *ops;
+	ops = purple_ssl_get_ops();
+	return (ops->rand_bytes)(buf, len);
+}
+
 void
 purple_ssl_set_ops(PurpleSslOps *ops)
 {
diff --git a/libpurple/sslconn.h b/libpurple/sslconn.h
--- a/libpurple/sslconn.h
+++ b/libpurple/sslconn.h
@@ -118,6 +118,11 @@ struct _PurpleSslConnection
  *                         <sbr/>@gsc:    Connection context
  *                         <sbr/>Returns: A newly allocated list containing the
  *                                        certificates the peer provided.
+ * @rand_bytes: Writes quality random data.
+ *         See purple_ssl_write().
+ *         <sbr/>@buf:    Data buffer to write data to
+ *         <sbr/>@len:    Number of bytes to write to the buffer
+ *         <sbr/>Returns: Zero on success, non-zero on error
  *
  * SSL implementation operations structure.
  *
@@ -133,10 +138,10 @@ struct _PurpleSslOps
 	void (*close)(PurpleSslConnection *gsc);
 	size_t (*read)(PurpleSslConnection *gsc, void *data, size_t len);
 	size_t (*write)(PurpleSslConnection *gsc, const void *data, size_t len);
-
 	/* TODO Decide whether the ordering of certificates in this list can be
 	        guaranteed. */
 	GList * (* get_peer_certificates)(PurpleSslConnection * gsc);
+	int (*rand_bytes)(void *buf, size_t len);
 
 	/*< private >*/
 	void (*_purple_reserved1)(void);
@@ -304,6 +309,21 @@ size_t purple_ssl_write(PurpleSslConnect
 GList * purple_ssl_get_peer_certificates(PurpleSslConnection *gsc);
 
 /**************************************************************************/
+/* Random data API                                                        */
+/**************************************************************************/
+
+/**
+ * purple_ssl_get_rand_bytes:
+ * @buf:    Data buffer to write data to
+ * @len:    Number of bytes to write to the buffer
+ *
+ * Writes quality random data.
+ *
+ * Returns: Zero on success, non-zero on error.
+ */
+int purple_ssl_rand_bytes(void *buf, size_t len);
+
+/**************************************************************************/
 /* Subsystem API                                                          */
 /**************************************************************************/
 
diff --git a/libpurple/util.c b/libpurple/util.c
--- a/libpurple/util.c
+++ b/libpurple/util.c
@@ -4988,6 +4988,38 @@ int
 	return ret;
 }
 
+int
+purple_util_random(void *buf, size_t len)
+{
+	int fd;
+	ssize_t res;
+	PurpleSslOps *ops = purple_ssl_get_ops();
+
+	/* use SSL API if possible... */
+	if (ops && ops->rand_bytes) {
+		return (ops->rand_bytes)(buf, len);
+	/* ...otherwise, fall back to /dev/urandom */
+	} else {
+		fd = open("/dev/urandom", O_RDONLY);
+		if (fd < 0) {
+			purple_debug_error("purple_random",
+					"could not open /dev/urandom: %s", g_strerror(errno));
+			return 1;
+		}
+		res = read(fd, buf, len);
+		if (res < 0) {
+			purple_debug_error("purple_random",
+					"/dev/urandom read failed: %s", g_strerror(errno));
+			return 1;
+		/* redundant condition to guard against overflow on cast */
+		} else if (res >= 0 && (size_t)res != len) {
+			purple_debug_error("purple_random", "/dev/urandom read returned too little data");
+			return 1;
+		}
+		return 0;
+	}
+}
+
 #if 0
 
 /* Temporarily removed - re-add this when you need ini file support. */
diff --git a/libpurple/util.h b/libpurple/util.h
--- a/libpurple/util.h
+++ b/libpurple/util.h
@@ -1610,6 +1610,23 @@ gchar *purple_http_digest_calculate_resp
 		const gchar *nonce_count, const gchar *client_nonce,
 		const gchar *session_key);
 
+
+/**************************************************************************/
+/* Randomness Functions                                                   */
+/**************************************************************************/
+
+/**
+ * purple_util_random:
+ * @buf:  The buffer to write to
+ * @len:  The number of bytes to write
+ *
+ * Writes quality random data to a buffer. Safe for cryptographic use.
+ * All random data used should be obtained from this function!
+ *
+ * Returns:  Zero on success, non-zero on failure.
+ */
+int purple_util_random(void *buf, size_t len);
+
 G_END_DECLS
 
 #endif /* _PURPLE_UTIL_H_ */



More information about the Commits mailing list