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, ¶ms)) || 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, ¶ms) || 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, ¶ms) <= 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, ¶ms) <= 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
|