00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(OPENSSL_NO_DH)
00012
00013 #include "ossl.h"
00014
00015 #define GetPKeyDH(obj, pkey) do { \
00016 GetPKey((obj), (pkey)); \
00017 if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DH) { \
00018 ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
00019 } \
00020 } while (0)
00021
00022 #define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
00023
00024 #ifdef OSSL_ENGINE_ENABLED
00025 # define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
00026 #else
00027 # define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
00028 #endif
00029
00030
00031
00032
00033
00034 VALUE cDH;
00035 VALUE eDHError;
00036
00037
00038
00039
00040 static VALUE
00041 dh_instance(VALUE klass, DH *dh)
00042 {
00043 EVP_PKEY *pkey;
00044 VALUE obj;
00045
00046 if (!dh) {
00047 return Qfalse;
00048 }
00049 if (!(pkey = EVP_PKEY_new())) {
00050 return Qfalse;
00051 }
00052 if (!EVP_PKEY_assign_DH(pkey, dh)) {
00053 EVP_PKEY_free(pkey);
00054 return Qfalse;
00055 }
00056 WrapPKey(klass, obj, pkey);
00057
00058 return obj;
00059 }
00060
00061 VALUE
00062 ossl_dh_new(EVP_PKEY *pkey)
00063 {
00064 VALUE obj;
00065
00066 if (!pkey) {
00067 obj = dh_instance(cDH, DH_new());
00068 } else {
00069 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) {
00070 ossl_raise(rb_eTypeError, "Not a DH key!");
00071 }
00072 WrapPKey(cDH, obj, pkey);
00073 }
00074 if (obj == Qfalse) {
00075 ossl_raise(eDHError, NULL);
00076 }
00077
00078 return obj;
00079 }
00080
00081
00082
00083
00084 #if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
00085 struct dh_blocking_gen_arg {
00086 DH *dh;
00087 int size;
00088 int gen;
00089 BN_GENCB *cb;
00090 int result;
00091 };
00092
00093 static void *
00094 dh_blocking_gen(void *arg)
00095 {
00096 struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
00097 gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
00098 return 0;
00099 }
00100 #endif
00101
00102 static DH *
00103 dh_generate(int size, int gen)
00104 {
00105 #if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
00106 BN_GENCB cb;
00107 struct ossl_generate_cb_arg cb_arg;
00108 struct dh_blocking_gen_arg gen_arg;
00109 DH *dh = DH_new();
00110
00111 if (!dh) return 0;
00112
00113 memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg));
00114 if (rb_block_given_p())
00115 cb_arg.yield = 1;
00116 BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg);
00117 gen_arg.dh = dh;
00118 gen_arg.size = size;
00119 gen_arg.gen = gen;
00120 gen_arg.cb = &cb;
00121 if (cb_arg.yield == 1) {
00122
00123 dh_blocking_gen(&gen_arg);
00124 } else {
00125
00126 rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
00127 }
00128
00129 if (!gen_arg.result) {
00130 DH_free(dh);
00131 if (cb_arg.state) rb_jump_tag(cb_arg.state);
00132 return 0;
00133 }
00134 #else
00135 DH *dh;
00136
00137 dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
00138 if (!dh) return 0;
00139 #endif
00140
00141 if (!DH_generate_key(dh)) {
00142 DH_free(dh);
00143 return 0;
00144 }
00145
00146 return dh;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static VALUE
00162 ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
00163 {
00164 DH *dh ;
00165 int g = 2;
00166 VALUE size, gen, obj;
00167
00168 if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
00169 g = NUM2INT(gen);
00170 }
00171 dh = dh_generate(NUM2INT(size), g);
00172 obj = dh_instance(klass, dh);
00173 if (obj == Qfalse) {
00174 DH_free(dh);
00175 ossl_raise(eDHError, NULL);
00176 }
00177
00178 return obj;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static VALUE
00205 ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
00206 {
00207 EVP_PKEY *pkey;
00208 DH *dh;
00209 int g = 2;
00210 BIO *in;
00211 VALUE arg, gen;
00212
00213 GetPKey(self, pkey);
00214 if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
00215 dh = DH_new();
00216 }
00217 else if (FIXNUM_P(arg)) {
00218 if (!NIL_P(gen)) {
00219 g = NUM2INT(gen);
00220 }
00221 if (!(dh = dh_generate(FIX2INT(arg), g))) {
00222 ossl_raise(eDHError, NULL);
00223 }
00224 }
00225 else {
00226 arg = ossl_to_der_if_possible(arg);
00227 in = ossl_obj2bio(arg);
00228 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
00229 if (!dh){
00230 OSSL_BIO_reset(in);
00231 dh = d2i_DHparams_bio(in, NULL);
00232 }
00233 BIO_free(in);
00234 if (!dh) {
00235 ossl_raise(eDHError, NULL);
00236 }
00237 }
00238 if (!EVP_PKEY_assign_DH(pkey, dh)) {
00239 DH_free(dh);
00240 ossl_raise(eDHError, NULL);
00241 }
00242 return self;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252 static VALUE
00253 ossl_dh_is_public(VALUE self)
00254 {
00255 EVP_PKEY *pkey;
00256
00257 GetPKeyDH(self, pkey);
00258
00259 return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 static VALUE
00270 ossl_dh_is_private(VALUE self)
00271 {
00272 EVP_PKEY *pkey;
00273
00274 GetPKeyDH(self, pkey);
00275
00276 return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 static VALUE
00288 ossl_dh_export(VALUE self)
00289 {
00290 EVP_PKEY *pkey;
00291 BIO *out;
00292 VALUE str;
00293
00294 GetPKeyDH(self, pkey);
00295 if (!(out = BIO_new(BIO_s_mem()))) {
00296 ossl_raise(eDHError, NULL);
00297 }
00298 if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
00299 BIO_free(out);
00300 ossl_raise(eDHError, NULL);
00301 }
00302 str = ossl_membio2str(out);
00303
00304 return str;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 static VALUE
00317 ossl_dh_to_der(VALUE self)
00318 {
00319 EVP_PKEY *pkey;
00320 unsigned char *p;
00321 long len;
00322 VALUE str;
00323
00324 GetPKeyDH(self, pkey);
00325 if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
00326 ossl_raise(eDHError, NULL);
00327 str = rb_str_new(0, len);
00328 p = (unsigned char *)RSTRING_PTR(str);
00329 if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
00330 ossl_raise(eDHError, NULL);
00331 ossl_str_adjust(str, p);
00332
00333 return str;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 static VALUE
00345 ossl_dh_get_params(VALUE self)
00346 {
00347 EVP_PKEY *pkey;
00348 VALUE hash;
00349
00350 GetPKeyDH(self, pkey);
00351
00352 hash = rb_hash_new();
00353
00354 rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
00355 rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
00356 rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
00357 rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
00358
00359 return hash;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 static VALUE
00371 ossl_dh_to_text(VALUE self)
00372 {
00373 EVP_PKEY *pkey;
00374 BIO *out;
00375 VALUE str;
00376
00377 GetPKeyDH(self, pkey);
00378 if (!(out = BIO_new(BIO_s_mem()))) {
00379 ossl_raise(eDHError, NULL);
00380 }
00381 if (!DHparams_print(out, pkey->pkey.dh)) {
00382 BIO_free(out);
00383 ossl_raise(eDHError, NULL);
00384 }
00385 str = ossl_membio2str(out);
00386
00387 return str;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 static VALUE
00412 ossl_dh_to_public_key(VALUE self)
00413 {
00414 EVP_PKEY *pkey;
00415 DH *dh;
00416 VALUE obj;
00417
00418 GetPKeyDH(self, pkey);
00419 dh = DHparams_dup(pkey->pkey.dh);
00420 obj = dh_instance(CLASS_OF(self), dh);
00421 if (obj == Qfalse) {
00422 DH_free(dh);
00423 ossl_raise(eDHError, NULL);
00424 }
00425
00426 return obj;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 static VALUE
00438 ossl_dh_check_params(VALUE self)
00439 {
00440 DH *dh;
00441 EVP_PKEY *pkey;
00442 int codes;
00443
00444 GetPKeyDH(self, pkey);
00445 dh = pkey->pkey.dh;
00446
00447 if (!DH_check(dh, &codes)) {
00448 return Qfalse;
00449 }
00450
00451 return codes == 0 ? Qtrue : Qfalse;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 static VALUE
00471 ossl_dh_generate_key(VALUE self)
00472 {
00473 DH *dh;
00474 EVP_PKEY *pkey;
00475
00476 GetPKeyDH(self, pkey);
00477 dh = pkey->pkey.dh;
00478
00479 if (!DH_generate_key(dh))
00480 ossl_raise(eDHError, "Failed to generate key");
00481 return self;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 static VALUE
00496 ossl_dh_compute_key(VALUE self, VALUE pub)
00497 {
00498 DH *dh;
00499 EVP_PKEY *pkey;
00500 BIGNUM *pub_key;
00501 VALUE str;
00502 int len;
00503
00504 GetPKeyDH(self, pkey);
00505 dh = pkey->pkey.dh;
00506 pub_key = GetBNPtr(pub);
00507 len = DH_size(dh);
00508 str = rb_str_new(0, len);
00509 if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
00510 ossl_raise(eDHError, NULL);
00511 }
00512 rb_str_set_len(str, len);
00513
00514 return str;
00515 }
00516
00517 OSSL_PKEY_BN(dh, p)
00518 OSSL_PKEY_BN(dh, g)
00519 OSSL_PKEY_BN(dh, pub_key)
00520 OSSL_PKEY_BN(dh, priv_key)
00521
00522
00523
00524
00525
00526
00527
00528 static unsigned char DEFAULT_DH_512_PRIM[] = {
00529 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
00530 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
00531 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
00532 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
00533 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
00534 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
00535 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
00536 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
00537 };
00538 static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
00539 DH *OSSL_DEFAULT_DH_512 = NULL;
00540
00541
00542
00543
00544
00545
00546
00547
00548 static unsigned char DEFAULT_DH_1024_PRIM[] = {
00549 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
00550 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
00551 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
00552 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
00553 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
00554 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
00555 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
00556 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
00557 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
00558 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
00559 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
00560 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
00561 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
00562 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
00563 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
00564 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
00565 };
00566 static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
00567 DH *OSSL_DEFAULT_DH_1024 = NULL;
00568
00569 static DH*
00570 ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
00571 {
00572 DH *dh;
00573
00574 if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
00575 dh->p = BN_bin2bn(p, rb_long2int(plen), NULL);
00576 dh->g = BN_bin2bn(g, rb_long2int(glen), NULL);
00577 if (dh->p == NULL || dh->g == NULL){
00578 DH_free(dh);
00579 ossl_raise(eDHError, NULL);
00580 }
00581
00582 return dh;
00583 }
00584
00585
00586
00587
00588 void
00589 Init_ossl_dh()
00590 {
00591 #if 0
00592 mOSSL = rb_define_module("OpenSSL");
00593 mPKey = rb_define_module_under(mOSSL, "PKey");
00594 #endif
00595
00596
00597
00598
00599
00600
00601
00602 eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 cDH = rb_define_class_under(mPKey, "DH", cPKey);
00631 rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
00632 rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
00633 rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
00634 rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
00635 rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
00636 rb_define_method(cDH, "export", ossl_dh_export, 0);
00637 rb_define_alias(cDH, "to_pem", "export");
00638 rb_define_alias(cDH, "to_s", "export");
00639 rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
00640 rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
00641 rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
00642 rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
00643 rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
00644
00645 DEF_OSSL_PKEY_BN(cDH, dh, p);
00646 DEF_OSSL_PKEY_BN(cDH, dh, g);
00647 DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
00648 DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
00649 rb_define_method(cDH, "params", ossl_dh_get_params, 0);
00650
00651 OSSL_DEFAULT_DH_512 = ossl_create_dh(
00652 DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
00653 DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
00654 OSSL_DEFAULT_DH_1024 = ossl_create_dh(
00655 DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
00656 DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
00657 }
00658
00659 #else
00660 void
00661 Init_ossl_dh()
00662 {
00663 }
00664 #endif
00665