diff options
author | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-06-06 00:33:41 +0000 |
---|---|---|
committer | Michal Rokos <m.rokos@sh.cvut.cz> | 2002-06-06 00:33:41 +0000 |
commit | b3538dbaeb0eefca399b2668a8bfb035080875c6 (patch) | |
tree | 217b66ceade5d2e6cd63cfafab27a683cb3f89c7 | |
parent | 7ad7aa4ecf8b0c5e49a5944cddbacf9e7f691797 (diff) | |
download | ruby-openssl-history-b3538dbaeb0eefca399b2668a8bfb035080875c6.tar.gz |
PKey (DH|DSA|RSA) cleanup and rewrite (EVP_PKEY is now wrapped), final cleaning for ossl.h
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | lib/openssl/pkey.rb | 47 | ||||
-rw-r--r-- | ossl.c | 16 | ||||
-rw-r--r-- | ossl.h | 67 | ||||
-rw-r--r-- | ossl_digest.c | 1 | ||||
-rw-r--r-- | ossl_ns_spki.c | 1 | ||||
-rw-r--r-- | ossl_pkcs7.c | 1 | ||||
-rw-r--r-- | ossl_pkey.c | 136 | ||||
-rw-r--r-- | ossl_pkey.h | 55 | ||||
-rw-r--r-- | ossl_pkey_dh.c | 273 | ||||
-rw-r--r-- | ossl_pkey_dsa.c | 378 | ||||
-rw-r--r-- | ossl_pkey_rsa.c | 422 | ||||
-rw-r--r-- | ossl_rand.c | 1 | ||||
-rw-r--r-- | ossl_ssl.c | 11 | ||||
-rw-r--r-- | ossl_ssl.h | 21 |
15 files changed, 639 insertions, 799 deletions
@@ -3,6 +3,11 @@ ChangeLog for ### CHANGE LOG ### +Thu, 6 Jun 2002 02:28:25 +0200 -- Michal Rokos <m.rokos@sh.cvut.cz> + * ssl.h: NEW (bits from ossl.h) + * ossl.h: is now tidy + * pkey*.[ch]: big internal rewrite and cleanup for (DH|DSA|RSA) as well as for PKey (EVP_PKEY is now wrapped - so no extra structs!) NEEDS TO BE TESTED!!! + Wed, 5 Jun 2002 12:17:18 +0200 -- Michal Rokos <m.rokos@sh.cvut.cz> * rand.h: NEW (bits from ossl.h) * rand.c: port & cleanup @@ -20,7 +25,8 @@ Wed, 5 Jun 2002 10:14:54 +0200 -- Michal Rokos <m.rokos@sh.cvut.cz> * ossl.c: helper function 'string2hex' * hmac.c: use 'string2hex' * digest.c: ditto. - * hmac:c: cleanup + * hmac.c: cleanup + * hmac.c: renamed #hmac to #digest and #hexhmac to #hexdigest Tue, 4 Jun 2002 23:26:07 +0200 -- Michal Rokos <m.rokos@sh.cvut.cz> * bn.c: cleanup (remove oddly initialized vars) diff --git a/lib/openssl/pkey.rb b/lib/openssl/pkey.rb index 609511a..7067130 100644 --- a/lib/openssl/pkey.rb +++ b/lib/openssl/pkey.rb @@ -23,20 +23,6 @@ module PKey if defined? DSA class DSA - def DSA::new(arg, pass=nil) - if arg.kind_of? Fixnum - DSA::generate(arg) {|p,n| - if block_given? then yield [p,n] end - } - else - DSA::new_from_pem(arg, pass) - end - end # DSA::new - # - # DSA::new_from_pem(PEM string, pass) is built-in - # DSA::new_from_fixnum(size) is an alias to DSA::generate(size) - # DSA::generate(size) is built-in; yields p,n - # def sign(digest, data) unless private? raise OpenSSL::PKey::DSAError, "Cannot sign with public key!" @@ -61,20 +47,6 @@ end #defined? DSA if defined? RSA class RSA - def RSA::new(arg, pass=nil) - if arg.kind_of? Fixnum - RSA::generate(arg) {|p,n| - if block_given? then yield [p,n] end - } - else - RSA::new_from_pem(arg, pass) - end - end # RSA::new - # - # RSA::new_from_pem(PEM string, pass) is built-in - # RSA::new_from_fixnum(size) is an alias to RSA::generate(size) - # RSA::generate(size) is built-in; yields p,n - # def sign(digest, data) unless self.private? raise OpenSSL::PKey::RSAError, "Cannot sign with public key!" @@ -99,25 +71,6 @@ if defined? RSA end # RSA end # defined? RSA -if defined? DH - class DH - def DH::new(arg, gen = 2) - if arg.kind_of? Fixnum - DH::generate(arg, gen) {|p,n| - if block_given? then yield [p,n] end - } - else - DH::new_from_pem(arg) - end - end # DH::new - # - # DH::new_from_pem(PEM string, pass) is built-in - # DH::new_from_fixnum(size, gen) is an alias to DH::generate(size, gen) - # DH::generate(size, gen) is built-in; yields p,n - # - end # DH -end # defined? DH - end # PKey end # OpenSSL @@ -123,14 +123,9 @@ string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len) } /* - * Modules + * main module */ VALUE mOSSL; -VALUE mDigest; -VALUE mNetscape; -VALUE mPKey; -VALUE mRandom; -VALUE mSSL; /* * OpenSSLError < StandardError @@ -146,7 +141,6 @@ Init_openssl() #if defined(OSSL_DEBUG) CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); #endif - /* * Init all digests, ciphers */ @@ -154,11 +148,9 @@ Init_openssl() ERR_load_crypto_strings(); /* - * Universe of Modules + * Init main module */ mOSSL = rb_define_module("OpenSSL"); - mPKey = rb_define_module_under(mOSSL, "PKey"); - mSSL = rb_define_module_under(mOSSL, "SSL"); /* * Constants @@ -182,9 +174,9 @@ Init_openssl() Init_ossl_hmac(); Init_ossl_ns_spki(); Init_ossl_pkcs7(); - Init_ossl_pkey(mPKey); + Init_ossl_pkey(); Init_ossl_rand(); - Init_ossl_ssl(mSSL); + Init_ossl_ssl(); Init_ossl_x509(); } @@ -55,29 +55,11 @@ extern "C" { * Common Module */ extern VALUE mOSSL; -extern VALUE mPKey; -extern VALUE mSSL; /* * Common Error Class */ -VALUE eOSSLError; - -/* - * Classes - */ -extern VALUE cSSLSocket; -extern VALUE eSSLError; -/* PKey */ -extern ID id_private_q; -extern VALUE cPKey; -extern VALUE ePKeyError; -extern VALUE cRSA; -extern VALUE eRSAError; -extern VALUE cDSA; -extern VALUE eDSAError; -extern VALUE cDH; -extern VALUE eDHError; +extern VALUE eOSSLError; /* * CheckTypes @@ -125,48 +107,8 @@ int string2hex(char *, int, char **, int *); #endif /* OSSL_DEBUG */ /* - * PKey - */ -VALUE ossl_pkey_new(EVP_PKEY *); -VALUE ossl_pkey_new_from_file(VALUE); -EVP_PKEY *ossl_pkey_get_EVP_PKEY(VALUE); -void Init_ossl_pkey(VALUE); - -/* - * RSA - */ -#if !defined(OPENSSL_NO_RSA) -VALUE ossl_rsa_new(RSA *); -RSA *ossl_rsa_get_RSA(VALUE); -EVP_PKEY *ossl_rsa_get_EVP_PKEY(VALUE); -#endif /* NO_RSA */ -void Init_ossl_rsa(VALUE, VALUE, VALUE); - -/* - * DSA - */ -#if !defined(OPENSSL_NO_DSA) -VALUE ossl_dsa_new(DSA *); -DSA *ossl_dsa_get_DSA(VALUE); -EVP_PKEY *ossl_dsa_get_EVP_PKEY(VALUE); -#endif /* NO_DSA */ -void Init_ossl_dsa(VALUE, VALUE, VALUE); - -/* - * DH - */ -#if !defined(OPENSSL_NO_DH) -VALUE ossl_dh_new(DH *); -DH *ossl_dh_get_DH(VALUE); -EVP_PKEY *ossl_dh_get_EVP_PKEY(VALUE); -#endif /* NO_DH */ -void Init_ossl_dh(VALUE, VALUE, VALUE); - -/* - * SSL + * Include all parts */ -void Init_ossl_ssl(VALUE); - #include "openssl_missing.h" #include "ossl_bn.h" #include "ossl_cipher.h" @@ -175,14 +117,9 @@ void Init_ossl_ssl(VALUE); #include "ossl_hmac.h" #include "ossl_ns_spki.h" #include "ossl_pkcs7.h" -/* - * TODO #include "ossl_pkey.h" - */ #include "ossl_rand.h" -/* #include "ossl_ssl.h" - */ #include "ossl_version.h" #include "ossl_x509.h" diff --git a/ossl_digest.c b/ossl_digest.c index 7a444ba..f90e589 100644 --- a/ossl_digest.c +++ b/ossl_digest.c @@ -30,6 +30,7 @@ /* * Classes */ +VALUE mDigest; VALUE cDigest; VALUE eDigestError; diff --git a/ossl_ns_spki.c b/ossl_ns_spki.c index d23cd97..4702988 100644 --- a/ossl_ns_spki.c +++ b/ossl_ns_spki.c @@ -26,6 +26,7 @@ /* * Classes */ +VALUE mNetscape; VALUE cSPKI; VALUE eSPKIError; diff --git a/ossl_pkcs7.c b/ossl_pkcs7.c index 0c33b89..edcd97a 100644 --- a/ossl_pkcs7.c +++ b/ossl_pkcs7.c @@ -54,6 +54,7 @@ /* * Classes */ +VALUE mPKCS7; VALUE cPKCS7; VALUE cPKCS7SignerInfo; VALUE ePKCS7Error; diff --git a/ossl_pkey.c b/ossl_pkey.c index 16e39c6..7d38293 100644 --- a/ossl_pkey.c +++ b/ossl_pkey.c @@ -9,81 +9,64 @@ * (See the file 'LICENCE'.) */ #include "ossl.h" -#include "ossl_pkey.h" - -#define GetPKey(obj, pkeyp) do {\ - Data_Get_Struct(obj, ossl_pkey, pkeyp);\ - if (!pkeyp->get_EVP_PKEY) rb_raise(ePKeyError, "not initialized!");\ -} while (0) /* * Classes */ -ID id_private_q; +VALUE mPKey; VALUE cPKey; VALUE ePKeyError; - -/* - * Struct - * see ossl_pkey.h - */ +ID id_private_q; /* * Public */ VALUE -ossl_pkey_new(EVP_PKEY *key) +ossl_pkey_new(EVP_PKEY *pkey) { - if (!key) + if (!pkey) { rb_raise(ePKeyError, "Cannot make new key from NULL."); - - switch (key->type) { + } + switch (EVP_PKEY_type(pkey->type)) { #if !defined(OPENSSL_NO_RSA) case EVP_PKEY_RSA: - return ossl_rsa_new(key->pkey.rsa); + return ossl_rsa_new(pkey); #endif #if !defined(OPENSSL_NO_DSA) case EVP_PKEY_DSA: - return ossl_dsa_new(key->pkey.dsa); + return ossl_dsa_new(pkey); #endif #if !defined(OPENSSL_NO_DH) case EVP_PKEY_DH: - return ossl_dh_new(key->pkey.dh); + return ossl_dh_new(pkey); #endif + default: + rb_raise(ePKeyError, "unsupported key type"); } - - rb_raise(ePKeyError, "unsupported key type"); - return Qnil; + return Qnil; /* not reached */ } VALUE ossl_pkey_new_from_file(VALUE filename) { - FILE *fp = NULL; - EVP_PKEY *pkey = NULL; + FILE *fp; + EVP_PKEY *pkey; VALUE obj; - filename = rb_str_to_str(filename); - Check_SafeStr(filename); + SafeStringValue(filename); - if ((fp = fopen(RSTRING(filename)->ptr, "r")) == NULL) + if (!(fp = fopen(StringValuePtr(filename), "r"))) { rb_raise(ePKeyError, "%s", strerror(errno)); - - /* - * MR: - * How about PublicKeys from file? - * pkey = PEM_read_PublicKey(fp, NULL, NULL, NULL); - * MISSING IN OPENSSL - */ + } /* * Will we handle user passwords? */ pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); fclose(fp); - if (!pkey) + if (!pkey) { OSSL_Raise(ePKeyError, ""); - + } obj = ossl_pkey_new(pkey); EVP_PKEY_free(pkey); @@ -93,45 +76,92 @@ ossl_pkey_new_from_file(VALUE filename) EVP_PKEY * ossl_pkey_get_EVP_PKEY(VALUE obj) { - ossl_pkey *pkeyp = NULL; + EVP_PKEY *pkey; - OSSL_Check_Type(obj, cPKey); - - GetPKey(obj, pkeyp); + SafeGetPKey(obj, pkey); - return pkeyp->get_EVP_PKEY(obj); + obj = ossl_pkey_new(pkey); + + GetPKey(obj, pkey); + + return pkey; } /* * Private */ static VALUE -ossl_pkey_s_new(int argc, VALUE *argv, VALUE klass) +ossl_pkey_s_allocate(VALUE klass) +{ + EVP_PKEY *pkey; + VALUE obj; + + if (!(pkey = EVP_PKEY_new())) { + OSSL_Raise(ePKeyError, ""); + } + WrapPKey(klass, obj, pkey); + + return obj; +} + +static VALUE +ossl_pkey_initialize(VALUE self) { - if (klass == cPKey) - rb_raise(rb_eNotImpError, "cannot do PKey::PKey.new - it is an abstract class"); + if (rb_obj_is_instance_of(self, cPKey)) { + rb_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class."); + } else { + rb_warn("PKey#initialize called! Something sucks here..."); + } + return self; +} + +static VALUE +ossl_pkey_to_der(VALUE self) +{ + EVP_PKEY *pkey = NULL; + X509_PUBKEY *key = NULL; + VALUE str; - return Qnil; + GetPKey(self, pkey); + + if (!(key = X509_PUBKEY_new())) { + OSSL_Raise(ePKeyError, ""); + } + if (!X509_PUBKEY_set(&key, pkey)) { + X509_PUBKEY_free(key); + OSSL_Raise(ePKeyError, ""); + } + + str = rb_str_new(key->public_key->data, key->public_key->length); + X509_PUBKEY_free(key); + + return str; } /* * INIT */ void -Init_ossl_pkey(VALUE module) +Init_ossl_pkey() { - id_private_q = rb_intern("private?"); + mPKey = rb_define_module_under(mOSSL, "PKey"); + + ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError); + + cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject); - ePKeyError = rb_define_class_under(module, "PKeyError", eOSSLError); + rb_define_singleton_method(cPKey, "allocate", ossl_pkey_s_allocate, 0); + rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); - cPKey = rb_define_class_under(module, "PKey", rb_cObject); - rb_define_singleton_method(cPKey, "new", ossl_pkey_s_new, -1); + rb_define_method(cPKey, "to_der", ossl_pkey_to_der, 0); + + id_private_q = rb_intern("private?"); /* * INIT rsa, dsa */ - Init_ossl_rsa(module, cPKey, ePKeyError); - Init_ossl_dsa(module, cPKey, ePKeyError); - Init_ossl_dh(module, cPKey, ePKeyError); + Init_ossl_rsa(); + Init_ossl_dsa(); + Init_ossl_dh(); } diff --git a/ossl_pkey.h b/ossl_pkey.h index 6d2e82c..f237151 100644 --- a/ossl_pkey.h +++ b/ossl_pkey.h @@ -11,12 +11,59 @@ #if !defined(_OSSL_PKEY_H_) #define _OSSL_PKEY_H_ +extern VALUE mPKey; +extern VALUE cPKey; +extern VALUE ePKeyError; +extern ID id_private_q; + +#define WrapPKey(klass, obj, pkey) do { \ + if (!pkey) { \ + rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \ + } \ + obj = Data_Wrap_Struct(klass, 0, EVP_PKEY_free, pkey); \ +} while (0) +#define GetPKey(obj, pkey) do {\ + Data_Get_Struct(obj, EVP_PKEY, pkey);\ + if (!pkey) { \ + rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\ + } \ +} while (0) +#define SafeGetPKey(obj, pkey) do { \ + OSSL_Check_Kind(obj, cPKey); \ + GetPKey(obj, pkey); \ +} while (0) + +VALUE ossl_pkey_new(EVP_PKEY *); +VALUE ossl_pkey_new_from_file(VALUE); +EVP_PKEY *ossl_pkey_get_EVP_PKEY(VALUE); +void Init_ossl_pkey(void); + +/* + * RSA + */ +extern VALUE cRSA; +extern VALUE eRSAError; + +VALUE ossl_rsa_new(EVP_PKEY *); +void Init_ossl_rsa(); + +/* + * DSA + */ +extern VALUE cDSA; +extern VALUE eDSAError; + +VALUE ossl_dsa_new(EVP_PKEY *); +void Init_ossl_dsa(); + /* - * Struct + * DH */ -typedef struct ossl_pkey_st { - EVP_PKEY *(*get_EVP_PKEY)(VALUE); -} ossl_pkey; +extern VALUE cDH; +extern VALUE eDHError; + +VALUE ossl_dh_new(EVP_PKEY *); +void Init_ossl_dh(); #endif /* _OSSL_PKEY_H_ */ diff --git a/ossl_pkey_dh.c b/ossl_pkey_dh.c index 9b79b9c..8a02562 100644 --- a/ossl_pkey_dh.c +++ b/ossl_pkey_dh.c @@ -11,16 +11,12 @@ #if !defined(OPENSSL_NO_DH) #include "ossl.h" -#include "ossl_pkey.h" -#define MakeDH(obj, dhp) do {\ - obj = Data_Make_Struct(cDH, ossl_dh, 0, ossl_dh_free, dhp);\ - dhp->pkey.get_EVP_PKEY = ossl_dh_get_EVP_PKEY;\ -} while (0) - -#define GetDH(obj, dhp) do {\ - Data_Get_Struct(obj, ossl_dh, dhp);\ - if (!dhp->dh) rb_raise(eDHError, "not initialized!");\ +#define GetPKeyDH(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { /* PARANOIA? */ \ + rb_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \ + } \ } while (0) #define DH_PRIVATE(dh) ((dh)->priv_key) @@ -32,113 +28,56 @@ VALUE cDH; VALUE eDHError; /* - * Struct - */ -typedef struct ossl_dh_st { - ossl_pkey pkey; - DH *dh; -} ossl_dh; - -static void -ossl_dh_free(ossl_dh *dhp) -{ - if (dhp) { - if (dhp->dh) DH_free(dhp->dh); - dhp->dh = NULL; - free(dhp); - } -} - -/* * Public */ -VALUE -ossl_dh_new(DH *dh) +static VALUE +dh_instance(VALUE klass, DH *dh) { - ossl_dh *dhp = NULL; - DH *new = NULL; + EVP_PKEY *pkey; VALUE obj; - - if (!dh) - new = DH_new(); - else new = DHparams_dup(dh); - - if (!new) - OSSL_Raise(eDHError, ""); - MakeDH(obj, dhp); - dhp->dh = new; - - return obj; -} - -DH * -ossl_dh_get_DH(VALUE obj) -{ - ossl_dh *dhp = NULL; - DH *dh = NULL; - - OSSL_Check_Kind(obj, cDH); - GetDH(obj, dhp); - - dh = DHparams_dup(dhp->dh); - - if (!dh) - OSSL_Raise(eDHError, ""); + if (!dh) { + return Qfalse; + } + if (!(pkey = EVP_PKEY_new())) { + return Qfalse; + } + if (!EVP_PKEY_assign_DH(pkey, dh)) { + EVP_PKEY_free(pkey); + return Qfalse; + } + WrapPKey(klass, obj, pkey); - return dh; + return obj; } -EVP_PKEY * -ossl_dh_get_EVP_PKEY(VALUE obj) +VALUE +ossl_dh_new(EVP_PKEY *pkey) { DH *dh = NULL; - EVP_PKEY *pkey = NULL; - - dh = ossl_dh_get_DH(obj); + VALUE obj; - if (!(pkey = EVP_PKEY_new())) { - DH_free(dh); - OSSL_Raise(eDHError, ""); + if (pkey && EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { + rb_raise(rb_eTypeError, "Not a DH key!"); + } + if (!pkey) { /* all errs handled by dh_instance */ + dh = DH_new(); + } else { + dh = DHparams_dup(dh); } - if (!EVP_PKEY_assign_DH(pkey, dh)) { /* NO DUP - don't free! */ + obj = dh_instance(cDH, dh); + + if (obj == Qfalse) { DH_free(dh); - EVP_PKEY_free(pkey); OSSL_Raise(eDHError, ""); } - - return pkey; + return obj; } /* * Private */ -static VALUE -ossl_dh_s_new_from_pem(VALUE klass, VALUE buffer) -{ - ossl_dh *dhp = NULL; - DH *dh = NULL; - BIO *in = NULL; - VALUE obj; - - buffer = rb_String(buffer); - - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) - OSSL_Raise(eDHError, ""); - - if (!(dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL))) { - BIO_free(in); - OSSL_Raise(eDHError, ""); - } - BIO_free(in); - - MakeDH(obj, dhp); - dhp->dh = dh; - - return obj; -} - /* * CB for yielding when generating DH params */ @@ -154,76 +93,126 @@ ossl_dh_generate_cb(int p, int n, void *arg) rb_yield(ary); } -static VALUE -ossl_dh_s_generate(VALUE klass, VALUE size, VALUE gen) +static DH * +dh_generate(int size, int gen) { - ossl_dh *dhp = NULL; - DH *dh = NULL; + DH *dh; void (*cb)(int, int, void *) = NULL; - VALUE obj; - - Check_Type(size, T_FIXNUM); - - if (rb_block_given_p()) - cb = ossl_dh_generate_cb; - if (!(dh = DH_generate_parameters(FIX2INT(size), FIX2INT(gen), cb, NULL))) { /* arg to cb = NULL */ - OSSL_Raise(eDHError, ""); + if (rb_block_given_p()) { + cb = ossl_dh_generate_cb; + } + if (!(dh = DH_generate_parameters(size, gen, cb, NULL))) { /* arg to cb = NULL */ + return 0; } if (!DH_generate_key(dh)) { DH_free(dh); - OSSL_Raise(eDHError, ""); + return 0; } + return dh; +} + +static VALUE +ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) +{ + DH *dh ; + int g = 2; + VALUE size, gen, obj; - MakeDH(obj, dhp); - dhp->dh = dh; + if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) { + g = FIX2INT(gen); + } + dh = dh_generate(FIX2INT(size), g); + obj = dh_instance(klass, dh); + + if (obj == Qfalse) { + DH_free(dh); + OSSL_Raise(eDHError, ""); + } return obj; } static VALUE +ossl_dh_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + DH *dh; + int g = 2; + BIO *in; + VALUE buffer, gen; + + GetPKeyDH(self, pkey); + + rb_scan_args(argc, argv, "11", &buffer, &gen); + + if (FIXNUM_P(buffer)) { + if (!NIL_P(gen)) { + g = FIX2INT(gen); + } + if (!(dh = dh_generate(FIX2INT(buffer), g))) { + OSSL_Raise(eDHError, ""); + } + } else { + StringValue(buffer); + + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) { + OSSL_Raise(eDHError, ""); + } + if (!(dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL))) { + BIO_free(in); + OSSL_Raise(eDHError, ""); + } + BIO_free(in); + } + if (!EVP_PKEY_assign_DH(pkey, dh)) { + DH_free(dh); + OSSL_Raise(eRSAError, ""); + } + return self; +} + +static VALUE ossl_dh_is_public(VALUE self) { - ossl_dh *dhp = NULL; + EVP_PKEY *pkey; - GetDH(self, dhp); + GetPKeyDH(self, pkey); /* * Do we need to check dhp->dh->public_pkey? * return Qtrue; */ - return (dhp->dh->pub_key) ? Qtrue : Qfalse; + return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse; } static VALUE ossl_dh_is_private(VALUE self) { - ossl_dh *dhp = NULL; - - GetDH(self, dhp); + EVP_PKEY *pkey; + + GetPKeyDH(self, pkey); - return (DH_PRIVATE(dhp->dh)) ? Qtrue : Qfalse; + return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse; } static VALUE ossl_dh_export(VALUE self) { - ossl_dh *dhp = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; VALUE str; - GetDH(self, dhp); + GetPKeyDH(self, pkey); if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eDHError, ""); } - - if (!PEM_write_bio_DHparams(out, dhp->dh)) { + if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) { BIO_free(out); OSSL_Raise(eDHError, ""); } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -239,21 +228,20 @@ ossl_dh_export(VALUE self) static VALUE ossl_dh_to_text(VALUE self) { - ossl_dh *dhp = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; VALUE str; - GetDH(self, dhp); + GetPKeyDH(self, pkey); if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eDHError, ""); } - if (!DHparams_print(out, dhp->dh)) { + if (!DHparams_print(out, pkey->pkey.dh)) { BIO_free(out); OSSL_Raise(eDHError, ""); } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -267,17 +255,19 @@ ossl_dh_to_text(VALUE self) static VALUE ossl_dh_to_public_key(VALUE self) { - ossl_dh *dhp1 = NULL, *dhp2 = NULL; + EVP_PKEY *pkey; + DH *dh; VALUE obj; - GetDH(self, dhp1); + GetPKeyDH(self, pkey); - MakeDH(obj, dhp2); - - if (!(dhp2->dh = DHparams_dup(dhp1->dh))) { + dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */ + obj = dh_instance(CLASS_OF(self), dh); + + if (obj == Qfalse) { + DH_free(dh); OSSL_Raise(eDHError, ""); } - return obj; } @@ -285,15 +275,14 @@ ossl_dh_to_public_key(VALUE self) * INIT */ void -Init_ossl_dh(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_dh() { eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError); cDH = rb_define_class_under(mPKey, "DH", cPKey); - rb_define_singleton_method(cDH, "new_from_pem", ossl_dh_s_new_from_pem, 1); - rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, 2); - rb_define_alias(CLASS_OF(cDH), "new_from_fixnum", "generate"); + rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); + rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); @@ -304,10 +293,10 @@ Init_ossl_dh(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) } #else /* defined NO_DH */ -# warning >>> OpenSSL is compiled without DH support <<< +# warning >>> OpenSSL is compiled without DH support <<< void -Init_ossl_dh(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_dh() { rb_warning("OpenSSL is compiled without DH support"); } diff --git a/ossl_pkey_dsa.c b/ossl_pkey_dsa.c index d0779ce..39ac50b 100644 --- a/ossl_pkey_dsa.c +++ b/ossl_pkey_dsa.c @@ -11,16 +11,12 @@ #if !defined(OPENSSL_NO_DSA) #include "ossl.h" -#include "ossl_pkey.h" -#define MakeDSA(obj, dsap) do {\ - obj = Data_Make_Struct(cDSA, ossl_dsa, 0, ossl_dsa_free, dsap);\ - dsap->pkey.get_EVP_PKEY = ossl_dsa_get_EVP_PKEY;\ -} while (0) - -#define GetDSA(obj, dsap) do {\ - Data_Get_Struct(obj, ossl_dsa, dsap);\ - if (!dsap->dsa) rb_raise(eDSAError, "not initialized!");\ +#define GetPKeyDSA(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \ + rb_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \ + } \ } while (0) #define DSA_PRIVATE(dsa) ((dsa)->priv_key) @@ -32,126 +28,57 @@ VALUE cDSA; VALUE eDSAError; /* - * Struct - */ -typedef struct ossl_dsa_st { - ossl_pkey pkey; - DSA *dsa; -} ossl_dsa; - -static void -ossl_dsa_free(ossl_dsa *dsap) -{ - if (dsap) { - if (dsap->dsa) DSA_free(dsap->dsa); - dsap->dsa = NULL; - free(dsap); - } -} - -/* * Public */ -VALUE -ossl_dsa_new(DSA *dsa) +static VALUE +dsa_instance(VALUE klass, DSA *dsa) { - ossl_dsa *dsap = NULL; - DSA *new = NULL; + EVP_PKEY *pkey; VALUE obj; - - if (!dsa) - new = DSA_new(); - else new = (DSA_PRIVATE(dsa)) ? DSAPrivateKey_dup(dsa) : DSAPublicKey_dup(dsa); - - if (!new) - OSSL_Raise(eDSAError, ""); - - MakeDSA(obj, dsap); - dsap->dsa = new; - - return obj; -} - -DSA * -ossl_dsa_get_DSA(VALUE obj) -{ - ossl_dsa *dsap = NULL; - DSA *dsa = NULL; - OSSL_Check_Type(obj, cDSA); - GetDSA(obj, dsap); - - dsa = (DSA_PRIVATE(dsap->dsa)) ? DSAPrivateKey_dup(dsap->dsa) : DSAPublicKey_dup(dsap->dsa); - if (!dsa) - OSSL_Raise(eDSAError, ""); - - return dsa; -} - -EVP_PKEY * -ossl_dsa_get_EVP_PKEY(VALUE obj) -{ - DSA *dsa = NULL; - EVP_PKEY *pkey = NULL; - - dsa = ossl_dsa_get_DSA(obj); - + if (!dsa) { + return Qfalse; + } if (!(pkey = EVP_PKEY_new())) { - DSA_free(dsa); - OSSL_Raise(eDSAError, ""); + return Qfalse; } - - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { /* NO DUP - don't free! */ - DSA_free(dsa); + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { EVP_PKEY_free(pkey); - OSSL_Raise(eDSAError, ""); + return Qfalse; } - - return pkey; + WrapPKey(klass, obj, pkey); + + return obj; } -/* - * Private - */ -static VALUE -ossl_dsa_s_new_from_pem(int argc, VALUE *argv, VALUE klass) +VALUE +ossl_dsa_new(EVP_PKEY *pkey) { - ossl_dsa *dsap = NULL; - DSA *dsa = NULL; - BIO *in = NULL; - char *passwd = NULL; - VALUE buffer, pass, obj; - - rb_scan_args(argc, argv, "11", &buffer, &pass); - - buffer = rb_String(buffer); - - if (!NIL_P(pass)) { - pass = rb_String(pass); - passwd = RSTRING(pass)->ptr; - } - /* else passwd = NULL; */ - - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) - OSSL_Raise(eDSAError, ""); + DSA *dsa; + VALUE obj; - if (!(dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL))) { - BIO_reset(in); - - if (!(dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, passwd))) { - BIO_free(in); - OSSL_Raise(eDSAError, "Neither PUB key nor PRIV key:"); - } + if (pkey && EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { + rb_raise(rb_eTypeError, "Not a DSA key!"); + } + if (!pkey) { + dsa = DSA_new(); + } else { + dsa = (DSA_PRIVATE(pkey->pkey.dsa)) ? DSAPrivateKey_dup(pkey->pkey.dsa) : DSAPublicKey_dup(pkey->pkey.dsa); } - BIO_free(in); - MakeDSA(obj, dsap); - dsap->dsa = dsa; + obj = dsa_instance(cDSA, dsa); + if (obj == Qfalse) { + DSA_free(dsa); + OSSL_Raise(eDSAError, ""); + } return obj; } /* + * Private + */ +/* * CB for yielding when generating DSA params */ static void @@ -166,101 +93,147 @@ ossl_dsa_generate_cb(int p, int n, void *arg) rb_yield(ary); } -static VALUE -ossl_dsa_s_generate(VALUE klass, VALUE size) +static DSA * +dsa_generate(int size) { - ossl_dsa *dsap = NULL; - DSA *dsa = NULL; + DSA *dsa; unsigned char seed[20]; - int seed_len = 20, counter = 0; - unsigned long h = 0; + int seed_len = 20, counter; + unsigned long h; void (*cb)(int, int, void *) = NULL; - VALUE obj; - - Check_Type(size, T_FIXNUM); if (!RAND_bytes(seed, seed_len)) { - OSSL_Raise(eDSAError, ""); + return 0; } - if (rb_block_given_p()) + if (rb_block_given_p()) { cb = ossl_dsa_generate_cb; - - if (!(dsa = DSA_generate_parameters(FIX2INT(size), seed, seed_len, &counter, &h, cb, NULL))) { /* arg to cb = NULL */ - OSSL_Raise(eDSAError, ""); + } + if (!(dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h, cb, NULL))) { /* arg to cb = NULL */ + return 0; } if (!DSA_generate_key(dsa)) { DSA_free(dsa); + return 0; + } + return dsa; +} + +static VALUE +ossl_dsa_s_generate(VALUE klass, VALUE size) +{ + DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */ + VALUE obj = dsa_instance(klass, dsa); + + if (obj == Qfalse) { + DSA_free(dsa); OSSL_Raise(eDSAError, ""); } + return obj; +} + +static VALUE +ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + DSA *dsa; + BIO *in; + char *passwd = NULL; + VALUE buffer, pass; - MakeDSA(obj, dsap); - dsap->dsa = dsa; + GetPKey(self, pkey); + + rb_scan_args(argc, argv, "11", &buffer, &pass); - return obj; + if (FIXNUM_P(buffer)) { + if (!(dsa = dsa_generate(FIX2INT(buffer)))) { + OSSL_Raise(eDSAError, ""); + } + } else { + StringValue(buffer); + + if (!NIL_P(pass)) { + passwd = StringValuePtr(pass); + } + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) { + OSSL_Raise(eDSAError, ""); + } + if (!(dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL))) { + BIO_reset(in); + + if (!(dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, passwd))) { + BIO_free(in); + OSSL_Raise(eDSAError, "Neither PUB key nor PRIV key:"); + } + } + BIO_free(in); + } + if (!EVP_PKEY_assign_DSA(pkey, dsa)) { + DSA_free(dsa); + OSSL_Raise(eDSAError, ""); + } + return self; } static VALUE ossl_dsa_is_public(VALUE self) { - ossl_dsa *dsap = NULL; + EVP_PKEY *pkey; - GetDSA(self, dsap); + GetPKeyDSA(self, pkey); /* * Do we need to check dsap->dsa->public_pkey? * return Qtrue; */ - return (dsap->dsa->pub_key) ? Qtrue : Qfalse; + return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse; } static VALUE ossl_dsa_is_private(VALUE self) { - ossl_dsa *dsap = NULL; + EVP_PKEY *pkey; - GetDSA(self, dsap); + GetPKeyDSA(self, pkey); - return (DSA_PRIVATE(dsap->dsa)) ? Qtrue : Qfalse; + return (DSA_PRIVATE(pkey->pkey.dsa)) ? Qtrue : Qfalse; } static VALUE ossl_dsa_export(int argc, VALUE *argv, VALUE self) { - ossl_dsa *dsap = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; const EVP_CIPHER *ciph = NULL; - char *pass = NULL; - VALUE cipher, password, str; + char *passwd = NULL; + VALUE cipher, pass, str; - GetDSA(self, dsap); + GetPKeyDSA(self, pkey); - rb_scan_args(argc, argv, "02", &cipher, &password); + rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { ciph = ossl_cipher_get_EVP_CIPHER(cipher); - if (!NIL_P(password)) { - password = rb_String(password); - pass = RSTRING(password)->ptr; + if (!NIL_P(pass)) { + passwd = StringValuePtr(pass); } } if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eDSAError, ""); } - if (DSA_PRIVATE(dsap->dsa)) { - if (!PEM_write_bio_DSAPrivateKey(out, dsap->dsa, ciph, NULL, 0, NULL, pass)) { + if (DSA_PRIVATE(pkey->pkey.dsa)) { + if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph, NULL, 0, NULL, passwd)) { BIO_free(out); OSSL_Raise(eDSAError, ""); } } else { - if (!PEM_write_bio_DSAPublicKey(out, dsap->dsa)) { + if (!PEM_write_bio_DSAPublicKey(out, pkey->pkey.dsa)) { BIO_free(out); OSSL_Raise(eDSAError, ""); } } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -268,42 +241,6 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) return str; } -static VALUE -ossl_dsa_to_der(VALUE self) -{ - DSA *dsa = NULL; - EVP_PKEY *pkey = NULL; - X509_PUBKEY *key = NULL; - VALUE str; - - dsa = ossl_dsa_get_DSA(self); - - if (!(pkey = EVP_PKEY_new())) { - DSA_free(dsa); - OSSL_Raise(eDSAError, ""); - } - if (!EVP_PKEY_assign_DSA(pkey, dsa)) { /* NO DUP - don't free! */ - DSA_free(dsa); - EVP_PKEY_free(pkey); - OSSL_Raise(eDSAError, ""); - } - if (!(key = X509_PUBKEY_new())) { - EVP_PKEY_free(pkey); - OSSL_Raise(eDSAError, ""); - } - if (!X509_PUBKEY_set(&key, pkey)) { /* safe to FREE pkey or NOT? */ - EVP_PKEY_free(pkey); - X509_PUBKEY_free(key); - OSSL_Raise(eDSAError, ""); - } - - str = rb_str_new(key->public_key->data, key->public_key->length); - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free?? */ - X509_PUBKEY_free(key); - - return str; -} - /* * Prints all parameters of key to buffer * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! @@ -312,21 +249,20 @@ ossl_dsa_to_der(VALUE self) static VALUE ossl_dsa_to_text(VALUE self) { - ossl_dsa *dsap = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; VALUE str; - GetDSA(self, dsap); + GetPKeyDSA(self, pkey); if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eDSAError, ""); } - if (!DSA_print(out, dsap->dsa, 0)) { //offset = 0 + if (!DSA_print(out, pkey->pkey.dsa, 0)) { //offset = 0 BIO_free(out); OSSL_Raise(eDSAError, ""); } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -340,45 +276,46 @@ ossl_dsa_to_text(VALUE self) static VALUE ossl_dsa_to_public_key(VALUE self) { - ossl_dsa *dsap1 = NULL, *dsap2 = NULL; + EVP_PKEY *pkey; + DSA *dsa; VALUE obj; - GetDSA(self, dsap1); + GetPKeyDSA(self, pkey); - MakeDSA(obj, dsap2); - - if (!(dsap2->dsa = DSAPublicKey_dup(dsap1->dsa))) { + dsa = DSAPublicKey_dup(pkey->pkey.dsa); /* err check performed by dsa_instance */ + obj = dsa_instance(CLASS_OF(self), dsa); + + if (obj == Qfalse) { + DSA_free(dsa); OSSL_Raise(eDSAError, ""); } - return obj; } static VALUE ossl_dsa_sign(VALUE self, VALUE data) { - ossl_dsa *dsap = NULL; - char *sig = NULL; - int sig_len = 0; + EVP_PKEY *pkey; + char *buf; + int buf_len; VALUE str; - GetDSA(self, dsap); - data = rb_String(data); + GetPKeyDSA(self, pkey); + + StringValue(data); - if (!DSA_PRIVATE(dsap->dsa)) { + if (!DSA_PRIVATE(pkey->pkey.dsa)) { rb_raise(eDSAError, "Private DSA key needed!"); } - - if (!(sig = OPENSSL_malloc(DSA_size(dsap->dsa)+16))) { + if (!(buf = OPENSSL_malloc(DSA_size(pkey->pkey.dsa) + 16))) { OSSL_Raise(eDSAError, ""); } - - if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, sig, &sig_len, dsap->dsa)) { /*type = 0*/ - OPENSSL_free(sig); + if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, buf, &buf_len, pkey->pkey.dsa)) { /*type = 0*/ + OPENSSL_free(buf); OSSL_Raise(eDSAError, ""); } - str = rb_str_new(sig, sig_len); - OPENSSL_free(sig); + str = rb_str_new(buf, buf_len); + OPENSSL_free(buf); return str; } @@ -386,22 +323,21 @@ ossl_dsa_sign(VALUE self, VALUE data) static VALUE ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) { - ossl_dsa *dsap = NULL; - int ret = -1; + EVP_PKEY *pkey; + int ret; - GetDSA(self, dsap); + GetPKeyDSA(self, pkey); - digest = rb_String(digest); - sig = rb_String(sig); + StringValue(digest); + StringValue(sig); - ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,\ - RSTRING(sig)->ptr, RSTRING(sig)->len, dsap->dsa); /*type = 0*/ + ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa); /*type = 0*/ if (ret < 0) { OSSL_Raise(eDSAError, ""); - } else if (ret == 1) + } else if (ret == 1) { return Qtrue; - + } return Qfalse; } @@ -409,15 +345,14 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) * INIT */ void -Init_ossl_dsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_dsa() { eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError); cDSA = rb_define_class_under(mPKey, "DSA", cPKey); - rb_define_singleton_method(cDSA, "new_from_pem", ossl_dsa_s_new_from_pem, -1); rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); - rb_define_alias(CLASS_OF(cDSA), "new_from_fixnum", "generate"); + rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); @@ -425,16 +360,15 @@ Init_ossl_dsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) rb_define_method(cDSA, "export", ossl_dsa_export, -1); rb_define_alias(cDSA, "to_pem", "export"); rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0); - rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0); rb_define_method(cDSA, "sign_digest", ossl_dsa_sign, 1); rb_define_method(cDSA, "verify_digest", ossl_dsa_verify, 2); } #else /* defined NO_DSA */ -# warning >>> OpenSSL is compiled without DSA support <<< +# warning >>> OpenSSL is compiled without DSA support <<< void -Init_ossl_dsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_dsa() { rb_warning("OpenSSL is compiled without DSA support"); } diff --git a/ossl_pkey_rsa.c b/ossl_pkey_rsa.c index e74892c..6b6a7ae 100644 --- a/ossl_pkey_rsa.c +++ b/ossl_pkey_rsa.c @@ -11,16 +11,12 @@ #if !defined(OPENSSL_NO_RSA) #include "ossl.h" -#include "ossl_pkey.h" -#define MakeRSA(obj, rsap) do {\ - obj = Data_Make_Struct(cRSA, ossl_rsa, 0, ossl_rsa_free, rsap);\ - rsap->pkey.get_EVP_PKEY = ossl_rsa_get_EVP_PKEY;\ -} while (0) - -#define GetRSA(obj, rsap) do {\ - Data_Get_Struct(obj, ossl_rsa, rsap);\ - if (!rsap->rsa) rb_raise(eRSAError, "not initialized!");\ +#define GetPKeyRSA(obj, pkey) do { \ + GetPKey(obj, pkey); \ + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \ + rb_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \ + } \ } while (0) #define RSA_PRIVATE(rsa) ((rsa)->p && (rsa)->q) @@ -32,126 +28,56 @@ VALUE cRSA; VALUE eRSAError; /* - * Struct - */ -typedef struct ossl_rsa_st { - ossl_pkey pkey; - RSA *rsa; -} ossl_rsa; - -static void -ossl_rsa_free(ossl_rsa *rsap) -{ - if (rsap) { - if (rsap->rsa) RSA_free(rsap->rsa); - rsap->rsa = NULL; - free(rsap); - } -} - -/* * Public */ -VALUE -ossl_rsa_new(RSA *rsa) +static VALUE +rsa_instance(VALUE klass, RSA *rsa) { - ossl_rsa *rsap = NULL; - RSA *new = NULL; + EVP_PKEY *pkey; VALUE obj; - - if (!rsa) - new = RSA_new(); - else new = (RSA_PRIVATE(rsa)) ? RSAPrivateKey_dup(rsa) : RSAPublicKey_dup(rsa); - - if (!new) - OSSL_Raise(eRSAError, ""); - MakeRSA(obj, rsap); - rsap->rsa = new; + if (!rsa) { + return Qfalse; + } + if (!(pkey = EVP_PKEY_new())) { + return Qfalse; + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + EVP_PKEY_free(pkey); + return Qfalse; + } + WrapPKey(klass, obj, pkey); return obj; } -RSA * -ossl_rsa_get_RSA(VALUE obj) +VALUE +ossl_rsa_new(EVP_PKEY *pkey) { - ossl_rsa *rsap = NULL; - RSA *rsa = NULL; - - OSSL_Check_Type(obj, cRSA); - GetRSA(obj, rsap); + RSA *rsa; + VALUE obj; - rsa = (RSA_PRIVATE(rsap->rsa)) ? RSAPrivateKey_dup(rsap->rsa) : RSAPublicKey_dup(rsap->rsa); + if (pkey && EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { + rb_raise(rb_eTypeError, "Not a RSA key!"); + } + if (!pkey) { /* all errs handled by rsa_instance */ + rsa = RSA_new(); + } else { + rsa = (RSA_PRIVATE(pkey->pkey.rsa)) ? RSAPrivateKey_dup(pkey->pkey.rsa) : RSAPublicKey_dup(pkey->pkey.rsa); + } - if (!rsa) - OSSL_Raise(eRSAError, ""); + obj = rsa_instance(cRSA, rsa); - return rsa; -} - -EVP_PKEY * -ossl_rsa_get_EVP_PKEY(VALUE obj) -{ - RSA *rsa = NULL; - EVP_PKEY *pkey = NULL; - - rsa = ossl_rsa_get_RSA(obj); - - if (!(pkey = EVP_PKEY_new())) { - RSA_free(rsa); - OSSL_Raise(eRSAError, ""); - } - - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + if (obj == Qfalse) { RSA_free(rsa); - EVP_PKEY_free(pkey); OSSL_Raise(eRSAError, ""); } - - return pkey; + return obj; } /* * Private */ -static VALUE -ossl_rsa_s_new_from_pem(int argc, VALUE *argv, VALUE klass) -{ - ossl_rsa *rsap = NULL; - RSA *rsa = NULL; - BIO *in = NULL; - char *passwd = NULL; - VALUE buffer, pass, obj; - - rb_scan_args(argc, argv, "11", &buffer, &pass); - - buffer = rb_String(buffer); - - if (!NIL_P(pass)) { - pass = rb_String(pass); - passwd = RSTRING(pass)->ptr; - } - /* else passwd = NULL; */ - - if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) { - OSSL_Raise(eRSAError, ""); - } - if (!(rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL))) { - BIO_reset(in); - - if (!(rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, passwd))) { - BIO_free(in); - OSSL_Raise(eRSAError, "Neither PUB key nor PRIV key:"); - } - } - BIO_free(in); - - MakeRSA(obj, rsap); - rsap->rsa = rsa; - - return obj; -} - /* * CB for yielding when generating RSA data */ @@ -167,35 +93,80 @@ ossl_rsa_generate_cb(int p, int n, void *arg) rb_yield(ary); } -static VALUE -ossl_rsa_s_generate(VALUE klass, VALUE size) +static RSA * +rsa_generate(int size) { - ossl_rsa *rsap = NULL; - RSA *rsa = NULL; void (*cb)(int, int, void *) = NULL; - VALUE obj; - - Check_Type(size, T_FIXNUM); - if (rb_block_given_p()) + if (rb_block_given_p()) { cb = ossl_rsa_generate_cb; + } + + return RSA_generate_key(size, RSA_F4, cb, NULL); +} - if (!(rsa = RSA_generate_key(FIX2INT(size), RSA_F4, cb, NULL))) { /* arg to cb = NULL */ +static VALUE +ossl_rsa_s_generate(VALUE klass, VALUE size) +{ + RSA *rsa = rsa_generate(FIX2INT(size)); /* err handled by rsa_instance */ + VALUE obj = rsa_instance(klass, rsa); + + if (obj == Qfalse) { + RSA_free(rsa); OSSL_Raise(eRSAError, ""); } + return obj; +} - MakeRSA(obj, rsap); - rsap->rsa = rsa; +static VALUE +ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) +{ + EVP_PKEY *pkey; + RSA *rsa; + BIO *in; + char *passwd = NULL; + VALUE buffer, pass; - return obj; + GetPKey(self, pkey); + + rb_scan_args(argc, argv, "11", &buffer, &pass); + + if (FIXNUM_P(buffer)) { + if (!(rsa = rsa_generate(FIX2INT(buffer)))) { + OSSL_Raise(eRSAError, ""); + } + } else { + StringValue(buffer); + + if (!NIL_P(pass)) { + passwd = StringValuePtr(pass); + } + if (!(in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len))) { + OSSL_Raise(eRSAError, ""); + } + if (!(rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL))) { + BIO_reset(in); + + if (!(rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, passwd))) { + BIO_free(in); + OSSL_Raise(eRSAError, "Neither PUB key nor PRIV key:"); + } + } + BIO_free(in); + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + RSA_free(rsa); + OSSL_Raise(eRSAError, ""); + } + return self; } static VALUE ossl_rsa_is_public(VALUE self) { - ossl_rsa *rsap = NULL; + EVP_PKEY *pkey; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); /* * SURPRISE! :-)) @@ -207,24 +178,24 @@ ossl_rsa_is_public(VALUE self) static VALUE ossl_rsa_is_private(VALUE self) { - ossl_rsa *rsap = NULL; + EVP_PKEY *pkey; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); - return (RSA_PRIVATE(rsap->rsa)) ? Qtrue : Qfalse; + return (RSA_PRIVATE(pkey->pkey.rsa)) ? Qtrue : Qfalse; } static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) { - ossl_rsa *rsap = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; const EVP_CIPHER *ciph = NULL; char *passwd = NULL; VALUE cipher, pass, str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); rb_scan_args(argc, argv, "02", &cipher, &pass); @@ -232,26 +203,23 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) ciph = ossl_cipher_get_EVP_CIPHER(cipher); if (!NIL_P(pass)) { - pass = rb_String(pass); - passwd = RSTRING(pass)->ptr; + passwd = StringValuePtr(pass); } } if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eRSAError, ""); } - - if (RSA_PRIVATE(rsap->rsa)) { - if (!PEM_write_bio_RSAPrivateKey(out, rsap->rsa, ciph, NULL, 0, NULL, passwd)) { + if (RSA_PRIVATE(pkey->pkey.rsa)) { + if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, NULL, 0, NULL, passwd)) { BIO_free(out); OSSL_Raise(eRSAError, ""); } } else { - if (!PEM_write_bio_RSAPublicKey(out, rsap->rsa)) { + if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) { BIO_free(out); OSSL_Raise(eRSAError, ""); } } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -262,117 +230,109 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_public_encrypt(VALUE self, VALUE buffer) { - ossl_rsa *rsap = NULL; - char *enc_text = NULL; - int len = 0, size = 0; - VALUE enc; + EVP_PKEY *pkey; + char *buf; + int buf_len; + VALUE str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); - buffer = rb_String(buffer); + StringValue(buffer); - size = RSA_size(rsap->rsa); - - if (!(enc_text = OPENSSL_malloc(size + 16))) { + if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { OSSL_Raise(eRSAError, ""); } - if ((len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, enc_text, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { - OPENSSL_free(enc_text); + if ((buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, buf, pkey->pkey.rsa, RSA_PKCS1_PADDING)) < 0) { + OPENSSL_free(buf); OSSL_Raise(eRSAError, ""); } - enc = rb_str_new(enc_text, len); - OPENSSL_free(enc_text); + str = rb_str_new(buf, buf_len); + OPENSSL_free(buf); - return enc; + return str; } static VALUE ossl_rsa_public_decrypt(VALUE self, VALUE buffer) { - ossl_rsa *rsap = NULL; - char *txt = NULL; - int len = 0, size = 0; - VALUE text; + EVP_PKEY *pkey; + char *buf; + int buf_len; + VALUE str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); - buffer = rb_String(buffer); + StringValue(buffer); - size = RSA_size(rsap->rsa); - - if (!(txt = OPENSSL_malloc(size + 16))) { + if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { OSSL_Raise(eRSAError, ""); } - if ((len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, txt, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { - OPENSSL_free(txt); + if ((buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, buf, pkey->pkey.rsa, RSA_PKCS1_PADDING)) < 0) { + OPENSSL_free(buf); OSSL_Raise(eRSAError, ""); } - text = rb_str_new(txt, len); - OPENSSL_free(txt); + str = rb_str_new(buf, buf_len); + OPENSSL_free(buf); - return text; + return str; } static VALUE ossl_rsa_private_encrypt(VALUE self, VALUE buffer) { - ossl_rsa *rsap = NULL; - char *enc_text = NULL; - int len = 0, size = 0; - VALUE enc; + EVP_PKEY *pkey; + char *buf; + int buf_len; + VALUE str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(rsap->rsa)) { + if (!RSA_PRIVATE(pkey->pkey.rsa)) { rb_raise(eRSAError, "PRIVATE key needed for this operation!"); } - buffer = rb_String(buffer); + StringValue(buffer); - size = RSA_size(rsap->rsa); - - if (!(enc_text = OPENSSL_malloc(size + 16))) { + if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { OSSL_Raise(eRSAError, "Memory alloc error"); } - if ((len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, enc_text, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { - OPENSSL_free(enc_text); + if ((buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, buf, pkey->pkey.rsa, RSA_PKCS1_PADDING)) < 0) { + OPENSSL_free(buf); OSSL_Raise(eRSAError, ""); } - enc = rb_str_new(enc_text, len); - OPENSSL_free(enc_text); + str = rb_str_new(buf, buf_len); + OPENSSL_free(buf); - return enc; + return str; } static VALUE ossl_rsa_private_decrypt(VALUE self, VALUE buffer) { - ossl_rsa *rsap = NULL; - char *txt = NULL; - int len = 0, size = 0; - VALUE text; + EVP_PKEY *pkey; + char *buf; + int buf_len; + VALUE str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(rsap->rsa)) { + if (!RSA_PRIVATE(pkey->pkey.rsa)) { rb_raise(eRSAError, "Private RSA key needed!"); } - - buffer = rb_String(buffer); - - size = RSA_size(rsap->rsa); - if (!(txt = OPENSSL_malloc(size + 16))) { + StringValue(buffer); + + if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { OSSL_Raise(eRSAError, "Memory alloc error"); } - if ((len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, txt, rsap->rsa, RSA_PKCS1_PADDING)) < 0) { - OPENSSL_free(txt); + if ((buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, buf, pkey->pkey.rsa, RSA_PKCS1_PADDING)) < 0) { + OPENSSL_free(buf); OSSL_Raise(eRSAError, ""); } - text = rb_str_new(txt, len); - OPENSSL_free(txt); + str = rb_str_new(buf, buf_len); + OPENSSL_free(buf); - return text; + return str; } /* @@ -406,42 +366,6 @@ ossl_rsa_get_n(VALUE self) } */ -static VALUE -ossl_rsa_to_der(VALUE self) -{ - RSA *rsa = NULL; - EVP_PKEY *pkey = NULL; - X509_PUBKEY *key = NULL; - VALUE str; - - rsa = ossl_rsa_get_RSA(self); - - if (!(pkey = EVP_PKEY_new())) { - RSA_free(rsa); - OSSL_Raise(eRSAError, ""); - } - if (!EVP_PKEY_assign_RSA(pkey, rsa)) { /* NO DUP - don't free! */ - RSA_free(rsa); - EVP_PKEY_free(pkey); - OSSL_Raise(eRSAError, ""); - } - if (!(key = X509_PUBKEY_new())) { - EVP_PKEY_free(pkey); - OSSL_Raise(eRSAError, ""); - } - if (!X509_PUBKEY_set(&key, pkey)) { /* safe to FREE pkey??? */ - EVP_PKEY_free(pkey); - X509_PUBKEY_free(key); - OSSL_Raise(eRSAError, ""); - } - - str = rb_str_new(key->public_key->data, key->public_key->length); - /* EVP_PKEY_free(pkey) = this does X509_PUBKEY_free?? */ - X509_PUBKEY_free(key); - - return str; -} - /* * Prints all parameters of key to buffer * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! @@ -450,21 +374,20 @@ ossl_rsa_to_der(VALUE self) static VALUE ossl_rsa_to_text(VALUE self) { - ossl_rsa *rsap = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; + EVP_PKEY *pkey; + BIO *out; + BUF_MEM *buf; VALUE str; - GetRSA(self, rsap); + GetPKeyRSA(self, pkey); if (!(out = BIO_new(BIO_s_mem()))) { OSSL_Raise(eRSAError, ""); } - if (!RSA_print(out, rsap->rsa, 0)) { //offset = 0 + if (!RSA_print(out, pkey->pkey.rsa, 0)) { //offset = 0 BIO_free(out); OSSL_Raise(eRSAError, ""); } - BIO_get_mem_ptr(out, &buf); str = rb_str_new(buf->data, buf->length); BIO_free(out); @@ -478,17 +401,19 @@ ossl_rsa_to_text(VALUE self) static VALUE ossl_rsa_to_public_key(VALUE self) { - ossl_rsa *rsap1 = NULL, *rsap2 = NULL; + EVP_PKEY *pkey; + RSA *rsa; VALUE obj; - GetRSA(self, rsap1); + GetPKeyRSA(self, pkey); - MakeRSA(obj, rsap2); - - if (!(rsap2->rsa = RSAPublicKey_dup(rsap1->rsa))) { + rsa = RSAPublicKey_dup(pkey->pkey.rsa); /* err check performed by rsa_instance */ + obj = rsa_instance(CLASS_OF(self), rsa); + + if (obj == Qfalse) { + RSA_free(rsa); OSSL_Raise(eRSAError, ""); } - return obj; } @@ -537,15 +462,15 @@ ossl_rsa_verify(VALUE self, VALUE digest, VALUE text) * INIT */ void -Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_rsa() { eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError); cRSA = rb_define_class_under(mPKey, "RSA", cPKey); - rb_define_singleton_method(cRSA, "new_from_pem", ossl_rsa_s_new_from_pem, -1); rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, 1); - rb_define_alias(CLASS_OF(cRSA), "new_from_fixnum", "generate"); + rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); + rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0); @@ -557,7 +482,6 @@ Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, 1); rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, 1); /*rb_define_method(cRSA, "n", ossl_rsa_get_n, 0);*/ - rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0); /* * Implemented in Ruby space... * @@ -567,10 +491,10 @@ Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) } #else /* defined NO_RSA */ -# warning >>> OpenSSL is compiled without RSA support <<< +# warning >>> OpenSSL is compiled without RSA support <<< void -Init_ossl_rsa(VALUE mPKey, VALUE cPKey, VALUE ePKeyError) +Init_ossl_rsa() { rb_warning("OpenSSL is compiled without RSA support"); } diff --git a/ossl_rand.c b/ossl_rand.c index 22a119a..9196ac4 100644 --- a/ossl_rand.c +++ b/ossl_rand.c @@ -13,6 +13,7 @@ /* * Classes */ +VALUE mRandom; VALUE eRandomError; /* @@ -70,6 +70,7 @@ static VALUE ssl_set_key_file2(VALUE, VALUE); /* * Classes */ +VALUE mSSL; VALUE cSSLSocket; VALUE eSSLError; @@ -608,15 +609,17 @@ ssl_set_key_file2(VALUE self, VALUE v) } void -Init_ossl_ssl(VALUE module) +Init_ossl_ssl() { int i; + mSSL = rb_define_module_under(mOSSL, "SSL"); + /* class SSLError */ - eSSLError = rb_define_class_under(module, "SSLError", eOSSLError); + eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError); /* class SSLSocket */ - cSSLSocket = rb_define_class_under(module, "SSLSocket", rb_cObject); + cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject); rb_define_singleton_method(cSSLSocket, "new", ssl_s_new, -1); rb_define_method(cSSLSocket, "initialize", ssl_initialize, -1); rb_define_method(cSSLSocket, "__connect", ssl_connect, 0); @@ -640,7 +643,7 @@ Init_ossl_ssl(VALUE module) rb_attr(cSSLSocket, rb_intern(ssl_attr_readers[i]), 1, 0, Qfalse); rb_define_alias(cSSLSocket, "to_io", "io"); -#define ssl_def_const(x) rb_define_const(module, #x, INT2FIX(SSL_##x)) +#define ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x)) ssl_def_const(VERIFY_NONE); ssl_def_const(VERIFY_PEER); diff --git a/ossl_ssl.h b/ossl_ssl.h new file mode 100644 index 0000000..1c9c236 --- /dev/null +++ b/ossl_ssl.h @@ -0,0 +1,21 @@ +/* + * $Id$ + * 'OpenSSL for Ruby' project + * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz> + * All rights reserved. + */ +/* + * This program is licenced under the same licence as Ruby. + * (See the file 'LICENCE'.) + */ +#if !defined(_OSSL_SSL_H_) +#define _OSSL_SSL_H_ + +extern VALUE mSSL; +extern VALUE cSSLSocket; +extern VALUE eSSLError; + +void Init_ossl_ssl(void); + +#endif /* _OSSL_SSL_H_ */ + |