stun: Add implementation using OpenSSL for rand/SHA1/MD5
authorBrendan Shanks <brendan.shanks@teradek.com>
Thu, 10 May 2018 00:18:44 +0000 (17:18 -0700)
committerOlivier CrĂȘte <olivier.crete@collabora.com>
Sun, 21 Oct 2018 07:32:15 +0000 (03:32 -0400)
stun/Makefile.am
stun/rand.c
stun/stunhmac.c

index c9b0cb2..9afcc75 100644 (file)
@@ -15,6 +15,7 @@ AM_CFLAGS = \
        -DG_LOG_DOMAIN=\"libnice-stun\" \
        $(LIBNICE_CFLAGS) \
        $(GNUTLS_CFLAGS) \
+       $(OPENSSL_CFLAGS) \
        $(NULL)
 AM_CPPFLAGS = -I$(top_srcdir)
 
@@ -38,7 +39,7 @@ libstun_la_SOURCES = constants.h \
        usages/turn.c usages/turn.h \
        usages/timer.c usages/timer.h
 
-libstun_la_LIBADD = $(LIBRT) $(GNUTLS_LIBS)
+libstun_la_LIBADD = $(LIBRT) $(GNUTLS_LIBS) $(OPENSSL_LIBS)
 
 EXTRA_DIST = win32_common.h
 
index 25dc402..cc0927f 100644 (file)
@@ -68,6 +68,17 @@ void nice_RAND_nonce (uint8_t *dst, int len)
 }
 #else
 
+#ifdef HAVE_OPENSSL
+
+#include <openssl/rand.h>
+
+void nice_RAND_nonce (uint8_t *dst, int len)
+{
+  RAND_bytes (dst, len);
+}
+
+#else
+
 #include <sys/types.h>
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
@@ -77,4 +88,6 @@ void nice_RAND_nonce (uint8_t *dst, int len)
   gnutls_rnd (GNUTLS_RND_NONCE, dst, len);
 }
 
+#endif /* HAVE_OPENSSL */
+
 #endif /* _WIN32 */
index c1e5180..c7d1432 100644 (file)
 
 #include <string.h>
 #include <assert.h>
+
+#ifdef HAVE_OPENSSL
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#else
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
+#endif
 
 void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len, uint8_t *sha,
     const void *key, size_t keylen, int padding)
 {
   uint16_t fakelen = htons (msg_len);
   uint8_t pad_char[64] = {0};
+
+  assert (len >= 44u);
+
+#ifdef HAVE_OPENSSL
+{
+#ifdef NDEBUG
+#define TRY(x) x;
+#else
+  int ret;
+#define TRY(x)                                  \
+  ret = x;                                      \
+  assert (ret == 1);
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  HMAC_CTX stackctx;
+  HMAC_CTX *ctx = &stackctx;
+  HMAC_CTX_init (ctx);
+#else
+  HMAC_CTX *ctx = HMAC_CTX_new ();
+#endif /* OPENSSL_VERSION_NUMBER */
+
+  assert (SHA_DIGEST_LENGTH == 20);
+
+  TRY (HMAC_Init_ex (ctx, key, keylen, EVP_sha1(), NULL));
+
+  TRY (HMAC_Update (ctx, msg, 2));
+  TRY (HMAC_Update (ctx, (unsigned char *)&fakelen, 2));
+  TRY (HMAC_Update (ctx, msg + 4, len - 28));
+
+  /* RFC 3489 specifies that the message's size should be 64 bytes,
+     and \x00 padding should be done */
+  if (padding && ((len - 24) % 64) > 0) {
+    uint16_t pad_size = 64 - ((len - 24) % 64);
+
+    TRY (HMAC_Update (ctx, pad_char, pad_size));
+  }
+
+  TRY (HMAC_Final (ctx, sha, NULL));
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  HMAC_CTX_cleanup (ctx);
+#else
+  HMAC_CTX_free (ctx);
+#endif /* OPENSSL_VERSION_NUMBER */
+}
+#else
+{
   gnutls_hmac_hd_t handle;
 
 #ifdef NDEBUG
@@ -66,8 +120,6 @@ void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len, uint8_t *sha,
   assert (ret >= 0);
 #endif
 
-  assert (len >= 44u);
-
   assert (gnutls_hmac_get_len (GNUTLS_MAC_SHA1) == 20);
   TRY (gnutls_hmac_init (&handle, GNUTLS_MAC_SHA1, key, keylen));
 
@@ -87,6 +139,8 @@ void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len, uint8_t *sha,
 
 #undef TRY
 }
+#endif /* HAVE_OPENSSL */
+}
 
 static const uint8_t *priv_trim_var (const uint8_t *var, size_t *var_len)
 {
@@ -114,6 +168,31 @@ void stun_hash_creds (const uint8_t *realm, size_t realm_len,
   const uint8_t *password_trimmed = priv_trim_var (password, &password_len);
   const uint8_t *realm_trimmed = priv_trim_var (realm, &realm_len);
   const uint8_t *colon = (uint8_t *)":";
+
+#ifdef HAVE_OPENSSL
+  EVP_MD_CTX *ctx;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  ctx = EVP_MD_CTX_create ();
+#else
+  ctx = EVP_MD_CTX_new ();
+#endif /* OPENSSL_VERSION_NUMBER */
+
+  EVP_DigestInit_ex (ctx, EVP_md5(), NULL);
+  EVP_DigestUpdate (ctx, username_trimmed, username_len);
+  EVP_DigestUpdate (ctx, colon, 1);
+  EVP_DigestUpdate (ctx, realm_trimmed, realm_len);
+  EVP_DigestUpdate (ctx, colon, 1);
+  EVP_DigestUpdate (ctx, password_trimmed, password_len);
+  EVP_DigestFinal_ex (ctx, md5, NULL);
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  EVP_MD_CTX_destroy (ctx);
+#else
+  EVP_MD_CTX_free (ctx);
+#endif /* OPENSSL_VERSION_NUMBER */
+
+#else
   gnutls_hash_hd_t handle;
 
   gnutls_hash_init (&handle, GNUTLS_DIG_MD5);
@@ -124,6 +203,7 @@ void stun_hash_creds (const uint8_t *realm, size_t realm_len,
   gnutls_hash (handle, password_trimmed, password_len);
 
   gnutls_hash_deinit (handle, md5);
+#endif /* HAVE_OPENSSL */
 }