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
00288
00289 static VALUE
00290 ossl_dh_export(VALUE self)
00291 {
00292 EVP_PKEY *pkey;
00293 BIO *out;
00294 VALUE str;
00295
00296 GetPKeyDH(self, pkey);
00297 if (!(out = BIO_new(BIO_s_mem()))) {
00298 ossl_raise(eDHError, NULL);
00299 }
00300 if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
00301 BIO_free(out);
00302 ossl_raise(eDHError, NULL);
00303 }
00304 str = ossl_membio2str(out);
00305
00306 return str;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 static VALUE
00319 ossl_dh_to_der(VALUE self)
00320 {
00321 EVP_PKEY *pkey;
00322 unsigned char *p;
00323 long len;
00324 VALUE str;
00325
00326 GetPKeyDH(self, pkey);
00327 if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
00328 ossl_raise(eDHError, NULL);
00329 str = rb_str_new(0, len);
00330 p = (unsigned char *)RSTRING_PTR(str);
00331 if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
00332 ossl_raise(eDHError, NULL);
00333 ossl_str_adjust(str, p);
00334
00335 return str;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 static VALUE
00347 ossl_dh_get_params(VALUE self)
00348 {
00349 EVP_PKEY *pkey;
00350 VALUE hash;
00351
00352 GetPKeyDH(self, pkey);
00353
00354 hash = rb_hash_new();
00355
00356 rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
00357 rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
00358 rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
00359 rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
00360
00361 return hash;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 static VALUE
00373 ossl_dh_to_text(VALUE self)
00374 {
00375 EVP_PKEY *pkey;
00376 BIO *out;
00377 VALUE str;
00378
00379 GetPKeyDH(self, pkey);
00380 if (!(out = BIO_new(BIO_s_mem()))) {
00381 ossl_raise(eDHError, NULL);
00382 }
00383 if (!DHparams_print(out, pkey->pkey.dh)) {
00384 BIO_free(out);
00385 ossl_raise(eDHError, NULL);
00386 }
00387 str = ossl_membio2str(out);
00388
00389 return str;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 static VALUE
00414 ossl_dh_to_public_key(VALUE self)
00415 {
00416 EVP_PKEY *pkey;
00417 DH *dh;
00418 VALUE obj;
00419
00420 GetPKeyDH(self, pkey);
00421 dh = DHparams_dup(pkey->pkey.dh);
00422 obj = dh_instance(CLASS_OF(self), dh);
00423 if (obj == Qfalse) {
00424 DH_free(dh);
00425 ossl_raise(eDHError, NULL);
00426 }
00427
00428 return obj;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 static VALUE
00440 ossl_dh_check_params(VALUE self)
00441 {
00442 DH *dh;
00443 EVP_PKEY *pkey;
00444 int codes;
00445
00446 GetPKeyDH(self, pkey);
00447 dh = pkey->pkey.dh;
00448
00449 if (!DH_check(dh, &codes)) {
00450 return Qfalse;
00451 }
00452
00453 return codes == 0 ? Qtrue : Qfalse;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 static VALUE
00473 ossl_dh_generate_key(VALUE self)
00474 {
00475 DH *dh;
00476 EVP_PKEY *pkey;
00477
00478 GetPKeyDH(self, pkey);
00479 dh = pkey->pkey.dh;
00480
00481 if (!DH_generate_key(dh))
00482 ossl_raise(eDHError, "Failed to generate key");
00483 return self;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static VALUE
00498 ossl_dh_compute_key(VALUE self, VALUE pub)
00499 {
00500 DH *dh;
00501 EVP_PKEY *pkey;
00502 BIGNUM *pub_key;
00503 VALUE str;
00504 int len;
00505
00506 GetPKeyDH(self, pkey);
00507 dh = pkey->pkey.dh;
00508 pub_key = GetBNPtr(pub);
00509 len = DH_size(dh);
00510 str = rb_str_new(0, len);
00511 if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
00512 ossl_raise(eDHError, NULL);
00513 }
00514 rb_str_set_len(str, len);
00515
00516 return str;
00517 }
00518
00519 OSSL_PKEY_BN(dh, p)
00520 OSSL_PKEY_BN(dh, g)
00521 OSSL_PKEY_BN(dh, pub_key)
00522 OSSL_PKEY_BN(dh, priv_key)
00523
00524
00525
00526
00527
00528
00529
00530 static unsigned char DEFAULT_DH_512_PRIM[] = {
00531 0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
00532 0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
00533 0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
00534 0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
00535 0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
00536 0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
00537 0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
00538 0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
00539 };
00540 static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
00541 DH *OSSL_DEFAULT_DH_512 = NULL;
00542
00543
00544
00545
00546
00547
00548
00549
00550 static unsigned char DEFAULT_DH_1024_PRIM[] = {
00551 0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
00552 0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
00553 0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
00554 0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
00555 0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
00556 0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
00557 0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
00558 0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
00559 0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
00560 0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
00561 0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
00562 0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
00563 0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
00564 0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
00565 0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
00566 0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
00567 };
00568 static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
00569 DH *OSSL_DEFAULT_DH_1024 = NULL;
00570
00571 static DH*
00572 ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
00573 {
00574 DH *dh;
00575
00576 if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
00577 dh->p = BN_bin2bn(p, rb_long2int(plen), NULL);
00578 dh->g = BN_bin2bn(g, rb_long2int(glen), NULL);
00579 if (dh->p == NULL || dh->g == NULL){
00580 DH_free(dh);
00581 ossl_raise(eDHError, NULL);
00582 }
00583
00584 return dh;
00585 }
00586
00587
00588
00589
00590 void
00591 Init_ossl_dh()
00592 {
00593 #if 0
00594 mOSSL = rb_define_module("OpenSSL");
00595 mPKey = rb_define_module_under(mOSSL, "PKey");
00596 #endif
00597
00598
00599
00600
00601
00602
00603
00604 eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
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
00631
00632 cDH = rb_define_class_under(mPKey, "DH", cPKey);
00633 rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
00634 rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
00635 rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
00636 rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
00637 rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
00638 rb_define_method(cDH, "export", ossl_dh_export, 0);
00639 rb_define_alias(cDH, "to_pem", "export");
00640 rb_define_alias(cDH, "to_s", "export");
00641 rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
00642 rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
00643 rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
00644 rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
00645 rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
00646
00647 DEF_OSSL_PKEY_BN(cDH, dh, p);
00648 DEF_OSSL_PKEY_BN(cDH, dh, g);
00649 DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
00650 DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
00651 rb_define_method(cDH, "params", ossl_dh_get_params, 0);
00652
00653 OSSL_DEFAULT_DH_512 = ossl_create_dh(
00654 DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
00655 DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
00656 OSSL_DEFAULT_DH_1024 = ossl_create_dh(
00657 DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
00658 DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
00659 }
00660
00661 #else
00662 void
00663 Init_ossl_dh()
00664 {
00665 }
00666 #endif
00667