From 30103702c367c5cdaa18b6a622f3916cec6c701e Mon Sep 17 00:00:00 2001 From: gotoyuzo Date: Wed, 17 Sep 2003 09:05:02 +0000 Subject: * ext/openssl: all files are reviewed to simplify and avoid memory leak. * ext/openssl/extconf.rb: add check for assert.h. * ext/openssl/ossl.c (ossl_buf2str): new function to convert C buffer to String and free buffer. * ext/openssl/ossl.c (ossl_x509_ary2sk): new function to convert Array of OpenSSL::X509 to STACK_OF(X509) with exception safe. * ext/openssl/ossl.c (ossl_to_der, ossl_to_der_if_possible): new functions to convert object to DER string. * ext/openssl/ossl.h: ditto. * ext/openssl/ossl_bio.c (ossl_membio2str): new function to convert BIO to String object and free BIO. * ext/openssl/ossl_bio.h: ditto. * ext/openssl/ossl_pkcs7.c (ossl_pkcs7_to_der): add for "to_der". * ext/openssl/ossl_x509name.c (ossl_x509name_to_der): ditto. * ext/openssl/ossl_x509ext.c (ossl_x509ext_to_der): ditto. * ext/openssl/ossl_x509ext.c (create_ext_from_array): removed and reimplement in openssl/x509.rb. * ext/openssl/ossl_x509attr.c: reimplemented and disable some method temporarily. this class doesn't work fine without ASN.1 data support;-) I'll rewrite in near future. * ext/openssl/lib/openssl/x509.c (X509::Attribute): get rid off unused code. * ext/openssl/lib/openssl/x509.c (X509::ExtensionFactory): refine all. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4558 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 3 +- ext/openssl/lib/openssl/x509.rb | 93 ++++------------------ ext/openssl/ossl.c | 66 +++++++++++++++- ext/openssl/ossl.h | 27 +++++++ ext/openssl/ossl_bio.c | 18 ++++- ext/openssl/ossl_bio.h | 1 + ext/openssl/ossl_bn.c | 30 ++----- ext/openssl/ossl_cipher.c | 43 ++++------ ext/openssl/ossl_digest.c | 6 +- ext/openssl/ossl_hmac.c | 11 +-- ext/openssl/ossl_ns_spki.c | 3 +- ext/openssl/ossl_ocsp.c | 70 +++++++++-------- ext/openssl/ossl_pkcs7.c | 79 ++++++++++--------- ext/openssl/ossl_pkey.c | 36 ++++----- ext/openssl/ossl_pkey_dh.c | 51 +++++------- ext/openssl/ossl_pkey_dsa.c | 63 +++++++-------- ext/openssl/ossl_pkey_rsa.c | 126 ++++++++++++------------------ ext/openssl/ossl_rand.c | 22 ++---- ext/openssl/ossl_x509attr.c | 169 +++++++++++++++++++++++++++------------- ext/openssl/ossl_x509cert.c | 42 +++------- ext/openssl/ossl_x509crl.c | 23 ++---- ext/openssl/ossl_x509ext.c | 112 ++++++++++++-------------- ext/openssl/ossl_x509name.c | 35 ++++++++- ext/openssl/ossl_x509req.c | 23 ++---- 24 files changed, 560 insertions(+), 592 deletions(-) (limited to 'ext') diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 59b222ac91..1dcb5e9c7e 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -40,6 +40,7 @@ have_library("nsl", "t_open") have_library("socket", "socket") have_header("unistd.h") have_header("sys/time.h") +have_header("assert.h") message "=== Checking for required stuff... ===\n" if $mingw @@ -100,7 +101,7 @@ test-link: $(OBJS) @$(RM) .testlink @echo "Done." -dep: $(SRCS) +dep: $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -MM | \\ $(RUBY) -p -e 'BEGIN{S = []' \\ -e 'while !ARGV.empty? and /^(\\w+)=(.*)/ =~ ARGV[0]' \\ diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb index 8efe3701c8..b8cc5bd4ed 100644 --- a/ext/openssl/lib/openssl/x509.rb +++ b/ext/openssl/lib/openssl/x509.rb @@ -20,53 +20,29 @@ module OpenSSL module X509 - class ExtensionFactory def create_extension(*arg) - if arg.size == 1 then arg = arg[0] end - type = arg.class - while type - method = "create_ext_from_#{type.name.downcase}".intern - return send(method, arg) if respond_to? method - type = type.superclass + if arg.size > 1 + create_ext(*arg) + else + send("create_ext_from_"+arg[0].class.name.downcase, arg[0]) end - raise TypeError, "Don't how to create ext from #{arg.class}" - ###send("create_ext_from_#{arg.class.name.downcase}", arg) end - # - # create_ext_from_array is built-in - # + def create_ext_from_array(ary) + raise ExtensionError, "unexpected array form" if ary.size > 3 + create_ext(ary[0], ary[1], ary[2]) + end + def create_ext_from_string(str) # "oid = critical, value" - unless str =~ /\s*=\s*/ - raise ArgumentError, "string in format \"oid = value\" expected" - end - ary = [] - ary << $`.sub(/^\s*/,"") # delete whitespaces from the beginning - rest = $'.sub(/\s*$/,"") # delete them from the end - if rest =~ /^critical,\s*/ # handle 'critical' option - ary << $' - ary << true - else - ary << rest - end - create_ext_from_array(ary) + oid, value = str.split(/=/, 2) + oid.strip! + value.strip! + create_ext(oid, value) end - # - # Create an extention from Hash - # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} - # def create_ext_from_hash(hash) - unless (hash.has_key? "oid" and hash.has_key? "value") - raise ArgumentError, - "hash in format {\"oid\"=>..., \"value\"=>...} expected" - end - ary = [] - ary << hash["oid"] - ary << hash["value"] - ary << hash["critical"] if hash.has_key? "critical" - create_ext_from_array(ary) + create_ext(hash["oid"], hash["value"], hash["critical"]) end end # ExtensionFactory @@ -87,47 +63,6 @@ module OpenSSL end end # Extension - class Attribute - def self.new(arg) - type = arg.class - while type - method = "new_from_#{type.name.downcase}".intern - return Attribute::send(method, arg) if Attribute::respond_to? method - type = type.superclass - end - raise "Don't how to make new #{self} from #{arg.class}" - ###Attribute::send("new_from_#{arg.class.name.downcase}", arg) - end - - # - # Attribute::new_from_array(ary) is built-in method - # - def Attribute::new_from_string(str) # "oid = value" - unless str =~ /\s*=\s*/ - raise ArgumentError, "string in format \"oid = value\" expected" - end - ary = [] - ary << $`.sub(/^\s*/,"") # delete whitespaces from the beginning - ary << $'.sub(/\s*$/,"") # delete them from the end - Attribute::new_from_array(ary) - end - - # - # Create an attribute from Hash - # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} - # - def Attribute::new_from_hash(hash) # {"oid"=>"...", "value"=>"..."} - unless (hash.has_key? "oid" and hash.has_key? "value") - raise ArgumentError, - "hash in format {\"oid\"=>..., \"value\"=>...} expected" - end - ary = [] - ary << hash["oid"] - ary << hash["value"] - Attribute::new_from_array(ary) - end - end # Attribute - class Name def self.parse(str) ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=") } diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index b90ea10780..f4a3fc4c99 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -48,7 +48,7 @@ string2hex(char *buf, int buf_len, char **hexbuf, int *hexbuf_len) * Data Conversion */ STACK_OF(X509) * -ossl_x509_ary2sk(VALUE ary) +ossl_x509_ary2sk0(VALUE ary) { STACK_OF(X509) *sk; VALUE val; @@ -74,7 +74,20 @@ ossl_x509_ary2sk(VALUE ary) STACK_OF(X509) * ossl_protect_x509_ary2sk(VALUE ary, int *status) { - return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk, ary, status); + return (STACK_OF(X509)*)rb_protect((VALUE(*)_((VALUE)))ossl_x509_ary2sk0, + ary, status); +} + +STACK_OF(X509) * +ossl_x509_ary2sk(VALUE ary) +{ + STACK_OF(X509) *sk; + int status = 0; + + sk = ossl_protect_x509_ary2sk(ary, &status); + if(status) rb_jump_tag(status); + + return sk; } #if 0 @@ -107,6 +120,26 @@ OSSL_SK2ARY(x509, X509) OSSL_SK2ARY(x509crl, X509_CRL) #endif +static VALUE +ossl_str_new(int size) +{ + return rb_str_new(0, size); +} + +VALUE +ossl_buf2str(char *buf, int len) +{ + VALUE str; + int status = 0; + + str = rb_protect((VALUE(*)_(()))ossl_str_new, len, &status); + memcpy(RSTRING(str)->ptr, buf, len); + OPENSSL_free(buf); + if(status) rb_jump_tag(status); + + return str; +} + /* * our default PEM callback */ @@ -214,6 +247,30 @@ VALUE mOSSL; */ VALUE eOSSLError; +/* + * Convert to DER string + */ +ID ossl_s_to_der; + +VALUE +ossl_to_der(VALUE obj) +{ + VALUE tmp; + + tmp = rb_funcall(obj, ossl_s_to_der, 0); + StringValue(tmp); + + return tmp; +} + +VALUE +ossl_to_der_if_possible(VALUE obj) +{ + if(rb_respond_to(obj, ossl_s_to_der)) + return ossl_to_der(obj); + return obj; +} + /* * Errors */ @@ -356,6 +413,11 @@ Init_openssl() rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0); rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); + /* + * Get ID of to_der + */ + ossl_s_to_der = rb_intern("to_der"); + /* * Init components */ diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index efb7057adb..33c2083311 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -22,6 +22,12 @@ extern "C" { */ #include +#ifdef HAVE_ASSERT_H +# include +#else +# define assert(condition) +#endif + #if defined(_WIN32) # define OpenFile WINAPI_OpenFile # define OSSL_NO_CONF_API 1 @@ -37,6 +43,10 @@ extern "C" { #include #undef X509_NAME #undef PKCS7_SIGNER_INFO +#if defined(HAVE_OPENSSL_ENGINE_H) && !defined(OPENSSL_NO_ENGINE) +# define OSSL_ENGINE_ENABLED +# include +#endif #if defined(HAVE_OPENSSL_OCSP_H) # define OSSL_OCSP_ENABLED # include @@ -95,8 +105,18 @@ int string2hex(char *, int, char **, int *); /* * Data Conversion */ +STACK_OF(X509) *ossl_x509_ary2sk0(VALUE); STACK_OF(X509) *ossl_x509_ary2sk(VALUE); STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); +VALUE ossl_buf2str(char *buf, int len); +#define ossl_str_adjust(str, p) \ +do{\ + int len = RSTRING(str)->len;\ + int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\ + assert(newlen <= len);\ + RSTRING(str)->len = newlen;\ + RSTRING(str)->ptr[newlen] = 0;\ +}while(0) /* * our default PEM callback @@ -123,6 +143,13 @@ struct ossl_verify_cb_args { VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *); int ossl_verify_cb(int, X509_STORE_CTX *); +/* + * String to DER String + */ +extern ID ossl_s_to_der; +VALUE ossl_to_der(VALUE); +VALUE ossl_to_der_if_possible(VALUE); + /* * Debug */ diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c index 364e2ed71f..8e80f412ee 100644 --- a/ext/openssl/ossl_bio.c +++ b/ext/openssl/ossl_bio.c @@ -38,8 +38,8 @@ ossl_protect_obj2bio(VALUE obj, int *status) return ret; } -VALUE -ossl_membio2str(BIO *bio) +VALUE +ossl_membio2str0(BIO *bio) { VALUE ret; BUF_MEM *buf; @@ -53,6 +53,18 @@ ossl_membio2str(BIO *bio) VALUE ossl_protect_membio2str(BIO *bio, int *status) { - return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str, (VALUE)bio, status); + return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status); } +VALUE +ossl_membio2str(BIO *bio) +{ + VALUE ret; + int status = 0; + + ret = ossl_protect_membio2str(bio, &status); + BIO_free(bio); + if(status) rb_jump_tag(status); + + return ret; +} diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h index 0795c5dbed..2d8f675c5b 100644 --- a/ext/openssl/ossl_bio.h +++ b/ext/openssl/ossl_bio.h @@ -13,6 +13,7 @@ BIO *ossl_obj2bio(VALUE); BIO *ossl_protect_obj2bio(VALUE,int*); +VALUE ossl_membio2str0(BIO*); VALUE ossl_membio2str(BIO*); VALUE ossl_protect_membio2str(BIO*,int*); diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 750d8ad87f..c3a371a008 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -167,41 +167,27 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self) switch (base) { case 0: len = BN_bn2mpi(bn, NULL); - if (!(buf = OPENSSL_malloc(len))) { - ossl_raise(eBNError, "Cannot allocate mem for BN"); - } - if (BN_bn2mpi(bn, buf) != len) { - OPENSSL_free(buf); + str = rb_str_new(0, len); + if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len) ossl_raise(eBNError, NULL); - } break; case 2: len = BN_num_bytes(bn); - if (!(buf = OPENSSL_malloc(len))) { - ossl_raise(eBNError, "Cannot allocate mem for BN"); - } - if (BN_bn2bin(bn, buf) != len) { - OPENSSL_free(buf); + str = rb_str_new(0, len); + if (BN_bn2bin(bn, RSTRING(str)->ptr) != len) ossl_raise(eBNError, NULL); - } break; case 10: - if (!(buf = BN_bn2dec(bn))) { - ossl_raise(eBNError, NULL); - } - len = strlen(buf); + if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, strlen(buf)); break; case 16: - if (!(buf = BN_bn2hex(bn))) { - ossl_raise(eBNError, NULL); - } - len = strlen(buf); + if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); + str = ossl_buf2str(buf, strlen(buf)); break; default: ossl_raise(rb_eArgError, "illegal radix %d", base); } - str = rb_str_new(buf, len); - OPENSSL_free(buf); return str; } diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index b639af2035..93b3f6ccf9 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -122,13 +122,13 @@ ossl_cipher_copy(VALUE self, VALUE other) static VALUE ossl_cipher_reset(VALUE self) { - EVP_CIPHER_CTX *ctx; + EVP_CIPHER_CTX *ctx; - GetCipher(self, ctx); - if (EVP_CipherInit(ctx, NULL, NULL, NULL, -1) != 1) - ossl_raise(eCipherError, NULL); + GetCipher(self, ctx); + if (EVP_CipherInit(ctx, NULL, NULL, NULL, -1) != 1) + ossl_raise(eCipherError, NULL); - return self; + return self; } static VALUE @@ -232,25 +232,20 @@ static VALUE ossl_cipher_update(VALUE self, VALUE data) { EVP_CIPHER_CTX *ctx; - char *in, *out; + char *in; int in_len, out_len; VALUE str; GetCipher(self, ctx); - StringValue(data); in = RSTRING(data)->ptr; in_len = RSTRING(data)->len; - - if (!(out = OPENSSL_malloc(in_len+EVP_CIPHER_CTX_block_size(ctx)))) { + str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx)); + if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len)) ossl_raise(eCipherError, NULL); - } - if (!EVP_CipherUpdate(ctx, out, &out_len, in, in_len)) { - OPENSSL_free(out); - ossl_raise(eCipherError, NULL); - } - str = rb_str_new(out, out_len); - OPENSSL_free(out); + assert(out_len < RSTRING(str)->len); + RSTRING(str)->len = out_len; + RSTRING(str)->ptr[out_len] = 0; return str; } @@ -259,23 +254,17 @@ static VALUE ossl_cipher_final(VALUE self) { EVP_CIPHER_CTX *ctx; - char *out; int out_len; VALUE str; GetCipher(self, ctx); - - if (!(out = OPENSSL_malloc(EVP_CIPHER_CTX_block_size(ctx)))) { + str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx)); + if (!EVP_CipherFinal(ctx, RSTRING(str)->ptr, &out_len)) ossl_raise(eCipherError, NULL); - } - if (!EVP_CipherFinal(ctx, out, &out_len)) { - OPENSSL_free(out); - ossl_raise(eCipherError, NULL); - } + assert(out_len <= RSTRING(str)->len); + RSTRING(str)->len = out_len; + RSTRING(str)->ptr[out_len] = 0; - str = rb_str_new(out, out_len); - OPENSSL_free(out); - return str; } diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index 74a7e1b348..b117ddd30d 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -166,8 +166,7 @@ ossl_digest_digest(VALUE self) GetDigest(self, ctx); digest_final(ctx, &buf, &buf_len); - digest = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + digest = ossl_buf2str(buf, buf_len); return digest; } @@ -186,9 +185,8 @@ ossl_digest_hexdigest(VALUE self) OPENSSL_free(buf); ossl_raise(eDigestError, "Memory alloc error"); } - hexdigest = rb_str_new(hexbuf, 2 * buf_len); OPENSSL_free(buf); - OPENSSL_free(hexbuf); + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); return hexdigest; } diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index ffd5ec3841..1e5d5bc09c 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -124,8 +124,7 @@ ossl_hmac_digest(VALUE self) GetHMAC(self, ctx); hmac_final(ctx, &buf, &buf_len); - digest = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + ossl_buf2str(buf, buf_len); return digest; } @@ -144,9 +143,8 @@ ossl_hmac_hexdigest(VALUE self) OPENSSL_free(buf); ossl_raise(eHMACError, "Memory alloc error"); } - hexdigest = rb_str_new(hexbuf, 2 * buf_len); OPENSSL_free(buf); - OPENSSL_free(hexbuf); + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); return hexdigest; } @@ -180,9 +178,8 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data) if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) { ossl_raise(eHMACError, "Cannot convert buf to hexbuf"); } - hexdigest = rb_str_new(hexbuf, 2 * buf_len); - OPENSSL_free(hexbuf); - + hexdigest = ossl_buf2str(hexbuf, 2 * buf_len); + return hexdigest; } diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index 3932f3e971..9aed773edc 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -80,8 +80,7 @@ ossl_spki_to_pem(VALUE self) if (!(data = NETSCAPE_SPKI_b64_encode(spki))) { ossl_raise(eSPKIError, NULL); } - str = rb_str_new2(data); - OPENSSL_free(data); + str = ossl_buf2str(data, strlen(data)); return str; } diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index 57d9cbee18..836bacfbc1 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -103,16 +103,16 @@ static VALUE ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg; - BIO *bio; + unsigned char *p; rb_scan_args(argc, argv, "01", &arg); if(!NIL_P(arg)){ - bio = ossl_obj2bio(arg); - if(!d2i_OCSP_REQUEST_bio(bio, (OCSP_REQUEST**)&DATA_PTR(self))){ - BIO_free(bio); + arg = ossl_to_der_if_possible(arg); + p = (unsigned char*)RSTRING(arg)->ptr; + if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p, + RSTRING(arg)->len)){ ossl_raise(eOCSPError, "cannot load DER encoded request"); } - BIO_free(bio); } return self; @@ -210,7 +210,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) EVP_PKEY *key; STACK_OF(X509) *x509s; unsigned long flg; - int ret, status = 0; + int ret; rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); GetOCSPReq(self, req); @@ -221,11 +221,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) x509s = sk_X509_new_null(); flags |= OCSP_NOCERTS; } - else x509s = ossl_protect_x509_ary2sk(certs, &status); - if(status){ - sk_X509_pop_free(x509s, X509_free); - rb_jump_tag(status); - } + else x509s = ossl_x509_ary2sk(certs); ret = OCSP_request_sign(req, signer, key, EVP_sha1(), x509s, flg); sk_X509_pop_free(x509s, X509_free); if(!ret) ossl_raise(eOCSPError, NULL); @@ -258,16 +254,19 @@ static VALUE ossl_ocspreq_to_der(VALUE self) { OCSP_REQUEST *req; - BIO *bio; VALUE str; - int status = 0; + unsigned char *p; + long len; GetOCSPReq(self, req); - if(!(bio = BIO_new(BIO_s_mem()))) rb_raise(eOCSPError, NULL); - i2d_OCSP_REQUEST_bio(bio, req); - str = ossl_protect_membio2str(bio, &status); - BIO_free(bio); - if(status) rb_jump_tag(status); + + if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_OCSP_REQUEST(req, &p) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); return str; } @@ -308,15 +307,17 @@ static VALUE ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self) { VALUE arg; - BIO *bio; + unsigned char *p; rb_scan_args(argc, argv, "01", &arg); - bio = ossl_obj2bio(arg); - if(!d2i_OCSP_RESPONSE_bio(bio, (OCSP_RESPONSE**)&DATA_PTR(self))){ - BIO_free(bio); - ossl_raise(eOCSPError, "cannot load DER encoded response"); + if(!NIL_P(arg)){ + arg = ossl_to_der_if_possible(arg); + p = RSTRING(arg)->ptr; + if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p, + RSTRING(arg)->len)){ + ossl_raise(eOCSPError, "cannot load DER encoded response"); + } } - BIO_free(bio); return self; } @@ -364,16 +365,18 @@ static VALUE ossl_ocspres_to_der(VALUE self) { OCSP_RESPONSE *res; - BIO *bio; VALUE str; - int status = 0; + long len; + unsigned char *p; GetOCSPRes(self, res); - if(!(bio = BIO_new(BIO_s_mem()))) rb_raise(eOCSPError, NULL); - i2d_OCSP_RESPONSE_bio(bio, res); - str = ossl_protect_membio2str(bio, &status); - BIO_free(bio); - if(status) rb_jump_tag(status); + if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0) + ossl_raise(eOCSPError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_OCSP_RESPONSE(res, NULL) <= 0) + ossl_raise(eOCSPError, NULL); + ossl_str_adjust(str, p); return str; } @@ -556,7 +559,7 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) EVP_PKEY *key; STACK_OF(X509) *x509s; unsigned long flg; - int ret, status = 0; + int ret; rb_scan_args(argc, argv, "22", &signer_cert, &signer_key, &certs, &flags); GetOCSPBasicRes(self, bs); @@ -568,8 +571,7 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) flg |= OCSP_NOCERTS; } else{ - x509s = ossl_protect_x509_ary2sk(certs, &status); - if(status) rb_jump_tag(status); + x509s = ossl_x509_ary2sk(certs); } ret = OCSP_basic_sign(bs, signer, key, EVP_sha1(), x509s, flg); sk_X509_pop_free(x509s, X509_free); diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 2ebf6d4a7b..66c40b9b39 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -98,20 +98,13 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) BIO *in, *out; PKCS7 *pkcs7; VALUE ret, data; - int status = 0; in = ossl_obj2bio(arg); out = NULL; - if((pkcs7 = SMIME_read_PKCS7(in, &out)) == NULL){ - BIO_free(in); - BIO_free(out); - ossl_raise(ePKCS7Error, NULL); - } - if(out) data = ossl_protect_membio2str(out, &status); - else data = Qnil; + pkcs7 = SMIME_read_PKCS7(in, &out); BIO_free(in); - BIO_free(out); - if(status) rb_jump_tag(status); + if(!pkcs7) ossl_raise(ePKCS7Error, NULL); + data = out ? ossl_membio2str(out) : Qnil; WrapPKCS7(cPKCS7, ret, pkcs7); ossl_pkcs7_set_data(ret, data); ossl_pkcs7_set_err_string(ret, Qnil); @@ -123,11 +116,10 @@ static VALUE ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) { VALUE pkcs7, data, flags; - BIO *out; - BIO *in; + BIO *out, *in; PKCS7 *p7; VALUE str; - int flg, status = 0; + int flg; rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); SafeGetPKCS7(pkcs7, p7); @@ -145,10 +137,8 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) BIO_free(in); ossl_raise(ePKCS7Error, NULL); } - str = ossl_protect_membio2str(out, &status); BIO_free(in); - BIO_free(out); - if(status) rb_jump_tag(status); + str = ossl_membio2str(out); return str; } @@ -231,9 +221,9 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) sk_X509_pop_free(x509s, X509_free); ossl_raise(ePKCS7Error, NULL); } + BIO_free(in); WrapPKCS7(cPKCS7, ret, p7); ossl_pkcs7_set_data(ret, data); - BIO_free(in); sk_X509_pop_free(x509s, X509_free); return ret; @@ -256,16 +246,18 @@ ossl_pkcs7_alloc(VALUE klass) static VALUE ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) { + PKCS7 *p7; BIO *in; - VALUE s; + VALUE arg; - if(rb_scan_args(argc, argv, "01", &s) == 0) + if(rb_scan_args(argc, argv, "01", &arg) == 0) return self; - in = ossl_obj2bio(s); - - if (!PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL)) { - BIO_free(in); - ossl_raise(ePKCS7Error, NULL); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL); + if (!p7) { + BIO_reset(in); + p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self)); } BIO_free(in); ossl_pkcs7_set_data(self, Qnil); @@ -534,14 +526,12 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) ossl_raise(ePKCS7Error, NULL); } ok = PKCS7_verify(p7, x509s, x509st, in, out, flg); + BIO_free(in); msg = ERR_reason_error_string(ERR_get_error()); ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); - data = ossl_protect_membio2str(out, &status); + data = ossl_membio2str(out); ossl_pkcs7_set_data(self, data); - BIO_free(in); - BIO_free(out); sk_X509_pop_free(x509s, X509_free); - if(status) rb_jump_tag(status); return (ok == 1) ? Qtrue : Qfalse; } @@ -556,7 +546,6 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) PKCS7 *p7; BIO *out; VALUE str; - int status = 0; rb_scan_args(argc, argv, "21", &pkey, &cert, &flags); GetPKCS7(self, p7); @@ -569,9 +558,7 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self) BIO_free(out); ossl_raise(ePKCS7Error, NULL); } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if(status) rb_jump_tag(status); + str = ossl_membio2str(out); /* out will be free */ return str; } @@ -611,13 +598,32 @@ ossl_pkcs7_add_data(VALUE self, VALUE data) return data; } +static VALUE +ossl_pkcs7_to_der(VALUE self) +{ + PKCS7 *pkcs7; + VALUE str; + long len; + unsigned char *p; + + GetPKCS7(self, pkcs7); + if((len = i2d_PKCS7(pkcs7, NULL)) <= 0) + ossl_raise(ePKCS7Error, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_PKCS7(pkcs7, &p) <= 0) + ossl_raise(ePKCS7Error, NULL); + ossl_str_adjust(str, p); + + return str; +} + static VALUE ossl_pkcs7_to_pem(VALUE self) { PKCS7 *pkcs7; BIO *out; VALUE str; - int status = 0; GetPKCS7(self, pkcs7); if (!(out = BIO_new(BIO_s_mem()))) { @@ -627,10 +633,8 @@ ossl_pkcs7_to_pem(VALUE self) BIO_free(out); ossl_raise(ePKCS7Error, NULL); } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if(status) rb_jump_tag(status); - + str = ossl_membio2str(out); + return str; } @@ -750,6 +754,7 @@ Init_ossl_pkcs7() rb_define_method(cPKCS7, "decrypt", ossl_pkcs7_decrypt, -1); rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); rb_define_alias(cPKCS7, "to_s", "to_pem"); + rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); cPKCS7Signer = rb_define_class_under(mPKCS7, "Signer", rb_cObject); rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc); diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index f9f8c0ad5e..dcae075ee8 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -149,23 +149,17 @@ ossl_pkey_to_der(VALUE self) { EVP_PKEY *pkey; VALUE str; - BIO *out; - BUF_MEM *buf; + long len; + unsigned char *p; GetPKey(self, pkey); - - out = BIO_new(BIO_s_mem()); - if (!out) ossl_raise(ePKeyError, NULL); - - if (!i2d_PUBKEY_bio(out, pkey)) { - BIO_free(out); + if((len = i2d_PUBKEY(pkey, NULL)) <= 0) ossl_raise(ePKeyError, NULL); - } - - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - - BIO_free(out); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(len = i2d_PUBKEY(pkey, &p) <= 0) + ossl_raise(ePKeyError, NULL); + ossl_str_adjust(str, p); return str; } @@ -175,7 +169,6 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) { EVP_PKEY *pkey; EVP_MD_CTX ctx; - char *buf; int buf_len; VALUE str; @@ -186,15 +179,12 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) EVP_SignInit(&ctx, GetDigestPtr(digest)); StringValue(data); EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len); - if (!(buf = OPENSSL_malloc(EVP_PKEY_size(pkey) + 16))) { - ossl_raise(ePKeyError, NULL); - } - if (!EVP_SignFinal(&ctx, buf, &buf_len, pkey)) { - OPENSSL_free(buf); + str = rb_str_new(0, EVP_PKEY_size(pkey)+16); + if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey)) ossl_raise(ePKeyError, NULL); - } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + assert(buf_len <= RSTRING(str)->len); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 84eff16f49..80f7f2a5bf 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -119,28 +119,28 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) DH *dh; int g = 2; BIO *in; - VALUE buffer, gen; + VALUE arg, gen; GetPKey(self, pkey); - rb_scan_args(argc, argv, "11", &buffer, &gen); - if (FIXNUM_P(buffer)) { + rb_scan_args(argc, argv, "11", &arg, &gen); + if (FIXNUM_P(arg)) { if (!NIL_P(gen)) { g = FIX2INT(gen); } - if (!(dh = dh_generate(FIX2INT(buffer), g))) { + if (!(dh = dh_generate(FIX2INT(arg), g))) { ossl_raise(eDHError, NULL); } - } else { - StringValue(buffer); - in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len); - if (!in){ - ossl_raise(eDHError, NULL); - } - if (!(dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL))) { - BIO_free(in); - ossl_raise(eDHError, NULL); + } + else { + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (!dh){ + BIO_reset(in); + dh = d2i_DHparams_bio(in, NULL); } BIO_free(in); + if (!dh) ossl_raise(eDHError, NULL); } if (!EVP_PKEY_assign_DH(pkey, dh)) { DH_free(dh); @@ -177,7 +177,6 @@ ossl_dh_export(VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; VALUE str; GetPKeyDH(self, pkey); @@ -188,9 +187,7 @@ ossl_dh_export(VALUE self) BIO_free(out); ossl_raise(eDHError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } @@ -228,7 +225,6 @@ ossl_dh_to_text(VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; VALUE str; GetPKeyDH(self, pkey); @@ -239,9 +235,7 @@ ossl_dh_to_text(VALUE self) BIO_free(out); ossl_raise(eDHError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } @@ -306,24 +300,17 @@ ossl_dh_compute_key(VALUE self, VALUE pub) BIGNUM *pub_key; VALUE str; int len; - char *buf; GetPKeyDH(self, pkey); dh = pkey->pkey.dh; pub_key = GetBNPtr(pub); - len = DH_size(dh); - if (!(buf = OPENSSL_malloc(len))) { - ossl_raise(eDHError, "Cannot allocate mem for shared secret"); - } - - if ((len = DH_compute_key(buf, pub_key, dh)) < 0) { - OPENSSL_free(buf); + str = rb_str_new(0, len); + if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) { ossl_raise(eDHError, NULL); } - - str = rb_str_new(buf, len); - OPENSSL_free(buf); + RSTRING(str)->len = len; + RSTRING(str)->ptr[len] = 0; return str; } diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 5cea9345e9..bbbd1b8839 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -119,40 +119,37 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) DSA *dsa; BIO *in; char *passwd = NULL; - VALUE buffer, pass; + VALUE arg, pass; GetPKey(self, pkey); - rb_scan_args(argc, argv, "11", &buffer, &pass); - if (FIXNUM_P(buffer)) { - if (!(dsa = dsa_generate(FIX2INT(buffer)))) { + rb_scan_args(argc, argv, "11", &arg, &pass); + if (FIXNUM_P(arg)) { + if (!(dsa = dsa_generate(FIX2INT(arg)))) { ossl_raise(eDSAError, NULL); } - } else { - StringValue(buffer); - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len); - if (!in){ - ossl_raise(eDSAError, NULL); - } - + } + else { + if (!NIL_P(pass)) passwd = StringValuePtr(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); - if (!dsa) { - BIO_reset(in); - + if (!dsa) { BIO_reset(in); dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); } if (!dsa) { BIO_reset(in); - dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); } - if (!dsa) { - BIO_free(in); - ossl_raise(eDSAError, "Neither PUB key nor PRIV key:"); + if (!dsa) { + BIO_reset(in); + dsa = d2i_DSAPrivateKey_bio(in, NULL); + } + if (!dsa) { + BIO_reset(in); + dsa = d2i_DSA_PUBKEY_bio(in, NULL); } BIO_free(in); + if (!dsa) ossl_raise(eDSAError, "Neither PUB key nor PRIV key:"); } if (!EVP_PKEY_assign_DSA(pkey, dsa)) { DSA_free(dsa); @@ -191,7 +188,6 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; const EVP_CIPHER *ciph = NULL; char *passwd = NULL; VALUE cipher, pass, str; @@ -219,9 +215,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) ossl_raise(eDSAError, NULL); } } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } @@ -260,7 +254,6 @@ ossl_dsa_to_text(VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; VALUE str; GetPKeyDSA(self, pkey); @@ -271,9 +264,7 @@ ossl_dsa_to_text(VALUE self) BIO_free(out); ossl_raise(eDSAError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } @@ -299,11 +290,12 @@ ossl_dsa_to_public_key(VALUE self) return obj; } +#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16) + static VALUE ossl_dsa_sign(VALUE self, VALUE data) { EVP_PKEY *pkey; - char *buf; int buf_len; VALUE str; @@ -312,16 +304,13 @@ ossl_dsa_sign(VALUE self, VALUE data) if (!DSA_PRIVATE(pkey->pkey.dsa)) { ossl_raise(eDSAError, "Private DSA key needed!"); } - if (!(buf = OPENSSL_malloc(DSA_size(pkey->pkey.dsa) + 16))) { - ossl_raise(eDSAError, NULL); - } - if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, buf, + str = rb_str_new(0, ossl_dsa_buf_size(pkey)); + if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr, &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */ - OPENSSL_free(buf); ossl_raise(eDSAError, NULL); } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index ce53a898e0..3b27a20121 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -110,43 +110,41 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) RSA *rsa; BIO *in; char *passwd = NULL; - VALUE buffer, pass; + VALUE arg, pass; GetPKey(self, pkey); - - rb_scan_args(argc, argv, "11", &buffer, &pass); - - if (FIXNUM_P(buffer)) { - rsa = rsa_generate(FIX2INT(buffer), NIL_P(pass) ? RSA_F4 : NUM2INT(pass)); - if (!rsa) { - ossl_raise(eRSAError, NULL); - } + rb_scan_args(argc, argv, "11", &arg, &pass); + if (FIXNUM_P(arg)) { + rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass)); + if (!rsa) ossl_raise(eRSAError, NULL); } 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, NULL); - } - + if (!NIL_P(pass)) passwd = StringValuePtr(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); if (!rsa) { BIO_reset(in); - rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); } if (!rsa) { BIO_reset(in); - rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); } - BIO_free(in); - if (!rsa) { - ossl_raise(eRSAError, "Neither PUB key nor PRIV key:"); + BIO_reset(in); + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } + if (!rsa) { + BIO_reset(in); + rsa = d2i_RSAPublicKey_bio(in, NULL); } + if (!rsa) { + BIO_reset(in); + rsa = d2i_RSA_PUBKEY_bio(in, NULL); + } + BIO_free(in); + if (!rsa) ossl_raise(eRSAError, "Neither PUB key nor PRIV key:"); } if (!EVP_PKEY_assign_RSA(pkey, rsa)) { RSA_free(rsa); @@ -184,7 +182,6 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; const EVP_CIPHER *ciph = NULL; char *passwd = NULL; VALUE cipher, pass, str; @@ -214,36 +211,29 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) ossl_raise(eRSAError, NULL); } } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } +#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) + static VALUE ossl_rsa_public_encrypt(VALUE self, VALUE buffer) { EVP_PKEY *pkey; - char *buf; int buf_len; VALUE str; GetPKeyRSA(self, pkey); - StringValue(buffer); - - if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { - ossl_raise(eRSAError, NULL); - } + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, - buf, pkey->pkey.rsa, RSA_PKCS1_PADDING); - if (buf_len < 0){ - OPENSSL_free(buf); - ossl_raise(eRSAError, NULL); - } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + RSTRING(str)->ptr, pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } @@ -252,23 +242,18 @@ static VALUE ossl_rsa_public_decrypt(VALUE self, VALUE buffer) { EVP_PKEY *pkey; - char *buf; int buf_len; VALUE str; GetPKeyRSA(self, pkey); StringValue(buffer); - if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { - ossl_raise(eRSAError, NULL); - } + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, - buf, pkey->pkey.rsa, RSA_PKCS1_PADDING); - if(buf_len < 0) { - OPENSSL_free(buf); - ossl_raise(eRSAError, NULL); - } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + RSTRING(str)->ptr, pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if(buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } @@ -277,7 +262,6 @@ static VALUE ossl_rsa_private_encrypt(VALUE self, VALUE buffer) { EVP_PKEY *pkey; - char *buf; int buf_len; VALUE str; @@ -286,17 +270,13 @@ ossl_rsa_private_encrypt(VALUE self, VALUE buffer) ossl_raise(eRSAError, "PRIVATE key needed for this operation!"); } StringValue(buffer); - if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { - ossl_raise(eRSAError, "Memory alloc error"); - } + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, - buf, pkey->pkey.rsa, RSA_PKCS1_PADDING); - if (buf_len < 0){ - OPENSSL_free(buf); - ossl_raise(eRSAError, NULL); - } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + RSTRING(str)->ptr, pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } @@ -305,7 +285,6 @@ static VALUE ossl_rsa_private_decrypt(VALUE self, VALUE buffer) { EVP_PKEY *pkey; - char *buf; int buf_len; VALUE str; @@ -314,17 +293,13 @@ ossl_rsa_private_decrypt(VALUE self, VALUE buffer) ossl_raise(eRSAError, "Private RSA key needed!"); } StringValue(buffer); - if (!(buf = OPENSSL_malloc(RSA_size(pkey->pkey.rsa) + 16))) { - ossl_raise(eRSAError, "Memory alloc error"); - } + str = rb_str_new(0, ossl_rsa_buf_size(pkey)); buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr, - buf, pkey->pkey.rsa, RSA_PKCS1_PADDING); - if(buf_len < 0) { - OPENSSL_free(buf); - ossl_raise(eRSAError, NULL); - } - str = rb_str_new(buf, buf_len); - OPENSSL_free(buf); + RSTRING(str)->ptr, pkey->pkey.rsa, + RSA_PKCS1_PADDING); + if (buf_len < 0) ossl_raise(eRSAError, NULL); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; return str; } @@ -359,14 +334,13 @@ ossl_rsa_get_params(VALUE self) /* * Prints all parameters of key to buffer * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) + * Don't use :-)) (It's up to you) */ static VALUE ossl_rsa_to_text(VALUE self) { EVP_PKEY *pkey; BIO *out; - BUF_MEM *buf; VALUE str; GetPKeyRSA(self, pkey); @@ -377,9 +351,7 @@ ossl_rsa_to_text(VALUE self) BIO_free(out); ossl_raise(eRSAError, NULL); } - BIO_get_mem_ptr(out, &buf); - str = rb_str_new(buf->data, buf->length); - BIO_free(out); + str = ossl_membio2str(out); return str; } diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index c30889221e..ec9883d70a 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -60,18 +60,12 @@ ossl_rand_write_file(VALUE self, VALUE filename) static VALUE ossl_rand_bytes(VALUE self, VALUE len) { - unsigned char *buffer = NULL; VALUE str; - if (!(buffer = OPENSSL_malloc(FIX2INT(len) + 1))) { + str = rb_str_new(0, FIX2INT(len)); + if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) { ossl_raise(eRandomError, NULL); } - if (!RAND_bytes(buffer, FIX2INT(len))) { - OPENSSL_free(buffer); - ossl_raise(eRandomError, NULL); - } - str = rb_str_new(buffer, FIX2INT(len)); - OPENSSL_free(buffer); return str; } @@ -79,18 +73,12 @@ ossl_rand_bytes(VALUE self, VALUE len) static VALUE ossl_rand_pseudo_bytes(VALUE self, VALUE len) { - unsigned char *buffer = NULL; VALUE str; - - if (!(buffer = OPENSSL_malloc(FIX2INT(len) + 1))) { - ossl_raise(eRandomError, NULL); - } - if (!RAND_pseudo_bytes(buffer, FIX2INT(len))) { - OPENSSL_free(buffer); + + str = rb_str_new(0, FIX2INT(len)); + if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) { ossl_raise(eRandomError, NULL); } - str = rb_str_new(buffer, FIX2INT(len)); - OPENSSL_free(buffer); return str; } diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index 6d5df51126..3309a070b4 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -71,70 +71,129 @@ DupX509AttrPtr(VALUE obj) /* * Private */ -static VALUE -ossl_x509attr_s_new_from_array(VALUE klass, VALUE ary) +static VALUE +ossl_x509attr_alloc(VALUE klass) { X509_ATTRIBUTE *attr; - int nid = NID_undef; - VALUE item, obj; + VALUE obj; - Check_Type(ary, T_ARRAY); - if (RARRAY(ary)->len != 2) { - ossl_raise(eX509AttrError, "unsupported ary structure"); - } - /* key [0] */ - item = RARRAY(ary)->ptr[0]; - StringValue(item); - if (!(nid = OBJ_ln2nid(RSTRING(item)->ptr))) { - if (!(nid = OBJ_sn2nid(RSTRING(item)->ptr))) { - ossl_raise(eX509AttrError, NULL); - } - } - /* data [1] */ - item = RARRAY(ary)->ptr[1]; - StringValuePtr(item); - if (!(attr = X509_ATTRIBUTE_create(nid, MBSTRING_ASC, RSTRING(item)->ptr))) { + if (!(attr = X509_ATTRIBUTE_new())) ossl_raise(eX509AttrError, NULL); - } WrapX509Attr(klass, obj, attr); - + return obj; } -#if 0 -/* - * is there any print for attribute? - * (NO, but check t_req.c in crypto/asn1) - */ static VALUE -ossl_x509attr_to_a(VALUE self) +ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) { - ossl_x509attr *attrp = NULL; - BIO *out = NULL; - BUF_MEM *buf = NULL; - int nid = NID_undef; - VALUE ary, value; - - GetX509Attr(obj, attrp); - ary = rb_ary_new2(2); - nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attrp->attribute)); - rb_ary_push(ary, rb_str_new2(OBJ_nid2sn(nid))); - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509ExtensionError, NULL); - if (!X509V3_???_print(out, extp->extension, 0, 0)) { - BIO_free(out); - ossl_raise(eX509ExtensionError, NULL); + VALUE oid, value; + X509_ATTRIBUTE *attr; + unsigned char *p; + + if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){ + GetX509Attr(self, attr); + oid = ossl_to_der_if_possible(oid); + p = RSTRING(oid)->ptr; + if(!d2i_X509_ATTRIBUTE(&attr, &p, RSTRING(oid)->len)){ + ossl_raise(eX509AttrError, NULL); + } + return self; } - BIO_get_mem_ptr(out, &buf); - value = rb_str_new(buf->data, buf->length); - BIO_free(out); - rb_funcall(value, rb_intern("tr!"), 2, rb_str_new2("\n"), rb_str_new2(",")); - rb_ary_push(ary, value); + rb_funcall(self, rb_intern("oid="), 1, oid); + rb_funcall(self, rb_intern("value="), 1, value); + + return self; +} + +static VALUE +ossl_x509attr_set_oid(VALUE self, VALUE oid) +{ + X509_ATTRIBUTE *attr; + ASN1_OBJECT *obj; + char *s; + + GetX509Attr(self, attr); + s = StringValuePtr(oid); + obj = OBJ_txt2obj(s, 0); + if(!obj) obj = OBJ_txt2obj(s, 1); + if(!obj) ossl_raise(eX509AttrError, NULL); + X509_ATTRIBUTE_set1_object(attr, obj); + + return oid; +} + +static VALUE +ossl_x509attr_get_oid(VALUE self) +{ + X509_ATTRIBUTE *attr; + ASN1_OBJECT *oid; + BIO *out; + VALUE ret; + int nid; - return ary; + GetX509Attr(self, attr); + oid = X509_ATTRIBUTE_get0_object(attr); + if ((nid = OBJ_obj2nid(oid)) != NID_undef) + ret = rb_str_new2(OBJ_nid2sn(nid)); + else{ + if (!(out = BIO_new(BIO_s_mem()))) + ossl_raise(eX509AttrError, NULL); + i2a_ASN1_OBJECT(out, oid); + ret = ossl_membio2str(out); + } + + return ret; } + +#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE) +# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single) +# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1) +#else +# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->set) +# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0) #endif +static VALUE +ossl_x509attr_set_value(VALUE self, VALUE value) +{ + /* + * It has not been work fine and temporarily disabled. + * It may be reimplemented with ASN.1 support. + */ + return value; +} + +static VALUE +ossl_x509attr_get_value(VALUE self) +{ + /* + * It has not been work fine and temporarily disabled. + * It may be reimplemented with ASN.1 support. + */ + return Qnil; +} + +static VALUE +ossl_x509attr_to_der(VALUE self) +{ + X509_ATTRIBUTE *attr; + VALUE str; + int len; + unsigned char *p; + + GetX509Attr(self, attr); + if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0) + ossl_raise(eX509AttrError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_ATTRIBUTE(attr, &p) <= 0) + ossl_raise(eX509AttrError, NULL); + RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr; + + return str; +} + /* * X509_ATTRIBUTE init */ @@ -144,9 +203,11 @@ Init_ossl_x509attr() eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError); cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject); - rb_define_singleton_method(cX509Attr, "new_from_array", ossl_x509attr_s_new_from_array, 1); -/* - * TODO: - rb_define_method(cX509Attr, "to_a", ossl_x509attr_to_a, 0); - */ + rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc); + rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1); + rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1); + rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0); + rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1); + rb_define_method(cX509Attr, "value", ossl_x509attr_get_value, 0); + rb_define_method(cX509Attr, "to_der", ossl_x509attr_to_der, 0); } diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index b689f578dc..443a2ba4c3 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -136,13 +136,8 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self) /* create just empty X509Cert */ return self; } + arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(arg); - - /* - * TODO: - * Check if we could free old X509 - X509_free(DATA_PTR(self)); - */ x509 = PEM_read_bio_X509(in, (X509 **)&DATA_PTR(self), NULL, NULL); if (!x509) { BIO_reset(in); @@ -178,22 +173,18 @@ static VALUE ossl_x509_to_der(VALUE self) { X509 *x509; - BIO *out; VALUE str; - int status=0; + long len; + unsigned char *p; GetX509(self, x509); - - out = BIO_new(BIO_s_mem()); - if (!out) ossl_raise(eX509CertError, NULL); - - if (!i2d_X509_bio(out, x509)) { - BIO_free(out); + if ((len = i2d_X509(x509, NULL)) <= 0) ossl_raise(eX509CertError, NULL); - } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if (status) rb_jump_tag(status); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if (i2d_X509(x509, &p) <= 0) + ossl_raise(eX509CertError, NULL); + ossl_str_adjust(str, p); return str; } @@ -204,7 +195,6 @@ ossl_x509_to_pem(VALUE self) X509 *x509; BIO *out; VALUE str; - int status=0; GetX509(self, x509); out = BIO_new(BIO_s_mem()); @@ -214,9 +204,7 @@ ossl_x509_to_pem(VALUE self) BIO_free(out); ossl_raise(eX509CertError, NULL); } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if (status) rb_jump_tag(status); + str = ossl_membio2str(out); return str; } @@ -227,7 +215,6 @@ ossl_x509_to_text(VALUE self) X509 *x509; BIO *out; VALUE str; - int status=0; GetX509(self, x509); @@ -238,9 +225,7 @@ ossl_x509_to_text(VALUE self) BIO_free(out); ossl_raise(eX509CertError, NULL); } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if (status) rb_jump_tag(status); + str = ossl_membio2str(out); return str; } @@ -323,7 +308,6 @@ ossl_x509_get_signature_algorithm(VALUE self) X509 *x509; BIO *out; VALUE str; - int status=0; GetX509(self, x509); @@ -334,9 +318,7 @@ ossl_x509_get_signature_algorithm(VALUE self) BIO_free(out); ossl_raise(eX509CertError, NULL); } - str = ossl_protect_membio2str(out, &status); - BIO_free(out); - if (status) rb_jump_tag(status); + str = ossl_membio2str(out); return str; } diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 517080b32d..a7746aa2b3 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -92,33 +92,20 @@ ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; X509_CRL *crl; - VALUE buffer; + VALUE arg; - if (rb_scan_args(argc, argv, "01", &buffer) == 0) { + if (rb_scan_args(argc, argv, "01", &arg) == 0) { return self; } - StringValue(buffer); - - in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len); - if (!in) { - ossl_raise(eX509CRLError, NULL); - } - /* - * TODO: - * Check if we should free CRL - X509_CRL_free(DATA_PTR(self)); - */ + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); crl = PEM_read_bio_X509_CRL(in, (X509_CRL **)&DATA_PTR(self), NULL, NULL); if (!crl) { BIO_reset(in); - crl = d2i_X509_CRL_bio(in, (X509_CRL **)&DATA_PTR(self)); } - if (!crl) { - BIO_free(in); - ossl_raise(eX509CRLError, NULL); - } BIO_free(in); + if (!crl) ossl_raise(eX509CRLError, NULL); return self; } diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index c1f443df66..495c18049a 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -181,20 +181,17 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) /*GetX509ExtFactory(self, ctx);*/ - rb_scan_args(argc, argv, "04", &issuer_cert, &subject_cert, &subject_req, &crl); - - if (!NIL_P(issuer_cert)) { + rb_scan_args(argc, argv, "04", + &issuer_cert, &subject_cert, &subject_req, &crl); + if (!NIL_P(issuer_cert)) ossl_x509extfactory_set_issuer_cert(self, issuer_cert); - } - if (!NIL_P(subject_cert)) { + if (!NIL_P(subject_cert)) ossl_x509extfactory_set_subject_cert(self, subject_cert); - } - if (!NIL_P(subject_req)) { + if (!NIL_P(subject_req)) ossl_x509extfactory_set_subject_req(self, subject_req); - } - if (!NIL_P(crl)) { + if (!NIL_P(crl)) ossl_x509extfactory_set_crl(self, crl); - } + return self; } @@ -207,46 +204,26 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) * ["ln", "value"] => not critical */ static VALUE -ossl_x509extfactory_create_ext_from_array(VALUE self, VALUE ary) +ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) { X509V3_CTX *ctx; X509_EXTENSION *ext; + VALUE oid, value, critical, valstr, obj; int nid; - char *value; - VALUE item, obj; GetX509ExtFactory(self, ctx); - Check_Type(ary, T_ARRAY); - if ((RARRAY(ary)->len) < 2 || (RARRAY(ary)->len > 3)) { /*2 or 3 allowed*/ - ossl_raise(eX509ExtError, "unsupported structure"); - } - /* key [0] */ - item = RARRAY(ary)->ptr[0]; - StringValue(item); - if (!(nid = OBJ_ln2nid(RSTRING(item)->ptr))) { - if (!(nid = OBJ_sn2nid(RSTRING(item)->ptr))) { - ossl_raise(eX509ExtError, NULL); - } - } - /* data [1] */ - item = RARRAY(ary)->ptr[1]; - StringValue(item); - /* (optional) critical [2] */ - if (RARRAY(ary)->len == 3 && RARRAY(ary)->ptr[2] == Qtrue) { - if (!(value = OPENSSL_malloc(strlen("critical,") + - (RSTRING(item)->len) + 1))) { - ossl_raise(eX509ExtError, "malloc error"); - } - strcpy(value, "critical,"); - strncat(value, RSTRING(item)->ptr, RSTRING(item)->len); - } else { - value = strdup(StringValuePtr(item)); - } - if (!(ext = X509V3_EXT_conf_nid(NULL, ctx, nid, value))) { - OPENSSL_free(value); - ossl_raise(eX509ExtError, NULL); - } - OPENSSL_free(value); + rb_scan_args(argc, argv, "21", &oid, &value, &critical); + StringValue(oid); + StringValue(value); + if(NIL_P(critical)) critical = Qfalse; + + nid = OBJ_ln2nid(RSTRING(oid)->ptr); + if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr); + if(!nid) ossl_raise(eX509ExtError, NULL); + valstr = rb_str_new2(RTEST(critical) ? "critical," : ""); + rb_str_append(valstr, value); + ext = X509V3_EXT_conf_nid(NULL, ctx, nid, RSTRING(valstr)->ptr); + if (!ext) ossl_raise(eX509ExtError, NULL); WrapX509Ext(cX509Ext, obj, ext); return obj; @@ -273,8 +250,18 @@ static VALUE ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) { VALUE oid, value, critical; + unsigned char *p; + X509_EXTENSION *ext; - rb_scan_args(argc, argv, "21", &oid, &value, &critical); + if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){ + /* evaluate oid as a DER string */ + oid = ossl_to_der_if_possible(oid); + GetX509Ext(self, ext); + p = RSTRING(oid)->ptr; + if(!d2i_X509_EXTENSION(&ext, &p, RSTRING(oid)->len)) + ossl_raise(eX509ExtError, NULL); + return self; + } rb_funcall(self, rb_intern("oid="), 1, oid); rb_funcall(self, rb_intern("value="), 1, value); if(argc > 2) rb_funcall(self, rb_intern("critical="), 1, critical); @@ -307,17 +294,17 @@ ossl_x509ext_set_value(VALUE self, VALUE data) char *s; GetX509Ext(self, ext); - StringValue(data); + data = ossl_to_der_if_possible(data); if(!(s = OPENSSL_malloc(RSTRING(data)->len))) ossl_raise(eX509ExtError, "malloc error"); memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len); if(!(asn1s = ASN1_OCTET_STRING_new())){ - free(s); + free(s); ossl_raise(eX509ExtError, NULL); } if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){ - free(s); - ASN1_OCTET_STRING_free(asn1s); + free(s); + ASN1_OCTET_STRING_free(asn1s); ossl_raise(eX509ExtError, NULL); } X509_EXTENSION_set_data(ext, asn1s); @@ -343,7 +330,7 @@ ossl_x509ext_get_oid(VALUE obj) ASN1_OBJECT *extobj; BIO *out; VALUE ret; - int nid, status = 0; + int nid; GetX509Ext(obj, ext); extobj = X509_EXTENSION_get_object(ext); @@ -353,9 +340,7 @@ ossl_x509ext_get_oid(VALUE obj) if (!(out = BIO_new(BIO_s_mem()))) ossl_raise(eX509ExtError, NULL); i2a_ASN1_OBJECT(out, extobj); - ret = ossl_protect_membio2str(out, &status); - BIO_free(out); - if(status) rb_jump_tag(status); + ret = ossl_membio2str(out); } return ret; @@ -367,16 +352,13 @@ ossl_x509ext_get_value(VALUE obj) X509_EXTENSION *ext; BIO *out; VALUE ret; - int status = 0; GetX509Ext(obj, ext); if (!(out = BIO_new(BIO_s_mem()))) ossl_raise(eX509ExtError, NULL); if (!X509V3_EXT_print(out, ext, 0, 0)) M_ASN1_OCTET_STRING_print(out, ext->value); - ret = ossl_protect_membio2str(out, &status); - BIO_free(out); - if(status) rb_jump_tag(status); + ret = ossl_membio2str(out); return ret; } @@ -394,15 +376,17 @@ ossl_x509ext_to_der(VALUE obj) { X509_EXTENSION *ext; unsigned char *p; - int len; + long len; VALUE str; GetX509Ext(obj, ext); - p = NULL; - if((len = i2d_X509_EXTENSION(ext, &p)) < 0) - ossl_raise(eX509ExtError, NULL); - str = rb_str_new(p, len); - free(p); + if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0) + ossl_raise(eX509ExtError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_EXTENSION(ext, &p) < 0) + ossl_raise(eX509ExtError, NULL); + ossl_str_adjust(str, p); return str; } @@ -431,7 +415,7 @@ Init_ossl_x509ext() rb_define_method(cX509ExtFactory, "subject_request=", ossl_x509extfactory_set_subject_req, 1); rb_define_method(cX509ExtFactory, "crl=", ossl_x509extfactory_set_crl, 1); rb_define_method(cX509ExtFactory, "config=", ossl_x509extfactory_set_config, 1); - rb_define_method(cX509ExtFactory, "create_ext_from_array", ossl_x509extfactory_create_ext_from_array, 1); + rb_define_method(cX509ExtFactory, "create_ext", ossl_x509extfactory_create_ext, -1); cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index dfc30de405..4f895f0cfd 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -89,11 +89,20 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self) X509_NAME *name; int i, type; VALUE arg, item, key, value; - + GetX509Name(self, name); if (rb_scan_args(argc, argv, "01", &arg) == 0) { return self; } + if (rb_respond_to(arg, ossl_s_to_der)){ + unsigned char *p; + VALUE str = rb_funcall(arg, ossl_s_to_der, 0); + StringValue(str); + p = RSTRING(str)->ptr; + if(!d2i_X509_NAME(&name, &p, RSTRING(str)->len)) + ossl_raise(eX509NameError, NULL); + return self; + } Check_Type(arg, T_ARRAY); for (i=0; ilen; i++) { item = RARRAY(arg)->ptr[i]; @@ -209,6 +218,26 @@ ossl_x509name_hash(VALUE self) return ULONG2NUM(hash); } +static VALUE +ossl_x509name_to_der(VALUE self) +{ + X509_NAME *name; + VALUE str; + long len; + unsigned char *p; + + GetX509Name(self, name); + if((len = i2d_X509_NAME(name, NULL)) <= 0) + ossl_raise(eX509NameError, NULL); + str = rb_str_new(0, len); + p = RSTRING(str)->ptr; + if(i2d_X509_NAME(name, &p) <= 0) + ossl_raise(eX509NameError, NULL); + ossl_str_adjust(str, p); + + return str; +} + /* * INIT */ @@ -221,13 +250,11 @@ Init_ossl_x509name() rb_define_alloc_func(cX509Name, ossl_x509name_alloc); rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1); - rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, 0); rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0); - rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1); rb_define_alias(cX509Name, "<=>", "cmp"); rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1); - rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0); + rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0); } diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index 4830f2ad34..b35bc2506e 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -90,33 +90,20 @@ ossl_x509req_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; X509_REQ *req; - VALUE buffer; + VALUE arg; - if (rb_scan_args(argc, argv, "01", &buffer) == 0) { + if (rb_scan_args(argc, argv, "01", &arg) == 0) { return self; } - StringValue(buffer); - - in = BIO_new_mem_buf(RSTRING(buffer)->ptr, RSTRING(buffer)->len); - if (!in) { - ossl_raise(eX509ReqError, NULL); - } - /* - * TODO: - * Check if we should - X509_REQ_free(DATA_PTR(self)); - */ + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(arg); req = PEM_read_bio_X509_REQ(in, (X509_REQ **)&DATA_PTR(self), NULL, NULL); if (!req) { BIO_reset(in); - req = d2i_X509_REQ_bio(in, (X509_REQ **)&DATA_PTR(self)); } - if (!req) { - BIO_free(in); - ossl_raise(eX509ReqError, NULL); - } BIO_free(in); + if (!req) ossl_raise(eX509ReqError, NULL); return self; } -- cgit v1.2.3