• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/openssl/ossl_pkey_dh.c

Go to the documentation of this file.
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 

Generated on Sat Jul 7 2012 15:29:11 for Ruby by  doxygen 1.7.1