blob: fc0c81dc25103d16528ec821cb23a1b3e24c31ec [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DiffieHellman.hpp"
#include <ace/Guard_T.h>
#include <geode/ExceptionTypes.hpp>
#include <geode/SystemProperties.hpp>
#include "util/Log.hpp"
namespace apache {
namespace geode {
namespace client {
ACE_DLL DiffieHellman::m_dll;
#define INIT_DH_FUNC_PTR(OrigName) \
DiffieHellman::OrigName##_Type DiffieHellman::OrigName##_Ptr = nullptr;
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 == nullptr) {
char msg[1000];
std::snprintf(msg, 1000, "cannot find function %s in library %s",
function_name, "cryptoImpl");
LOGERROR(msg);
throw IllegalStateException(msg);
}
return func;
}
void DiffieHellman::initOpenSSLFuncPtrs() {
static bool inited = false;
if (inited) {
return;
}
const char* libName = "cryptoImpl";
if (m_dll.open(libName, ACE_DEFAULT_SHLIB_MODE, 0) == -1) {
char msg[1000];
std::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)
inited = true;
}
void DiffieHellman::initDhKeys(const std::shared_ptr<Properties>& props) {
m_dhCtx = nullptr;
const auto& dhAlgo = props->find(SecurityClientDhAlgo);
const auto& 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->value().c_str(),
ksPath != nullptr ? ksPath->value().c_str() : nullptr);
if (error == DH_ERR_UNSUPPORTED_ALGO) { // Unsupported Algorithm
char msg[64] = {'\0'};
std::snprintf(msg, 64, "Algorithm %s is not supported.",
dhAlgo->value().c_str());
throw IllegalArgumentException(msg);
} else if (error == DH_ERR_ILLEGAL_KEYSIZE) { // Illegal Key size
char msg[64] = {'\0'};
std::snprintf(msg, 64, "Illegal key size for algorithm %s.",
dhAlgo->value().c_str());
throw IllegalArgumentException(msg);
} else if (m_dhCtx == nullptr) {
throw IllegalStateException(
"Could not initialize the Diffie-Hellman helper");
}
}
void DiffieHellman::clearDhKeys(void) {
// Sanity check for accidental calls
if (gf_clearDhKeys_Ptr == nullptr) {
return;
}
gf_clearDhKeys_Ptr(m_dhCtx);
m_dhCtx = nullptr;
return;
}
std::shared_ptr<CacheableBytes> DiffieHellman::getPublicKey(void) {
int keyLen = 0;
auto pubKeyPtr = gf_getPublicKey_Ptr(m_dhCtx, &keyLen);
return CacheableBytes::create(
std::vector<int8_t>(pubKeyPtr, pubKeyPtr + keyLen));
}
void DiffieHellman::setPublicKeyOther(
const std::shared_ptr<CacheableBytes>& pubkey) {
return gf_setPublicKeyOther_Ptr(
m_dhCtx, reinterpret_cast<const uint8_t*>(pubkey->value().data()),
pubkey->length());
}
void DiffieHellman::computeSharedSecret(void) {
return gf_computeSharedSecret_Ptr(m_dhCtx);
}
std::shared_ptr<CacheableBytes> DiffieHellman::encrypt(
const std::shared_ptr<CacheableBytes>& cleartext) {
return encrypt(reinterpret_cast<const uint8_t*>(cleartext->value().data()),
cleartext->length());
}
std::shared_ptr<CacheableBytes> DiffieHellman::encrypt(const uint8_t* cleartext,
int len) {
int cipherLen = 0;
auto ciphertextPtr = gf_encryptDH_Ptr(m_dhCtx, cleartext, len, &cipherLen);
return CacheableBytes::create(
std::vector<int8_t>(ciphertextPtr, ciphertextPtr + cipherLen));
}
std::shared_ptr<CacheableBytes> DiffieHellman::decrypt(
const std::shared_ptr<CacheableBytes>& cleartext) {
return decrypt(reinterpret_cast<const uint8_t*>(cleartext->value().data()),
cleartext->length());
}
std::shared_ptr<CacheableBytes> DiffieHellman::decrypt(const uint8_t* cleartext,
int len) {
int cipherLen = 0;
auto ciphertextPtr = gf_decryptDH_Ptr(m_dhCtx, cleartext, len, &cipherLen);
return CacheableBytes::create(
std::vector<int8_t>(ciphertextPtr, ciphertextPtr + cipherLen));
}
bool DiffieHellman::verify(const std::shared_ptr<CacheableString>& subject,
const std::shared_ptr<CacheableBytes>& challenge,
const std::shared_ptr<CacheableBytes>& response) {
int errCode = DH_ERR_NO_ERROR;
LOGDEBUG("DiffieHellman::verify");
bool result = gf_verifyDH_Ptr(
m_dhCtx, subject->value().c_str(),
reinterpret_cast<const uint8_t*>(challenge->value().data()),
challenge->length(),
reinterpret_cast<const uint8_t*>(response->value().data()),
response->length(), &errCode);
LOGDEBUG("DiffieHellman::verify 2");
if (errCode == DH_ERR_SUBJECT_NOT_FOUND) {
LOGERROR("Subject name %s not found in imported certificates.",
subject->value().c_str());
} 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 client
} // namespace geode
} // namespace apache