blob: cf9b5cac0b621d9c986397876074a8b27cf6d85c [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*========================================================================
*/
#include "DiffieHellman.hpp"
#include "../Log.hpp"
#include "../ExceptionTypes.hpp"
#include "../SystemProperties.hpp"
#include <ace/Guard_T.h>
namespace gemfire {
ACE_DLL DiffieHellman::m_dll;
bool DiffieHellman::m_inited = false;
ACE_Recursive_Thread_Mutex DiffieHellman::s_mutex;
#define INIT_DH_FUNC_PTR(OrigName) \
DiffieHellman::OrigName##_Type DiffieHellman::OrigName##_Ptr = NULL;
INIT_DH_FUNC_PTR(gf_initDhKeys)
INIT_DH_FUNC_PTR(gf_clearDhKeys)
INIT_DH_FUNC_PTR(gf_getPublicKey)
INIT_DH_FUNC_PTR(gf_setPublicKeyOther)
INIT_DH_FUNC_PTR(gf_computeSharedSecret)
INIT_DH_FUNC_PTR(gf_encryptDH)
INIT_DH_FUNC_PTR(gf_decryptDH)
INIT_DH_FUNC_PTR(gf_verifyDH)
void* DiffieHellman::getOpenSSLFuncPtr(const char* function_name) {
void* func = m_dll.symbol( function_name );
if ( func == NULL ) {
char msg[1000];
ACE_OS::snprintf( msg, 1000, "cannot find function %s in library %s", function_name, "cryptoImpl" );
LOGERROR(msg);
throw IllegalStateException( msg );
}
return func;
}
void DiffieHellman::initOpenSSLFuncPtrs(){
if (DiffieHellman::m_inited) {
return;
}
const char* libName = "cryptoImpl";
if ( m_dll.open( libName, ACE_DEFAULT_SHLIB_MODE, 0 ) == -1 ) {
char msg[1000];
ACE_OS::snprintf( msg, 1000, "cannot open library: %s", libName );
LOGERROR(msg);
throw FileNotFoundException( msg );
}
#define ASSIGN_DH_FUNC_PTR(OrigName) \
OrigName##_Ptr = (OrigName##_Type)getOpenSSLFuncPtr(#OrigName);
ASSIGN_DH_FUNC_PTR(gf_initDhKeys)
ASSIGN_DH_FUNC_PTR(gf_clearDhKeys)
ASSIGN_DH_FUNC_PTR(gf_getPublicKey)
ASSIGN_DH_FUNC_PTR(gf_setPublicKeyOther)
ASSIGN_DH_FUNC_PTR(gf_computeSharedSecret)
ASSIGN_DH_FUNC_PTR(gf_encryptDH)
ASSIGN_DH_FUNC_PTR(gf_decryptDH)
ASSIGN_DH_FUNC_PTR(gf_verifyDH)
DiffieHellman::m_inited = true;
}
void DiffieHellman::initDhKeys(const PropertiesPtr & props) {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(DiffieHellman::s_mutex);
m_dhCtx = NULL;
CacheableStringPtr dhAlgo = props->find(SecurityClientDhAlgo);
CacheableStringPtr ksPath = props->find(SecurityClientKsPath);
//Null check only for DH Algo
if (dhAlgo == NULLPTR) {
LOGFINE("DH algo not available");
return;
}
int error = gf_initDhKeys_Ptr(&m_dhCtx, dhAlgo->asChar(), ksPath != NULLPTR ? ksPath->asChar() : NULL);
if(error == DH_ERR_UNSUPPORTED_ALGO ) { // Unsupported Algorithm
char msg[64] = {'\0'};
ACE_OS::snprintf(msg, 64, "Algorithm %s is not supported.",dhAlgo->asChar());
throw IllegalArgumentException(msg);
} else if (error == DH_ERR_ILLEGAL_KEYSIZE ) { // Illegal Key size
char msg[64] = {'\0'};
ACE_OS::snprintf(msg,64, "Illegal key size for algorithm %s.",dhAlgo->asChar());
throw IllegalArgumentException(msg);
} else if (m_dhCtx == NULL) {
throw IllegalStateException("Could not initialize the Diffie-Hellman helper");
}
}
void DiffieHellman::clearDhKeys(void) {
//Sanity check for accidental calls
if(gf_clearDhKeys_Ptr == NULL) {
return;
}
gf_clearDhKeys_Ptr(m_dhCtx);
m_dhCtx = NULL;
/*
//reset all pointers
#define CLEAR_DH_FUNC_PTR(OrigName) \
OrigName##_Ptr = NULL;
CLEAR_DH_FUNC_PTR(gf_initDhKeys)
CLEAR_DH_FUNC_PTR(gf_clearDhKeys)
CLEAR_DH_FUNC_PTR(gf_getPublicKey)
CLEAR_DH_FUNC_PTR(gf_setPublicKeyOther)
CLEAR_DH_FUNC_PTR(gf_computeSharedSecret)
CLEAR_DH_FUNC_PTR(gf_encryptDH)
CLEAR_DH_FUNC_PTR(gf_verifyDH)
*/
return;
}
CacheableBytesPtr DiffieHellman::getPublicKey(void) {
int keyLen = 0;
unsigned char* pubKeyPtr = gf_getPublicKey_Ptr(m_dhCtx, &keyLen);
return CacheableBytes::createNoCopy(pubKeyPtr,keyLen);
}
void DiffieHellman::setPublicKeyOther(const CacheableBytesPtr & pubkey) {
return gf_setPublicKeyOther_Ptr(m_dhCtx, pubkey->value(),pubkey->length());
}
void DiffieHellman::computeSharedSecret(void) {
return gf_computeSharedSecret_Ptr(m_dhCtx);
}
CacheableBytesPtr DiffieHellman::encrypt(const CacheableBytesPtr & cleartext) {
return encrypt(cleartext->value(), cleartext->length());
}
CacheableBytesPtr DiffieHellman::encrypt(const uint8_t * cleartext, int len) {
int cipherLen = 0;
unsigned char* ciphertextPtr = gf_encryptDH_Ptr(m_dhCtx, cleartext, len, &cipherLen);
return CacheableBytes::createNoCopy(ciphertextPtr,cipherLen);
}
CacheableBytesPtr DiffieHellman::decrypt(const CacheableBytesPtr & cleartext) {
return decrypt(cleartext->value(), cleartext->length());
}
CacheableBytesPtr DiffieHellman::decrypt(const uint8_t * cleartext, int len) {
int cipherLen = 0;
unsigned char* ciphertextPtr = gf_decryptDH_Ptr(m_dhCtx, cleartext, len, &cipherLen);
return CacheableBytes::createNoCopy(ciphertextPtr,cipherLen);
}
bool DiffieHellman::verify( const CacheableStringPtr & subject,
const CacheableBytesPtr & challenge,
const CacheableBytesPtr & response) {
int errCode = DH_ERR_NO_ERROR;
LOGDEBUG("DiffieHellman::verify");
bool result = gf_verifyDH_Ptr( m_dhCtx, subject->asChar(), challenge->value(), challenge->length(),
response->value(), response->length(),&errCode);
LOGDEBUG("DiffieHellman::verify 2");
if(errCode == DH_ERR_SUBJECT_NOT_FOUND ) {
LOGERROR("Subject name %s not found in imported certificates.",subject->asChar());
}else if(errCode == DH_ERR_NO_CERTIFICATES ) {
LOGERROR("No imported certificates.");
}else if(errCode == DH_ERR_INVALID_SIGN ) {
LOGERROR("Signature varification failed.");
}
return result;
}
}; // namespace gemfire