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