|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_pkey_dh.c 31796 2011-05-29 22:49:10Z yugui $ 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 (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 * call-seq: 00191 * dh.public? -> true | false 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 * call-seq: 00206 * dh.private? -> true | false 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 * call-seq: 00221 * dh.to_pem -> aString 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 * call-seq: 00246 * dh.to_der -> aString 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 * call-seq: 00271 * dh.params -> hash 00272 * 00273 * Stores all parameters of key to the hash 00274 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! 00275 * Don't use :-)) (I's up to you) 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 * call-seq: 00297 * dh.to_text -> aString 00298 * 00299 * Prints all parameters of key to buffer 00300 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! 00301 * Don't use :-)) (I's up to you) 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 * call-seq: 00325 * dh.public_key -> aDH 00326 * 00327 * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY 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); /* err check perfomed by dh_instance */ 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 * call-seq: 00349 * dh.check_params -> true | false 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 * call-seq: 00371 * dh.generate_key -> self 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 * call-seq: 00390 * dh.compute_key(pub_bn) -> aString 00391 * 00392 * === Parameters 00393 * * +pub_bn+ is a OpenSSL::BN. 00394 * 00395 * Returns aString containing a shared secret computed from the other parties public value. 00396 * 00397 * See DH_compute_key() for further information. 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 * -----BEGIN DH PARAMETERS----- 00429 * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2 00430 * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC 00431 * -----END DH PARAMETERS----- 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 * -----BEGIN DH PARAMETERS----- 00448 * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ 00449 * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR 00450 * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC 00451 * -----END DH PARAMETERS----- 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 * INIT 00492 */ 00493 void 00494 Init_ossl_dh() 00495 { 00496 #if 0 /* let rdoc know about mOSSL and mPKey */ 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 /* defined NO_DH */ 00531 void 00532 Init_ossl_dh() 00533 { 00534 } 00535 #endif /* NO_DH */ 00536 00537
1.7.3