unfinished changes to allow use of native crypto libraries (MacOS X should be built...
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 30 Nov 2016 21:16:52 +0000 (23:16 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 30 Nov 2016 21:16:52 +0000 (23:16 +0200)
configure.ac
include/nms_common.h
include/nxcpapi.h
include/nxcrypto.h [new file with mode: 0644]
src/libnetxms/crypto.cpp
src/libnetxms/libnetxms.h

index 1dbae85..041f788 100644 (file)
@@ -107,6 +107,8 @@ LIBVIRT_BASE=""
 DISABLE_IPV6="no"
 IPV6_SUPPORT="no"
 INSTALL_LIBPATH=""
+WITH_ENCRYPTION="no"
+DISABLE_COMMONCRYPTO="no"
 OPENSSL_LIBSSL="ssl"
 OPENSSL_LIBCRYPTO="crypto"
 
@@ -484,6 +486,14 @@ AC_ARG_WITH(openssl,
        fi
 ])
 
+AC_ARG_ENABLE(commoncrypto,
+[AS_HELP_STRING(--disable-commoncrypto,disable CommonCrypto usage on Mac OS X)],
+[
+       if test "x$enableval" = "xno"; then
+               DISABLE_COMMONCRYPTO="yes"
+       fi
+])
+
 AC_ARG_WITH(bundled-openssl,
 [AS_HELP_STRING(--with-bundled-openssl,use bundled OpenSSL libraries with product-specific prefix)],
 [
@@ -1535,30 +1545,41 @@ fi
 
 
 #--------------------------------------------------------------------
-# Checks for OpenSSL
+# Checks for OpenSSL/CommonCrypto
 #--------------------------------------------------------------------
 
 if test "x$DISABLE_ENCRYPTION" != "xyes" ; then
-       AC_CHECK_LIB($OPENSSL_LIBCRYPTO, RSA_new,
-               [
-                       AC_DEFINE(WITH_OPENSSL, 1, Define to 1 if you have OpenSSL library and headers)
-                       AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_aes_256_cbc,
-                                                        [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_AES,,[desc])])
-                       AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_bf_cbc,
-                                                        [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_BF,,[desc])])
-                       AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_idea_cbc,
-                                                        [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_IDEA,,[desc])])
-                       AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_des_ede3_cbc,
-                                                        [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_DES,,[desc])])
-                       if test "x$HAVE_LIBCRYPTO" = "xyes"; then
-                               LIBS="$LIBS -l$OPENSSL_LIBSSL -l$OPENSSL_LIBCRYPTO"
-                       else
-                               AC_MSG_ERROR(lib$OPENSSL_LIBCRYPTO does not provide any suitable encryption algorithm)
-                       fi
-               ],
-               [
-                       AC_MSG_ERROR(lib$OPENSSL_LIBCRYPTO is required for encryption support)
+       USE_COMMONCRYPTO="no"
+       if test "x$PLATFORM" = "xDarwin" -a "x$DISABLE_COMMONCRYPTO" != "xyes"; then
+               AC_CHECK_FUNC(CC_MD5_Init, [ 
+                       AC_DEFINE(WITH_COMMONCRYPTO, 1, Define to 1 if you have CommonCrypto library and headers)
+                       USE_COMMONCRYPTO="yes"
+                       WITH_ENCRYPTION="yes"
                ])
+       fi
+       if test "x$USE_COMMONCRYPTO" != "xyes"; then
+               AC_CHECK_LIB($OPENSSL_LIBCRYPTO, RSA_new,
+                       [
+                               AC_DEFINE(WITH_OPENSSL, 1, Define to 1 if you have OpenSSL library and headers)
+                               AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_aes_256_cbc,
+                                                                [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_AES,,[desc])])
+                               AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_bf_cbc,
+                                                                [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_BF,,[desc])])
+                               AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_idea_cbc,
+                                                                [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_IDEA,,[desc])])
+                               AC_CHECK_LIB($OPENSSL_LIBCRYPTO, EVP_des_ede3_cbc,
+                                                                [HAVE_LIBCRYPTO="yes"], [AC_DEFINE(NETXMS_NO_DES,,[desc])])
+                               if test "x$HAVE_LIBCRYPTO" = "xyes"; then
+                                       WITH_ENCRYPTION="yes"
+                                       LIBS="$LIBS -l$OPENSSL_LIBSSL -l$OPENSSL_LIBCRYPTO"
+                               else
+                                       AC_MSG_ERROR(lib$OPENSSL_LIBCRYPTO does not provide any suitable encryption algorithm)
+                               fi
+                       ],
+                       [
+                               AC_MSG_ERROR(lib$OPENSSL_LIBCRYPTO is required for encryption support)
+                       ])
+       fi
 fi
 
 
@@ -3092,7 +3113,7 @@ AM_CONDITIONAL([USE_INTERNAL_SQLITE], [test "x$HAVE_SQLITE" = "xno"])
 AM_CONDITIONAL([USE_INTERNAL_ZLIB], [test "$HAVE_ZLIB" = "no"])
 AM_CONDITIONAL([STATIC_BUILD], [test "x$STATIC_BUILD" = "xyes"])
 AM_CONDITIONAL([ALL_STATIC], [test "x$ALL_STATIC" = "xyes"])
-AM_CONDITIONAL([USE_ENCRYPTION], [test "x${HAVE_LIBCRYPTO}" = "xyes"])
+AM_CONDITIONAL([USE_ENCRYPTION], [test "x${WITH_ENCRYPTION}" = "xyes"])
 AM_CONDITIONAL([HPUX_HPPA], [test "x$HPUX_HPPA" = "xyes"])
 AM_CONDITIONAL([XMPP_SUPPORT], [test "x$XMPP_SUPPORT" = "xyes"])
 AM_CONDITIONAL([ZEROMQ_SUPPORT], [test "x$ZEROMQ_SUPPORT" = "xyes"])
@@ -3486,7 +3507,7 @@ if test "x${BUILD_SERVER}" = "xyes"; then
 else
        echo "Build Server            : NO"
 fi
-if test "x${HAVE_LIBCRYPTO}" = "xyes"; then
+if test "x${WITH_ENCRYPTION}" = "xyes"; then
        echo "Encryption enabled      : YES"
 else
        echo "Encryption enabled      : NO"
index 4e066d1..6a59af4 100644 (file)
@@ -42,7 +42,7 @@
 #include <config-netware.h>
 #else
 #include <config.h>
-#ifdef WITH_OPENSSL
+#if defined(WITH_OPENSSL) || defined(WITH_COMMONCRYPTO)
 #define _WITH_ENCRYPTION   1
 #endif
 #endif
@@ -779,56 +779,6 @@ typedef struct hostent HOSTENT;
 #endif
 
 /**
- * OpenSSL
- */
-#if defined(_WITH_ENCRYPTION) && !defined(ORA_PROC)
-
-#include <openssl/crypto.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
-
-#ifdef NETXMS_NO_AES
-#ifndef OPENSSL_NO_AES
-#define OPENSSL_NO_AES
-#endif
-#endif
-
-#ifdef NETXMS_NO_BF
-#ifndef OPENSSL_NO_BF
-#define OPENSSL_NO_BF
-#endif
-#endif
-
-#ifdef NETXMS_NO_IDEA
-#ifndef OPENSSL_NO_IDEA
-#define OPENSSL_NO_IDEA
-#endif
-#endif
-
-#ifdef NETXMS_NO_DES
-#ifndef OPENSSL_NO_DES
-#define OPENSSL_NO_DES
-#endif
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= 0x00907000
-#define OPENSSL_CONST const
-#else
-#define OPENSSL_CONST
-#endif
-
-#else
-
-// Prevent compilation errors on function prototypes
-#define RSA void
-
-#endif
-
-/**
  * open() flags compatibility
  */
 #ifndef O_BINARY
index eb63dfb..6b614d2 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <nms_util.h>
 #include <nms_threads.h>
+#include <nxcrypto.h>
 #include <uuid.h>
 
 #ifdef _WIN32
@@ -251,9 +252,14 @@ private:
        int m_keyLength;
        BYTE m_iv[EVP_MAX_IV_LENGTH];
 #ifdef _WITH_ENCRYPTION
+   MUTEX m_encryptorLock;
+#if WITH_OPENSSL
    EVP_CIPHER_CTX m_encryptor;
    EVP_CIPHER_CTX m_decryptor;
-   MUTEX m_encryptorLock;
+#elif WITH_COMMONCRYPTO
+   CCCryptorRef m_encryptor;
+   CCCryptorRef m_decryptor;
+#endif
 #endif
 
        NXCPEncryptionContext();
diff --git a/include/nxcrypto.h b/include/nxcrypto.h
new file mode 100644 (file)
index 0000000..8591c69
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _nxcrypto_h_
+#define _nxcrypto_h_
+
+#if defined(_WITH_ENCRYPTION) && !defined(ORA_PROC)
+
+#if WITH_OPENSSL
+
+#include <openssl/crypto.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/opensslv.h>
+#include <openssl/err.h>
+
+#ifdef NETXMS_NO_AES
+#ifndef OPENSSL_NO_AES
+#define OPENSSL_NO_AES
+#endif
+#endif
+
+#ifdef NETXMS_NO_BF
+#ifndef OPENSSL_NO_BF
+#define OPENSSL_NO_BF
+#endif
+#endif
+
+#ifdef NETXMS_NO_IDEA
+#ifndef OPENSSL_NO_IDEA
+#define OPENSSL_NO_IDEA
+#endif
+#endif
+
+#ifdef NETXMS_NO_DES
+#ifndef OPENSSL_NO_DES
+#define OPENSSL_NO_DES
+#endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000
+#define OPENSSL_CONST const
+#else
+#define OPENSSL_CONST
+#endif
+
+#elif WITH_COMMONCRYPTO
+
+#include <CommonCrypto/CommonCrypto.h>
+#include <Security/SecBase.h>
+#include <Security/SecKey.h>
+
+struct RSA
+{
+       SecKeyRef pubkey;
+       SecKeyRef privkey;
+};
+
+#endif
+
+#else /* no encryption */
+
+// Prevent compilation errors on function prototypes
+#define RSA void
+
+#endif
+
+#endif
index 9fe3965..4266cd6 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "libnetxms.h"
 #include "ice.h"
+#include <nxcpapi.h>
 
 /**
  * Constants
@@ -56,8 +57,9 @@ static UINT32 s_supportedCiphers =
  * Static data
  */
 static WORD s_noEncryptionFlag = 0;
+static const TCHAR *s_cipherNames[NETXMS_MAX_CIPHERS] = { _T("AES-256"), _T("Blowfish-256"), _T("IDEA"), _T("3DES"), _T("AES-128"), _T("Blowfish-128") };
 
-#ifdef _WITH_ENCRYPTION
+#if defined(_WITH_ENCRYPTION) && WITH_OPENSSL
 
 extern "C" typedef OPENSSL_CONST EVP_CIPHER * (*CIPHER_FUNC)();
 static CIPHER_FUNC s_ciphers[NETXMS_MAX_CIPHERS] =
@@ -93,7 +95,6 @@ static CIPHER_FUNC s_ciphers[NETXMS_MAX_CIPHERS] =
    NULL
 #endif
 };
-static const TCHAR *s_cipherNames[NETXMS_MAX_CIPHERS] = { _T("AES-256"), _T("Blowfish-256"), _T("IDEA"), _T("3DES"), _T("AES-128"), _T("Blowfish-128") };
 static MUTEX *s_cryptoMutexList = NULL;
 
 /**
@@ -125,8 +126,55 @@ static unsigned long CryptoIdCallback()
 
 #endif
 
+/**
+ * Create RSA key from binary representation
+ */
+RSA *RSAKeyFromData(const BYTE *data, size_t size, bool withPrivate)
+{
+   const BYTE *bp = data;
+   RSA *key = d2i_RSAPublicKey(NULL, (OPENSSL_CONST BYTE **)&bp, (int)size);
+   if ((key != NULL) && withPrivate)
+   {
+      if (d2i_RSAPrivateKey(&key, (OPENSSL_CONST BYTE **)&bp, (int)(size - CAST_FROM_POINTER((bp - data), size_t))) == NULL)
+      {
+         RSA_free(key);
+         key = NULL;
+      }
+   }
+   return key;
+}
+
+/**
+ * Destroy RSA key
+ */
+void RSAFree(RSA *key)
+{
+   RSA_free(key);
+}
+
 #endif   /* _WITH_ENCRYPTION */
 
+#if defined(_WITH_ENCRYPTION) && WITH_COMMONCRYPTO
+
+/**
+ * Create RSA key from binary representation
+ */
+RSA *RSAKeyFromData(const BYTE *data, size_t size, bool withPrivate)
+{
+   SecKeyCreateWithData(keyData, keyAttr);
+       return NULL;
+}
+
+/**
+ * Destroy RSA key
+ */
+void RSAFree(RSA *key)
+{
+   free(key);
+}
+
+#endif
+
 /**
  * Initialize OpenSSL library
  */
@@ -134,7 +182,7 @@ bool LIBNETXMS_EXPORTABLE InitCryptoLib(UINT32 dwEnabledCiphers)
 {
    s_noEncryptionFlag = htons(MF_DONT_ENCRYPT);
 
-#ifdef _WITH_ENCRYPTION
+#if _WITH_ENCRYPTION && WITH_OPENSSL
    BYTE random[8192];
    int i;
 
@@ -175,7 +223,8 @@ bool LIBNETXMS_EXPORTABLE InitCryptoLib(UINT32 dwEnabledCiphers)
    }
 
    nxlog_debug(1, _T("Crypto library initialized"));
-
+#elif _WITH_ENCRYPTION && WITH_COMMONCRYPTO
+   nxlog_debug(1, _T("Crypto library initialized"));
 #else
    nxlog_debug(1, _T("Crypto library will not be initialized because libnetxms was built without encryption support"));
 #endif   /* _WITH_ENCRYPTION */
@@ -272,9 +321,8 @@ UINT32 LIBNETXMS_EXPORTABLE SetupEncryptionContext(NXCPMessage *msg,
          if (*ppCtx != NULL)
          {
             // Encrypt key
-            int size = msg->getFieldAsBinary(VID_PUBLIC_KEY, ucKeyBuffer, KEY_BUFFER_SIZE);
-            pBufPos = ucKeyBuffer;
-            pServerKey = d2i_RSAPublicKey(NULL, (OPENSSL_CONST BYTE **)&pBufPos, size);
+            size_t size = msg->getFieldAsBinary(VID_PUBLIC_KEY, ucKeyBuffer, KEY_BUFFER_SIZE);
+            pServerKey = RSAKeyFromData(ucKeyBuffer, size, false);
             if (pServerKey != NULL)
             {
                (*ppResponse)->setField(VID_RCC, RCC_SUCCESS);
@@ -376,37 +424,24 @@ void LIBNETXMS_EXPORTABLE PrepareKeyRequestMsg(NXCPMessage *msg, RSA *pServerKey
 RSA LIBNETXMS_EXPORTABLE *LoadRSAKeys(const TCHAR *pszKeyFile)
 {
 #ifdef _WITH_ENCRYPTION
-   FILE *fp;
-   BYTE *pKeyBuffer, *pBufPos, hash[SHA1_DIGEST_SIZE];
-   UINT32 dwLen;
    RSA *pKey = NULL;
-
-   fp = _tfopen(pszKeyFile, _T("rb"));
+   FILE *fp = _tfopen(pszKeyFile, _T("rb"));
    if (fp != NULL)
    {
+      UINT32 dwLen;
       if (fread(&dwLen, 1, sizeof(UINT32), fp) == sizeof(UINT32) && dwLen < 10 * 1024)
       {
-         pKeyBuffer = (BYTE *)malloc(dwLen);
-         pBufPos = pKeyBuffer;
+         BYTE *pKeyBuffer = (BYTE *)malloc(dwLen);
          if (fread(pKeyBuffer, 1, dwLen, fp) == dwLen)
          {
-            BYTE hash2[SHA1_DIGEST_SIZE];
-
+            BYTE hash[SHA1_DIGEST_SIZE];
             if (fread(hash, 1, SHA1_DIGEST_SIZE, fp) == SHA1_DIGEST_SIZE)
             {
+               BYTE hash2[SHA1_DIGEST_SIZE];
                CalculateSHA1Hash(pKeyBuffer, dwLen, hash2);
                if (!memcmp(hash, hash2, SHA1_DIGEST_SIZE))
                {
-                  pKey = d2i_RSAPublicKey(NULL, (OPENSSL_CONST BYTE **)&pBufPos, dwLen);
-                  if (pKey != NULL)
-                  {
-                     if (d2i_RSAPrivateKey(&pKey, (OPENSSL_CONST BYTE **)&pBufPos,
-                                           dwLen - CAST_FROM_POINTER((pBufPos - pKeyBuffer), UINT32)) == NULL)
-                     {
-                        RSA_free(pKey);
-                        pKey = NULL;
-                     }
-                  }
+                  pKey = RSAKeyFromData(pKeyBuffer, dwLen, true);
                }
             }
          }
@@ -414,7 +449,6 @@ RSA LIBNETXMS_EXPORTABLE *LoadRSAKeys(const TCHAR *pszKeyFile)
       }
       fclose(fp);
    }
-
    return pKey;
 #else
    return NULL;
index 6bfcf08..e3cdfec 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <nms_common.h>
 #include <nms_util.h>
-#include <nxcpapi.h>
 #include <nxcldefs.h>
 
 #define MAX_CODEPAGE_LEN               64