LCOV - code coverage report
Current view: top level - DCPS/security/SSL - DiffieHellman.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 209 308 67.9 %
Date: 2023-04-30 01:32:43 Functions: 32 33 97.0 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.OpenDDS.org/license.html
       4             :  */
       5             : 
       6             : #include "DiffieHellman.h"
       7             : #include "Utils.h"
       8             : #include "Err.h"
       9             : 
      10             : #include <openssl/evp.h>
      11             : #include <openssl/dh.h>
      12             : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
      13             : #include <openssl/core_names.h>
      14             : #include <openssl/param_build.h>
      15             : #endif
      16             : #include "../OpenSSL_legacy.h"  // Must come after all other OpenSSL includes
      17             : 
      18             : #include <ace/OS_NS_strings.h>
      19             : 
      20             : #include <cstring>
      21             : 
      22             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      23             : 
      24             : namespace OpenDDS {
      25             : namespace Security {
      26             : namespace SSL {
      27             : 
      28             : namespace {
      29             :   // Assumes both buffers are null-terminated (and that s2_len includes final null, as with sizeof() for a const char[])
      30          14 :   int compare(const DDS::OctetSeq& s1, const char* s2, const size_t s2_len) {
      31          14 :     return s1.length() != s2_len ? -1 : std::memcmp(s1.get_buffer(), s2, s2_len);
      32             :   }
      33             : }
      34             : 
      35             : #ifndef OPENSSL_V_3_0
      36             : struct DH_Handle {
      37             :   DH* dh_;
      38             :   explicit DH_Handle(EVP_PKEY* key)
      39             : #if defined OPENSSL_V_1_0 || defined OPENSSL_V_3_0
      40             :     : dh_(EVP_PKEY_get1_DH(key))
      41             : #else
      42             :     : dh_(EVP_PKEY_get0_DH(key))
      43             : #endif
      44             :   {}
      45             :   operator DH*() { return dh_; }
      46             :   ~DH_Handle()
      47             :   {
      48             : #if defined OPENSSL_V_1_0 || defined OPENSSL_V_3_0
      49             :     DH_free(dh_);
      50             : #endif
      51             :   }
      52             : };
      53             : #endif
      54             : 
      55          22 : DHAlgorithm::~DHAlgorithm() { EVP_PKEY_free(k_); }
      56             : 
      57           2 : bool DHAlgorithm::cmp_shared_secret(const DHAlgorithm& other) const
      58             : {
      59           2 :   if (shared_secret_.length() != other.get_shared_secret().length()) {
      60           0 :     return false;
      61             :   }
      62             : 
      63           6 :   return (0 == std::memcmp(shared_secret_.get_buffer(),
      64           2 :                            other.get_shared_secret().get_buffer(),
      65           4 :                            shared_secret_.length()));
      66             : }
      67             : 
      68          14 : int DHAlgorithm::hash_shared_secret()
      69             : {
      70          14 :   DDS::OctetSeq tmp = shared_secret_;
      71          14 :   std::vector<const DDS::OctetSeq*> hash_data;
      72          14 :   hash_data.push_back(&tmp);
      73          28 :   return SSL::hash(hash_data, shared_secret_);
      74          14 : }
      75             : 
      76           4 : DH_2048_MODP_256_PRIME::DH_2048_MODP_256_PRIME() { init(); }
      77             : 
      78           8 : DH_2048_MODP_256_PRIME::~DH_2048_MODP_256_PRIME() {}
      79             : 
      80             : class dh_constructor
      81             : {
      82             : public:
      83           4 :   dh_constructor() : params(0), paramgen_ctx(0), keygen_ctx(0) {}
      84             : 
      85           4 :   ~dh_constructor()
      86             :   {
      87           4 :     EVP_PKEY_free(params);
      88           4 :     EVP_PKEY_CTX_free(paramgen_ctx);
      89           4 :     EVP_PKEY_CTX_free(keygen_ctx);
      90           4 :   }
      91             : 
      92           4 :   EVP_PKEY* get_key()
      93             :   {
      94           4 :     EVP_PKEY* result = 0;
      95             : 
      96             : #if OPENSSL_VERSION_NUMBER < 0x10002000L
      97             :     OPENDDS_SSL_LOG_ERR("RFC 5114 2.3 - 2048-bit MODP Group with 256-bit Prime Order Subgroup - not provided by this OpenSSL library");
      98             : #else
      99             : 
     100           4 :     if (0 == (params = EVP_PKEY_new())) {
     101           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_new failed");
     102           0 :       return 0;
     103             :     }
     104             : 
     105           4 :     if (0 == (paramgen_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DHX, 0))) {
     106           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new_id");
     107           0 :       return 0;
     108             :     }
     109             : 
     110           4 :     if (1 != EVP_PKEY_paramgen_init(paramgen_ctx)) {
     111           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen_init failed");
     112           0 :       return 0;
     113             :     }
     114             : 
     115           4 :     if (1 != EVP_PKEY_CTX_set_dh_rfc5114(paramgen_ctx, 3)) {
     116           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_set_dh_rfc5114 failed");
     117           0 :       return 0;
     118             :     }
     119             : 
     120           4 :     if ((1 != EVP_PKEY_paramgen(paramgen_ctx, &params)) || params == 0) {
     121           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen failed");
     122           0 :       return 0;
     123             :     }
     124             : 
     125           4 :     if (0 == (keygen_ctx = EVP_PKEY_CTX_new(params, 0))) {
     126           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new failed");
     127           0 :       return 0;
     128             :     }
     129             : 
     130           4 :     if (1 != EVP_PKEY_keygen_init(keygen_ctx)) {
     131           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen_init failed");
     132           0 :       return 0;
     133             :     }
     134             : 
     135           4 :     if (1 != EVP_PKEY_keygen(keygen_ctx, &result)) {
     136           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen failed");
     137           0 :       return 0;
     138             :     }
     139             : 
     140             : #endif
     141           4 :     return result;
     142             :   }
     143             : 
     144             : private:
     145             :   EVP_PKEY* params;
     146             :   EVP_PKEY_CTX* paramgen_ctx;
     147             :   EVP_PKEY_CTX* keygen_ctx;
     148             : };
     149             : 
     150           4 : int DH_2048_MODP_256_PRIME::init()
     151             : {
     152           4 :   if (k_) return 0;
     153             : 
     154           4 :   dh_constructor dh;
     155           4 :   k_ = dh.get_key();
     156           4 :   return k_ ? 0 : 1;
     157           4 : }
     158             : 
     159           2 : int DH_2048_MODP_256_PRIME::pub_key(DDS::OctetSeq& dst)
     160             : {
     161           2 :   int result = 1;
     162             : 
     163           2 :   if (k_) {
     164             : #ifndef OPENSSL_V_3_0
     165             :     DH_Handle dh(k_);
     166             :     if (dh) {
     167             :       const BIGNUM *pubkey = 0, *privkey = 0;
     168             :       DH_get0_key(dh, &pubkey, &privkey);
     169             :       if (pubkey) {
     170             :         dst.length(BN_num_bytes(pubkey));
     171             :         if (0 < BN_bn2bin(pubkey, dst.get_buffer())) {
     172             :           result = 0;
     173             :         } else {
     174             :           OPENDDS_SSL_LOG_ERR("BN_bn2bin failed");
     175             :         }
     176             :       } else {
     177             :         OPENDDS_SSL_LOG_ERR("DH_get0_key failed");
     178             :       }
     179             :     }
     180             : #else
     181           2 :     BIGNUM* pubkey = 0;
     182           2 :     if (EVP_PKEY_get_bn_param(k_, OSSL_PKEY_PARAM_PUB_KEY, &pubkey)) {
     183           2 :       dst.length(BN_num_bytes(pubkey));
     184           2 :       if (0 < BN_bn2bin(pubkey, dst.get_buffer())) {
     185           2 :         result = 0;
     186             :       } else {
     187           0 :         OPENDDS_SSL_LOG_ERR("BN_bn2bin failed");
     188             :       }
     189             :     } else {
     190           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_get_bn_param failed");
     191             :     }
     192           2 :     BN_free(pubkey);
     193             : #endif
     194             :   }
     195           2 :   return result;
     196             : }
     197             : 
     198             : class dh_shared_secret
     199             : {
     200             : public:
     201           2 :   explicit dh_shared_secret(EVP_PKEY* pkey)
     202           2 :     : keypair(pkey)
     203             : #ifdef OPENSSL_V_3_0
     204           2 :     , dh_ctx(0)
     205           2 :     , fd_ctx(0)
     206           2 :     , peer(0)
     207           2 :     , param_bld(0)
     208           2 :     , params(0)
     209           2 :     , glen(32)
     210           2 :     , grp(new char[glen])
     211             : #endif
     212           2 :     , pubkey(0)
     213             :   {
     214           2 :     if (!keypair) {
     215             : #ifndef OPENSSL_V_3_0
     216             :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_DH failed");
     217             : #endif
     218             :     }
     219           2 :   }
     220             : 
     221           2 :   ~dh_shared_secret()
     222             :   {
     223           2 :     BN_free(pubkey);
     224             : #ifdef OPENSSL_V_3_0
     225           2 :     EVP_PKEY_CTX_free(dh_ctx);
     226           2 :     EVP_PKEY_CTX_free(fd_ctx);
     227           2 :     EVP_PKEY_free(peer);
     228           2 :     OSSL_PARAM_BLD_free(param_bld);
     229           2 :     OSSL_PARAM_free(params);
     230           2 :     delete [] grp;
     231             : #endif
     232           2 :   }
     233             : 
     234           2 :   int operator()(const DDS::OctetSeq& pub_key, DDS::OctetSeq& dst)
     235             :   {
     236           2 :     if (!keypair) return 1;
     237             : 
     238           2 :     if (0 == (pubkey = BN_bin2bn(pub_key.get_buffer(), pub_key.length(), 0))) {
     239           0 :       OPENDDS_SSL_LOG_ERR("BN_bin2bn failed");
     240           0 :       return 1;
     241             :     }
     242             : 
     243             : #ifndef OPENSSL_V_3_0
     244             :     int len = DH_size(keypair);
     245             :     dst.length(len);
     246             :     len = DH_compute_key(dst.get_buffer(), pubkey, keypair);
     247             :     if (len < 0) {
     248             :       OPENDDS_SSL_LOG_ERR("DH_compute_key failed");
     249             :       dst.length(0u);
     250             :       return 1;
     251             :     }
     252             : #else
     253           2 :     if (!EVP_PKEY_get_utf8_string_param(keypair, "group", grp, glen, &glen)) {
     254           0 :       OPENDDS_SSL_LOG_ERR("Failed to find group name");
     255           0 :       return 1;
     256             :     }
     257           2 :     OSSL_PARAM_free(params);
     258           2 :     params = 0;
     259             : 
     260           2 :     if ((param_bld = OSSL_PARAM_BLD_new()) == 0) {
     261           0 :       OPENDDS_SSL_LOG_ERR("OSSL_PARAM_BLD_new failed");
     262           0 :       return 1;
     263             :     }
     264             : 
     265           2 :     if ((OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", grp, 0) == 0)) {
     266           0 :       OPENDDS_SSL_LOG_ERR("Building prarms list failed");
     267           0 :       return 1;
     268             :     }
     269             : 
     270           2 :     if ((OSSL_PARAM_BLD_push_BN(param_bld, "pub", pubkey) == 0)) {
     271           0 :       OPENDDS_SSL_LOG_ERR("Building prarms list failed");
     272           0 :       return 1;
     273             :     }
     274           2 :     params = OSSL_PARAM_BLD_to_param(param_bld);
     275             : 
     276           2 :     if ((fd_ctx = EVP_PKEY_CTX_new(keypair, 0)) == 0) {
     277           0 :       OPENDDS_SSL_LOG_ERR("new ctx failed.");
     278           0 :       return 1;
     279             :     }
     280             : 
     281           2 :     EVP_PKEY_fromdata_init(fd_ctx);
     282             : 
     283           2 :     if (EVP_PKEY_fromdata(fd_ctx, &peer, EVP_PKEY_PUBLIC_KEY, params) != 1) {
     284           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_fromdata Failed");
     285           0 :       return 1;
     286             :     }
     287             : 
     288           2 :     if ((dh_ctx = EVP_PKEY_CTX_new(keypair,0)) == 0) {
     289           0 :       OPENDDS_SSL_LOG_ERR("new ctx from name BH failed.");
     290           0 :       return 1;
     291             :     }
     292             : 
     293           2 :     if (!EVP_PKEY_derive_init(dh_ctx)) {
     294           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive_init failed");
     295           0 :       return 1;
     296             :     }
     297             : 
     298           2 :     if (EVP_PKEY_derive_set_peer(dh_ctx, peer) <= 0) {
     299           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive_set peer failed");
     300           0 :       return 1;
     301             :     }
     302             : 
     303           2 :     size_t len = 0;
     304           2 :     if (EVP_PKEY_derive(dh_ctx, 0, &len) <= 0) {
     305           0 :       OPENDDS_SSL_LOG_ERR("DH compute_key error getting length");
     306           0 :       return 1;
     307             :     }
     308           2 :     dst.length(static_cast<ACE_CDR::ULong>(len));
     309           2 :     if (EVP_PKEY_derive(dh_ctx, dst.get_buffer(), &len) <= 0) {
     310           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive failed");
     311           0 :       dst.length(0u);
     312           0 :       return 1;
     313             :     }
     314             : #endif
     315           2 :     return 0;
     316             :   }
     317             : 
     318             : private:
     319             : #ifndef OPENSSL_V_3_0
     320             :   DH_Handle keypair;
     321             : #else
     322             :   EVP_PKEY* keypair;
     323             :   EVP_PKEY_CTX* dh_ctx;
     324             :   EVP_PKEY_CTX* fd_ctx;
     325             :   EVP_PKEY* peer;
     326             :   OSSL_PARAM_BLD* param_bld;
     327             :   OSSL_PARAM* params;
     328             :   size_t glen;
     329             :   char* grp;
     330             : #endif
     331             :   BIGNUM* pubkey;
     332             : };
     333             : 
     334           2 : int DH_2048_MODP_256_PRIME::compute_shared_secret(const DDS::OctetSeq& pub_key)
     335             : {
     336           2 :   dh_shared_secret secret(k_);
     337           4 :   return secret(pub_key, shared_secret_);
     338           2 : }
     339             : 
     340             : #ifndef OPENSSL_V_3_0
     341             : struct EC_Handle {
     342             :   EC_KEY* ec_;
     343             :   explicit EC_Handle(EVP_PKEY* key)
     344             : #if defined OPENSSL_V_1_0 || defined OPENSSL_V_3_0
     345             :     : ec_(EVP_PKEY_get1_EC_KEY(key))
     346             : #else
     347             :     : ec_(EVP_PKEY_get0_EC_KEY(key))
     348             : #endif
     349             :   {}
     350             :   operator EC_KEY*() { return ec_; }
     351             :   ~EC_Handle()
     352             :   {
     353             : #if defined OPENSSL_V_1_0 || defined OPENSSL_V_3_0
     354             :     EC_KEY_free(ec_);
     355             : #endif
     356             :   }
     357             : };
     358             : #endif
     359             : 
     360          18 : ECDH_PRIME_256_V1_CEUM::ECDH_PRIME_256_V1_CEUM() { init(); }
     361             : 
     362          36 : ECDH_PRIME_256_V1_CEUM::~ECDH_PRIME_256_V1_CEUM() {}
     363             : 
     364             : class ecdh_constructor
     365             : {
     366             : public:
     367          18 :   ecdh_constructor() : params(0), paramgen_ctx(0), keygen_ctx(0) {}
     368             : 
     369          18 :   ~ecdh_constructor()
     370             :   {
     371          18 :     EVP_PKEY_free(params);
     372          18 :     EVP_PKEY_CTX_free(paramgen_ctx);
     373          18 :     EVP_PKEY_CTX_free(keygen_ctx);
     374          18 :   }
     375             : 
     376          18 :   EVP_PKEY* get_key()
     377             :   {
     378          18 :     EVP_PKEY* result = 0;
     379             : 
     380          18 :     if (0 == (params = EVP_PKEY_new())) {
     381           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_new failed");
     382           0 :       return 0;
     383             :     }
     384             : 
     385          18 :     if (0 == (paramgen_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, 0))) {
     386           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new_id");
     387           0 :       return 0;
     388             :     }
     389             : 
     390          18 :     if (1 != EVP_PKEY_paramgen_init(paramgen_ctx)) {
     391           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen_init failed");
     392           0 :       return 0;
     393             :     }
     394             : 
     395          18 :     if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(paramgen_ctx, NID_X9_62_prime256v1)) {
     396           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_set_ec_paramgen_curve_ni = failed");
     397           0 :       return 0;
     398             :     }
     399             : 
     400          18 :     if (1 != EVP_PKEY_paramgen(paramgen_ctx, &params) || params == 0) {
     401           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen failed");
     402           0 :       return 0;
     403             :     }
     404             : 
     405          18 :     if (0 == (keygen_ctx = EVP_PKEY_CTX_new(params, 0))) {
     406           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new failed");
     407           0 :       return 0;
     408             :     }
     409             : 
     410          18 :     if (1 != EVP_PKEY_keygen_init(keygen_ctx)) {
     411           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen_init failed");
     412           0 :       return 0;
     413             :     }
     414             : 
     415          18 :     if (1 != EVP_PKEY_keygen(keygen_ctx, &result)) {
     416           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen failed");
     417           0 :       return 0;
     418             :     }
     419             : 
     420          18 :     return result;
     421             :   }
     422             : 
     423             : private:
     424             :   EVP_PKEY* params;
     425             :   EVP_PKEY_CTX* paramgen_ctx;
     426             :   EVP_PKEY_CTX* keygen_ctx;
     427             : };
     428             : 
     429          18 : int ECDH_PRIME_256_V1_CEUM::init()
     430             : {
     431          18 :   if (k_) return 0;
     432             : 
     433          18 :   ecdh_constructor ecdh;
     434          18 :   k_ = ecdh.get_key();
     435             : 
     436          18 :   return k_ ? 0 : 1;
     437          18 : }
     438             : 
     439             : class ecdh_pubkey_as_octets
     440             : {
     441             : public:
     442          16 :   explicit ecdh_pubkey_as_octets(EVP_PKEY* pkey)
     443          16 :     : keypair(pkey)
     444             : #ifdef OPENSSL_V_3_0
     445          16 :     , params(0)
     446             : #endif
     447             :   {
     448          16 :   }
     449             : 
     450             : #ifdef OPENSSL_V_3_0
     451          16 :   ~ecdh_pubkey_as_octets()
     452             :   {
     453          16 :     OSSL_PARAM_free(params);
     454          16 :   }
     455             : #endif
     456             : 
     457          16 :   int operator()(DDS::OctetSeq& dst)
     458             :   {
     459          16 :     if (!keypair) return 1;
     460             : 
     461             : #ifndef OPENSSL_V_3_0
     462             :     EC_Handle keypair_ecdh(keypair);
     463             :     if (!keypair_ecdh) {
     464             :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_EC_KEY failed");
     465             :       return 1;
     466             :     }
     467             : 
     468             :     const EC_POINT* pubkey = EC_KEY_get0_public_key(keypair_ecdh);
     469             :     if (!pubkey) {
     470             :       OPENDDS_SSL_LOG_ERR("EC_KEY_get0_public_key failed");
     471             :       return 1;
     472             :     }
     473             : 
     474             :     size_t len = EC_POINT_point2oct(EC_KEY_get0_group(keypair_ecdh), pubkey,
     475             :                                     EC_KEY_get_conv_form(keypair_ecdh), 0,
     476             :                                     0u, 0);
     477             :     if (!len) {
     478             :       OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
     479             :       return 1;
     480             :     }
     481             : 
     482             :     dst.length(static_cast<unsigned int>(len));
     483             :     if (0 == EC_POINT_point2oct(EC_KEY_get0_group(keypair_ecdh), pubkey,
     484             :                                 EC_KEY_get_conv_form(keypair_ecdh),
     485             :                                 dst.get_buffer(), len, 0)) {
     486             :       OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
     487             :       return 1;
     488             :     }
     489             : #else
     490          16 :     if (EVP_PKEY_todata(keypair, EVP_PKEY_KEYPAIR, &params) <= 0) {
     491           0 :       OPENDDS_SSL_LOG_ERR("pkey to data failed");
     492           0 :       return 1;
     493             :     } else {
     494          16 :       const char* gname = 0;
     495          16 :       const unsigned char* pubbuf = 0;
     496          16 :       size_t pubbuflen = 0;
     497         144 :       for (OSSL_PARAM* p = params; p != 0 && p->key != 0; ++p) {
     498         128 :         if (ACE_OS::strcasecmp(p->key, "group") == 0) {
     499          16 :           gname = static_cast<const char*>(p->data);
     500         112 :         } else if (ACE_OS::strcasecmp(p->key, "pub") == 0) {
     501          16 :           pubbuf = static_cast<const unsigned char*>(p->data);
     502          16 :           pubbuflen = p->data_size;
     503             :         }
     504             :       }
     505             : 
     506          16 :       const int nid = OBJ_txt2nid(gname);
     507          16 :       if (nid == 0) {
     508           0 :         OPENDDS_SSL_LOG_ERR("failed to find Nid");
     509           0 :         return 1;
     510             :       }
     511          16 :       EC_GROUP* const ecg = EC_GROUP_new_by_curve_name(nid);
     512          16 :       const point_conversion_form_t cf = EC_GROUP_get_point_conversion_form(ecg);
     513          16 :       EC_POINT* const ec = EC_POINT_new(ecg);
     514          16 :       if (!EC_POINT_oct2point(ecg, ec, pubbuf, pubbuflen, 0)) {
     515           0 :         OPENDDS_SSL_LOG_ERR("failed to extract ec point from octet sequence");
     516           0 :         EC_POINT_free(ec);
     517           0 :         EC_GROUP_free(ecg);
     518           0 :         return 1;
     519             :       }
     520          16 :       const size_t eclen = EC_POINT_point2oct(ecg, ec, cf, 0, 0u, 0);
     521          16 :       dst.length(static_cast<ACE_CDR::ULong>(eclen));
     522          16 :       EC_POINT_point2oct(ecg, ec, cf, dst.get_buffer(), eclen, 0);
     523          16 :       EC_POINT_free(ec);
     524          16 :       EC_GROUP_free(ecg);
     525             :     }
     526             : #endif
     527          16 :     return 0;
     528             :   }
     529             : 
     530             : private:
     531             :   EVP_PKEY* keypair;
     532             : #ifdef OPENSSL_V_3_0
     533             :   OSSL_PARAM* params;
     534             : #endif
     535             : };
     536             : 
     537          16 : int ECDH_PRIME_256_V1_CEUM::pub_key(DDS::OctetSeq& dst)
     538             : {
     539          16 :   ecdh_pubkey_as_octets pubkey(k_);
     540          32 :   return pubkey(dst);
     541          16 : }
     542             : 
     543             : class ecdh_shared_secret_from_octets
     544             : {
     545             : public:
     546          12 :   explicit ecdh_shared_secret_from_octets(EVP_PKEY* pkey)
     547          12 :     : keypair(pkey)
     548             : #ifdef OPENSSL_V_3_0
     549          12 :     , ec_ctx(0)
     550          12 :     , fd_ctx(0)
     551          12 :     , peer(0)
     552          12 :     , param_bld(0)
     553          12 :     , params(0)
     554             : #else
     555             :     , group(0)
     556             : #endif
     557          12 :     , pubkey(0)
     558          12 :     , bignum_ctx(0)
     559             :   {
     560          12 :     if (!keypair) {
     561           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_EC_KEY failed");
     562             :     }
     563          12 :   }
     564             : 
     565          12 :   ~ecdh_shared_secret_from_octets()
     566             :   {
     567          12 :     EC_POINT_free(pubkey);
     568          12 :     BN_CTX_free(bignum_ctx);
     569             : #ifdef OPENSSL_V_3_0
     570          12 :     EVP_PKEY_CTX_free(ec_ctx);
     571          12 :     EVP_PKEY_CTX_free(fd_ctx);
     572          12 :     EVP_PKEY_free(peer);
     573          12 :     OSSL_PARAM_BLD_free(param_bld);
     574          12 :     OSSL_PARAM_free(params);
     575             : #endif
     576          12 :   }
     577             : 
     578          12 :   int operator()(const DDS::OctetSeq& src, DDS::OctetSeq& dst)
     579             :   {
     580          12 :     if (!keypair) return 1;
     581             : 
     582          12 :     if (0 == (bignum_ctx = BN_CTX_new())) {
     583           0 :       OPENDDS_SSL_LOG_ERR("BN_CTX_new failed");
     584           0 :       return 1;
     585             :     }
     586             : #ifndef OPENSSL_V_3_0
     587             :     if (0 == (group = EC_KEY_get0_group(keypair))) {
     588             :       OPENDDS_SSL_LOG_ERR("EC_KEY_get0_group failed");
     589             :       return 1;
     590             :     }
     591             : 
     592             :     pubkey = EC_POINT_new(group);
     593             :     if (1 != EC_POINT_oct2point(group, pubkey, src.get_buffer(),
     594             :                                 src.length(), bignum_ctx)) {
     595             :       OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
     596             :       return 1;
     597             :     }
     598             : 
     599             :     const int numbits = EC_GROUP_get_degree(group);
     600             :     dst.length((numbits + 7) / 8);
     601             : 
     602             :     const int len = ECDH_compute_key(dst.get_buffer(), dst.length(), pubkey,
     603             :                                      keypair, 0);
     604             : 
     605             :     if (0 == len) {
     606             :       OPENDDS_SSL_LOG_ERR("ECDH_compute_key failed");
     607             :       return 1;
     608             :     }
     609             : #else
     610          12 :     const char* grp = 0;
     611          12 :     if (EVP_PKEY_todata(keypair, EVP_PKEY_PUBLIC_KEY, &params) <= 0) {
     612           0 :       OPENDDS_SSL_LOG_ERR("pkey to data failed");
     613           0 :       return 1;
     614             :     } else {
     615          48 :       for (OSSL_PARAM* p = params; grp == 0 && p != 0 && p->key != 0; p++) {
     616          36 :         if (strcmp(p->key, "group") == 0) {
     617          12 :           grp = static_cast<const char*>(p->data);
     618             :         }
     619             :       }
     620          12 :       if (grp == 0) {
     621           0 :         OPENDDS_SSL_LOG_ERR("could not find group id");
     622           0 :         return 1;
     623             :       }
     624             :     }
     625             : 
     626          12 :     if ((param_bld = OSSL_PARAM_BLD_new()) == 0) {
     627           0 :       OPENDDS_SSL_LOG_ERR("OSSL_PARAM_BLD_new failed");
     628           0 :       return 1;
     629             :     }
     630             : 
     631          12 :     if ((OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", grp, 0) == 0)) {
     632           0 :       OPENDDS_SSL_LOG_ERR("Building prarms list failed");
     633           0 :       return 1;
     634             :     }
     635             : 
     636          12 :     if ((OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", src.get_buffer(),src.length()) == 0)) {
     637           0 :       OPENDDS_SSL_LOG_ERR("Building prarms list failed");
     638           0 :       return 1;
     639             :     }
     640             : 
     641          12 :     OSSL_PARAM* old_params = params;
     642          12 :     params = OSSL_PARAM_BLD_to_param(param_bld);
     643          12 :     OSSL_PARAM_free(old_params);
     644             : 
     645          12 :     if ((fd_ctx = EVP_PKEY_CTX_new(keypair,0)) == 0) {
     646           0 :       OPENDDS_SSL_LOG_ERR("new ctx from name ECBH failed.");
     647           0 :       return 1;
     648             :     }
     649             : 
     650          12 :     EVP_PKEY_fromdata_init(fd_ctx);
     651             : 
     652          12 :     if (EVP_PKEY_fromdata(fd_ctx, &peer, EVP_PKEY_PUBLIC_KEY, params) != 1) {
     653           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_fromdata Failed");
     654           0 :       return 1;
     655             :     }
     656             : 
     657          12 :     if ((ec_ctx = EVP_PKEY_CTX_new(keypair,0)) == 0) {
     658           0 :       OPENDDS_SSL_LOG_ERR("new ctx from name ECBH failed.");
     659           0 :       return 1;
     660             :     }
     661             : 
     662          12 :     if (!EVP_PKEY_derive_init(ec_ctx)) {
     663           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive_init failed");
     664           0 :       return 1;
     665             :     }
     666             : 
     667          12 :     if (EVP_PKEY_derive_set_peer(ec_ctx, peer) <= 0) {
     668           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive_set peer failed");
     669           0 :       return 1;
     670             :     }
     671             : 
     672          12 :     size_t len = 0;
     673          12 :     if (EVP_PKEY_derive(ec_ctx, 0, &len) <= 0) {
     674           0 :       OPENDDS_SSL_LOG_ERR("DH compute_key error getting length");
     675           0 :       return 1;
     676             :     }
     677          12 :     dst.length(static_cast<ACE_CDR::ULong>(len));
     678          12 :     if (EVP_PKEY_derive(ec_ctx, dst.get_buffer(), &len) <= 0) {
     679           0 :       OPENDDS_SSL_LOG_ERR("EVP_PKEY_derive failed");
     680           0 :       dst.length(0u);
     681           0 :       return 1;
     682             :     }
     683             : #endif
     684          12 :     return 0;
     685             :   }
     686             : 
     687             : private:
     688             : #ifndef OPENSSL_V_3_0
     689             :   EC_Handle keypair;
     690             :   const EC_GROUP* group;
     691             : #else
     692             :   EVP_PKEY* keypair;
     693             :   EVP_PKEY_CTX* ec_ctx;
     694             :   EVP_PKEY_CTX* fd_ctx;
     695             :   EVP_PKEY* peer;
     696             :   OSSL_PARAM_BLD* param_bld;
     697             :   OSSL_PARAM* params;
     698             : #endif
     699             :   EC_POINT* pubkey;
     700             :   BN_CTX* bignum_ctx;
     701             : };
     702             : 
     703          12 : int ECDH_PRIME_256_V1_CEUM::compute_shared_secret(const DDS::OctetSeq& pub_key)
     704             : {
     705          12 :   ecdh_shared_secret_from_octets secret(k_);
     706          24 :   return secret(pub_key, shared_secret_);
     707          12 : }
     708             : 
     709           7 : DiffieHellman* DiffieHellman::factory(const DDS::OctetSeq& kagree_algo)
     710             : {
     711           7 :   if (0 == compare(kagree_algo, DH_2048_MODP_256_PRIME_STR, sizeof (DH_2048_MODP_256_PRIME_STR))) {
     712           0 :     return new DiffieHellman(new DH_2048_MODP_256_PRIME);
     713             : 
     714           7 :   } else if (0 == compare(kagree_algo, ECDH_PRIME_256_V1_CEUM_STR, sizeof (ECDH_PRIME_256_V1_CEUM_STR))) {
     715           7 :     return new DiffieHellman(new ECDH_PRIME_256_V1_CEUM);
     716             : 
     717             :   } else {
     718           0 :     ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) SSL::DiffieHellman::factory: ERROR, unknown kagree_algo\n")));
     719           0 :     return 0;
     720             :   }
     721             : }
     722             : 
     723             : }  // namespace SSL
     724             : }  // namespace Security
     725             : }  // namespace OpenDDS
     726             : 
     727             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16