1/*
2 * $Id: ossl_pkey_dh.c 44982 2014-02-15 15:52:34Z nagachika $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7/*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11#if !defined(OPENSSL_NO_DH)
12
13#include "ossl.h"
14
15#define GetPKeyDH(obj, pkey) do { \
16    GetPKey((obj), (pkey)); \
17    if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DH) { /* PARANOIA? */ \
18	ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
19    } \
20} while (0)
21
22#define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
23
24#ifdef OSSL_ENGINE_ENABLED
25#  define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
26#else
27#  define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
28#endif
29
30
31/*
32 * Classes
33 */
34VALUE cDH;
35VALUE eDHError;
36
37/*
38 * Public
39 */
40static VALUE
41dh_instance(VALUE klass, DH *dh)
42{
43    EVP_PKEY *pkey;
44    VALUE obj;
45
46    if (!dh) {
47	return Qfalse;
48    }
49    if (!(pkey = EVP_PKEY_new())) {
50	return Qfalse;
51    }
52    if (!EVP_PKEY_assign_DH(pkey, dh)) {
53	EVP_PKEY_free(pkey);
54	return Qfalse;
55    }
56    WrapPKey(klass, obj, pkey);
57
58    return obj;
59}
60
61VALUE
62ossl_dh_new(EVP_PKEY *pkey)
63{
64    VALUE obj;
65
66    if (!pkey) {
67	obj = dh_instance(cDH, DH_new());
68    } else {
69	if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) {
70	    ossl_raise(rb_eTypeError, "Not a DH key!");
71	}
72	WrapPKey(cDH, obj, pkey);
73    }
74    if (obj == Qfalse) {
75	ossl_raise(eDHError, NULL);
76    }
77
78    return obj;
79}
80
81/*
82 * Private
83 */
84#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
85struct dh_blocking_gen_arg {
86    DH *dh;
87    int size;
88    int gen;
89    BN_GENCB *cb;
90    int result;
91};
92
93static void *
94dh_blocking_gen(void *arg)
95{
96    struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
97    gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
98    return 0;
99}
100#endif
101
102static DH *
103dh_generate(int size, int gen)
104{
105#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
106    BN_GENCB cb;
107    struct ossl_generate_cb_arg cb_arg;
108    struct dh_blocking_gen_arg gen_arg;
109    DH *dh = DH_new();
110
111    if (!dh) return 0;
112
113    memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg));
114    if (rb_block_given_p())
115	cb_arg.yield = 1;
116    BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg);
117    gen_arg.dh = dh;
118    gen_arg.size = size;
119    gen_arg.gen = gen;
120    gen_arg.cb = &cb;
121    if (cb_arg.yield == 1) {
122	/* we cannot release GVL when callback proc is supplied */
123	dh_blocking_gen(&gen_arg);
124    } else {
125	/* there's a chance to unblock */
126	rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
127    }
128
129    if (!gen_arg.result) {
130	DH_free(dh);
131	if (cb_arg.state) rb_jump_tag(cb_arg.state);
132	return 0;
133    }
134#else
135    DH *dh;
136
137    dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
138    if (!dh) return 0;
139#endif
140
141    if (!DH_generate_key(dh)) {
142        DH_free(dh);
143        return 0;
144    }
145
146    return dh;
147}
148
149/*
150 *  call-seq:
151 *     DH.generate(size [, generator]) -> dh
152 *
153 * Creates a new DH instance from scratch by generating the private and public
154 * components alike.
155 *
156 * === Parameters
157 * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
158 * * +generator+ is a small number > 1, typically 2 or 5.
159 *
160 */
161static VALUE
162ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
163{
164    DH *dh ;
165    int g = 2;
166    VALUE size, gen, obj;
167
168    if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
169	g = NUM2INT(gen);
170    }
171    dh = dh_generate(NUM2INT(size), g);
172    obj = dh_instance(klass, dh);
173    if (obj == Qfalse) {
174	DH_free(dh);
175	ossl_raise(eDHError, NULL);
176    }
177
178    return obj;
179}
180
181/*
182 *  call-seq:
183 *     DH.new([size [, generator] | string]) -> dh
184 *
185 * Either generates a DH instance from scratch or by reading already existing
186 * DH parameters from +string+. Note that when reading a DH instance from
187 * data that was encoded from a DH instance by using DH#to_pem or DH#to_der
188 * the result will *not* contain a public/private key pair yet. This needs to
189 * be generated using DH#generate_key! first.
190 *
191 * === Parameters
192 * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
193 * * +generator+ is a small number > 1, typically 2 or 5.
194 * * +string+ contains the DER or PEM encoded key.
195 *
196 * === Examples
197 *  DH.new # -> dh
198 *  DH.new(1024) # -> dh
199 *  DH.new(1024, 5) # -> dh
200 *  #Reading DH parameters
201 *  dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
202 *  dh.generate_key! # -> dh with public and private key
203 */
204static VALUE
205ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
206{
207    EVP_PKEY *pkey;
208    DH *dh;
209    int g = 2;
210    BIO *in;
211    VALUE arg, gen;
212
213    GetPKey(self, pkey);
214    if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
215      dh = DH_new();
216    }
217    else if (FIXNUM_P(arg)) {
218	if (!NIL_P(gen)) {
219	    g = NUM2INT(gen);
220	}
221	if (!(dh = dh_generate(FIX2INT(arg), g))) {
222	    ossl_raise(eDHError, NULL);
223	}
224    }
225    else {
226	arg = ossl_to_der_if_possible(arg);
227	in = ossl_obj2bio(arg);
228	dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
229	if (!dh){
230	    OSSL_BIO_reset(in);
231	    dh = d2i_DHparams_bio(in, NULL);
232	}
233	BIO_free(in);
234	if (!dh) {
235	    ossl_raise(eDHError, NULL);
236	}
237    }
238    if (!EVP_PKEY_assign_DH(pkey, dh)) {
239	DH_free(dh);
240	ossl_raise(eDHError, NULL);
241    }
242    return self;
243}
244
245/*
246 *  call-seq:
247 *     dh.public? -> true | false
248 *
249 * Indicates whether this DH instance has a public key associated with it or
250 * not. The public key may be retrieved with DH#pub_key.
251 */
252static VALUE
253ossl_dh_is_public(VALUE self)
254{
255    EVP_PKEY *pkey;
256
257    GetPKeyDH(self, pkey);
258
259    return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
260}
261
262/*
263 *  call-seq:
264 *     dh.private? -> true | false
265 *
266 * Indicates whether this DH instance has a private key associated with it or
267 * not. The private key may be retrieved with DH#priv_key.
268 */
269static VALUE
270ossl_dh_is_private(VALUE self)
271{
272    EVP_PKEY *pkey;
273
274    GetPKeyDH(self, pkey);
275
276    return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
277}
278
279/*
280 *  call-seq:
281 *     dh.to_pem -> aString
282 *
283 * Encodes this DH to its PEM encoding. Note that any existing per-session
284 * public/private keys will *not* get encoded, just the Diffie-Hellman
285 * parameters will be encoded.
286 */
287static VALUE
288ossl_dh_export(VALUE self)
289{
290    EVP_PKEY *pkey;
291    BIO *out;
292    VALUE str;
293
294    GetPKeyDH(self, pkey);
295    if (!(out = BIO_new(BIO_s_mem()))) {
296	ossl_raise(eDHError, NULL);
297    }
298    if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
299	BIO_free(out);
300	ossl_raise(eDHError, NULL);
301    }
302    str = ossl_membio2str(out);
303
304    return str;
305}
306
307/*
308 *  call-seq:
309 *     dh.to_der -> aString
310 *
311 * Encodes this DH to its DER encoding. Note that any existing per-session
312 * public/private keys will *not* get encoded, just the Diffie-Hellman
313 * parameters will be encoded.
314
315 */
316static VALUE
317ossl_dh_to_der(VALUE self)
318{
319    EVP_PKEY *pkey;
320    unsigned char *p;
321    long len;
322    VALUE str;
323
324    GetPKeyDH(self, pkey);
325    if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
326	ossl_raise(eDHError, NULL);
327    str = rb_str_new(0, len);
328    p = (unsigned char *)RSTRING_PTR(str);
329    if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
330	ossl_raise(eDHError, NULL);
331    ossl_str_adjust(str, p);
332
333    return str;
334}
335
336/*
337 *  call-seq:
338 *     dh.params -> hash
339 *
340 * Stores all parameters of key to the hash
341 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
342 * Don't use :-)) (I's up to you)
343 */
344static VALUE
345ossl_dh_get_params(VALUE self)
346{
347    EVP_PKEY *pkey;
348    VALUE hash;
349
350    GetPKeyDH(self, pkey);
351
352    hash = rb_hash_new();
353
354    rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
355    rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
356    rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
357    rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
358
359    return hash;
360}
361
362/*
363 *  call-seq:
364 *     dh.to_text -> aString
365 *
366 * Prints all parameters of key to buffer
367 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
368 * Don't use :-)) (I's up to you)
369 */
370static VALUE
371ossl_dh_to_text(VALUE self)
372{
373    EVP_PKEY *pkey;
374    BIO *out;
375    VALUE str;
376
377    GetPKeyDH(self, pkey);
378    if (!(out = BIO_new(BIO_s_mem()))) {
379	ossl_raise(eDHError, NULL);
380    }
381    if (!DHparams_print(out, pkey->pkey.dh)) {
382	BIO_free(out);
383	ossl_raise(eDHError, NULL);
384    }
385    str = ossl_membio2str(out);
386
387    return str;
388}
389
390/*
391 *  call-seq:
392 *     dh.public_key -> aDH
393 *
394 * Returns a new DH instance that carries just the public information, i.e.
395 * the prime +p+ and the generator +g+, but no public/private key yet. Such
396 * a pair may be generated using DH#generate_key!. The "public key" needed
397 * for a key exchange with DH#compute_key is considered as per-session
398 * information and may be retrieved with DH#pub_key once a key pair has
399 * been generated.
400 * If the current instance already contains private information (and thus a
401 * valid public/private key pair), this information will no longer be present
402 * in the new instance generated by DH#public_key. This feature is helpful for
403 * publishing the Diffie-Hellman parameters without leaking any of the private
404 * per-session information.
405 *
406 * === Example
407 *  dh = OpenSSL::PKey::DH.new(2048) # has public and private key set
408 *  public_key = dh.public_key # contains only prime and generator
409 *  parameters = public_key.to_der # it's safe to publish this
410 */
411static VALUE
412ossl_dh_to_public_key(VALUE self)
413{
414    EVP_PKEY *pkey;
415    DH *dh;
416    VALUE obj;
417
418    GetPKeyDH(self, pkey);
419    dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */
420    obj = dh_instance(CLASS_OF(self), dh);
421    if (obj == Qfalse) {
422	DH_free(dh);
423	ossl_raise(eDHError, NULL);
424    }
425
426    return obj;
427}
428
429/*
430 *  call-seq:
431 *     dh.check_params -> true | false
432 *
433 * Validates the Diffie-Hellman parameters associated with this instance.
434 * It checks whether a safe prime and a suitable generator are used. If this
435 * is not the case, +false+ is returned.
436 */
437static VALUE
438ossl_dh_check_params(VALUE self)
439{
440    DH *dh;
441    EVP_PKEY *pkey;
442    int codes;
443
444    GetPKeyDH(self, pkey);
445    dh = pkey->pkey.dh;
446
447    if (!DH_check(dh, &codes)) {
448	return Qfalse;
449    }
450
451    return codes == 0 ? Qtrue : Qfalse;
452}
453
454/*
455 *  call-seq:
456 *     dh.generate_key! -> self
457 *
458 * Generates a private and public key unless a private key already exists.
459 * If this DH instance was generated from public DH parameters (e.g. by
460 * encoding the result of DH#public_key), then this method needs to be
461 * called first in order to generate the per-session keys before performing
462 * the actual key exchange.
463 *
464 * === Example
465 *   dh = OpenSSL::PKey::DH.new(2048)
466 *   public_key = dh.public_key #contains no private/public key yet
467 *   public_key.generate_key!
468 *   puts public_key.private? # => true
469 */
470static VALUE
471ossl_dh_generate_key(VALUE self)
472{
473    DH *dh;
474    EVP_PKEY *pkey;
475
476    GetPKeyDH(self, pkey);
477    dh = pkey->pkey.dh;
478
479    if (!DH_generate_key(dh))
480	ossl_raise(eDHError, "Failed to generate key");
481    return self;
482}
483
484/*
485 *  call-seq:
486 *     dh.compute_key(pub_bn) -> aString
487 *
488 * Returns a String containing a shared secret computed from the other party's public value.
489 * See DH_compute_key() for further information.
490 *
491 * === Parameters
492 * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by
493 * DH#public_key as that contains the DH parameters only.
494 */
495static VALUE
496ossl_dh_compute_key(VALUE self, VALUE pub)
497{
498    DH *dh;
499    EVP_PKEY *pkey;
500    BIGNUM *pub_key;
501    VALUE str;
502    int len;
503
504    GetPKeyDH(self, pkey);
505    dh = pkey->pkey.dh;
506    pub_key = GetBNPtr(pub);
507    len = DH_size(dh);
508    str = rb_str_new(0, len);
509    if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
510	ossl_raise(eDHError, NULL);
511    }
512    rb_str_set_len(str, len);
513
514    return str;
515}
516
517OSSL_PKEY_BN(dh, p)
518OSSL_PKEY_BN(dh, g)
519OSSL_PKEY_BN(dh, pub_key)
520OSSL_PKEY_BN(dh, priv_key)
521
522/*
523 * -----BEGIN DH PARAMETERS-----
524 * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
525 * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
526 * -----END DH PARAMETERS-----
527 */
528static unsigned char DEFAULT_DH_512_PRIM[] = {
529    0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
530    0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
531    0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
532    0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
533    0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
534    0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
535    0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
536    0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
537};
538static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
539DH *OSSL_DEFAULT_DH_512 = NULL;
540
541/*
542 * -----BEGIN DH PARAMETERS-----
543 * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
544 * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
545 * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
546 * -----END DH PARAMETERS-----
547 */
548static unsigned char DEFAULT_DH_1024_PRIM[] = {
549    0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
550    0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
551    0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
552    0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
553    0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
554    0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
555    0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
556    0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
557    0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
558    0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
559    0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
560    0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
561    0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
562    0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
563    0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
564    0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
565};
566static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
567DH *OSSL_DEFAULT_DH_1024 = NULL;
568
569static DH*
570ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
571{
572    DH *dh;
573
574    if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
575    dh->p = BN_bin2bn(p, rb_long2int(plen), NULL);
576    dh->g = BN_bin2bn(g, rb_long2int(glen), NULL);
577    if (dh->p == NULL || dh->g == NULL){
578        DH_free(dh);
579	ossl_raise(eDHError, NULL);
580    }
581
582    return dh;
583}
584
585/*
586 * INIT
587 */
588void
589Init_ossl_dh()
590{
591#if 0
592    mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
593    mPKey = rb_define_module_under(mOSSL, "PKey");
594#endif
595
596    /* Document-class: OpenSSL::PKey::DHError
597     *
598     * Generic exception that is raised if an operation on a DH PKey
599     * fails unexpectedly or in case an instantiation of an instance of DH
600     * fails due to non-conformant input data.
601     */
602    eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
603    /* Document-class: OpenSSL::PKey::DH
604     *
605     * An implementation of the Diffie-Hellman key exchange protocol based on
606     * discrete logarithms in finite fields, the same basis that DSA is built
607     * on.
608     *
609     * === Accessor methods for the Diffie-Hellman parameters
610     * * DH#p
611     * The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
612     * * DH#g
613     * The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
614     * * DH#pub_key
615     * The per-session public key (an OpenSSL::BN) matching the private key.
616     * This needs to be passed to DH#compute_key.
617     * * DH#priv_key
618     * The per-session private key, an OpenSSL::BN.
619     *
620     * === Example of a key exchange
621     *  dh1 = OpenSSL::PKey::DH.new(2048)
622     *  der = dh1.public_key.to_der #you may send this publicly to the participating party
623     *  dh2 = OpenSSL::PKey::DH.new(der)
624     *  dh2.generate_key! #generate the per-session key pair
625     *  symm_key1 = dh1.compute_key(dh2.pub_key)
626     *  symm_key2 = dh2.compute_key(dh1.pub_key)
627     *
628     *  puts symm_key1 == symm_key2 # => true
629     */
630    cDH = rb_define_class_under(mPKey, "DH", cPKey);
631    rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
632    rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
633    rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
634    rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
635    rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
636    rb_define_method(cDH, "export", ossl_dh_export, 0);
637    rb_define_alias(cDH, "to_pem", "export");
638    rb_define_alias(cDH, "to_s", "export");
639    rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
640    rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
641    rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
642    rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
643    rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
644
645    DEF_OSSL_PKEY_BN(cDH, dh, p);
646    DEF_OSSL_PKEY_BN(cDH, dh, g);
647    DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
648    DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
649    rb_define_method(cDH, "params", ossl_dh_get_params, 0);
650
651    OSSL_DEFAULT_DH_512 = ossl_create_dh(
652	DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
653	DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
654    OSSL_DEFAULT_DH_1024 = ossl_create_dh(
655	DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
656	DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
657}
658
659#else /* defined NO_DH */
660void
661Init_ossl_dh()
662{
663}
664#endif /* NO_DH */
665