summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOle André Vadla Ravnås <oleavr@gmail.com>2021-04-06 22:47:17 +0200
committerOlivier Crête <olivier.crete@ocrete.ca>2021-11-01 19:55:51 +0000
commit48a8a4983f68ba23b6f7b2b0ccbd60a3ab973d30 (patch)
treefb4efa560ffcf5bbb8951a1e88574e21ca8edc15
parent47a96334448838c43d7e72f4ef51b317befbfae1 (diff)
downloadlibnice-48a8a4983f68ba23b6f7b2b0ccbd60a3ab973d30.tar.gz
Use native crypto support on Windows by default
As we only need a few primitives there isn't much OS-specific code needed, and for applications that don't already depend on OpenSSL or GnuTLS it simplifies the build process quite a lot. Note that we use the vintage WinCrypt APIs as the Cryptography Next Generation APIs are only available on Vista and newer.
-rw-r--r--meson.build4
-rw-r--r--stun/rand.c15
-rw-r--r--stun/stunhmac.c92
3 files changed, 106 insertions, 5 deletions
diff --git a/meson.build b/meson.build
index e1d525e..30b565e 100644
--- a/meson.build
+++ b/meson.build
@@ -190,7 +190,9 @@ gthread_dep = dependency('gthread-2.0',
# Cryto library
opt_cryptolib = get_option('crypto-library')
message('Crypto library requested: ' + opt_cryptolib)
-if opt_cryptolib != 'openssl'
+if opt_cryptolib == 'auto' and host_machine.system() == 'windows'
+ crypto_dep = cc.find_library('advapi32')
+elif opt_cryptolib != 'openssl'
crypto_dep = dependency('gnutls', version: gnutls_req, required: false)
cdata.set('HAVE_GNUTLS', crypto_dep.found())
if not crypto_dep.found() and opt_cryptolib == 'auto'
diff --git a/stun/rand.c b/stun/rand.c
index 1361245..43d9149 100644
--- a/stun/rand.c
+++ b/stun/rand.c
@@ -39,7 +39,20 @@
#include "rand.h"
-#if defined(HAVE_OPENSSL)
+#if defined(_WIN32)
+
+#include <windows.h>
+
+void nice_RAND_nonce (uint8_t *dst, int len)
+{
+ HCRYPTPROV prov;
+
+ CryptAcquireContextW (&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ CryptGenRandom (prov, len, dst);
+ CryptReleaseContext (prov, 0);
+}
+
+#elif defined(HAVE_OPENSSL)
#include <openssl/rand.h>
diff --git a/stun/stunhmac.c b/stun/stunhmac.c
index c9d183f..b42fc2e 100644
--- a/stun/stunhmac.c
+++ b/stun/stunhmac.c
@@ -48,7 +48,14 @@
#include <string.h>
#include <assert.h>
-#ifdef HAVE_OPENSSL
+#if defined(_WIN32)
+#include <malloc.h>
+typedef struct _StunKeyBlob {
+ BLOBHEADER header;
+ DWORD key_size;
+ BYTE key_data[0];
+} StunKeyBlob;
+#elif defined(HAVE_OPENSSL)
#include <openssl/hmac.h>
#include <openssl/sha.h>
#else
@@ -64,7 +71,67 @@ void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len, uint8_t *sha,
assert (len >= 44u);
-#ifdef HAVE_OPENSSL
+#if defined(_WIN32)
+{
+ HCRYPTPROV prov;
+ size_t blob_size;
+ StunKeyBlob *blob;
+ BLOBHEADER *header;
+ HCRYPTKEY key_handle;
+ HCRYPTHASH hash;
+ HMAC_INFO info = {0};
+ DWORD sha_digest_len;
+
+#ifdef NDEBUG
+#define TRY(x) x;
+#else
+ BOOL success;
+#define TRY(x) \
+ success = x; \
+ assert (success);
+#endif
+
+ TRY (CryptAcquireContextW (&prov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT));
+
+ blob_size = sizeof (StunKeyBlob) + keylen;
+ blob = _malloca (blob_size);
+ header = &blob->header;
+ header->bType = PLAINTEXTKEYBLOB;
+ header->bVersion = CUR_BLOB_VERSION;
+ header->reserved = 0;
+ header->aiKeyAlg = CALG_RC2;
+ blob->key_size = keylen;
+ memcpy (blob->key_data, key, keylen);
+ TRY (CryptImportKey (prov, (const BYTE *) blob, blob_size, 0,
+ CRYPT_IPSEC_HMAC_KEY, &key_handle));
+ _freea (blob);
+
+ TRY (CryptCreateHash (prov, CALG_HMAC, key_handle, 0, &hash));
+
+ info.HashAlgid = CALG_SHA1;
+ TRY (CryptSetHashParam (hash, HP_HMAC_INFO, (const BYTE *) &info, 0));
+
+ TRY (CryptHashData (hash, msg, 2, 0));
+ TRY (CryptHashData (hash, (const BYTE *) &fakelen, 2, 0));
+ TRY (CryptHashData (hash, msg + 4, len - 28, 0));
+
+ /* 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 (CryptHashData (hash, pad_char, pad_size, 0));
+ }
+
+ sha_digest_len = 20;
+ TRY (CryptGetHashParam (hash, HP_HASHVAL, sha, &sha_digest_len, 0));
+
+ TRY (CryptDestroyHash (hash));
+ TRY (CryptDestroyKey (key_handle));
+ TRY (CryptReleaseContext (prov, 0));
+}
+#elif defined(HAVE_OPENSSL)
{
#ifdef NDEBUG
#define TRY(x) x;
@@ -171,7 +238,26 @@ void stun_hash_creds (const uint8_t *realm, size_t realm_len,
const uint8_t *realm_trimmed = priv_trim_var (realm, &realm_len);
const uint8_t *colon = (uint8_t *)":";
-#ifdef HAVE_OPENSSL
+#if defined(_WIN32)
+ HCRYPTPROV prov;
+ HCRYPTHASH hash;
+ DWORD md5_digest_len;
+
+ CryptAcquireContextW (&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ CryptCreateHash (prov, CALG_MD5, 0, 0, &hash);
+
+ CryptHashData (hash, username_trimmed, username_len, 0);
+ CryptHashData (hash, colon, 1, 0);
+ CryptHashData (hash, realm_trimmed, realm_len, 0);
+ CryptHashData (hash, colon, 1, 0);
+ CryptHashData (hash, password_trimmed, password_len, 0);
+
+ md5_digest_len = 16;
+ CryptGetHashParam (hash, HP_HASHVAL, md5, &md5_digest_len, 0);
+
+ CryptDestroyHash (hash);
+ CryptReleaseContext (prov, 0);
+#elif defined(HAVE_OPENSSL)
EVP_MD_CTX *ctx;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \