|
Ruby 1.9.2p180(2011-02-18revision30909)
|
00001 /* 00002 * $Id: ossl_pkey_dh.c 27440 2010-04-22 08:21:01Z nobu $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 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) { /* PARANOIA? */ \ 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 * Classes 00033 */ 00034 VALUE cDH; 00035 VALUE eDHError; 00036 00037 /* 00038 * Public 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 * Private 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 * call-seq: 00104 * DH.generate(size [, generator]) -> dh 00105 * 00106 * === Parameters 00107 * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure. 00108 * * +generator+ is a small number > 1, typically 2 or 5. 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 * call-seq: 00133 * DH.new([size [, generator] | string]) -> dh 00134 * 00135 * === Parameters 00136 * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure. 00137 * * +generator+ is a small number > 1, typically 2 or 5. 00138 * * +string+ contains the DER or PEM encoded key. 00139 * 00140 * === Examples 00141 * * DH.new -> dh 00142 * * DH.new(1024) -> dh 00143 * * DH.new(1024, 5) -> dh 00144 * * DH.new(File.read('key.pem')) -> dh 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 * call-seq: 00187 * dh.public? -> true | false 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 * call-seq: 00202 * dh.private? -> true | false 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 * call-seq: 00217 * dh.to_pem -> aString 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 * call-seq: 00242 * dh.to_der -> aString 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 * call-seq: 00267 * dh.params -> hash 00268 * 00269 * Stores all parameters of key to the hash 00270 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! 00271 * Don't use :-)) (I's up to you) 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 * call-seq: 00293 * dh.to_text -> aString 00294 * 00295 * Prints all parameters of key to buffer 00296 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! 00297 * Don't use :-)) (I's up to you) 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 * call-seq: 00321 * dh.public_key -> aDH 00322 * 00323 * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY 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); /* err check perfomed by dh_instance */ 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 * call-seq: 00345 * dh.check_params -> true | false 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 * call-seq: 00367 * dh.generate_key -> self 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 * call-seq: 00386 * dh.compute_key(pub_bn) -> aString 00387 * 00388 * === Parameters 00389 * * +pub_bn+ is a OpenSSL::BN. 00390 * 00391 * Returns aString containing a shared secret computed from the other parties public value. 00392 * 00393 * See DH_compute_key() for further information. 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 * -----BEGIN DH PARAMETERS----- 00425 * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2 00426 * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC 00427 * -----END DH PARAMETERS----- 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 * -----BEGIN DH PARAMETERS----- 00444 * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ 00445 * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR 00446 * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC 00447 * -----END DH PARAMETERS----- 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 * INIT 00488 */ 00489 void 00490 Init_ossl_dh() 00491 { 00492 #if 0 /* let rdoc know about mOSSL and mPKey */ 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 /* defined NO_DH */ 00527 void 00528 Init_ossl_dh() 00529 { 00530 } 00531 #endif /* NO_DH */ 00532 00533
1.7.3