| /* |
| * 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 |