00001
00002
00003
00004
00005
00006 #include "DiffieHellman.h"
00007 #include "Utils.h"
00008 #include "Err.h"
00009 #include <openssl/dh.h>
00010 #include "../OpenSSL_legacy.h"
00011 #include <cstring>
00012
00013 namespace OpenDDS {
00014 namespace Security {
00015 namespace SSL {
00016
00017 struct DH_Handle {
00018 DH* dh_;
00019 explicit DH_Handle(EVP_PKEY* key)
00020 #ifdef OPENSSL_V_1_0
00021 : dh_(EVP_PKEY_get1_DH(key))
00022 #else
00023 : dh_(EVP_PKEY_get0_DH(key))
00024 #endif
00025 {}
00026 operator DH*() { return dh_; }
00027 ~DH_Handle()
00028 {
00029 #ifdef OPENSSL_V_1_0
00030 DH_free(dh_);
00031 #endif
00032 }
00033 };
00034
00035 DHAlgorithm::~DHAlgorithm() { EVP_PKEY_free(k_); }
00036
00037 bool DHAlgorithm::cmp_shared_secret(const DHAlgorithm& other) const
00038 {
00039 if (shared_secret_.length() != other.get_shared_secret().length()) {
00040 return false;
00041 }
00042 return (0 == std::memcmp(shared_secret_.get_buffer(),
00043 other.get_shared_secret().get_buffer(),
00044 shared_secret_.length()));
00045 }
00046
00047 int DHAlgorithm::hash_shared_secret()
00048 {
00049 DDS::OctetSeq tmp = shared_secret_;
00050 std::vector<const DDS::OctetSeq*> hash_data;
00051 hash_data.push_back(&tmp);
00052 return SSL::hash(hash_data, shared_secret_);
00053 }
00054
00055 DH_2048_MODP_256_PRIME::DH_2048_MODP_256_PRIME() { init(); }
00056
00057 DH_2048_MODP_256_PRIME::~DH_2048_MODP_256_PRIME() {}
00058
00059 class dh_constructor
00060 {
00061 public:
00062 dh_constructor()
00063 : result(NULL), params(NULL), keygen_ctx(NULL), dh_2048_256(NULL)
00064 {
00065 }
00066 ~dh_constructor()
00067 {
00068 EVP_PKEY_free(params);
00069 EVP_PKEY_CTX_free(keygen_ctx);
00070 DH_free(dh_2048_256);
00071 }
00072
00073 EVP_PKEY* operator()()
00074 {
00075 if (!(params = EVP_PKEY_new())) {
00076 OPENDDS_SSL_LOG_ERR("EVP_PKEY_new failed");
00077 return NULL;
00078 }
00079
00080 if (NULL == (dh_2048_256 = DH_get_2048_256())) {
00081 OPENDDS_SSL_LOG_ERR("DH_get_2048_256 failed");
00082 return NULL;
00083 }
00084
00085 if (1 != EVP_PKEY_set1_DH(params, dh_2048_256)) {
00086 OPENDDS_SSL_LOG_ERR("EVP_PKEY_set1_DH failed");
00087 return NULL;
00088 }
00089
00090 if (!(keygen_ctx = EVP_PKEY_CTX_new(params, NULL))) {
00091 OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new failed");
00092 return NULL;
00093 }
00094
00095 if (1 != EVP_PKEY_keygen_init(keygen_ctx)) {
00096 OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen_init failed");
00097 return NULL;
00098 }
00099
00100 if (1 != EVP_PKEY_keygen(keygen_ctx, &result)) {
00101 OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen failed");
00102 return NULL;
00103 }
00104
00105 return result;
00106 }
00107
00108 private:
00109 EVP_PKEY* result;
00110 EVP_PKEY* params;
00111 EVP_PKEY_CTX* keygen_ctx;
00112 DH* dh_2048_256;
00113 };
00114
00115 int DH_2048_MODP_256_PRIME::init()
00116 {
00117 if (k_) return 0;
00118
00119 dh_constructor dh;
00120 k_ = dh();
00121
00122 if (k_) {
00123 return 0;
00124
00125 } else {
00126 return 1;
00127 }
00128 }
00129
00130 int DH_2048_MODP_256_PRIME::pub_key(DDS::OctetSeq& dst)
00131 {
00132 int result = 1;
00133
00134 if (k_) {
00135 DH_Handle dh(k_);
00136 if (dh) {
00137 const BIGNUM *pubkey,
00138 *privkey;
00139
00140 pubkey = privkey = NULL;
00141 DH_get0_key(dh, &pubkey, &privkey);
00142 if (pubkey) {
00143 dst.length(DH_size(dh));
00144 if (0 < BN_bn2bin(pubkey, dst.get_buffer())) {
00145 result = 0;
00146
00147 } else {
00148 OPENDDS_SSL_LOG_ERR("BN_bn2bin failed");
00149 }
00150 }
00151 }
00152 }
00153 return result;
00154 }
00155
00156 class dh_shared_secret
00157 {
00158 public:
00159 explicit dh_shared_secret(EVP_PKEY* pkey)
00160 : keypair(pkey), pubkey(NULL)
00161 {
00162 if (!keypair) {
00163 OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_DH failed");
00164 }
00165 }
00166
00167 ~dh_shared_secret() { BN_free(pubkey); }
00168
00169 int operator()(const DDS::OctetSeq& pub_key, DDS::OctetSeq& dst)
00170 {
00171 if (!keypair) return 1;
00172
00173 if (NULL == (pubkey = BN_bin2bn(pub_key.get_buffer(), pub_key.length(),
00174 NULL))) {
00175 OPENDDS_SSL_LOG_ERR("BN_bin2bn failed");
00176 return 1;
00177 }
00178
00179 int len = DH_size(keypair);
00180 dst.length(len);
00181
00182 len = DH_compute_key(dst.get_buffer(), pubkey, keypair);
00183 if (len < 0) {
00184 OPENDDS_SSL_LOG_ERR("DH_compute_key failed");
00185 dst.length(0u);
00186 return 1;
00187 }
00188
00189 dst.length(len);
00190 return 0;
00191 }
00192
00193 private:
00194 DH_Handle keypair;
00195 BIGNUM* pubkey;
00196 };
00197
00198 int DH_2048_MODP_256_PRIME::compute_shared_secret(
00199 const DDS::OctetSeq& pub_key)
00200 {
00201 dh_shared_secret secret(k_);
00202 return secret(pub_key, shared_secret_);
00203 }
00204
00205 struct EC_Handle {
00206 EC_KEY* ec_;
00207 explicit EC_Handle(EVP_PKEY* key)
00208 #ifdef OPENSSL_V_1_0
00209 : ec_(EVP_PKEY_get1_EC_KEY(key))
00210 #else
00211 : ec_(EVP_PKEY_get0_EC_KEY(key))
00212 #endif
00213 {}
00214 operator EC_KEY*() { return ec_; }
00215 ~EC_Handle()
00216 {
00217 #ifdef OPENSSL_V_1_0
00218 EC_KEY_free(ec_);
00219 #endif
00220 }
00221 };
00222
00223 ECDH_PRIME_256_V1_CEUM::ECDH_PRIME_256_V1_CEUM() { init(); }
00224
00225 ECDH_PRIME_256_V1_CEUM::~ECDH_PRIME_256_V1_CEUM() {}
00226
00227 class ecdh_constructor
00228 {
00229 public:
00230 ecdh_constructor() : params(NULL), paramgen_ctx(NULL), keygen_ctx(NULL) {}
00231
00232 ~ecdh_constructor()
00233 {
00234 EVP_PKEY_free(params);
00235 EVP_PKEY_CTX_free(paramgen_ctx);
00236 EVP_PKEY_CTX_free(keygen_ctx);
00237 }
00238
00239 EVP_PKEY* operator()()
00240 {
00241 EVP_PKEY* result = NULL;
00242
00243 if (NULL == (paramgen_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) {
00244 OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new_id");
00245 return NULL;
00246 }
00247
00248 if (NULL == (params = EVP_PKEY_new())) {
00249 OPENDDS_SSL_LOG_ERR("EVP_PKEY_new failed");
00250 return NULL;
00251 }
00252
00253 if (1 != EVP_PKEY_paramgen_init(paramgen_ctx)) {
00254 OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen_init failed");
00255 return NULL;
00256 }
00257
00258 if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(paramgen_ctx,
00259 NID_X9_62_prime256v1)) {
00260 OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed");
00261 return NULL;
00262 }
00263
00264 if (1 != EVP_PKEY_paramgen(paramgen_ctx, ¶ms)) {
00265 OPENDDS_SSL_LOG_ERR("EVP_PKEY_paramgen failed");
00266 return NULL;
00267 }
00268
00269 if (NULL == (keygen_ctx = EVP_PKEY_CTX_new(params, NULL))) {
00270 OPENDDS_SSL_LOG_ERR("EVP_PKEY_CTX_new failed");
00271 return NULL;
00272 }
00273
00274 if (1 != EVP_PKEY_keygen_init(keygen_ctx)) {
00275 OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen_init failed");
00276 return NULL;
00277 }
00278
00279 if (1 != EVP_PKEY_keygen(keygen_ctx, &result)) {
00280 OPENDDS_SSL_LOG_ERR("EVP_PKEY_keygen failed");
00281 return NULL;
00282 }
00283
00284 return result;
00285 }
00286
00287 private:
00288 EVP_PKEY* params;
00289 EVP_PKEY_CTX* paramgen_ctx;
00290 EVP_PKEY_CTX* keygen_ctx;
00291 };
00292
00293 int ECDH_PRIME_256_V1_CEUM::init()
00294 {
00295 if (k_) return 0;
00296
00297 ecdh_constructor ecdh;
00298 k_ = ecdh();
00299
00300 if (k_) {
00301 return 0;
00302
00303 } else {
00304 return 1;
00305 }
00306 }
00307
00308 class ecdh_pubkey_as_octets
00309 {
00310 public:
00311 ecdh_pubkey_as_octets(EVP_PKEY* pkey)
00312 : keypair(pkey)
00313 {
00314 }
00315
00316 ~ecdh_pubkey_as_octets() {}
00317
00318 int operator()(DDS::OctetSeq& dst)
00319 {
00320 if (!keypair) return 1;
00321
00322 EC_Handle keypair_ecdh(keypair);
00323 if (!keypair_ecdh) {
00324 OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_EC_KEY failed");
00325 return 1;
00326 }
00327
00328 const EC_POINT* pubkey = EC_KEY_get0_public_key(keypair_ecdh);
00329 if (!pubkey) {
00330 OPENDDS_SSL_LOG_ERR("EC_KEY_get0_public_key failed");
00331 return 1;
00332 }
00333
00334 size_t len = 0u;
00335 if (0 == (len = EC_POINT_point2oct(
00336 EC_KEY_get0_group(keypair_ecdh), pubkey,
00337 EC_KEY_get_conv_form(keypair_ecdh), NULL, 0u, NULL))) {
00338 OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
00339 return 1;
00340 }
00341
00342 dst.length(len);
00343
00344 if (0 ==
00345 (len = EC_POINT_point2oct(EC_KEY_get0_group(keypair_ecdh), pubkey,
00346 EC_KEY_get_conv_form(keypair_ecdh),
00347 dst.get_buffer(), len, NULL))) {
00348 OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
00349 return 1;
00350 }
00351
00352 return 0;
00353 }
00354
00355 private:
00356 EVP_PKEY* keypair;
00357 };
00358
00359 int ECDH_PRIME_256_V1_CEUM::pub_key(DDS::OctetSeq& dst)
00360 {
00361 ecdh_pubkey_as_octets pubkey(k_);
00362 return pubkey(dst);
00363 }
00364
00365 class ecdh_shared_secret_from_octets
00366 {
00367 public:
00368 ecdh_shared_secret_from_octets(EVP_PKEY* pkey)
00369 : keypair(pkey), pubkey(NULL), group(NULL), bignum_ctx(NULL)
00370 {
00371 if (!keypair) {
00372 OPENDDS_SSL_LOG_ERR("EVP_PKEY_get0_EC_KEY failed");
00373 }
00374 }
00375
00376 ~ecdh_shared_secret_from_octets()
00377 {
00378 EC_POINT_free(pubkey);
00379 BN_CTX_free(bignum_ctx);
00380 }
00381
00382 int operator()(const DDS::OctetSeq& src, DDS::OctetSeq& dst)
00383 {
00384 if (!keypair) return 1;
00385
00386 if (NULL == (bignum_ctx = BN_CTX_new())) {
00387 OPENDDS_SSL_LOG_ERR("BN_CTX_new failed");
00388 return 1;
00389 }
00390
00391 if (NULL == (group = EC_KEY_get0_group(keypair))) {
00392 OPENDDS_SSL_LOG_ERR("EC_KEY_get0_group failed");
00393 return 1;
00394 }
00395
00396 pubkey = EC_POINT_new(group);
00397 if (1 != EC_POINT_oct2point(group, pubkey, src.get_buffer(),
00398 src.length(), bignum_ctx)) {
00399 OPENDDS_SSL_LOG_ERR("EC_POINT_point2oct failed");
00400 return 1;
00401 }
00402
00403 int numbits = EC_GROUP_get_degree(group);
00404 dst.length((numbits + 7) / 8);
00405
00406 int len = ECDH_compute_key(dst.get_buffer(), dst.length(), pubkey,
00407 keypair, NULL);
00408
00409 if (0 == len) {
00410 OPENDDS_SSL_LOG_ERR("ECDH_compute_key failed");
00411 return 1;
00412 }
00413
00414 return 0;
00415 }
00416
00417 private:
00418 EC_Handle keypair;
00419 EC_POINT* pubkey;
00420 const EC_GROUP* group;
00421 BN_CTX* bignum_ctx;
00422 };
00423
00424 int ECDH_PRIME_256_V1_CEUM::compute_shared_secret(
00425 const DDS::OctetSeq& pub_key)
00426 {
00427 ecdh_shared_secret_from_octets secret(k_);
00428 return secret(pub_key, shared_secret_);
00429 }
00430
00431 DiffieHellman* DiffieHellman::factory(const DDS::OctetSeq& kagree_algo)
00432 {
00433 if (0 == std::memcmp(kagree_algo.get_buffer(), "DH+MODP-2048-256",
00434 kagree_algo.length())) {
00435 return new DiffieHellman(new DH_2048_MODP_256_PRIME);
00436
00437 } else if (0 == std::memcmp(kagree_algo.get_buffer(),
00438 "ECDH+prime256v1-CEUM",
00439 kagree_algo.length())) {
00440 return new DiffieHellman(new ECDH_PRIME_256_V1_CEUM);
00441
00442 } else {
00443 ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) SSL::DiffieHellman::factory: ERROR, unknown kagree_algo\n")));
00444 return NULL;
00445 }
00446 }
00447
00448 }
00449 }
00450 }