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