• 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 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 

Generated on Wed Sep 8 2010 21:54:06 for Ruby by  doxygen 1.7.1