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